Skip to content

Commit a07f6b9

Browse files
authored
Merge pull request #604 from devforth/next
Next
2 parents 4909fdc + a0c405c commit a07f6b9

24 files changed

Lines changed: 522 additions & 102 deletions

File tree

adminforth/commands/createApp/.env.hbs

Whitespace-only changes.

adminforth/commands/createApp/templates/.agents/skills/adminforth-custom-vue/SKILL.md.hbs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ show: {
134134
/>
135135

136136
<p v-if="errorMessage" class="text-sm text-red-600">
137-
{{ errorMessage }}
137+
\{{ errorMessage }}
138138
</p>
139139

140140
<p v-else-if="isEmpty" class="text-sm text-amber-600">
@@ -227,9 +227,9 @@ function syncState() {
227227
<template>
228228
<div class="flex items-center gap-2">
229229
<span>
230-
{{ meta?.filler?.repeat(record.number_of_rooms || 0) }}
230+
\{{ meta?.filler?.repeat(record.number_of_rooms || 0) }}
231231
</span>
232-
<span>{{ record.number_of_rooms }} {{ meta?.suffix }}</span>
232+
<span>\{{ record.number_of_rooms }} \{{ meta?.suffix }}</span>
233233
</div>
234234
</template>
235235

adminforth/commands/createApp/templates/package.json.hbs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
"dev": "{{packageManagerEnvDev}} tsx watch index.ts",
1212
"prod": "{{packageManagerEnvProd}} tsx index.ts",
1313
"start": "{{packageManagerRun}} dev",
14+
{{#if includePrismaMigrations}}
1415
"makemigration": "{{packageManagerEnvDev}} npx --yes prisma migrate dev --create-only",
1516
"migrate:local": "{{packageManagerEnvDev}} npx --yes prisma migrate deploy",
1617
"migrate:prod": "{{packageManagerEnvProd}} npx --yes prisma migrate deploy",
18+
{{/if}}
1719
"_env:dev": "dotenvx run -f .env -f .env.local --",
1820
"_env:prod": "dotenvx run -f .env.prod --"
1921
},
@@ -27,7 +29,7 @@
2729
"zod": "^4.3.6"
2830
},
2931
"devDependencies": {
30-
"typescript": "5.4.5",
32+
"typescript": "6.0.3",
3133
"tsx": "4.11.2",
3234
"@types/express": "^4.17.21",
3335
"@types/node": "latest",

adminforth/commands/createApp/utils.js

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export function parseArgumentsIntoOptions(rawArgs) {
5656
appName: args['--app-name'],
5757
db: args['--db'],
5858
useNpm: args['--use-npm'],
59+
includePrismaMigrations: args['--include-prisma-migrations'],
5960
};
6061
}
6162

@@ -93,12 +94,27 @@ export async function promptForMissingOptions(options) {
9394
});
9495
}
9596

97+
if (!options.includePrismaMigrations) {
98+
questions.push({
99+
type: 'select',
100+
name: 'includePrismaMigrations',
101+
message: 'Include Prisma migrations? >',
102+
choices: [
103+
{ name: 'Yes', value: true },
104+
{ name: 'No', value: false },
105+
],
106+
default: true,
107+
});
108+
109+
}
110+
96111
const answers = await inquirer.prompt(questions);
97112
return {
98113
...options,
99114
appName: options.appName || answers.appName,
100115
db: options.db || answers.db,
101116
useNpm: options.useNpm || answers.useNpm,
117+
includePrismaMigrations: options.includePrismaMigrations || answers.includePrismaMigrations,
102118
};
103119
}
104120

@@ -246,7 +262,7 @@ async function scaffoldProject(ctx, options, cwd) {
246262
await fse.copy(sourceAssetsDir, targetAssetsDir);
247263

248264
// Write templated files
249-
await writeTemplateFiles(dirname, projectDir, options.useNpm, {
265+
await writeTemplateFiles(dirname, projectDir, options.useNpm, options.includePrismaMigrations, {
250266
dbUrl: connectionString.toString(),
251267
dbUrlProd: connectionStringProd,
252268
prismaDbUrl,
@@ -274,7 +290,7 @@ function getPackageManagerTemplateData(useNpm, nodeMajor) {
274290
};
275291
}
276292

277-
async function writeTemplateFiles(dirname, cwd, useNpm, options) {
293+
async function writeTemplateFiles(dirname, cwd, useNpm, includePrismaMigrations, options) {
278294
const {
279295
dbUrl, prismaDbUrl, appName, provider, nodeMajor,
280296
dbUrlProd, prismaDbUrlProd, sqliteFile
@@ -288,17 +304,6 @@ async function writeTemplateFiles(dirname, cwd, useNpm, options) {
288304
dest: 'tsconfig.json',
289305
data: {},
290306
},
291-
{
292-
src: 'schema.prisma.hbs',
293-
dest: 'schema.prisma',
294-
data: { provider },
295-
condition: Boolean(prismaDbUrl), // only create if prismaDbUrl is truthy
296-
},
297-
{
298-
src: 'prisma.config.ts.hbs',
299-
dest: 'prisma.config.ts',
300-
data: {},
301-
},
302307
{
303308
src: 'index.ts.hbs',
304309
dest: 'index.ts',
@@ -354,14 +359,14 @@ async function writeTemplateFiles(dirname, cwd, useNpm, options) {
354359
dest: '.agents/skills/adminforth-hooks/SKILL.md',
355360
data: {},
356361
},
357-
// {
358-
// src: '.agents/skills/adminforth-custom-vue/SKILL.md.hbs',
359-
// dest: '.agents/skills/adminforth-custom-vue/SKILL.md',
360-
// data: {},
361-
// },
362+
{
363+
src: '.agents/skills/adminforth-custom-vue/SKILL.md.hbs',
364+
dest: '.agents/skills/adminforth-custom-vue/SKILL.md',
365+
data: {},
366+
},
362367
{
363368
// We'll write .env using the same content as .env.sample
364-
src: '.env.local.hbs',
369+
src: '.env.hbs',
365370
dest: '.env',
366371
data: {dbUrl, prismaDbUrl},
367372
},
@@ -393,6 +398,7 @@ async function writeTemplateFiles(dirname, cwd, useNpm, options) {
393398
data: {
394399
appName,
395400
adminforthVersion: adminforthVersion,
401+
includePrismaMigrations,
396402
},
397403
},
398404
{
@@ -417,6 +423,22 @@ async function writeTemplateFiles(dirname, cwd, useNpm, options) {
417423
)
418424
}
419425

426+
if (includePrismaMigrations) {
427+
templateTasks.push(
428+
{
429+
src: 'schema.prisma.hbs',
430+
dest: 'schema.prisma',
431+
data: { provider },
432+
condition: Boolean(prismaDbUrl), // only create if prismaDbUrl is truthy
433+
},
434+
{
435+
src: 'prisma.config.ts.hbs',
436+
dest: 'prisma.config.ts',
437+
data: {},
438+
},
439+
)
440+
}
441+
420442
for (const task of templateTasks) {
421443
// If a condition is specified and false, skip this file
422444
if (task.condition === false) continue;

adminforth/commands/createCustomComponent/templates/customCrud/bottom.vue.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
@click="handleClick"
66
class="text-white bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-500 dark:hover:bg-blue-600 dark:focus:ring-blue-800"
77
>
8-
{{ $t('Example') }}
8+
\{{ $t('Example') }}
99
</button>
1010
</div>
1111
</template>

adminforth/dataConnectors/baseConnector.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,12 +271,13 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
271271
}
272272
}
273273

274-
getDataWithOriginalTypes({ resource, limit, offset, sort, filters }: {
274+
getDataWithOriginalTypes({ resource, limit, offset, sort, filters, columns }: {
275275
resource: AdminForthResource,
276276
limit: number,
277277
offset: number,
278278
sort: IAdminForthSort[],
279279
filters: IAdminForthAndOrFilter,
280+
columns?: AdminForthResourceColumn[],
280281
}): Promise<any[]> {
281282
throw new Error('Method not implemented.');
282283
}
@@ -407,6 +408,10 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
407408
if (value === "" || value === null) {
408409
return this.setFieldValue(field, null);
409410
}
411+
// Accept numbers from JSON/OpenAPI clients.
412+
if (typeof value === "number" && Number.isFinite(value)) {
413+
return this.setFieldValue(field, String(value));
414+
}
410415
// Accept string
411416
if (typeof value === "string") {
412417
const string = value.trim();
@@ -605,13 +610,14 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
605610
throw new Error('Method not implemented.');
606611
}
607612

608-
async getData({ resource, limit, offset, sort, filters, getTotals }: {
613+
async getData({ resource, limit, offset, sort, filters, getTotals, columns }: {
609614
resource: AdminForthResource,
610615
limit: number,
611616
offset: number,
612617
sort: { field: string, direction: AdminForthSortDirections }[],
613618
filters: IAdminForthAndOrFilter,
614619
getTotals: boolean,
620+
columns?: AdminForthResourceColumn[],
615621
}): Promise<{ data: any[], total: number }> {
616622
let normalizedFilters = filters;
617623

@@ -623,7 +629,8 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
623629
normalizedFilters = filterValidation.normalizedFilters as IAdminForthAndOrFilter;
624630
}
625631

626-
const promises: Promise<any>[] = [this.getDataWithOriginalTypes({ resource, limit, offset, sort, filters: normalizedFilters })];
632+
const dataSourceColumns = columns ?? resource.dataSourceColumns;
633+
const promises: Promise<any>[] = [this.getDataWithOriginalTypes({ resource, limit, offset, sort, filters: normalizedFilters, columns: dataSourceColumns })];
627634
if (getTotals) {
628635
promises.push(this.getCount({ resource, filters }));
629636
} else {
@@ -634,7 +641,7 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
634641

635642
// call getFieldValue for each field
636643
data.map((record) => {
637-
for (const col of resource.dataSourceColumns) {
644+
for (const col of dataSourceColumns) {
638645
record[col.name] = this.getFieldValue(col, record[col.name]);
639646
}
640647
});

adminforth/dataConnectors/clickhouse.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,14 +510,15 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
510510
}));
511511
}
512512

513-
async getDataWithOriginalTypes({ resource, limit, offset, sort, filters }: {
513+
async getDataWithOriginalTypes({ resource, limit, offset, sort, filters, columns }: {
514514
resource: AdminForthResource,
515515
limit: number,
516516
offset: number,
517517
sort: { field: string, direction: AdminForthSortDirections }[],
518518
filters: IAdminForthAndOrFilter,
519+
columns?: AdminForthResourceColumn[],
519520
}): Promise<Array<{ group?: string, [key: string]: any }>> {
520-
const columns = resource.dataSourceColumns.map((col) => {
521+
const selectedColumns = (columns ?? resource.dataSourceColumns).map((col) => {
521522
// for decimal cast to string
522523
if (col.type == AdminForthDataTypes.DECIMAL) {
523524
return `toString(${col.name}) as ${col.name}`
@@ -532,7 +533,7 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
532533
const orderBy = sort.length ? `ORDER BY ${sort.map((s) => `${s.field} ${this.SortDirectionsMap[s.direction]}`).join(', ')}` : '';
533534

534535

535-
const q = `SELECT ${columns} FROM ${tableName} ${where} ${orderBy} LIMIT {limit:Int} OFFSET {offset:Int}`;
536+
const q = `SELECT ${selectedColumns} FROM ${tableName} ${where} ${orderBy} LIMIT {limit:Int} OFFSET {offset:Int}`;
536537
const d = {
537538
...params,
538539
limit,

adminforth/dataConnectors/mongo.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,14 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
408408
});
409409
}
410410

411-
async getDataWithOriginalTypes({ resource, limit, offset, sort, filters }:
411+
async getDataWithOriginalTypes({ resource, limit, offset, sort, filters, columns }:
412412
{
413413
resource: AdminForthResource,
414414
limit: number,
415415
offset: number,
416416
sort: { field: string, direction: AdminForthSortDirections }[],
417417
filters: IAdminForthAndOrFilter,
418+
columns?: Array<{ name: string }>,
418419
}
419420
): Promise<any[]> {
420421

@@ -429,7 +430,11 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
429430
return [s.field, this.SortDirectionsMap[s.direction]];
430431
});
431432

432-
const result = await collection.find(query)
433+
const projection = columns
434+
? Object.fromEntries(columns.map((col) => [col.name, 1]))
435+
: undefined;
436+
437+
const result = await collection.find(query, projection ? { projection } : undefined)
433438
.sort(sortArray)
434439
.skip(offset)
435440
.limit(limit)

adminforth/dataConnectors/mysql.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,14 +453,14 @@ class MysqlConnector extends AdminForthBaseConnector implements IAdminForthDataS
453453
return rows;
454454
}
455455

456-
async getDataWithOriginalTypes({ resource, limit, offset, sort, filters }): Promise<any[]> {
457-
const columns = resource.dataSourceColumns.map((col: { name: string }) => `${col.name}`).join(', ');
456+
async getDataWithOriginalTypes({ resource, limit, offset, sort, filters, columns }): Promise<any[]> {
457+
const selectedColumns = (columns ?? resource.dataSourceColumns).map((col: { name: string }) => `${col.name}`).join(', ');
458458
const tableName = resource.table;
459459

460460
const { sql: where, values: filterValues } = this.whereClauseAndValues(filters);
461461

462462
const orderBy = sort.length ? `ORDER BY ${sort.map((s: { field: string; direction: AdminForthSortDirections }) => `${s.field} ${this.SortDirectionsMap[s.direction]}`).join(', ')}` : '';
463-
let selectQuery = `SELECT ${columns} FROM ${tableName}`;
463+
let selectQuery = `SELECT ${selectedColumns} FROM ${tableName}`;
464464
if (where) selectQuery += ` ${where}`;
465465
if (orderBy) selectQuery += ` ${orderBy}`;
466466
if (limit) selectQuery += ` LIMIT ${limit}`;

adminforth/dataConnectors/postgres.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,16 +428,16 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
428428
return stmt.rows;
429429
}
430430

431-
async getDataWithOriginalTypes({ resource, limit, offset, sort, filters }): Promise<any[]> {
432-
const columns = resource.dataSourceColumns.map((col) => `"${col.name}"`).join(', ');
431+
async getDataWithOriginalTypes({ resource, limit, offset, sort, filters, columns }): Promise<any[]> {
432+
const selectedColumns = (columns ?? resource.dataSourceColumns).map((col) => `"${col.name}"`).join(', ');
433433
const tableName = resource.table;
434434

435435
const { sql: where, paramsCount, values: filterValues } = this.whereClauseAndValues(resource, filters);
436436

437437
const limitOffset = `LIMIT $${paramsCount} OFFSET $${paramsCount + 1}`;
438438
const d = [...filterValues, limit, offset];
439439
const orderBy = sort.length ? `ORDER BY ${sort.map((s) => `"${s.field}" ${this.SortDirectionsMap[s.direction]}`).join(', ')}` : '';
440-
const selectQuery = `SELECT ${columns} FROM "${tableName}" ${where} ${orderBy} ${limitOffset}`;
440+
const selectQuery = `SELECT ${selectedColumns} FROM "${tableName}" ${where} ${orderBy} ${limitOffset}`;
441441
dbLogger.trace(`🪲📜 PG Q: ${selectQuery}, params: ${JSON.stringify(d)}`);
442442
const stmt = await this.client.query(selectQuery, d);
443443
const rows = stmt.rows;

0 commit comments

Comments
 (0)