@stonecrop/utilities 0.13.12 → 0.13.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/dist/assets/sample_data/coa.json +0 -2362
- package/dist/assets/sample_data/financials.json +0 -252
- package/dist/assets/sample_data/forecast.json +0 -2792
- package/dist/assets/sample_data/forecast_items.json +0 -126
- package/dist/assets/sample_data/http_logs.json +0 -252
- package/dist/assets/sample_data/inbox.json +0 -355
- package/dist/assets/sample_data/parts.json +0 -1322
- package/dist/assets/sample_data/repos.json +0 -1142
- package/dist/composables/keyboard.js +0 -473
- package/dist/composables/visibility/index.js +0 -47
- package/dist/index.js +0 -8
- package/dist/naming-conventions.js +0 -135
- package/dist/sql-introspection.js +0 -260
- package/dist/src/naming-conventions.d.ts +0 -107
- package/dist/src/naming-conventions.d.ts.map +0 -1
- package/dist/src/naming-conventions.js +0 -135
- package/dist/src/sql-introspection.d.ts +0 -111
- package/dist/src/sql-introspection.d.ts.map +0 -1
- package/dist/src/sql-introspection.js +0 -260
- package/dist/src/tsdoc-metadata.json +0 -11
- package/dist/src/workflow-scaffolder.d.ts +0 -77
- package/dist/src/workflow-scaffolder.d.ts.map +0 -1
- package/dist/src/workflow-scaffolder.js +0 -194
- package/dist/tests/setup.d.ts +0 -2
- package/dist/tests/setup.d.ts.map +0 -1
- package/dist/tests/setup.js +0 -4
- package/dist/types/index.js +0 -0
- package/dist/utilities.umd.cjs +0 -2
- package/dist/utilities.umd.cjs.map +0 -1
- package/dist/workflow-scaffolder.js +0 -194
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SQL Schema Introspection Utilities
|
|
3
|
-
* Parses PostgreSQL DDL and converts to Stonecrop schema format
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Maps PostgreSQL data types to Stonecrop field types
|
|
8
|
-
* @param sqlType - PostgreSQL data type
|
|
9
|
-
* @param enumValues - Enum values if type is ENUM
|
|
10
|
-
* @returns Corresponding Stonecrop field type
|
|
11
|
-
* @public
|
|
12
|
-
*/
|
|
13
|
-
export function mapSQLTypeToFieldType(sqlType, enumValues) {
|
|
14
|
-
const normalizedType = sqlType.toLowerCase().trim();
|
|
15
|
-
// Handle parameterized types (e.g., varchar(255) -> varchar)
|
|
16
|
-
const baseType = normalizedType.split('(')[0].trim();
|
|
17
|
-
// Enum types become Select fields
|
|
18
|
-
if (enumValues && enumValues.length > 0) {
|
|
19
|
-
return 'Select';
|
|
20
|
-
}
|
|
21
|
-
// Type mapping based on PostgreSQL types
|
|
22
|
-
const typeMap = {
|
|
23
|
-
// Text types
|
|
24
|
-
varchar: 'Data',
|
|
25
|
-
character: 'Data',
|
|
26
|
-
char: 'Data',
|
|
27
|
-
text: 'Text',
|
|
28
|
-
// Numeric types
|
|
29
|
-
integer: 'Int',
|
|
30
|
-
int: 'Int',
|
|
31
|
-
int2: 'Int',
|
|
32
|
-
int4: 'Int',
|
|
33
|
-
int8: 'Int',
|
|
34
|
-
smallint: 'Int',
|
|
35
|
-
bigint: 'Int',
|
|
36
|
-
serial: 'Int',
|
|
37
|
-
bigserial: 'Int',
|
|
38
|
-
// Float types
|
|
39
|
-
numeric: 'Float',
|
|
40
|
-
decimal: 'Float',
|
|
41
|
-
real: 'Float',
|
|
42
|
-
float: 'Float',
|
|
43
|
-
float4: 'Float',
|
|
44
|
-
float8: 'Float',
|
|
45
|
-
double: 'Float',
|
|
46
|
-
money: 'Currency',
|
|
47
|
-
// Boolean
|
|
48
|
-
boolean: 'Check',
|
|
49
|
-
bool: 'Check',
|
|
50
|
-
// Date/Time types
|
|
51
|
-
timestamp: 'Datetime',
|
|
52
|
-
timestamptz: 'Datetime',
|
|
53
|
-
date: 'Date',
|
|
54
|
-
time: 'Time',
|
|
55
|
-
timetz: 'Time',
|
|
56
|
-
// JSON types (use Code for now)
|
|
57
|
-
json: 'Code',
|
|
58
|
-
jsonb: 'Code',
|
|
59
|
-
xml: 'Code',
|
|
60
|
-
// Array types (use Text for serialization)
|
|
61
|
-
array: 'Text',
|
|
62
|
-
};
|
|
63
|
-
return typeMap[baseType] || 'Data';
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Parses a PostgreSQL CREATE TABLE statement
|
|
67
|
-
* @param ddl - SQL DDL string
|
|
68
|
-
* @returns Array of parsed tables
|
|
69
|
-
* @public
|
|
70
|
-
*/
|
|
71
|
-
export function parseDDL(ddl) {
|
|
72
|
-
const tables = [];
|
|
73
|
-
// Split by CREATE TABLE statements
|
|
74
|
-
const createTableRegex = /CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:(\w+)\.)?(\w+)\s*\(([\s\S]*?)\);/gi;
|
|
75
|
-
let match;
|
|
76
|
-
while ((match = createTableRegex.exec(ddl)) !== null) {
|
|
77
|
-
const schema = match[1];
|
|
78
|
-
const tableName = match[2];
|
|
79
|
-
const columnsDef = match[3];
|
|
80
|
-
const table = {
|
|
81
|
-
name: tableName,
|
|
82
|
-
columns: [],
|
|
83
|
-
schema: schema || 'public',
|
|
84
|
-
};
|
|
85
|
-
// Parse columns and constraints
|
|
86
|
-
const lines = columnsDef.split(',').map(l => l.trim());
|
|
87
|
-
const primaryKeys = [];
|
|
88
|
-
const foreignKeys = new Map();
|
|
89
|
-
const uniqueColumns = new Set();
|
|
90
|
-
for (const line of lines) {
|
|
91
|
-
// Skip empty lines
|
|
92
|
-
if (!line)
|
|
93
|
-
continue;
|
|
94
|
-
// Handle PRIMARY KEY constraint
|
|
95
|
-
if (/PRIMARY\s+KEY/i.test(line)) {
|
|
96
|
-
const pkMatch = line.match(/PRIMARY\s+KEY\s*\(([^)]+)\)/i);
|
|
97
|
-
if (pkMatch) {
|
|
98
|
-
const cols = pkMatch[1].split(',').map(c => c.trim().replace(/"/g, ''));
|
|
99
|
-
primaryKeys.push(...cols);
|
|
100
|
-
}
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
// Handle FOREIGN KEY constraint
|
|
104
|
-
if (/FOREIGN\s+KEY/i.test(line)) {
|
|
105
|
-
const fkMatch = line.match(/FOREIGN\s+KEY\s*\(([^)]+)\)\s*REFERENCES\s+(\w+)\s*\(([^)]+)\)/i);
|
|
106
|
-
if (fkMatch) {
|
|
107
|
-
const localCol = fkMatch[1].trim().replace(/"/g, '');
|
|
108
|
-
const refTable = fkMatch[2].trim();
|
|
109
|
-
const refCol = fkMatch[3].trim().replace(/"/g, '');
|
|
110
|
-
foreignKeys.set(localCol, { table: refTable, column: refCol });
|
|
111
|
-
}
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
// Handle UNIQUE constraint
|
|
115
|
-
if (/UNIQUE/i.test(line) && /UNIQUE\s*\(/i.test(line)) {
|
|
116
|
-
const uniqueMatch = line.match(/UNIQUE\s*\(([^)]+)\)/i);
|
|
117
|
-
if (uniqueMatch) {
|
|
118
|
-
const cols = uniqueMatch[1].split(',').map(c => c.trim().replace(/"/g, ''));
|
|
119
|
-
cols.forEach(c => uniqueColumns.add(c));
|
|
120
|
-
}
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
// Parse column definition
|
|
124
|
-
const columnMatch = line.match(/^(\w+)\s+([A-Za-z0-9_()]+)(.*)$/i);
|
|
125
|
-
if (columnMatch) {
|
|
126
|
-
const columnName = columnMatch[1];
|
|
127
|
-
const dataType = columnMatch[2];
|
|
128
|
-
const modifiers = columnMatch[3] || '';
|
|
129
|
-
const column = {
|
|
130
|
-
name: columnName,
|
|
131
|
-
sqlType: dataType,
|
|
132
|
-
notNull: /NOT\s+NULL/i.test(modifiers),
|
|
133
|
-
primaryKey: false,
|
|
134
|
-
unique: /UNIQUE/i.test(modifiers),
|
|
135
|
-
};
|
|
136
|
-
// Extract enum values
|
|
137
|
-
if (/^ENUM/i.test(dataType)) {
|
|
138
|
-
const enumMatch = dataType.match(/ENUM\s*\(([^)]+)\)/i);
|
|
139
|
-
if (enumMatch) {
|
|
140
|
-
column.enumValues = enumMatch[1].split(',').map(v => v.trim().replace(/^'|'$/g, ''));
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
// Extract default value
|
|
144
|
-
const defaultMatch = modifiers.match(/DEFAULT\s+([^,\s]+)/i);
|
|
145
|
-
if (defaultMatch) {
|
|
146
|
-
column.defaultValue = defaultMatch[1];
|
|
147
|
-
}
|
|
148
|
-
// Extract CHECK constraint
|
|
149
|
-
const checkMatch = modifiers.match(/CHECK\s*\(([^)]+)\)/i);
|
|
150
|
-
if (checkMatch) {
|
|
151
|
-
column.checkConstraint = checkMatch[1];
|
|
152
|
-
}
|
|
153
|
-
// Check for inline REFERENCES (foreign key)
|
|
154
|
-
const refMatch = modifiers.match(/REFERENCES\s+(\w+)\s*\(([^)]+)\)/i);
|
|
155
|
-
if (refMatch) {
|
|
156
|
-
column.foreignKey = {
|
|
157
|
-
table: refMatch[1],
|
|
158
|
-
column: refMatch[2].trim().replace(/"/g, ''),
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
table.columns.push(column);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
// Apply primary keys
|
|
165
|
-
primaryKeys.forEach(pk => {
|
|
166
|
-
const col = table.columns.find(c => c.name === pk);
|
|
167
|
-
if (col) {
|
|
168
|
-
col.primaryKey = true;
|
|
169
|
-
col.notNull = true; // PKs are always NOT NULL
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
// Apply foreign keys
|
|
173
|
-
foreignKeys.forEach((fk, colName) => {
|
|
174
|
-
const col = table.columns.find(c => c.name === colName);
|
|
175
|
-
if (col) {
|
|
176
|
-
col.foreignKey = fk;
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
// Apply unique constraints
|
|
180
|
-
uniqueColumns.forEach(colName => {
|
|
181
|
-
const col = table.columns.find(c => c.name === colName);
|
|
182
|
-
if (col) {
|
|
183
|
-
col.unique = true;
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
tables.push(table);
|
|
187
|
-
}
|
|
188
|
-
return tables;
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Converts SQL table to Stonecrop schema format
|
|
192
|
-
* @param table - Parsed SQL table
|
|
193
|
-
* @param namingConverter - Function to convert field names
|
|
194
|
-
* @returns Conversion result with schema and relationships
|
|
195
|
-
* @public
|
|
196
|
-
*/
|
|
197
|
-
export function convertTableToSchema(table, namingConverter) {
|
|
198
|
-
const result = {
|
|
199
|
-
doctype: table.name,
|
|
200
|
-
schema: [],
|
|
201
|
-
relationships: [],
|
|
202
|
-
};
|
|
203
|
-
for (const column of table.columns) {
|
|
204
|
-
const { fieldname, label } = namingConverter
|
|
205
|
-
? namingConverter(column.name)
|
|
206
|
-
: { fieldname: column.name, label: column.name };
|
|
207
|
-
const fieldtype = column.foreignKey ? 'Link' : mapSQLTypeToFieldType(column.sqlType, column.enumValues);
|
|
208
|
-
const field = {
|
|
209
|
-
fieldname,
|
|
210
|
-
label,
|
|
211
|
-
fieldtype,
|
|
212
|
-
};
|
|
213
|
-
// Add required flag for NOT NULL columns (except PKs which are readonly)
|
|
214
|
-
if (column.notNull && !column.primaryKey) {
|
|
215
|
-
field.required = true;
|
|
216
|
-
}
|
|
217
|
-
// Make primary keys readonly
|
|
218
|
-
if (column.primaryKey) {
|
|
219
|
-
field.readonly = true;
|
|
220
|
-
}
|
|
221
|
-
// Handle foreign keys (Link fields)
|
|
222
|
-
if (column.foreignKey) {
|
|
223
|
-
field.options = column.foreignKey.table;
|
|
224
|
-
result.relationships.push({
|
|
225
|
-
fieldname,
|
|
226
|
-
targetDoctype: column.foreignKey.table,
|
|
227
|
-
targetField: column.foreignKey.column,
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
// Handle enum values (Select fields)
|
|
231
|
-
if (column.enumValues && column.enumValues.length > 0) {
|
|
232
|
-
field.options = column.enumValues.join('\n');
|
|
233
|
-
}
|
|
234
|
-
// Handle default values
|
|
235
|
-
if (column.defaultValue) {
|
|
236
|
-
// Clean up default value (remove quotes, casts, etc.)
|
|
237
|
-
let defaultVal = column.defaultValue.replace(/^'|'$/g, '');
|
|
238
|
-
if (fieldtype === 'Int' || fieldtype === 'Float') {
|
|
239
|
-
defaultVal = parseFloat(defaultVal);
|
|
240
|
-
}
|
|
241
|
-
else if (fieldtype === 'Check') {
|
|
242
|
-
defaultVal = defaultVal === 'true' || defaultVal === 't';
|
|
243
|
-
}
|
|
244
|
-
field.default = defaultVal;
|
|
245
|
-
}
|
|
246
|
-
result.schema.push(field);
|
|
247
|
-
}
|
|
248
|
-
return result;
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Introspects SQL DDL and converts all tables to Stonecrop schemas
|
|
252
|
-
* @param ddl - PostgreSQL DDL string
|
|
253
|
-
* @param namingConverter - Optional function to convert field names
|
|
254
|
-
* @returns Array of conversion results
|
|
255
|
-
* @public
|
|
256
|
-
*/
|
|
257
|
-
export function introspectSQL(ddl, namingConverter) {
|
|
258
|
-
const tables = parseDDL(ddl);
|
|
259
|
-
return tables.map(table => convertTableToSchema(table, namingConverter));
|
|
260
|
-
}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Naming Convention Utilities
|
|
3
|
-
* Converts between SQL snake_case and JavaScript camelCase naming conventions
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Result of name conversion
|
|
8
|
-
* @public
|
|
9
|
-
*/
|
|
10
|
-
export interface NameConversion {
|
|
11
|
-
/** Converted fieldname (camelCase) */
|
|
12
|
-
fieldname: string;
|
|
13
|
-
/** Human-readable label */
|
|
14
|
-
label: string;
|
|
15
|
-
/** Original SQL name */
|
|
16
|
-
originalName: string;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Converts snake_case to camelCase
|
|
20
|
-
* @param snakeCase - Snake case string
|
|
21
|
-
* @returns Camel case string
|
|
22
|
-
* @public
|
|
23
|
-
* @example
|
|
24
|
-
* ```typescript
|
|
25
|
-
* snakeToCamel('user_email') // 'userEmail'
|
|
26
|
-
* snakeToCamel('created_at') // 'createdAt'
|
|
27
|
-
* snakeToCamel('user_id') // 'userId'
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
export declare function snakeToCamel(snakeCase: string): string;
|
|
31
|
-
/**
|
|
32
|
-
* Converts camelCase to snake_case
|
|
33
|
-
* @param camelCase - Camel case string
|
|
34
|
-
* @returns Snake case string
|
|
35
|
-
* @public
|
|
36
|
-
* @example
|
|
37
|
-
* ```typescript
|
|
38
|
-
* camelToSnake('userEmail') // 'user_email'
|
|
39
|
-
* camelToSnake('createdAt') // 'created_at'
|
|
40
|
-
* camelToSnake('userId') // 'user_id'
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
export declare function camelToSnake(camelCase: string): string;
|
|
44
|
-
/**
|
|
45
|
-
* Converts snake_case to Title Case label
|
|
46
|
-
* @param snakeCase - Snake case string
|
|
47
|
-
* @returns Title case label
|
|
48
|
-
* @public
|
|
49
|
-
* @example
|
|
50
|
-
* ```typescript
|
|
51
|
-
* snakeToLabel('user_email') // 'User Email'
|
|
52
|
-
* snakeToLabel('first_name') // 'First Name'
|
|
53
|
-
* snakeToLabel('created_at') // 'Created At'
|
|
54
|
-
* ```
|
|
55
|
-
*/
|
|
56
|
-
export declare function snakeToLabel(snakeCase: string): string;
|
|
57
|
-
/**
|
|
58
|
-
* Converts camelCase to Title Case label
|
|
59
|
-
* @param camelCase - Camel case string
|
|
60
|
-
* @returns Title case label
|
|
61
|
-
* @public
|
|
62
|
-
* @example
|
|
63
|
-
* ```typescript
|
|
64
|
-
* camelToLabel('userEmail') // 'User Email'
|
|
65
|
-
* camelToLabel('firstName') // 'First Name'
|
|
66
|
-
* camelToLabel('createdAt') // 'Created At'
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
export declare function camelToLabel(camelCase: string): string;
|
|
70
|
-
/**
|
|
71
|
-
* Converts SQL column name to Stonecrop field naming convention
|
|
72
|
-
* Handles special cases like ID suffixes
|
|
73
|
-
* @param sqlName - SQL column name (snake_case)
|
|
74
|
-
* @returns Field name and label
|
|
75
|
-
* @public
|
|
76
|
-
* @example
|
|
77
|
-
* ```typescript
|
|
78
|
-
* convertSQLName('user_email')
|
|
79
|
-
* // { fieldname: 'userEmail', label: 'User Email', originalName: 'user_email' }
|
|
80
|
-
*
|
|
81
|
-
* convertSQLName('user_id')
|
|
82
|
-
* // { fieldname: 'userId', label: 'User', originalName: 'user_id' }
|
|
83
|
-
*
|
|
84
|
-
* convertSQLName('created_at')
|
|
85
|
-
* // { fieldname: 'createdAt', label: 'Created At', originalName: 'created_at' }
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
88
|
-
export declare function convertSQLName(sqlName: string): NameConversion;
|
|
89
|
-
/**
|
|
90
|
-
* Batch converts multiple SQL column names
|
|
91
|
-
* @param sqlNames - Array of SQL column names
|
|
92
|
-
* @returns Array of name conversions
|
|
93
|
-
* @public
|
|
94
|
-
*/
|
|
95
|
-
export declare function convertSQLNames(sqlNames: string[]): NameConversion[];
|
|
96
|
-
/**
|
|
97
|
-
* Creates a bidirectional mapping between SQL and Stonecrop names
|
|
98
|
-
* @param sqlNames - Array of SQL column names
|
|
99
|
-
* @returns Mapping object with both directions
|
|
100
|
-
* @public
|
|
101
|
-
*/
|
|
102
|
-
export declare function createNameMapping(sqlNames: string[]): {
|
|
103
|
-
sqlToFieldname: Map<string, string>;
|
|
104
|
-
fieldnameToSQL: Map<string, string>;
|
|
105
|
-
conversions: NameConversion[];
|
|
106
|
-
};
|
|
107
|
-
//# sourceMappingURL=naming-conventions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"naming-conventions.d.ts","sourceRoot":"","sources":["../../src/naming-conventions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,wBAAwB;IACxB,YAAY,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAItD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAkB9D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG;IACtD,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,WAAW,EAAE,cAAc,EAAE,CAAA;CAC7B,CAeA"}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Naming Convention Utilities
|
|
3
|
-
* Converts between SQL snake_case and JavaScript camelCase naming conventions
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Converts snake_case to camelCase
|
|
8
|
-
* @param snakeCase - Snake case string
|
|
9
|
-
* @returns Camel case string
|
|
10
|
-
* @public
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* snakeToCamel('user_email') // 'userEmail'
|
|
14
|
-
* snakeToCamel('created_at') // 'createdAt'
|
|
15
|
-
* snakeToCamel('user_id') // 'userId'
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
export function snakeToCamel(snakeCase) {
|
|
19
|
-
return snakeCase.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Converts camelCase to snake_case
|
|
23
|
-
* @param camelCase - Camel case string
|
|
24
|
-
* @returns Snake case string
|
|
25
|
-
* @public
|
|
26
|
-
* @example
|
|
27
|
-
* ```typescript
|
|
28
|
-
* camelToSnake('userEmail') // 'user_email'
|
|
29
|
-
* camelToSnake('createdAt') // 'created_at'
|
|
30
|
-
* camelToSnake('userId') // 'user_id'
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
export function camelToSnake(camelCase) {
|
|
34
|
-
return camelCase.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Converts snake_case to Title Case label
|
|
38
|
-
* @param snakeCase - Snake case string
|
|
39
|
-
* @returns Title case label
|
|
40
|
-
* @public
|
|
41
|
-
* @example
|
|
42
|
-
* ```typescript
|
|
43
|
-
* snakeToLabel('user_email') // 'User Email'
|
|
44
|
-
* snakeToLabel('first_name') // 'First Name'
|
|
45
|
-
* snakeToLabel('created_at') // 'Created At'
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
export function snakeToLabel(snakeCase) {
|
|
49
|
-
return snakeCase
|
|
50
|
-
.split('_')
|
|
51
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
52
|
-
.join(' ');
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Converts camelCase to Title Case label
|
|
56
|
-
* @param camelCase - Camel case string
|
|
57
|
-
* @returns Title case label
|
|
58
|
-
* @public
|
|
59
|
-
* @example
|
|
60
|
-
* ```typescript
|
|
61
|
-
* camelToLabel('userEmail') // 'User Email'
|
|
62
|
-
* camelToLabel('firstName') // 'First Name'
|
|
63
|
-
* camelToLabel('createdAt') // 'Created At'
|
|
64
|
-
* ```
|
|
65
|
-
*/
|
|
66
|
-
export function camelToLabel(camelCase) {
|
|
67
|
-
// Insert space before capital letters and capitalize first letter
|
|
68
|
-
const withSpaces = camelCase.replace(/([A-Z])/g, ' $1').trim();
|
|
69
|
-
return withSpaces.charAt(0).toUpperCase() + withSpaces.slice(1);
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Converts SQL column name to Stonecrop field naming convention
|
|
73
|
-
* Handles special cases like ID suffixes
|
|
74
|
-
* @param sqlName - SQL column name (snake_case)
|
|
75
|
-
* @returns Field name and label
|
|
76
|
-
* @public
|
|
77
|
-
* @example
|
|
78
|
-
* ```typescript
|
|
79
|
-
* convertSQLName('user_email')
|
|
80
|
-
* // { fieldname: 'userEmail', label: 'User Email', originalName: 'user_email' }
|
|
81
|
-
*
|
|
82
|
-
* convertSQLName('user_id')
|
|
83
|
-
* // { fieldname: 'userId', label: 'User', originalName: 'user_id' }
|
|
84
|
-
*
|
|
85
|
-
* convertSQLName('created_at')
|
|
86
|
-
* // { fieldname: 'createdAt', label: 'Created At', originalName: 'created_at' }
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
export function convertSQLName(sqlName) {
|
|
90
|
-
const fieldname = snakeToCamel(sqlName);
|
|
91
|
-
// Generate label - special handling for _id suffix
|
|
92
|
-
let label;
|
|
93
|
-
if (sqlName.endsWith('_id')) {
|
|
94
|
-
// Remove _id suffix for label: user_id -> User
|
|
95
|
-
const withoutId = sqlName.slice(0, -3);
|
|
96
|
-
label = snakeToLabel(withoutId);
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
label = snakeToLabel(sqlName);
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
fieldname,
|
|
103
|
-
label,
|
|
104
|
-
originalName: sqlName,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Batch converts multiple SQL column names
|
|
109
|
-
* @param sqlNames - Array of SQL column names
|
|
110
|
-
* @returns Array of name conversions
|
|
111
|
-
* @public
|
|
112
|
-
*/
|
|
113
|
-
export function convertSQLNames(sqlNames) {
|
|
114
|
-
return sqlNames.map(convertSQLName);
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Creates a bidirectional mapping between SQL and Stonecrop names
|
|
118
|
-
* @param sqlNames - Array of SQL column names
|
|
119
|
-
* @returns Mapping object with both directions
|
|
120
|
-
* @public
|
|
121
|
-
*/
|
|
122
|
-
export function createNameMapping(sqlNames) {
|
|
123
|
-
const conversions = convertSQLNames(sqlNames);
|
|
124
|
-
const sqlToFieldname = new Map();
|
|
125
|
-
const fieldnameToSQL = new Map();
|
|
126
|
-
for (const conversion of conversions) {
|
|
127
|
-
sqlToFieldname.set(conversion.originalName, conversion.fieldname);
|
|
128
|
-
fieldnameToSQL.set(conversion.fieldname, conversion.originalName);
|
|
129
|
-
}
|
|
130
|
-
return {
|
|
131
|
-
sqlToFieldname,
|
|
132
|
-
fieldnameToSQL,
|
|
133
|
-
conversions,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SQL Schema Introspection Utilities
|
|
3
|
-
* Parses PostgreSQL DDL and converts to Stonecrop schema format
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Represents a parsed SQL column with metadata
|
|
8
|
-
* @public
|
|
9
|
-
*/
|
|
10
|
-
export interface SQLColumn {
|
|
11
|
-
/** Column name from SQL */
|
|
12
|
-
name: string;
|
|
13
|
-
/** PostgreSQL data type */
|
|
14
|
-
sqlType: string;
|
|
15
|
-
/** Whether column is NOT NULL */
|
|
16
|
-
notNull: boolean;
|
|
17
|
-
/** Whether column is PRIMARY KEY */
|
|
18
|
-
primaryKey: boolean;
|
|
19
|
-
/** Whether column is UNIQUE */
|
|
20
|
-
unique: boolean;
|
|
21
|
-
/** Default value expression */
|
|
22
|
-
defaultValue?: string;
|
|
23
|
-
/** Foreign key reference (table.column) */
|
|
24
|
-
foreignKey?: {
|
|
25
|
-
table: string;
|
|
26
|
-
column: string;
|
|
27
|
-
};
|
|
28
|
-
/** CHECK constraint expression */
|
|
29
|
-
checkConstraint?: string;
|
|
30
|
-
/** Enum values for ENUM types */
|
|
31
|
-
enumValues?: string[];
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Represents a parsed SQL table
|
|
35
|
-
* @public
|
|
36
|
-
*/
|
|
37
|
-
export interface SQLTable {
|
|
38
|
-
/** Table name */
|
|
39
|
-
name: string;
|
|
40
|
-
/** List of columns */
|
|
41
|
-
columns: SQLColumn[];
|
|
42
|
-
/** Schema name (default: public) */
|
|
43
|
-
schema?: string;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Stonecrop field type
|
|
47
|
-
* @public
|
|
48
|
-
*/
|
|
49
|
-
export type StonecropFieldType = 'Data' | 'Text' | 'Int' | 'Float' | 'Check' | 'Datetime' | 'Date' | 'Time' | 'Select' | 'Link' | 'Table' | 'Code' | 'Phone' | 'Currency';
|
|
50
|
-
/**
|
|
51
|
-
* Maps PostgreSQL data types to Stonecrop field types
|
|
52
|
-
* @param sqlType - PostgreSQL data type
|
|
53
|
-
* @param enumValues - Enum values if type is ENUM
|
|
54
|
-
* @returns Corresponding Stonecrop field type
|
|
55
|
-
* @public
|
|
56
|
-
*/
|
|
57
|
-
export declare function mapSQLTypeToFieldType(sqlType: string, enumValues?: string[]): StonecropFieldType;
|
|
58
|
-
/**
|
|
59
|
-
* Parses a PostgreSQL CREATE TABLE statement
|
|
60
|
-
* @param ddl - SQL DDL string
|
|
61
|
-
* @returns Array of parsed tables
|
|
62
|
-
* @public
|
|
63
|
-
*/
|
|
64
|
-
export declare function parseDDL(ddl: string): SQLTable[];
|
|
65
|
-
/**
|
|
66
|
-
* Result of SQL to Stonecrop conversion
|
|
67
|
-
* @public
|
|
68
|
-
*/
|
|
69
|
-
export interface ConversionResult {
|
|
70
|
-
/** Doctype name (from table name) */
|
|
71
|
-
doctype: string;
|
|
72
|
-
/** Stonecrop schema fields */
|
|
73
|
-
schema: Array<{
|
|
74
|
-
fieldname: string;
|
|
75
|
-
label: string;
|
|
76
|
-
fieldtype: StonecropFieldType;
|
|
77
|
-
required?: boolean;
|
|
78
|
-
readonly?: boolean;
|
|
79
|
-
options?: string;
|
|
80
|
-
default?: any;
|
|
81
|
-
}>;
|
|
82
|
-
/** Detected relationships */
|
|
83
|
-
relationships: Array<{
|
|
84
|
-
fieldname: string;
|
|
85
|
-
targetDoctype: string;
|
|
86
|
-
targetField: string;
|
|
87
|
-
}>;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Converts SQL table to Stonecrop schema format
|
|
91
|
-
* @param table - Parsed SQL table
|
|
92
|
-
* @param namingConverter - Function to convert field names
|
|
93
|
-
* @returns Conversion result with schema and relationships
|
|
94
|
-
* @public
|
|
95
|
-
*/
|
|
96
|
-
export declare function convertTableToSchema(table: SQLTable, namingConverter?: (sqlName: string) => {
|
|
97
|
-
fieldname: string;
|
|
98
|
-
label: string;
|
|
99
|
-
}): ConversionResult;
|
|
100
|
-
/**
|
|
101
|
-
* Introspects SQL DDL and converts all tables to Stonecrop schemas
|
|
102
|
-
* @param ddl - PostgreSQL DDL string
|
|
103
|
-
* @param namingConverter - Optional function to convert field names
|
|
104
|
-
* @returns Array of conversion results
|
|
105
|
-
* @public
|
|
106
|
-
*/
|
|
107
|
-
export declare function introspectSQL(ddl: string, namingConverter?: (sqlName: string) => {
|
|
108
|
-
fieldname: string;
|
|
109
|
-
label: string;
|
|
110
|
-
}): ConversionResult[];
|
|
111
|
-
//# sourceMappingURL=sql-introspection.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sql-introspection.d.ts","sourceRoot":"","sources":["../../src/sql-introspection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,WAAW,SAAS;IACzB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAA;IAChB,oCAAoC;IACpC,UAAU,EAAE,OAAO,CAAA;IACnB,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAA;IACf,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2CAA2C;IAC3C,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9C,kCAAkC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACxB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,sBAAsB;IACtB,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAC3B,MAAM,GACN,MAAM,GACN,KAAK,GACL,OAAO,GACP,OAAO,GACP,UAAU,GACV,MAAM,GACN,MAAM,GACN,QAAQ,GACR,MAAM,GACN,OAAO,GACP,MAAM,GACN,OAAO,GACP,UAAU,CAAA;AAEb;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,kBAAkB,CA6DhG;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CA0IhD;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAA;IACf,8BAA8B;IAC9B,MAAM,EAAE,KAAK,CAAC;QACb,SAAS,EAAE,MAAM,CAAA;QACjB,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,EAAE,kBAAkB,CAAA;QAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,GAAG,CAAA;KACb,CAAC,CAAA;IACF,6BAA6B;IAC7B,aAAa,EAAE,KAAK,CAAC;QACpB,SAAS,EAAE,MAAM,CAAA;QACjB,aAAa,EAAE,MAAM,CAAA;QACrB,WAAW,EAAE,MAAM,CAAA;KACnB,CAAC,CAAA;CACF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,QAAQ,EACf,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACzE,gBAAgB,CA6DlB;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC5B,GAAG,EAAE,MAAM,EACX,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACzE,gBAAgB,EAAE,CAGpB"}
|