Skip to content

Commit 3200c80

Browse files
committed
增加对查找字段的支持,更新唯一约束信息的提取,修复 CLI 命令中的字段类型
1 parent 85f6f7f commit 3200c80

3 files changed

Lines changed: 89 additions & 1 deletion

File tree

packages/drivers/sql/src/index.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,12 @@ export class SqlDriver implements Driver {
387387
case 'file':
388388
case 'avatar':
389389
case 'location': col = table.json(name); break;
390+
case 'lookup':
391+
col = table.string(name);
392+
if (field.reference_to) {
393+
table.foreign(name).references('id').inTable(field.reference_to);
394+
}
395+
break;
390396
case 'summary': col = table.float(name); break; // Stored calculation result
391397
case 'auto_number': col = table.string(name); break; // Generated string
392398
case 'formula': return; // Virtual field, do not create column
@@ -532,6 +538,17 @@ export class SqlDriver implements Driver {
532538
const columns = await this.introspectColumns(tableName);
533539
const foreignKeys = await this.introspectForeignKeys(tableName);
534540
const primaryKeys = await this.introspectPrimaryKeys(tableName);
541+
const uniqueConstraints = await this.introspectUniqueConstraints(tableName);
542+
543+
// Update columns with primary key and unique information
544+
for (const col of columns) {
545+
if (primaryKeys.includes(col.name)) {
546+
col.isPrimary = true;
547+
}
548+
if (uniqueConstraints.includes(col.name)) {
549+
col.isUnique = true;
550+
}
551+
}
535552

536553
tables[tableName] = {
537554
name: tableName,
@@ -730,6 +747,72 @@ export class SqlDriver implements Driver {
730747
return primaryKeys;
731748
}
732749

750+
/**
751+
* Get unique constraint information for a specific table.
752+
*/
753+
private async introspectUniqueConstraints(tableName: string): Promise<string[]> {
754+
const uniqueColumns: string[] = [];
755+
756+
try {
757+
if (this.config.client === 'pg' || this.config.client === 'postgresql') {
758+
const result = await this.knex.raw(`
759+
SELECT c.column_name
760+
FROM information_schema.table_constraints tc
761+
JOIN information_schema.constraint_column_usage AS ccu
762+
ON tc.constraint_schema = ccu.constraint_schema
763+
AND tc.constraint_name = ccu.constraint_name
764+
WHERE tc.constraint_type = 'UNIQUE'
765+
AND tc.table_name = ?
766+
`, [tableName]);
767+
768+
for (const row of result.rows) {
769+
uniqueColumns.push(row.column_name);
770+
}
771+
} else if (this.config.client === 'mysql' || this.config.client === 'mysql2') {
772+
const result = await this.knex.raw(`
773+
SELECT COLUMN_NAME
774+
FROM information_schema.TABLE_CONSTRAINTS tc
775+
JOIN information_schema.KEY_COLUMN_USAGE kcu
776+
USING (CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME)
777+
WHERE CONSTRAINT_TYPE = 'UNIQUE'
778+
AND TABLE_SCHEMA = DATABASE()
779+
AND TABLE_NAME = ?
780+
`, [tableName]);
781+
782+
for (const row of result[0]) {
783+
uniqueColumns.push(row.COLUMN_NAME);
784+
}
785+
} else if (this.config.client === 'sqlite3') {
786+
const safeTableName = tableName.replace(/[^a-zA-Z0-9_]/g, '');
787+
788+
// Validate table exists
789+
const tablesResult = await this.knex.raw("SELECT name FROM sqlite_master WHERE type = 'table'");
790+
const tableNames = Array.isArray(tablesResult) ? tablesResult.map((row: any) => row.name) : [];
791+
792+
if (!tableNames.includes(safeTableName)) {
793+
return uniqueColumns;
794+
}
795+
796+
const indexes = await this.knex.raw(`PRAGMA index_list(${safeTableName})`);
797+
798+
for (const idx of indexes) {
799+
// Check if unique
800+
if (idx.unique === 1) {
801+
const info = await this.knex.raw(`PRAGMA index_info(${idx.name})`);
802+
// Only handle single column unique constraints for now
803+
if (info.length === 1) {
804+
uniqueColumns.push(info[0].name);
805+
}
806+
}
807+
}
808+
}
809+
} catch (error) {
810+
console.warn('Could not introspect unique constraints for a table:', error);
811+
}
812+
813+
return uniqueColumns;
814+
}
815+
733816
async disconnect() {
734817
await this.knex.destroy();
735818
}

packages/tools/cli/__tests__/commands.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ describe('CLI Commands', () => {
177177
name: 'users',
178178
label: 'Users',
179179
fields: {
180-
username: { type: 'text', required: true, unique: true },
180+
username: { type: 'string', required: true, unique: true },
181181
email: { type: 'email', required: true },
182182
is_active: { type: 'boolean', defaultValue: true }
183183
}

packages/tools/cli/src/commands/new.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ const TEMPLATES: Record<string, any> = {
7070
type: 'record',
7171
handler: 'action_{{name}}'
7272
},
73+
hook: {
74+
label: '{{label}} Hook',
75+
object: '{{objectName}}',
76+
triggers: ['before_insert', 'after_insert']
77+
},
7378
permission: {
7479
label: '{{label}} Permissions',
7580
object: '{{objectName}}',

0 commit comments

Comments
 (0)