@ganju/utils 0.0.20 → 0.0.21
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/constants.d.ts +16 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +43 -0
- package/dist/data.d.ts +6 -4
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +13 -3
- package/dist/dataApi.d.ts +50 -4
- package/dist/dataApi.d.ts.map +1 -1
- package/dist/dataApi.js +36 -3
- package/dist/dataAttachment.d.ts +8 -0
- package/dist/dataAttachment.d.ts.map +1 -0
- package/dist/dataAttachment.js +19 -0
- package/dist/dataCompiler.d.ts +3 -0
- package/dist/dataCompiler.d.ts.map +1 -1
- package/dist/dataCompiler.js +25 -1
- package/dist/dataDdl.d.ts.map +1 -1
- package/dist/dataDdl.js +5 -0
- package/dist/dataEngine.d.ts +9 -3
- package/dist/dataEngine.d.ts.map +1 -1
- package/dist/dataEngine.js +141 -5
- package/dist/dataIndexAdvice.d.ts +36 -0
- package/dist/dataIndexAdvice.d.ts.map +1 -0
- package/dist/dataIndexAdvice.js +89 -0
- package/dist/dataRpc.d.ts +12 -1
- package/dist/dataRpc.d.ts.map +1 -1
- package/dist/dataTools.js +3 -3
- package/dist/dataTriggers.d.ts +23 -0
- package/dist/dataTriggers.d.ts.map +1 -1
- package/dist/dataTriggers.js +46 -2
- package/dist/dataTypes.d.ts +46 -0
- package/dist/dataTypes.d.ts.map +1 -1
- package/dist/dataTypes.js +7 -1
- package/dist/index.d.ts +56 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/localizeDataError.d.ts.map +1 -1
- package/dist/localizeDataError.js +64 -2
- package/dist/schema.d.ts +34 -2
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +32 -0
- package/dist/whatsappWebhook.d.ts +28 -0
- package/dist/whatsappWebhook.d.ts.map +1 -0
- package/dist/whatsappWebhook.js +30 -0
- package/package.json +1 -1
- package/src/constants.ts +46 -0
- package/src/data.ts +14 -0
- package/src/dataApi.ts +40 -2
- package/src/dataAttachment.ts +23 -0
- package/src/dataCompiler.ts +37 -0
- package/src/dataDdl.ts +7 -0
- package/src/dataEngine.ts +195 -5
- package/src/dataIndexAdvice.ts +127 -0
- package/src/dataRpc.ts +17 -1
- package/src/dataTools.ts +3 -3
- package/src/dataTriggers.ts +71 -1
- package/src/dataTypes.ts +62 -0
- package/src/index.ts +11 -0
- package/src/localizeDataError.ts +101 -3
- package/src/schema.ts +34 -0
- package/src/whatsappWebhook.ts +55 -0
package/dist/dataEngine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataEngine.d.ts","sourceRoot":"","sources":["../src/dataEngine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dataEngine.d.ts","sourceRoot":"","sources":["../src/dataEngine.ts"],"names":[],"mappings":"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"}
|
package/dist/dataEngine.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.exportRows = exports.dropColumn = exports.updateColumn = exports.copyTableStep = exports.clearFailedTableCopy = exports.writeReachesCopy = exports.readTableCopy = exports.dropColumnNeedsRebuild = exports.columnChangeNeedsRebuild = exports.addColumn = exports.dropTable = exports.updateTable = exports.createTable = exports.pruneHistory = exports.rowHistory = exports.deleteImpact = exports.write = exports.assertWritable = exports.assertActor = exports.query = exports.describe = exports.translateSqliteError = exports.normaliseColumn = exports.toTableInput = exports.loadSchema = exports.migrateInternal = exports.setMeta = exports.getMeta = exports.hasInternalTables = exports.INTERNAL_SCHEMA_VERSION = exports.INTERNAL_MIGRATIONS = void 0;
|
|
3
|
+
exports.exportRows = exports.dropColumn = exports.updateColumn = exports.copyTableStep = exports.clearFailedTableCopy = exports.writeReachesCopy = exports.readTableCopy = exports.dropColumnNeedsRebuild = exports.columnChangeNeedsRebuild = exports.addColumn = exports.dropTable = exports.updateTable = exports.createTable = exports.pruneHistory = exports.rowHistory = exports.replaceFileLinks = exports.fileLinks = exports.deleteImpact = exports.write = exports.assertWritable = exports.assertActor = exports.query = exports.describe = exports.translateSqliteError = exports.normaliseColumn = exports.toTableInput = exports.loadSchema = exports.migrateInternal = exports.setMeta = exports.getMeta = exports.hasInternalTables = exports.INTERNAL_SCHEMA_VERSION = exports.INTERNAL_MIGRATIONS = void 0;
|
|
4
4
|
// What a project's database does, written against a tiny SQL runner so the
|
|
5
5
|
// same code runs inside the Durable Object (apps/data) and on node:sqlite in
|
|
6
6
|
// the tests and the tool-design eval. The runner executes; everything about
|
|
@@ -335,8 +335,11 @@ const normaliseColumn = (input, schema, selfTable) => {
|
|
|
335
335
|
if (column.unique && !dataDdl_1.UNIQUE_TYPES.has(column.type)) {
|
|
336
336
|
throw new dataTypes_1.DataError(`${label}: a ${column.type} column can't be unique.`);
|
|
337
337
|
}
|
|
338
|
-
|
|
339
|
-
|
|
338
|
+
// On a file column, searchable means its uploads are indexed in knowledge.
|
|
339
|
+
if (column.searchable &&
|
|
340
|
+
!dataDdl_1.SEARCHABLE_TYPES.has(column.type) &&
|
|
341
|
+
column.type !== 'file') {
|
|
342
|
+
throw new dataTypes_1.DataError(`${label}: only text and file columns can be searchable (text, long_text, email, url, phone, enum, file).`);
|
|
340
343
|
}
|
|
341
344
|
// The search table has a column of its own called rank.
|
|
342
345
|
if (column.searchable && column.name === 'rank') {
|
|
@@ -548,6 +551,9 @@ const shapeRow = (schema, table, raw, caller) => {
|
|
|
548
551
|
: label
|
|
549
552
|
};
|
|
550
553
|
}
|
|
554
|
+
else if (column.type === 'file') {
|
|
555
|
+
row[column.name] = value === null ? null : { uri: String(value) };
|
|
556
|
+
}
|
|
551
557
|
else {
|
|
552
558
|
row[column.name] = value;
|
|
553
559
|
}
|
|
@@ -626,8 +632,19 @@ const query = (runner, schema, caller, rawArgs) => {
|
|
|
626
632
|
caller,
|
|
627
633
|
table,
|
|
628
634
|
joins: new Map(),
|
|
629
|
-
params: []
|
|
635
|
+
params: [],
|
|
636
|
+
filtered: new Set()
|
|
630
637
|
};
|
|
638
|
+
// What this query read, noted for index advice once it has its rows.
|
|
639
|
+
const readBefore = runner.usageSoFar?.().rowsRead ?? 0;
|
|
640
|
+
const sorted = [];
|
|
641
|
+
const noteShape = (returned) => runner.noteQuery?.({
|
|
642
|
+
table: table.name,
|
|
643
|
+
filtered: [...(ctx.filtered ?? [])],
|
|
644
|
+
sorted,
|
|
645
|
+
rowsRead: (runner.usageSoFar?.().rowsRead ?? 0) - readBefore,
|
|
646
|
+
returned
|
|
647
|
+
});
|
|
631
648
|
const indexed = new Set();
|
|
632
649
|
const where = (0, dataCompiler_1.compileWhere)(ctx, args.where, indexed);
|
|
633
650
|
if ((0, dataCompiler_1.isScoped)(caller, table)) {
|
|
@@ -639,7 +656,10 @@ const query = (runner, schema, caller, rawArgs) => {
|
|
|
639
656
|
throw new dataTypes_1.DataError(`"${table.name}" has no searchable columns; filter with "where" instead (e.g. { "name": { "contains": "..." } }).`);
|
|
640
657
|
}
|
|
641
658
|
if (args.aggregate !== undefined && args.aggregate !== null) {
|
|
642
|
-
|
|
659
|
+
const result = aggregate(runner, ctx, args, where, searching, indexed.size > 0);
|
|
660
|
+
const groups = result.groups;
|
|
661
|
+
noteShape(Array.isArray(groups) ? groups.length : 1);
|
|
662
|
+
return result;
|
|
643
663
|
}
|
|
644
664
|
const limit = args.limit === undefined || args.limit === null ? dataTypes_1.DATA_DEFAULT_PAGE : args.limit;
|
|
645
665
|
if (typeof limit !== 'number' || !Number.isInteger(limit) || limit < 1 || limit > dataTypes_1.DATA_MAX_PAGE) {
|
|
@@ -672,6 +692,8 @@ const query = (runner, schema, caller, rawArgs) => {
|
|
|
672
692
|
descending,
|
|
673
693
|
...(servedByIndex ? {} : { unindexed: resolved.column.name })
|
|
674
694
|
});
|
|
695
|
+
if (resolved.own && resolved.column.name !== 'id')
|
|
696
|
+
sorted.push(resolved.column.name);
|
|
675
697
|
if (resolved.own && resolved.column.name === 'id') {
|
|
676
698
|
endsUnique = true;
|
|
677
699
|
break;
|
|
@@ -763,14 +785,17 @@ const query = (runner, schema, caller, rawArgs) => {
|
|
|
763
785
|
throw (0, exports.translateSqliteError)(schema, table, error);
|
|
764
786
|
}
|
|
765
787
|
const { rows: out, last, more } = result;
|
|
788
|
+
noteShape(out.length);
|
|
766
789
|
const includeTruncated = args.include !== undefined && args.include !== null
|
|
767
790
|
? includeRelations(runner, schema, caller, table, out, args.include, dataTypes_1.DATA_MAX_RESULT_BYTES - result.bytes)
|
|
768
791
|
: false;
|
|
792
|
+
const fileFields = fileFieldPaths(schema, table, args.include);
|
|
769
793
|
return {
|
|
770
794
|
table: table.name,
|
|
771
795
|
...((0, dataCompiler_1.isScoped)(caller, table) ? { scope: SCOPE_NOTE } : {}),
|
|
772
796
|
...(result.total !== undefined ? { total: result.total } : {}),
|
|
773
797
|
...(matched ? { searchMatched: matched } : {}),
|
|
798
|
+
...(fileFields.length ? { fileFields } : {}),
|
|
774
799
|
rows: out,
|
|
775
800
|
...(includeTruncated
|
|
776
801
|
? {
|
|
@@ -789,6 +814,25 @@ const query = (runner, schema, caller, rawArgs) => {
|
|
|
789
814
|
};
|
|
790
815
|
};
|
|
791
816
|
exports.query = query;
|
|
817
|
+
// Where a query's rows hold file values, as key paths within each row: the
|
|
818
|
+
// table's file columns, and those of each included relation. The workers
|
|
819
|
+
// fill those in from knowledge and drop this before answering; a json
|
|
820
|
+
// column holding { "uri": … } is never mistaken for one.
|
|
821
|
+
const fileFieldPaths = (schema, table, include) => {
|
|
822
|
+
const own = table.columns
|
|
823
|
+
.filter(column => column.type === 'file')
|
|
824
|
+
.map(column => [column.name]);
|
|
825
|
+
const included = (Array.isArray(include) ? include : []).flatMap(name => {
|
|
826
|
+
const column = typeof name === 'string' ? (0, dataCompiler_1.columnFor)(table, name) : undefined;
|
|
827
|
+
if (!column || (0, dataCompiler_1.isSystemColumn)(column) || column.type !== 'relation')
|
|
828
|
+
return [];
|
|
829
|
+
const target = schema.tables.find(t => t.name === column.table);
|
|
830
|
+
return (target?.columns ?? [])
|
|
831
|
+
.filter(c => c.type === 'file')
|
|
832
|
+
.map(c => [name, c.name]);
|
|
833
|
+
});
|
|
834
|
+
return [...own, ...included];
|
|
835
|
+
};
|
|
792
836
|
// Replaces each relation in `rows` named in `include` with the related row,
|
|
793
837
|
// read as the caller may see it, within `budget` bytes. Returns whether any
|
|
794
838
|
// was left as { id, label } to stay inside it.
|
|
@@ -1353,7 +1397,12 @@ const write = (runner, schema, caller, rawArgs) => {
|
|
|
1353
1397
|
const results = [];
|
|
1354
1398
|
operations.forEach((op, index) => {
|
|
1355
1399
|
try {
|
|
1400
|
+
const before = runner.usageSoFar?.().rowsWritten ?? 0;
|
|
1356
1401
|
results.push(runOperation(runner, schema, caller, op, index, results));
|
|
1402
|
+
runner.noteWrite?.({
|
|
1403
|
+
table: results[results.length - 1].table,
|
|
1404
|
+
rowsWritten: (runner.usageSoFar?.().rowsWritten ?? 0) - before
|
|
1405
|
+
});
|
|
1357
1406
|
}
|
|
1358
1407
|
catch (error) {
|
|
1359
1408
|
if (error instanceof dataTypes_1.DataError) {
|
|
@@ -1461,6 +1510,93 @@ const deleteImpact = (runner, schema, caller, rawArgs) => {
|
|
|
1461
1510
|
};
|
|
1462
1511
|
};
|
|
1463
1512
|
exports.deleteImpact = deleteImpact;
|
|
1513
|
+
// File links
|
|
1514
|
+
const fileColumns = (schema) => schema.tables.flatMap(table => table.columns
|
|
1515
|
+
.filter(column => column.type === 'file')
|
|
1516
|
+
.map(column => ({ table, column })));
|
|
1517
|
+
const fileUriList = (value) => {
|
|
1518
|
+
if (!Array.isArray(value) ||
|
|
1519
|
+
value.length === 0 ||
|
|
1520
|
+
value.length > dataTypes_1.DATA_FILE_LINKS_MAX_URIS) {
|
|
1521
|
+
throw new dataTypes_1.DataError(`"uris" lists 1 to ${dataTypes_1.DATA_FILE_LINKS_MAX_URIS} knowledge item uris.`);
|
|
1522
|
+
}
|
|
1523
|
+
return [...new Set(value.map(uri => (0, dataCompiler_1.fileUriOf)(uri, 'uris')))];
|
|
1524
|
+
};
|
|
1525
|
+
// The rows whose file columns point at `uris`, per column: knowledge asks
|
|
1526
|
+
// before it deletes an item. Each file column is indexed.
|
|
1527
|
+
const fileLinks = (runner, schema, caller, rawArgs) => {
|
|
1528
|
+
(0, exports.assertActor)(caller);
|
|
1529
|
+
if (caller.restricted) {
|
|
1530
|
+
throw new dataTypes_1.DataError('File links are for the owner.', 'forbidden');
|
|
1531
|
+
}
|
|
1532
|
+
const uris = JSON.stringify(fileUriList((0, dataCompiler_1.tidyArgs)(rawArgs).uris));
|
|
1533
|
+
const links = [];
|
|
1534
|
+
for (const { table, column } of fileColumns(schema)) {
|
|
1535
|
+
const rows = Number(first(runner, `SELECT count(*) AS n FROM ${(0, dataIdentifiers_1.quoteIdentifier)(table.name)} WHERE ${(0, dataIdentifiers_1.quoteIdentifier)(column.name)} IN (SELECT value FROM json_each(?))`, [uris])?.n ?? 0);
|
|
1536
|
+
if (rows === 0)
|
|
1537
|
+
continue;
|
|
1538
|
+
links.push({
|
|
1539
|
+
table: table.name,
|
|
1540
|
+
tableLabel: table.label,
|
|
1541
|
+
column: column.name,
|
|
1542
|
+
columnLabel: column.label,
|
|
1543
|
+
required: column.required,
|
|
1544
|
+
rows
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1547
|
+
return { links };
|
|
1548
|
+
};
|
|
1549
|
+
exports.fileLinks = fileLinks;
|
|
1550
|
+
// Points the links at `from` to `to`, or clears them (`to: null`) once the
|
|
1551
|
+
// item is gone. A required column keeps its link, which then reads as
|
|
1552
|
+
// missing. Recorded in row history; triggers don't see it.
|
|
1553
|
+
const replaceFileLinks = (runner, schema, caller, rawArgs) => {
|
|
1554
|
+
(0, exports.assertActor)(caller);
|
|
1555
|
+
if (caller.restricted) {
|
|
1556
|
+
throw new dataTypes_1.DataError('File links are for the owner.', 'forbidden');
|
|
1557
|
+
}
|
|
1558
|
+
const raw = (0, dataCompiler_1.tidyArgs)(rawArgs).changes;
|
|
1559
|
+
if (!Array.isArray(raw) ||
|
|
1560
|
+
raw.length === 0 ||
|
|
1561
|
+
raw.length > dataTypes_1.DATA_FILE_LINKS_MAX_URIS) {
|
|
1562
|
+
throw new dataTypes_1.DataError(`"changes" lists 1 to ${dataTypes_1.DATA_FILE_LINKS_MAX_URIS} { from, to } pairs.`);
|
|
1563
|
+
}
|
|
1564
|
+
const changes = raw.map(change => {
|
|
1565
|
+
if (!isPlainObject(change)) {
|
|
1566
|
+
throw new dataTypes_1.DataError('Each change is { from, to }; to is null to clear.');
|
|
1567
|
+
}
|
|
1568
|
+
return {
|
|
1569
|
+
from: (0, dataCompiler_1.fileUriOf)(change.from, 'from'),
|
|
1570
|
+
to: change.to === null ? null : (0, dataCompiler_1.fileUriOf)(change.to, 'to')
|
|
1571
|
+
};
|
|
1572
|
+
});
|
|
1573
|
+
const columns = fileColumns(schema);
|
|
1574
|
+
if (columns.length === 0)
|
|
1575
|
+
return { updated: 0, kept: [] };
|
|
1576
|
+
(0, exports.assertWritable)(runner, caller, changes.some(change => change.to !== null));
|
|
1577
|
+
return runner.transaction(() => {
|
|
1578
|
+
setContextActor(runner, caller.actor);
|
|
1579
|
+
runner.all('DELETE FROM _ganju_changes');
|
|
1580
|
+
let updated = 0;
|
|
1581
|
+
const kept = [];
|
|
1582
|
+
for (const { table, column } of columns) {
|
|
1583
|
+
for (const change of changes) {
|
|
1584
|
+
if (change.to === null && column.required) {
|
|
1585
|
+
const rows = Number(first(runner, `SELECT count(*) AS n FROM ${(0, dataIdentifiers_1.quoteIdentifier)(table.name)} WHERE ${(0, dataIdentifiers_1.quoteIdentifier)(column.name)} = ?`, [change.from])?.n ?? 0);
|
|
1586
|
+
if (rows > 0)
|
|
1587
|
+
kept.push({ table: table.name, column: column.name, rows });
|
|
1588
|
+
continue;
|
|
1589
|
+
}
|
|
1590
|
+
updated += runner.all(`UPDATE ${(0, dataIdentifiers_1.quoteIdentifier)(table.name)} SET ${(0, dataIdentifiers_1.quoteIdentifier)(column.name)} = ?, version = version + 1, updated_at = ${dataDdl_1.DATA_NOW_SQL}, updated_by = ? WHERE ${(0, dataIdentifiers_1.quoteIdentifier)(column.name)} = ? RETURNING id`, [change.to, caller.actor, change.from]).length;
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
// Tidying links after a knowledge change isn't the owner's edit: it
|
|
1594
|
+
// stays in row history but fires no trigger.
|
|
1595
|
+
runner.all('DELETE FROM _ganju_changes');
|
|
1596
|
+
return { updated, kept };
|
|
1597
|
+
});
|
|
1598
|
+
};
|
|
1599
|
+
exports.replaceFileLinks = replaceFileLinks;
|
|
1464
1600
|
// Row history
|
|
1465
1601
|
const rowHistory = (runner, schema, caller, args) => {
|
|
1466
1602
|
const table = (0, dataCompiler_1.tableFor)(schema, caller, args.table);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DataSchema } from './dataTypes';
|
|
2
|
+
export interface IndexAdviceStat {
|
|
3
|
+
tableName: string;
|
|
4
|
+
columnName: string;
|
|
5
|
+
queries: number;
|
|
6
|
+
rowsRead: number;
|
|
7
|
+
rowsReturned: number;
|
|
8
|
+
rowsWritten: number;
|
|
9
|
+
}
|
|
10
|
+
export interface IndexAdviceCandidate {
|
|
11
|
+
tableName: string;
|
|
12
|
+
columnName: string;
|
|
13
|
+
kind: 'add' | 'unused';
|
|
14
|
+
queries: number;
|
|
15
|
+
avgRowsRead: number;
|
|
16
|
+
avgRowsReturned: number;
|
|
17
|
+
rowsWritten: number;
|
|
18
|
+
}
|
|
19
|
+
export interface IndexAdviceInput {
|
|
20
|
+
schema: DataSchema;
|
|
21
|
+
week: IndexAdviceStat[];
|
|
22
|
+
month: IndexAdviceStat[];
|
|
23
|
+
monthCovered: boolean;
|
|
24
|
+
recentlyIndexed: Set<string>;
|
|
25
|
+
}
|
|
26
|
+
export declare const adviseIndexes: (input: IndexAdviceInput) => IndexAdviceCandidate[];
|
|
27
|
+
export declare const adviceDoubled: (current: {
|
|
28
|
+
queries: number;
|
|
29
|
+
avgRowsRead: number;
|
|
30
|
+
rowsWritten: number;
|
|
31
|
+
}, dismissed: {
|
|
32
|
+
queries: number | null;
|
|
33
|
+
avgRowsRead: number | null;
|
|
34
|
+
rowsWritten: number | null;
|
|
35
|
+
}) => boolean;
|
|
36
|
+
//# sourceMappingURL=dataIndexAdvice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataIndexAdvice.d.ts","sourceRoot":"","sources":["../src/dataIndexAdvice.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,GAAG,QAAQ,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,CAAC;IAEnB,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,KAAK,EAAE,eAAe,EAAE,CAAC;IAEzB,YAAY,EAAE,OAAO,CAAC;IAEtB,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC9B;AAMD,eAAO,MAAM,aAAa,GACxB,OAAO,gBAAgB,KACtB,oBAAoB,EA+DtB,CAAC;AAGF,eAAO,MAAM,aAAa,GACxB,SAAS;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EACtE,WAAW;IACT,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,KACA,OASkD,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.adviceDoubled = exports.adviseIndexes = void 0;
|
|
4
|
+
// Which columns of a database are worth an index, and which indexes nobody
|
|
5
|
+
// uses, from the API's daily query stats and the database's schema. Pure, so
|
|
6
|
+
// the daily job and the tests apply the same rule.
|
|
7
|
+
const constants_1 = require("./constants");
|
|
8
|
+
const dataDdl_1 = require("./dataDdl");
|
|
9
|
+
// Indexes the owner can add or remove: a column marked filterable. Unique and
|
|
10
|
+
// relation columns are indexed for what they are, and stay.
|
|
11
|
+
const canIndex = (type) => type !== 'json' && type !== 'long_text';
|
|
12
|
+
const adviseIndexes = (input) => {
|
|
13
|
+
const out = [];
|
|
14
|
+
const tables = new Map(input.schema.tables.map(t => [t.name, t]));
|
|
15
|
+
for (const stat of input.week) {
|
|
16
|
+
if (!stat.columnName)
|
|
17
|
+
continue;
|
|
18
|
+
const table = tables.get(stat.tableName);
|
|
19
|
+
const column = table?.columns.find(c => c.name === stat.columnName);
|
|
20
|
+
if (!column || (0, dataDdl_1.isIndexedColumn)(column) || !canIndex(column.type))
|
|
21
|
+
continue;
|
|
22
|
+
if (stat.queries < constants_1.constants.DATA_INDEX_ADVICE_MIN_QUERIES)
|
|
23
|
+
continue;
|
|
24
|
+
const avgRead = stat.rowsRead / stat.queries;
|
|
25
|
+
const avgReturned = stat.rowsReturned / stat.queries;
|
|
26
|
+
if (avgRead < constants_1.constants.DATA_INDEX_ADVICE_MIN_ROWS_READ)
|
|
27
|
+
continue;
|
|
28
|
+
// Scanning, not just a small table: many rows read for each one returned.
|
|
29
|
+
if (stat.rowsRead <
|
|
30
|
+
constants_1.constants.DATA_INDEX_ADVICE_MIN_READ_RATIO * stat.rowsReturned) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
out.push({
|
|
34
|
+
tableName: stat.tableName,
|
|
35
|
+
columnName: stat.columnName,
|
|
36
|
+
kind: constants_1.constants.DATA_INDEX_ADVICE_ADD,
|
|
37
|
+
queries: stat.queries,
|
|
38
|
+
avgRowsRead: Math.round(avgRead),
|
|
39
|
+
avgRowsReturned: Math.round(avgReturned),
|
|
40
|
+
rowsWritten: 0
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (input.monthCovered) {
|
|
44
|
+
const used = new Set(input.month
|
|
45
|
+
.filter(s => s.columnName && s.queries > 0)
|
|
46
|
+
.map(s => `${s.tableName}.${s.columnName}`));
|
|
47
|
+
for (const table of input.schema.tables) {
|
|
48
|
+
const totals = input.month.find(s => s.tableName === table.name && s.columnName === '');
|
|
49
|
+
const written = totals?.rowsWritten ?? 0;
|
|
50
|
+
if (written < constants_1.constants.DATA_INDEX_UNUSED_MIN_ROWS_WRITTEN)
|
|
51
|
+
continue;
|
|
52
|
+
if (written <= (totals?.queries ?? 0))
|
|
53
|
+
continue;
|
|
54
|
+
if (input.recentlyIndexed.has(table.name))
|
|
55
|
+
continue;
|
|
56
|
+
for (const column of table.columns) {
|
|
57
|
+
if (!column.filterable || column.unique)
|
|
58
|
+
continue;
|
|
59
|
+
if (column.type === 'relation' || column.type === 'file')
|
|
60
|
+
continue;
|
|
61
|
+
const key = `${table.name}.${column.name}`;
|
|
62
|
+
if (used.has(key) || input.recentlyIndexed.has(key))
|
|
63
|
+
continue;
|
|
64
|
+
out.push({
|
|
65
|
+
tableName: table.name,
|
|
66
|
+
columnName: column.name,
|
|
67
|
+
kind: constants_1.constants.DATA_INDEX_ADVICE_UNUSED,
|
|
68
|
+
queries: 0,
|
|
69
|
+
avgRowsRead: 0,
|
|
70
|
+
avgRowsReturned: 0,
|
|
71
|
+
rowsWritten: written
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
};
|
|
78
|
+
exports.adviseIndexes = adviseIndexes;
|
|
79
|
+
// A dismissed suggestion comes back once its numbers have doubled.
|
|
80
|
+
const adviceDoubled = (current, dismissed) => (dismissed.queries !== null &&
|
|
81
|
+
dismissed.queries > 0 &&
|
|
82
|
+
current.queries >= 2 * dismissed.queries) ||
|
|
83
|
+
(dismissed.avgRowsRead !== null &&
|
|
84
|
+
dismissed.avgRowsRead > 0 &&
|
|
85
|
+
current.avgRowsRead >= 2 * dismissed.avgRowsRead) ||
|
|
86
|
+
(dismissed.rowsWritten !== null &&
|
|
87
|
+
dismissed.rowsWritten > 0 &&
|
|
88
|
+
current.rowsWritten >= 2 * dismissed.rowsWritten);
|
|
89
|
+
exports.adviceDoubled = adviceDoubled;
|
package/dist/dataRpc.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DataCaller, DataDeleteImpact, DataResult, DataSchema, DataTable, DataTableCopy } from './dataTypes';
|
|
1
|
+
import type { DataCaller, DataDeleteImpact, DataFileLinkChange, DataFileLinks, DataFileLinksReplaced, DataResult, DataSchema, DataTable, DataTableCopy } from './dataTypes';
|
|
2
2
|
import type { DataQuery } from './dataQueries';
|
|
3
3
|
import type { DataTrigger, DataTriggerWithSecret, SavedTrigger } from './dataTriggers';
|
|
4
4
|
export type ExportFormat = 'jsonl' | 'csv';
|
|
@@ -45,6 +45,7 @@ export interface DatabaseInfo {
|
|
|
45
45
|
name: string;
|
|
46
46
|
label: string | null;
|
|
47
47
|
columns: number;
|
|
48
|
+
rows: number;
|
|
48
49
|
}[];
|
|
49
50
|
copy: DataTableCopy | null;
|
|
50
51
|
}
|
|
@@ -109,6 +110,10 @@ export interface ProjectDatabaseRpc {
|
|
|
109
110
|
}>;
|
|
110
111
|
describe(caller: DataCaller, args?: unknown): R<unknown>;
|
|
111
112
|
query(caller: DataCaller, args: unknown): R<unknown>;
|
|
113
|
+
eventRow(caller: DataCaller, args: {
|
|
114
|
+
table: string;
|
|
115
|
+
id?: number;
|
|
116
|
+
}): R<Record<string, unknown> | null>;
|
|
112
117
|
write(caller: DataCaller, args: unknown): R<{
|
|
113
118
|
ok: true;
|
|
114
119
|
results: unknown[];
|
|
@@ -117,6 +122,12 @@ export interface ProjectDatabaseRpc {
|
|
|
117
122
|
table: string;
|
|
118
123
|
ids?: number[];
|
|
119
124
|
}): R<DataDeleteImpact>;
|
|
125
|
+
fileLinks(caller: DataCaller, args: {
|
|
126
|
+
uris: string[];
|
|
127
|
+
}): R<DataFileLinks>;
|
|
128
|
+
replaceFileLinks(caller: DataCaller, args: {
|
|
129
|
+
changes: DataFileLinkChange[];
|
|
130
|
+
}): R<DataFileLinksReplaced>;
|
|
120
131
|
history(caller: DataCaller, args: {
|
|
121
132
|
table: string;
|
|
122
133
|
id: number;
|
package/dist/dataRpc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataRpc.d.ts","sourceRoot":"","sources":["../src/dataRpc.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACd,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEvF,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,UAAU;IAEzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE;YAAE,UAAU,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAC9C,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QAGd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,GAAG,IAAI,CAAC;IACT,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"dataRpc.d.ts","sourceRoot":"","sources":["../src/dataRpc.ts"],"names":[],"mappings":"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"}
|
package/dist/dataTools.js
CHANGED
|
@@ -39,7 +39,7 @@ const CHANGES = {
|
|
|
39
39
|
destructiveHint: true,
|
|
40
40
|
openWorldHint: false
|
|
41
41
|
};
|
|
42
|
-
const WHERE_HELP = 'Filter object. { "column": value } matches exactly; { "column": { "op": value } } with op one of eq, ne, gt, gte, lt, lte, in, notIn (lists), contains, startsWith (text, case-insensitive), isNull (true/false). Several keys must all match; { "or": [ {...}, {...} ] } matches any. A relation column takes the related row\'s id, or filter on a column of the related table with "relation.column", e.g. { "product.name": "Margherita" }. Datetimes are ISO 8601; include the offset for local times, e.g. "2026-10-19T00:00:00-05:00".';
|
|
42
|
+
const WHERE_HELP = 'Filter object. { "column": value } matches exactly; { "column": { "op": value } } with op one of eq, ne, gt, gte, lt, lte, in, notIn (lists), contains, startsWith (text, case-insensitive), isNull (true/false). Several keys must all match; { "or": [ {...}, {...} ] } matches any. A relation column takes the related row\'s id, or filter on a column of the related table with "relation.column", e.g. { "product.name": "Margherita" }. A file column matches the item\'s uri. Datetimes are ISO 8601; include the offset for local times, e.g. "2026-10-19T00:00:00-05:00".';
|
|
43
43
|
const accessOf = (caller, table) => caller.restricted ? table.access : 'full';
|
|
44
44
|
const visible = (schema, caller) => schema.tables.filter(table => dataTypes_1.DATA_ACCESS_RANK[accessOf(caller, table)] >= 1);
|
|
45
45
|
// One column as data-query's description lists it: the type when it isn't
|
|
@@ -100,7 +100,7 @@ const dataToolDefinitions = (schema, caller, options = {}) => {
|
|
|
100
100
|
title: exports.DATA_TOOL_TITLES[exports.DATA_TOOL_QUERY],
|
|
101
101
|
description: [
|
|
102
102
|
"Read rows from the project's database: structured records such as products, prices, stock, orders, bookings or customers. Use it for anything with fields and numbers; use the knowledge/resource tools for documents and pages.",
|
|
103
|
-
'Returns matching rows (relation columns come back as { id, label }), the total that match, and nextCursor when there are more. With "aggregate" it returns counts, sums, averages, minimums or maximums instead of rows, optionally per group: use that for "how many" and "how much" rather than adding rows up yourself.',
|
|
103
|
+
'Returns matching rows (relation columns come back as { id, label }; file columns as { uri, title, mimeType }, or { uri, missing: true } when the item is gone: deliver one with send-resource and its uri, or read a document with read-resource), the total that match, and nextCursor when there are more. With "aggregate" it returns counts, sums, averages, minimums or maximums instead of rows, optionally per group: use that for "how many" and "how much" rather than adding rows up yourself.',
|
|
104
104
|
"The database holds only what these tables and columns hold. When a question needs something they don't have (opening hours, parking, calories, reviews, forecasts), look in the knowledge tools if you have them; if nothing has it, say you don't have that information. Never guess it.",
|
|
105
105
|
`Every table also has id, created_at and updated_at. Datetimes come back in the project's time zone (${timeZone}) with their offset; read them as local times.`,
|
|
106
106
|
'Tables:',
|
|
@@ -185,7 +185,7 @@ const dataToolDefinitions = (schema, caller, options = {}) => {
|
|
|
185
185
|
title: exports.DATA_TOOL_TITLES[exports.DATA_TOOL_WRITE],
|
|
186
186
|
description: [
|
|
187
187
|
"Add, change or delete rows in the project's database. All operations in one call succeed together or none is applied, so put everything that belongs together (an order, its lines and the stock they use) in one call.",
|
|
188
|
-
'- insert: { "op": "insert", "table": "...", "values": { column: value } }. A relation column takes the related row\'s id; to point at a row inserted earlier in the same call use { "$ref": n }, n being that operation\'s position (0-based).',
|
|
188
|
+
'- insert: { "op": "insert", "table": "...", "values": { column: value } }. A relation column takes the related row\'s id; to point at a row inserted earlier in the same call use { "$ref": n }, n being that operation\'s position (0-based). A file column takes the uri of an item in the project\'s knowledge (from list-resources or search-resources), or null.',
|
|
189
189
|
'- update: { "op": "update", "table": "...", "id": 12, "set": { column: value } }. For numbers, { "decrement": 2 } or { "increment": 2 } changes the value relative to what is stored. Instead of id you can give "where" (same format as data-query).',
|
|
190
190
|
'- delete: { "op": "delete", "table": "...", "id": 12 } (or "where").',
|
|
191
191
|
'Guards: an update or delete also takes "where" conditions that must hold, e.g. "where": { "stock": { "gte": 2 } }, and "expect", how many rows must change (1 by default when id is given). If a guard fails, nothing in the call is written and the error says why (e.g. how much stock is left).',
|
package/dist/dataTriggers.d.ts
CHANGED
|
@@ -113,6 +113,7 @@ export interface DataTriggerEventMessage {
|
|
|
113
113
|
depth: number;
|
|
114
114
|
at: string;
|
|
115
115
|
truncated?: true;
|
|
116
|
+
participantId?: string;
|
|
116
117
|
error?: string;
|
|
117
118
|
}
|
|
118
119
|
/**
|
|
@@ -128,6 +129,21 @@ export declare const conditionMatches: (when: DataTriggerCondition | null | unde
|
|
|
128
129
|
* senders send it as text.
|
|
129
130
|
*/
|
|
130
131
|
export declare const renderTriggerText: (text: string, row: Record<string, unknown> | null) => string;
|
|
132
|
+
export interface DataTriggerCustomerMessage {
|
|
133
|
+
text: string;
|
|
134
|
+
template: {
|
|
135
|
+
name: string;
|
|
136
|
+
language: string;
|
|
137
|
+
params: string[];
|
|
138
|
+
} | null;
|
|
139
|
+
}
|
|
140
|
+
export declare const renderCustomerMessage: (action: {
|
|
141
|
+
text: string;
|
|
142
|
+
template?: DataTriggerTemplate;
|
|
143
|
+
}, row: Record<string, unknown> | null) => DataTriggerCustomerMessage;
|
|
144
|
+
export declare const normaliseCustomerAction: (schema: DataSchema, tableName: string, value: unknown) => Extract<DataTriggerAction, {
|
|
145
|
+
type: "customer";
|
|
146
|
+
}>;
|
|
131
147
|
interface NormalisedTrigger {
|
|
132
148
|
name: string;
|
|
133
149
|
defaultName: boolean;
|
|
@@ -173,6 +189,13 @@ export declare const changeCaptureTriggers: (table: Pick<DataTable, "id" | "name
|
|
|
173
189
|
sql: string;
|
|
174
190
|
}[];
|
|
175
191
|
export declare const ensureChangeCapture: (runner: SqlRunner, table: DataTable) => void;
|
|
192
|
+
/**
|
|
193
|
+
* A row as a trigger event carries it, read from the table: `id`, or the
|
|
194
|
+
* newest row. Null when there is none. A test send and a run whose event
|
|
195
|
+
* was too large to carry its row build their message from it, so it reads
|
|
196
|
+
* as it does for the event, system fields and the customer included.
|
|
197
|
+
*/
|
|
198
|
+
export declare const readEventRow: (runner: SqlRunner, schema: DataSchema, tableName: string, id?: number) => Record<string, unknown> | null;
|
|
176
199
|
/**
|
|
177
200
|
* Turns the changes a write captured into events, inside the write's
|
|
178
201
|
* transaction. A trigger never matches the writes of a run it started
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataTriggers.d.ts","sourceRoot":"","sources":["../src/dataTriggers.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dataTriggers.d.ts","sourceRoot":"","sources":["../src/dataTriggers.ts"],"names":[],"mappings":"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"}
|
package/dist/dataTriggers.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.renameColumnInTriggers = exports.triggersUsingColumn = exports.clearOutbox = exports.outboxSize = exports.deleteOutbox = exports.readOutbox = exports.collectTriggerEvents = exports.ensureChangeCapture = exports.changeCaptureTriggers = exports.replaceManagedTriggers = exports.setTriggerEnabled = exports.dropTrigger = exports.saveTrigger = exports.getTrigger = exports.listTriggers = exports.normaliseTrigger = exports.renderTriggerText = exports.conditionMatches = exports.utf8Bytes = exports.DATA_TRIGGER_MAX_MESSAGE_BYTES = exports.DATA_TRIGGER_MAX_ROW_BYTES = exports.DATA_OUTBOX_BATCH = exports.DATA_TRIGGER_MAX_EMAILS = exports.DATA_TRIGGER_MAX_TEXT = exports.DATA_TRIGGER_MAX_RATE = exports.DATA_TRIGGER_DEFAULT_RATE = exports.DATA_TRIGGER_MAX_DEPTH = exports.DATA_MAX_TRIGGERS = exports.DATA_TRIGGER_ACTIONS = exports.DATA_TRIGGER_EVENTS = void 0;
|
|
3
|
+
exports.renameColumnInTriggers = exports.triggersUsingColumn = exports.clearOutbox = exports.outboxSize = exports.deleteOutbox = exports.readOutbox = exports.collectTriggerEvents = exports.readEventRow = exports.ensureChangeCapture = exports.changeCaptureTriggers = exports.replaceManagedTriggers = exports.setTriggerEnabled = exports.dropTrigger = exports.saveTrigger = exports.getTrigger = exports.listTriggers = exports.normaliseTrigger = exports.normaliseCustomerAction = exports.renderCustomerMessage = exports.renderTriggerText = exports.conditionMatches = exports.utf8Bytes = exports.DATA_TRIGGER_MAX_MESSAGE_BYTES = exports.DATA_TRIGGER_MAX_ROW_BYTES = exports.DATA_OUTBOX_BATCH = exports.DATA_TRIGGER_MAX_EMAILS = exports.DATA_TRIGGER_MAX_TEXT = exports.DATA_TRIGGER_MAX_RATE = exports.DATA_TRIGGER_DEFAULT_RATE = exports.DATA_TRIGGER_MAX_DEPTH = exports.DATA_MAX_TRIGGERS = exports.DATA_TRIGGER_ACTIONS = exports.DATA_TRIGGER_EVENTS = void 0;
|
|
4
4
|
const dataCompiler_1 = require("./dataCompiler");
|
|
5
5
|
const dataTypes_1 = require("./dataTypes");
|
|
6
6
|
exports.DATA_TRIGGER_EVENTS = ['insert', 'update', 'delete'];
|
|
@@ -152,6 +152,19 @@ const renderTriggerText = (text, row) => text.replace(/\{\{\s*([a-z][a-z0-9_]*)\
|
|
|
152
152
|
return typeof value === 'object' ? JSON.stringify(value) : String(value);
|
|
153
153
|
});
|
|
154
154
|
exports.renderTriggerText = renderTriggerText;
|
|
155
|
+
// What a "customer" action sends for a row: its text, and the template with
|
|
156
|
+
// each value filled in. A test send builds it the same way as a real run.
|
|
157
|
+
const renderCustomerMessage = (action, row) => ({
|
|
158
|
+
text: (0, exports.renderTriggerText)(action.text, row),
|
|
159
|
+
template: action.template
|
|
160
|
+
? {
|
|
161
|
+
name: action.template.name,
|
|
162
|
+
language: action.template.language,
|
|
163
|
+
params: (action.template.params ?? []).map(p => (0, exports.renderTriggerText)(p, row))
|
|
164
|
+
}
|
|
165
|
+
: null
|
|
166
|
+
});
|
|
167
|
+
exports.renderCustomerMessage = renderCustomerMessage;
|
|
155
168
|
const templateFields = (text) => [...text.matchAll(/\{\{\s*([a-z][a-z0-9_]*)\s*\}\}/g)].map(m => m[1]);
|
|
156
169
|
// Definitions
|
|
157
170
|
const cleanText = (value, label, max = exports.DATA_TRIGGER_MAX_TEXT) => {
|
|
@@ -261,6 +274,16 @@ const normaliseAction = (table, input) => {
|
|
|
261
274
|
}
|
|
262
275
|
}
|
|
263
276
|
};
|
|
277
|
+
// A "customer" action as the dialog has it, saved or not, checked against
|
|
278
|
+
// its table the way saving it would be.
|
|
279
|
+
const normaliseCustomerAction = (schema, tableName, value) => {
|
|
280
|
+
const table = schema.tables.find(t => t.name === tableName);
|
|
281
|
+
if (!table) {
|
|
282
|
+
throw new dataTypes_1.DataError(`There is no table named ${tableName}.`, 'not_found');
|
|
283
|
+
}
|
|
284
|
+
return normaliseAction(table, { customer: value });
|
|
285
|
+
};
|
|
286
|
+
exports.normaliseCustomerAction = normaliseCustomerAction;
|
|
264
287
|
const defaultName = (table, on, action) => {
|
|
265
288
|
const target = action.type === 'function'
|
|
266
289
|
? action.function.toLowerCase().replace(/[^a-z0-9_-]/g, '-')
|
|
@@ -575,6 +598,23 @@ const shape = (table, raw) => {
|
|
|
575
598
|
delete out.participant_id;
|
|
576
599
|
return out;
|
|
577
600
|
};
|
|
601
|
+
/**
|
|
602
|
+
* A row as a trigger event carries it, read from the table: `id`, or the
|
|
603
|
+
* newest row. Null when there is none. A test send and a run whose event
|
|
604
|
+
* was too large to carry its row build their message from it, so it reads
|
|
605
|
+
* as it does for the event, system fields and the customer included.
|
|
606
|
+
*/
|
|
607
|
+
const readEventRow = (runner, schema, tableName, id) => {
|
|
608
|
+
const table = schema.tables.find(t => t.name === tableName);
|
|
609
|
+
if (!table) {
|
|
610
|
+
throw new dataTypes_1.DataError(`There is no table named ${tableName}.`, 'not_found');
|
|
611
|
+
}
|
|
612
|
+
const [stored] = id === undefined
|
|
613
|
+
? runner.all(`SELECT * FROM "${table.name}" ORDER BY id DESC LIMIT 1`)
|
|
614
|
+
: runner.all(`SELECT * FROM "${table.name}" WHERE id = ?`, [id]);
|
|
615
|
+
return stored ? shape(table, JSON.stringify(stored)) : null;
|
|
616
|
+
};
|
|
617
|
+
exports.readEventRow = readEventRow;
|
|
578
618
|
const DEPTH_PATTERN = /^trigger:([^\s]+)$/;
|
|
579
619
|
/**
|
|
580
620
|
* Turns the changes a write captured into events, inside the write's
|
|
@@ -605,6 +645,7 @@ const collectTriggerEvents = (runner, schema, caller) => {
|
|
|
605
645
|
continue;
|
|
606
646
|
const row = shape(table, change.new);
|
|
607
647
|
const previous = shape(table, change.old);
|
|
648
|
+
const customer = row?.participant_id ?? previous?.participant_id;
|
|
608
649
|
for (const trigger of listening) {
|
|
609
650
|
if (trigger.id === ownTrigger)
|
|
610
651
|
continue;
|
|
@@ -622,7 +663,10 @@ const collectTriggerEvents = (runner, schema, caller) => {
|
|
|
622
663
|
previous,
|
|
623
664
|
actor: change.actor ?? null,
|
|
624
665
|
depth,
|
|
625
|
-
at: new Date().toISOString()
|
|
666
|
+
at: new Date().toISOString(),
|
|
667
|
+
...(typeof customer === 'string' && customer
|
|
668
|
+
? { participantId: customer }
|
|
669
|
+
: {})
|
|
626
670
|
};
|
|
627
671
|
if (depth > exports.DATA_TRIGGER_MAX_DEPTH) {
|
|
628
672
|
message.row = null;
|