relq 1.0.58 → 1.0.60
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/dist/cjs/cli/commands/import.cjs +2 -2
- package/dist/cjs/cli/utils/ast-codegen.cjs +20 -5
- package/dist/cjs/cli/utils/ast-transformer.cjs +26 -3
- package/dist/cjs/cli/utils/schema-introspect.cjs +6 -2
- package/dist/cjs/schema-definition/column-types.cjs +4 -2
- package/dist/cjs/schema-definition/defaults.cjs +2 -0
- package/dist/cjs/schema-definition/pg-function.cjs +6 -1
- package/dist/esm/cli/commands/import.js +2 -2
- package/dist/esm/cli/utils/ast-codegen.js +20 -5
- package/dist/esm/cli/utils/ast-transformer.js +26 -3
- package/dist/esm/cli/utils/schema-introspect.js +6 -2
- package/dist/esm/schema-definition/column-types.js +1 -0
- package/dist/esm/schema-definition/defaults.js +2 -0
- package/dist/esm/schema-definition/pg-function.js +6 -1
- package/dist/schema-builder.d.ts +15 -0
- package/package.json +1 -1
|
@@ -597,11 +597,11 @@ function convertToDbSchema(parsed, functions = [], triggers = [], comments = [])
|
|
|
597
597
|
partitions: [],
|
|
598
598
|
functions: functions.map(f => ({
|
|
599
599
|
...f,
|
|
600
|
-
comment: functionComments.get(f.name) ||
|
|
600
|
+
comment: functionComments.get(f.name) || undefined,
|
|
601
601
|
})),
|
|
602
602
|
triggers: triggers.map(t => ({
|
|
603
603
|
...t,
|
|
604
|
-
comment: triggerComments.get(`${t.name}.${t.tableName}`) ||
|
|
604
|
+
comment: triggerComments.get(`${t.name}.${t.tableName}`) || undefined,
|
|
605
605
|
})),
|
|
606
606
|
policies: [],
|
|
607
607
|
foreignServers: [],
|
|
@@ -699,6 +699,10 @@ function generateFunctionCode(func, useCamelCase, varNameOverride) {
|
|
|
699
699
|
parts.push(` strict: true,`);
|
|
700
700
|
if (func.securityDefiner)
|
|
701
701
|
parts.push(` securityDefiner: true,`);
|
|
702
|
+
if (func.comment) {
|
|
703
|
+
const escapedComment = func.comment.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/'/g, "\\'");
|
|
704
|
+
parts.push(` comment: '${escapedComment}',`);
|
|
705
|
+
}
|
|
702
706
|
parts.push(`})`);
|
|
703
707
|
if (func.trackingId) {
|
|
704
708
|
parts[parts.length - 1] = parts[parts.length - 1].replace('})', `}).$id('${func.trackingId}')`);
|
|
@@ -716,7 +720,7 @@ function generateTriggerCode(trigger, useCamelCase, functionNames) {
|
|
|
716
720
|
const tableName = useCamelCase ? (0, utils_1.toCamelCase)(trigger.table) : trigger.table;
|
|
717
721
|
const parts = [];
|
|
718
722
|
parts.push(`export const ${triggerName} = pgTrigger('${trigger.name}', {`);
|
|
719
|
-
parts.push(`
|
|
723
|
+
parts.push(` on: ${tableName},`);
|
|
720
724
|
parts.push(` timing: '${trigger.timing}',`);
|
|
721
725
|
parts.push(` events: [${trigger.events.map(e => `'${e}'`).join(', ')}],`);
|
|
722
726
|
parts.push(` forEach: '${trigger.forEach}',`);
|
|
@@ -735,7 +739,14 @@ function generateTriggerCode(trigger, useCamelCase, functionNames) {
|
|
|
735
739
|
parts.push(` deferrable: true,`);
|
|
736
740
|
if (trigger.initiallyDeferred)
|
|
737
741
|
parts.push(` initiallyDeferred: true,`);
|
|
742
|
+
if (trigger.comment) {
|
|
743
|
+
const escapedComment = trigger.comment.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/'/g, "\\'");
|
|
744
|
+
parts.push(` comment: '${escapedComment}',`);
|
|
745
|
+
}
|
|
738
746
|
parts.push(`})`);
|
|
747
|
+
if (trigger.trackingId) {
|
|
748
|
+
parts[parts.length - 1] = parts[parts.length - 1].replace('})', `}).$id('${trigger.trackingId}')`);
|
|
749
|
+
}
|
|
739
750
|
return parts.join('\n');
|
|
740
751
|
}
|
|
741
752
|
function generateTypeScriptFromAST(schema, options = {}) {
|
|
@@ -1273,12 +1284,16 @@ function generateTriggersFile(schema, options = {}) {
|
|
|
1273
1284
|
parts.push(` deferrable: true,`);
|
|
1274
1285
|
if (trigger.initiallyDeferred)
|
|
1275
1286
|
parts.push(` initially: 'DEFERRED',`);
|
|
1276
|
-
|
|
1277
|
-
|
|
1287
|
+
let closing = '})';
|
|
1288
|
+
if (trigger.comment) {
|
|
1289
|
+
const escapedComment = trigger.comment.replace(/'/g, "\\'");
|
|
1290
|
+
closing += `.$comment('${escapedComment}')`;
|
|
1278
1291
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1292
|
+
if (trigger.trackingId) {
|
|
1293
|
+
closing += `.$id('${trigger.trackingId}')`;
|
|
1281
1294
|
}
|
|
1295
|
+
closing += ';';
|
|
1296
|
+
parts.push(closing);
|
|
1282
1297
|
parts.push('');
|
|
1283
1298
|
}
|
|
1284
1299
|
parts.push('// =============================================================================');
|
|
@@ -715,6 +715,7 @@ async function introspectedToParsedSchema(schema) {
|
|
|
715
715
|
volatility: f.volatility,
|
|
716
716
|
isStrict: false,
|
|
717
717
|
securityDefiner: false,
|
|
718
|
+
comment: f.comment,
|
|
718
719
|
});
|
|
719
720
|
}
|
|
720
721
|
for (const t of schema.triggers || []) {
|
|
@@ -726,6 +727,7 @@ async function introspectedToParsedSchema(schema) {
|
|
|
726
727
|
forEach: t.forEach || 'ROW',
|
|
727
728
|
functionName: t.functionName || '',
|
|
728
729
|
isConstraint: false,
|
|
730
|
+
comment: t.comment,
|
|
729
731
|
});
|
|
730
732
|
}
|
|
731
733
|
return parsed;
|
|
@@ -809,9 +811,26 @@ function parseArgTypes(argTypes) {
|
|
|
809
811
|
if (!argTypes)
|
|
810
812
|
return [];
|
|
811
813
|
const parts = Array.isArray(argTypes) ? argTypes : argTypes.split(',');
|
|
812
|
-
return parts.map(arg =>
|
|
813
|
-
|
|
814
|
-
|
|
814
|
+
return parts.map(arg => {
|
|
815
|
+
const trimmed = typeof arg === 'string' ? arg.trim() : String(arg);
|
|
816
|
+
if (!trimmed)
|
|
817
|
+
return { type: '' };
|
|
818
|
+
const firstSpace = trimmed.indexOf(' ');
|
|
819
|
+
if (firstSpace === -1) {
|
|
820
|
+
return { type: trimmed };
|
|
821
|
+
}
|
|
822
|
+
const firstPart = trimmed.substring(0, firstSpace);
|
|
823
|
+
const restPart = trimmed.substring(firstSpace + 1).trim();
|
|
824
|
+
const commonTypeStarts = ['integer', 'bigint', 'smallint', 'text', 'varchar', 'char', 'boolean',
|
|
825
|
+
'timestamp', 'date', 'time', 'interval', 'numeric', 'decimal', 'real', 'double', 'uuid',
|
|
826
|
+
'json', 'jsonb', 'bytea', 'inet', 'cidr', 'macaddr', 'point', 'line', 'circle', 'box',
|
|
827
|
+
'tsvector', 'tsquery', 'void', 'trigger', 'record', 'setof', 'array'];
|
|
828
|
+
const lowerFirst = firstPart.toLowerCase();
|
|
829
|
+
if (commonTypeStarts.some(t => lowerFirst === t || lowerFirst.startsWith(t + '['))) {
|
|
830
|
+
return { type: trimmed };
|
|
831
|
+
}
|
|
832
|
+
return { name: firstPart, type: restPart };
|
|
833
|
+
}).filter(arg => arg.type !== '');
|
|
815
834
|
}
|
|
816
835
|
function extractFunctionBody(definition) {
|
|
817
836
|
if (!definition)
|
|
@@ -931,6 +950,8 @@ function normalizedToParsedSchema(schema) {
|
|
|
931
950
|
volatility: f.volatility || 'VOLATILE',
|
|
932
951
|
isStrict: f.isStrict ?? false,
|
|
933
952
|
securityDefiner: f.securityDefiner ?? false,
|
|
953
|
+
comment: f.comment,
|
|
954
|
+
trackingId: f.trackingId,
|
|
934
955
|
})),
|
|
935
956
|
triggers: (schema.triggers || []).map(t => ({
|
|
936
957
|
name: t.name,
|
|
@@ -941,6 +962,8 @@ function normalizedToParsedSchema(schema) {
|
|
|
941
962
|
functionName: t.functionName || '',
|
|
942
963
|
whenClause: t.when,
|
|
943
964
|
isConstraint: false,
|
|
965
|
+
comment: t.comment,
|
|
966
|
+
trackingId: t.trackingId,
|
|
944
967
|
})),
|
|
945
968
|
};
|
|
946
969
|
}
|
|
@@ -294,7 +294,8 @@ async function introspectDatabase(connection, onProgress, options) {
|
|
|
294
294
|
l.lanname as language,
|
|
295
295
|
pg_get_functiondef(p.oid) as definition,
|
|
296
296
|
p.prokind = 'a' as is_aggregate,
|
|
297
|
-
p.provolatile as volatility
|
|
297
|
+
p.provolatile as volatility,
|
|
298
|
+
obj_description(p.oid, 'pg_proc') as comment
|
|
298
299
|
FROM pg_proc p
|
|
299
300
|
JOIN pg_namespace n ON p.pronamespace = n.oid
|
|
300
301
|
JOIN pg_language l ON p.prolang = l.oid
|
|
@@ -322,6 +323,7 @@ async function introspectDatabase(connection, onProgress, options) {
|
|
|
322
323
|
definition: f.definition || '',
|
|
323
324
|
isAggregate: f.is_aggregate || false,
|
|
324
325
|
volatility: f.volatility === 'i' ? 'IMMUTABLE' : f.volatility === 's' ? 'STABLE' : 'VOLATILE',
|
|
326
|
+
comment: f.comment || undefined,
|
|
325
327
|
}));
|
|
326
328
|
}
|
|
327
329
|
let triggers = [];
|
|
@@ -347,7 +349,8 @@ async function introspectDatabase(connection, onProgress, options) {
|
|
|
347
349
|
END as for_each,
|
|
348
350
|
p.proname as function_name,
|
|
349
351
|
pg_get_triggerdef(t.oid) as definition,
|
|
350
|
-
t.tgenabled != 'D' as is_enabled
|
|
352
|
+
t.tgenabled != 'D' as is_enabled,
|
|
353
|
+
obj_description(t.oid, 'pg_trigger') as comment
|
|
351
354
|
FROM pg_trigger t
|
|
352
355
|
JOIN pg_class c ON t.tgrelid = c.oid
|
|
353
356
|
JOIN pg_namespace n ON c.relnamespace = n.oid
|
|
@@ -370,6 +373,7 @@ async function introspectDatabase(connection, onProgress, options) {
|
|
|
370
373
|
functionName: t.function_name,
|
|
371
374
|
definition: t.definition || '',
|
|
372
375
|
isEnabled: t.is_enabled,
|
|
376
|
+
comment: t.comment || undefined,
|
|
373
377
|
}));
|
|
374
378
|
}
|
|
375
379
|
const policiesResult = await pool.query(`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.index = exports.raw = exports.emptyArray = exports.emptyObject = exports.currentDate = exports.currentTimestamp = exports.now = exports.uuidV4 = exports.genRandomUuid = exports.SQL_BRAND = exports.compositeType = exports.domainType = exports.enumType = exports.customType = exports.box3d = exports.box2d = exports.geoPoint = exports.geography = exports.geometry = exports.semver = exports.cube = exports.hstore = exports.ltxtquery = exports.lquery = exports.ltree = exports.citext = exports.pgSnapshot = exports.pgLsn = exports.regtype = exports.regproc = exports.regclass = exports.oid = exports.datemultirange = exports.tstzmultirange = exports.tsmultirange = exports.nummultirange = exports.int8multirange = exports.int4multirange = exports.daterange = exports.tstzrange = exports.tsrange = exports.numrange = exports.int8range = exports.int4range = exports.jsonb = void 0;
|
|
3
|
+
exports.xml = exports.uuid = exports.tsquery = exports.tsvector = exports.varbit = exports.bitVarying = exports.bit = exports.macaddr8 = exports.macaddr = exports.inet = exports.cidr = exports.circle = exports.polygon = exports.path = exports.box = exports.lseg = exports.line = exports.point = exports.bool = exports.boolean = exports.timeWithTimeZone = exports.date = exports.timestampWithTimeZone = exports.bytea = exports.text = exports.character = exports.characterVarying = exports.money = exports.float8 = exports.doublePrecision = exports.float4 = exports.real = exports.numeric = exports.decimal = exports.epoch = exports.serial8 = exports.bigserial = exports.serial2 = exports.smallserial = exports.serial4 = exports.serial = exports.int8 = exports.bigint = exports.int2 = exports.smallint = exports.int4 = exports.int = exports.integer = exports.EMPTY_ARRAY = exports.EMPTY_OBJECT = void 0;
|
|
4
|
+
exports.index = exports.raw = exports.emptyArray = exports.emptyObject = exports.currentDate = exports.currentTimestamp = exports.now = exports.uuidV4 = exports.genRandomUuid = exports.SQL_BRAND = exports.compositeType = exports.domainType = exports.enumType = exports.customType = exports.box3d = exports.box2d = exports.geoPoint = exports.geography = exports.geometry = exports.semver = exports.cube = exports.hstore = exports.ltxtquery = exports.lquery = exports.ltree = exports.citext = exports.pgSnapshot = exports.pgLsn = exports.regtype = exports.regproc = exports.regclass = exports.oid = exports.datemultirange = exports.tstzmultirange = exports.tsmultirange = exports.nummultirange = exports.int8multirange = exports.int4multirange = exports.daterange = exports.tstzrange = exports.tsrange = exports.numrange = exports.int8range = exports.int4range = exports.jsonb = exports.json = void 0;
|
|
5
5
|
exports.createFluentGenExpr = createFluentGenExpr;
|
|
6
6
|
exports.varchar = varchar;
|
|
7
7
|
exports.char = char;
|
|
@@ -653,6 +653,8 @@ exports.serial2 = exports.smallserial;
|
|
|
653
653
|
const bigserial = (columnName) => createColumnWithName('BIGSERIAL', columnName);
|
|
654
654
|
exports.bigserial = bigserial;
|
|
655
655
|
exports.serial8 = exports.bigserial;
|
|
656
|
+
const epoch = (columnName) => createColumnWithName('BIGINT', columnName);
|
|
657
|
+
exports.epoch = epoch;
|
|
656
658
|
const decimal = (columnNameOrOpts, scale) => {
|
|
657
659
|
if (typeof columnNameOrOpts === 'string' && !columnNameOrOpts.includes('.')) {
|
|
658
660
|
return createColumnWithName('DECIMAL', columnNameOrOpts);
|
|
@@ -21,6 +21,8 @@ exports.DEFAULT = {
|
|
|
21
21
|
clockTimestamp: () => createDefault('clock_timestamp()'),
|
|
22
22
|
timeofday: () => createDefault('timeofday()'),
|
|
23
23
|
interval: (value) => createDefault(`INTERVAL '${value}'`),
|
|
24
|
+
epochNow: () => createDefault('(EXTRACT(EPOCH FROM NOW()) * 1000)::bigint'),
|
|
25
|
+
epochSeconds: () => createDefault('EXTRACT(EPOCH FROM NOW())::bigint'),
|
|
24
26
|
currentUser: () => createDefault('CURRENT_USER'),
|
|
25
27
|
sessionUser: () => createDefault('SESSION_USER'),
|
|
26
28
|
user: () => createDefault('USER'),
|
|
@@ -13,7 +13,12 @@ function generateFunctionSQL(config) {
|
|
|
13
13
|
if (arg.mode && arg.mode !== 'IN') {
|
|
14
14
|
argStr += arg.mode + ' ';
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
if (arg.name) {
|
|
17
|
+
argStr += arg.name + ' ' + arg.type;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
argStr += arg.type;
|
|
21
|
+
}
|
|
17
22
|
if (arg.default !== undefined) {
|
|
18
23
|
argStr += ' DEFAULT ' + arg.default;
|
|
19
24
|
}
|
|
@@ -561,11 +561,11 @@ function convertToDbSchema(parsed, functions = [], triggers = [], comments = [])
|
|
|
561
561
|
partitions: [],
|
|
562
562
|
functions: functions.map(f => ({
|
|
563
563
|
...f,
|
|
564
|
-
comment: functionComments.get(f.name) ||
|
|
564
|
+
comment: functionComments.get(f.name) || undefined,
|
|
565
565
|
})),
|
|
566
566
|
triggers: triggers.map(t => ({
|
|
567
567
|
...t,
|
|
568
|
-
comment: triggerComments.get(`${t.name}.${t.tableName}`) ||
|
|
568
|
+
comment: triggerComments.get(`${t.name}.${t.tableName}`) || undefined,
|
|
569
569
|
})),
|
|
570
570
|
policies: [],
|
|
571
571
|
foreignServers: [],
|
|
@@ -691,6 +691,10 @@ function generateFunctionCode(func, useCamelCase, varNameOverride) {
|
|
|
691
691
|
parts.push(` strict: true,`);
|
|
692
692
|
if (func.securityDefiner)
|
|
693
693
|
parts.push(` securityDefiner: true,`);
|
|
694
|
+
if (func.comment) {
|
|
695
|
+
const escapedComment = func.comment.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/'/g, "\\'");
|
|
696
|
+
parts.push(` comment: '${escapedComment}',`);
|
|
697
|
+
}
|
|
694
698
|
parts.push(`})`);
|
|
695
699
|
if (func.trackingId) {
|
|
696
700
|
parts[parts.length - 1] = parts[parts.length - 1].replace('})', `}).$id('${func.trackingId}')`);
|
|
@@ -708,7 +712,7 @@ function generateTriggerCode(trigger, useCamelCase, functionNames) {
|
|
|
708
712
|
const tableName = useCamelCase ? toCamelCase(trigger.table) : trigger.table;
|
|
709
713
|
const parts = [];
|
|
710
714
|
parts.push(`export const ${triggerName} = pgTrigger('${trigger.name}', {`);
|
|
711
|
-
parts.push(`
|
|
715
|
+
parts.push(` on: ${tableName},`);
|
|
712
716
|
parts.push(` timing: '${trigger.timing}',`);
|
|
713
717
|
parts.push(` events: [${trigger.events.map(e => `'${e}'`).join(', ')}],`);
|
|
714
718
|
parts.push(` forEach: '${trigger.forEach}',`);
|
|
@@ -727,7 +731,14 @@ function generateTriggerCode(trigger, useCamelCase, functionNames) {
|
|
|
727
731
|
parts.push(` deferrable: true,`);
|
|
728
732
|
if (trigger.initiallyDeferred)
|
|
729
733
|
parts.push(` initiallyDeferred: true,`);
|
|
734
|
+
if (trigger.comment) {
|
|
735
|
+
const escapedComment = trigger.comment.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/'/g, "\\'");
|
|
736
|
+
parts.push(` comment: '${escapedComment}',`);
|
|
737
|
+
}
|
|
730
738
|
parts.push(`})`);
|
|
739
|
+
if (trigger.trackingId) {
|
|
740
|
+
parts[parts.length - 1] = parts[parts.length - 1].replace('})', `}).$id('${trigger.trackingId}')`);
|
|
741
|
+
}
|
|
731
742
|
return parts.join('\n');
|
|
732
743
|
}
|
|
733
744
|
export function generateTypeScriptFromAST(schema, options = {}) {
|
|
@@ -1265,12 +1276,16 @@ export function generateTriggersFile(schema, options = {}) {
|
|
|
1265
1276
|
parts.push(` deferrable: true,`);
|
|
1266
1277
|
if (trigger.initiallyDeferred)
|
|
1267
1278
|
parts.push(` initially: 'DEFERRED',`);
|
|
1268
|
-
|
|
1269
|
-
|
|
1279
|
+
let closing = '})';
|
|
1280
|
+
if (trigger.comment) {
|
|
1281
|
+
const escapedComment = trigger.comment.replace(/'/g, "\\'");
|
|
1282
|
+
closing += `.$comment('${escapedComment}')`;
|
|
1270
1283
|
}
|
|
1271
|
-
|
|
1272
|
-
|
|
1284
|
+
if (trigger.trackingId) {
|
|
1285
|
+
closing += `.$id('${trigger.trackingId}')`;
|
|
1273
1286
|
}
|
|
1287
|
+
closing += ';';
|
|
1288
|
+
parts.push(closing);
|
|
1274
1289
|
parts.push('');
|
|
1275
1290
|
}
|
|
1276
1291
|
parts.push('// =============================================================================');
|
|
@@ -705,6 +705,7 @@ export async function introspectedToParsedSchema(schema) {
|
|
|
705
705
|
volatility: f.volatility,
|
|
706
706
|
isStrict: false,
|
|
707
707
|
securityDefiner: false,
|
|
708
|
+
comment: f.comment,
|
|
708
709
|
});
|
|
709
710
|
}
|
|
710
711
|
for (const t of schema.triggers || []) {
|
|
@@ -716,6 +717,7 @@ export async function introspectedToParsedSchema(schema) {
|
|
|
716
717
|
forEach: t.forEach || 'ROW',
|
|
717
718
|
functionName: t.functionName || '',
|
|
718
719
|
isConstraint: false,
|
|
720
|
+
comment: t.comment,
|
|
719
721
|
});
|
|
720
722
|
}
|
|
721
723
|
return parsed;
|
|
@@ -799,9 +801,26 @@ function parseArgTypes(argTypes) {
|
|
|
799
801
|
if (!argTypes)
|
|
800
802
|
return [];
|
|
801
803
|
const parts = Array.isArray(argTypes) ? argTypes : argTypes.split(',');
|
|
802
|
-
return parts.map(arg =>
|
|
803
|
-
|
|
804
|
-
|
|
804
|
+
return parts.map(arg => {
|
|
805
|
+
const trimmed = typeof arg === 'string' ? arg.trim() : String(arg);
|
|
806
|
+
if (!trimmed)
|
|
807
|
+
return { type: '' };
|
|
808
|
+
const firstSpace = trimmed.indexOf(' ');
|
|
809
|
+
if (firstSpace === -1) {
|
|
810
|
+
return { type: trimmed };
|
|
811
|
+
}
|
|
812
|
+
const firstPart = trimmed.substring(0, firstSpace);
|
|
813
|
+
const restPart = trimmed.substring(firstSpace + 1).trim();
|
|
814
|
+
const commonTypeStarts = ['integer', 'bigint', 'smallint', 'text', 'varchar', 'char', 'boolean',
|
|
815
|
+
'timestamp', 'date', 'time', 'interval', 'numeric', 'decimal', 'real', 'double', 'uuid',
|
|
816
|
+
'json', 'jsonb', 'bytea', 'inet', 'cidr', 'macaddr', 'point', 'line', 'circle', 'box',
|
|
817
|
+
'tsvector', 'tsquery', 'void', 'trigger', 'record', 'setof', 'array'];
|
|
818
|
+
const lowerFirst = firstPart.toLowerCase();
|
|
819
|
+
if (commonTypeStarts.some(t => lowerFirst === t || lowerFirst.startsWith(t + '['))) {
|
|
820
|
+
return { type: trimmed };
|
|
821
|
+
}
|
|
822
|
+
return { name: firstPart, type: restPart };
|
|
823
|
+
}).filter(arg => arg.type !== '');
|
|
805
824
|
}
|
|
806
825
|
function extractFunctionBody(definition) {
|
|
807
826
|
if (!definition)
|
|
@@ -922,6 +941,8 @@ export function normalizedToParsedSchema(schema) {
|
|
|
922
941
|
volatility: f.volatility || 'VOLATILE',
|
|
923
942
|
isStrict: f.isStrict ?? false,
|
|
924
943
|
securityDefiner: f.securityDefiner ?? false,
|
|
944
|
+
comment: f.comment,
|
|
945
|
+
trackingId: f.trackingId,
|
|
925
946
|
})),
|
|
926
947
|
triggers: (schema.triggers || []).map(t => ({
|
|
927
948
|
name: t.name,
|
|
@@ -932,6 +953,8 @@ export function normalizedToParsedSchema(schema) {
|
|
|
932
953
|
functionName: t.functionName || '',
|
|
933
954
|
whenClause: t.when,
|
|
934
955
|
isConstraint: false,
|
|
956
|
+
comment: t.comment,
|
|
957
|
+
trackingId: t.trackingId,
|
|
935
958
|
})),
|
|
936
959
|
};
|
|
937
960
|
}
|
|
@@ -257,7 +257,8 @@ export async function introspectDatabase(connection, onProgress, options) {
|
|
|
257
257
|
l.lanname as language,
|
|
258
258
|
pg_get_functiondef(p.oid) as definition,
|
|
259
259
|
p.prokind = 'a' as is_aggregate,
|
|
260
|
-
p.provolatile as volatility
|
|
260
|
+
p.provolatile as volatility,
|
|
261
|
+
obj_description(p.oid, 'pg_proc') as comment
|
|
261
262
|
FROM pg_proc p
|
|
262
263
|
JOIN pg_namespace n ON p.pronamespace = n.oid
|
|
263
264
|
JOIN pg_language l ON p.prolang = l.oid
|
|
@@ -285,6 +286,7 @@ export async function introspectDatabase(connection, onProgress, options) {
|
|
|
285
286
|
definition: f.definition || '',
|
|
286
287
|
isAggregate: f.is_aggregate || false,
|
|
287
288
|
volatility: f.volatility === 'i' ? 'IMMUTABLE' : f.volatility === 's' ? 'STABLE' : 'VOLATILE',
|
|
289
|
+
comment: f.comment || undefined,
|
|
288
290
|
}));
|
|
289
291
|
}
|
|
290
292
|
let triggers = [];
|
|
@@ -310,7 +312,8 @@ export async function introspectDatabase(connection, onProgress, options) {
|
|
|
310
312
|
END as for_each,
|
|
311
313
|
p.proname as function_name,
|
|
312
314
|
pg_get_triggerdef(t.oid) as definition,
|
|
313
|
-
t.tgenabled != 'D' as is_enabled
|
|
315
|
+
t.tgenabled != 'D' as is_enabled,
|
|
316
|
+
obj_description(t.oid, 'pg_trigger') as comment
|
|
314
317
|
FROM pg_trigger t
|
|
315
318
|
JOIN pg_class c ON t.tgrelid = c.oid
|
|
316
319
|
JOIN pg_namespace n ON c.relnamespace = n.oid
|
|
@@ -333,6 +336,7 @@ export async function introspectDatabase(connection, onProgress, options) {
|
|
|
333
336
|
functionName: t.function_name,
|
|
334
337
|
definition: t.definition || '',
|
|
335
338
|
isEnabled: t.is_enabled,
|
|
339
|
+
comment: t.comment || undefined,
|
|
336
340
|
}));
|
|
337
341
|
}
|
|
338
342
|
const policiesResult = await pool.query(`
|
|
@@ -630,6 +630,7 @@ export const smallserial = (columnName) => createColumnWithName('SMALLSERIAL', c
|
|
|
630
630
|
export const serial2 = smallserial;
|
|
631
631
|
export const bigserial = (columnName) => createColumnWithName('BIGSERIAL', columnName);
|
|
632
632
|
export const serial8 = bigserial;
|
|
633
|
+
export const epoch = (columnName) => createColumnWithName('BIGINT', columnName);
|
|
633
634
|
export const decimal = (columnNameOrOpts, scale) => {
|
|
634
635
|
if (typeof columnNameOrOpts === 'string' && !columnNameOrOpts.includes('.')) {
|
|
635
636
|
return createColumnWithName('DECIMAL', columnNameOrOpts);
|
|
@@ -18,6 +18,8 @@ export const DEFAULT = {
|
|
|
18
18
|
clockTimestamp: () => createDefault('clock_timestamp()'),
|
|
19
19
|
timeofday: () => createDefault('timeofday()'),
|
|
20
20
|
interval: (value) => createDefault(`INTERVAL '${value}'`),
|
|
21
|
+
epochNow: () => createDefault('(EXTRACT(EPOCH FROM NOW()) * 1000)::bigint'),
|
|
22
|
+
epochSeconds: () => createDefault('EXTRACT(EPOCH FROM NOW())::bigint'),
|
|
21
23
|
currentUser: () => createDefault('CURRENT_USER'),
|
|
22
24
|
sessionUser: () => createDefault('SESSION_USER'),
|
|
23
25
|
user: () => createDefault('USER'),
|
|
@@ -7,7 +7,12 @@ export function generateFunctionSQL(config) {
|
|
|
7
7
|
if (arg.mode && arg.mode !== 'IN') {
|
|
8
8
|
argStr += arg.mode + ' ';
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
if (arg.name) {
|
|
11
|
+
argStr += arg.name + ' ' + arg.type;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
argStr += arg.type;
|
|
15
|
+
}
|
|
11
16
|
if (arg.default !== undefined) {
|
|
12
17
|
argStr += ' DEFAULT ' + arg.default;
|
|
13
18
|
}
|
package/dist/schema-builder.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export declare const DEFAULT: {
|
|
|
23
23
|
readonly clockTimestamp: () => DefaultValue;
|
|
24
24
|
readonly timeofday: () => DefaultValue;
|
|
25
25
|
readonly interval: (value: string) => DefaultValue;
|
|
26
|
+
/** Current time as epoch milliseconds (BIGINT) - use with epoch() column */
|
|
27
|
+
readonly epochNow: () => DefaultValue;
|
|
28
|
+
/** Current time as epoch seconds (BIGINT) */
|
|
29
|
+
readonly epochSeconds: () => DefaultValue;
|
|
26
30
|
readonly currentUser: () => DefaultValue;
|
|
27
31
|
readonly sessionUser: () => DefaultValue;
|
|
28
32
|
readonly user: () => DefaultValue;
|
|
@@ -978,6 +982,17 @@ export declare const smallserial: (columnName?: string) => ColumnBuilder<number,
|
|
|
978
982
|
export declare const serial2: (columnName?: string) => ColumnBuilder<number, ColumnConfig<number>>;
|
|
979
983
|
export declare const bigserial: (columnName?: string) => ColumnBuilder<bigint, ColumnConfig<bigint>>;
|
|
980
984
|
export declare const serial8: (columnName?: string) => ColumnBuilder<bigint, ColumnConfig<bigint>>;
|
|
985
|
+
/**
|
|
986
|
+
* Epoch timestamp column (BIGINT storing milliseconds since Unix epoch)
|
|
987
|
+
* Use with DEFAULT.epochNow() for auto-generated timestamps
|
|
988
|
+
*
|
|
989
|
+
* @example
|
|
990
|
+
* ```typescript
|
|
991
|
+
* createdAt: epoch().default(DEFAULT.epochNow()),
|
|
992
|
+
* updatedAt: epoch().default(DEFAULT.epochNow()),
|
|
993
|
+
* ```
|
|
994
|
+
*/
|
|
995
|
+
export declare const epoch: (columnName?: string) => ColumnBuilder<number, ColumnConfig<number>>;
|
|
981
996
|
export declare const decimal: (columnNameOrOpts?: string | number | {
|
|
982
997
|
precision?: number;
|
|
983
998
|
scale?: number;
|