@ganju/utils 0.0.20 → 0.0.22
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 +7 -5
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +27 -3
- package/dist/dataApi.d.ts +82 -6
- package/dist/dataApi.d.ts.map +1 -1
- package/dist/dataApi.js +47 -4
- 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 +4 -0
- package/dist/dataCompiler.d.ts.map +1 -1
- package/dist/dataCompiler.js +27 -2
- package/dist/dataDdl.d.ts.map +1 -1
- package/dist/dataDdl.js +5 -0
- package/dist/dataEngine.d.ts +25 -3
- package/dist/dataEngine.d.ts.map +1 -1
- package/dist/dataEngine.js +508 -14
- package/dist/dataImport.d.ts +3 -0
- package/dist/dataImport.d.ts.map +1 -1
- package/dist/dataImport.js +12 -2
- 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 +20 -1
- package/dist/dataRpc.d.ts.map +1 -1
- package/dist/dataSheet.d.ts +34 -0
- package/dist/dataSheet.d.ts.map +1 -0
- package/dist/dataSheet.js +100 -0
- package/dist/dataTools.js +3 -3
- package/dist/dataTriggers.d.ts +66 -4
- package/dist/dataTriggers.d.ts.map +1 -1
- package/dist/dataTriggers.js +446 -20
- package/dist/dataTypes.d.ts +69 -0
- package/dist/dataTypes.d.ts.map +1 -1
- package/dist/dataTypes.js +21 -1
- package/dist/index.d.ts +91 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/localizeDataError.d.ts.map +1 -1
- package/dist/localizeDataError.js +109 -3
- package/dist/schema.d.ts +67 -6
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +57 -2
- package/dist/untrustedContent.d.ts +7 -0
- package/dist/untrustedContent.d.ts.map +1 -1
- package/dist/untrustedContent.js +13 -1
- 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 +33 -3
- package/src/dataApi.ts +54 -4
- package/src/dataAttachment.ts +23 -0
- package/src/dataCompiler.ts +41 -1
- package/src/dataDdl.ts +7 -0
- package/src/dataEngine.ts +680 -15
- package/src/dataImport.ts +16 -1
- package/src/dataIndexAdvice.ts +127 -0
- package/src/dataRpc.ts +27 -2
- package/src/dataSheet.ts +147 -0
- package/src/dataTools.ts +3 -3
- package/src/dataTriggers.ts +599 -20
- package/src/dataTypes.ts +108 -0
- package/src/index.ts +15 -0
- package/src/localizeDataError.ts +183 -4
- package/src/schema.ts +60 -2
- package/src/untrustedContent.ts +15 -0
- package/src/whatsappWebhook.ts +55 -0
package/dist/dataImport.d.ts
CHANGED
|
@@ -66,6 +66,7 @@ export interface ImportedRow {
|
|
|
66
66
|
values: Record<string, unknown>;
|
|
67
67
|
errors: string[];
|
|
68
68
|
warnings: NumberGuess[];
|
|
69
|
+
repeated: string[];
|
|
69
70
|
}
|
|
70
71
|
export declare const importRows: (table: Pick<DataTable, "name" | "columns">, mapping: (string | null)[], rows: ImportRow[], options?: {
|
|
71
72
|
relations?: Record<string, RelationLookup>;
|
|
@@ -76,4 +77,6 @@ export declare const importRows: (table: Pick<DataTable, "name" | "columns">, ma
|
|
|
76
77
|
export declare const csvLine: (cells: ImportCell[]) => string;
|
|
77
78
|
export { detectSeparator, parseCsv } from './dataCsv';
|
|
78
79
|
export type { ParsedCsv } from './dataCsv';
|
|
80
|
+
export { DATA_CSV_MIME, DATA_SPREADSHEET_MIME, cellFromSheet, isTabularMimeType, readCsvText, readSheet, readTabularFile } from './dataSheet';
|
|
81
|
+
export type { SheetJs, TabularFile } from './dataSheet';
|
|
79
82
|
//# sourceMappingURL=dataImport.d.ts.map
|
package/dist/dataImport.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataImport.d.ts","sourceRoot":"","sources":["../src/dataImport.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dataImport.d.ts","sourceRoot":"","sources":["../src/dataImport.ts"],"names":[],"mappings":"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"}
|
package/dist/dataImport.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseCsv = exports.detectSeparator = exports.csvLine = exports.importRows = exports.importCell = exports.relationKey = exports.matchHeaders = exports.guessColumns = exports.guessColumnType = exports.columnNameFromHeader = exports.normaliseHeader = exports.parseNumber = exports.detectDecimalMark = exports.DATA_IMPORT_BATCH = exports.DATA_IMPORT_SAMPLE_ROWS = exports.toTableInput = exports.isValidIdentifier = exports.identifierIssue = void 0;
|
|
3
|
+
exports.readTabularFile = exports.readSheet = exports.readCsvText = exports.isTabularMimeType = exports.cellFromSheet = exports.DATA_SPREADSHEET_MIME = exports.DATA_CSV_MIME = exports.parseCsv = exports.detectSeparator = exports.csvLine = exports.importRows = exports.importCell = exports.relationKey = exports.matchHeaders = exports.guessColumns = exports.guessColumnType = exports.columnNameFromHeader = exports.normaliseHeader = exports.parseNumber = exports.detectDecimalMark = exports.DATA_IMPORT_BATCH = exports.DATA_IMPORT_SAMPLE_ROWS = exports.toTableInput = exports.isValidIdentifier = exports.identifierIssue = void 0;
|
|
4
4
|
// Reading a spreadsheet into a table: the column types guessed for a new
|
|
5
5
|
// table, the headers matched to an existing one's columns, and each cell
|
|
6
6
|
// checked the way the database will check it. The dashboard's import and
|
|
@@ -405,6 +405,7 @@ const importRows = (table, mapping, rows, options = {}) => {
|
|
|
405
405
|
const values = {};
|
|
406
406
|
const errors = missing.map(c => `${c.name} is required.`);
|
|
407
407
|
const warnings = [];
|
|
408
|
+
const repeated = [];
|
|
408
409
|
mapping.forEach((name, i) => {
|
|
409
410
|
if (name === null)
|
|
410
411
|
return;
|
|
@@ -432,11 +433,12 @@ const importRows = (table, mapping, rows, options = {}) => {
|
|
|
432
433
|
if (first === undefined)
|
|
433
434
|
lines.set(key, line);
|
|
434
435
|
else {
|
|
436
|
+
repeated.push(column.name);
|
|
435
437
|
errors.push(`${column.name}: "${text(row[i])}" is already on line ${first}, and this column takes each value once.`);
|
|
436
438
|
}
|
|
437
439
|
}
|
|
438
440
|
});
|
|
439
|
-
return { index, line, values, errors, warnings };
|
|
441
|
+
return { index, line, values, errors, warnings, repeated };
|
|
440
442
|
});
|
|
441
443
|
};
|
|
442
444
|
exports.importRows = importRows;
|
|
@@ -451,3 +453,11 @@ exports.csvLine = csvLine;
|
|
|
451
453
|
var dataCsv_1 = require("./dataCsv");
|
|
452
454
|
Object.defineProperty(exports, "detectSeparator", { enumerable: true, get: function () { return dataCsv_1.detectSeparator; } });
|
|
453
455
|
Object.defineProperty(exports, "parseCsv", { enumerable: true, get: function () { return dataCsv_1.parseCsv; } });
|
|
456
|
+
var dataSheet_1 = require("./dataSheet");
|
|
457
|
+
Object.defineProperty(exports, "DATA_CSV_MIME", { enumerable: true, get: function () { return dataSheet_1.DATA_CSV_MIME; } });
|
|
458
|
+
Object.defineProperty(exports, "DATA_SPREADSHEET_MIME", { enumerable: true, get: function () { return dataSheet_1.DATA_SPREADSHEET_MIME; } });
|
|
459
|
+
Object.defineProperty(exports, "cellFromSheet", { enumerable: true, get: function () { return dataSheet_1.cellFromSheet; } });
|
|
460
|
+
Object.defineProperty(exports, "isTabularMimeType", { enumerable: true, get: function () { return dataSheet_1.isTabularMimeType; } });
|
|
461
|
+
Object.defineProperty(exports, "readCsvText", { enumerable: true, get: function () { return dataSheet_1.readCsvText; } });
|
|
462
|
+
Object.defineProperty(exports, "readSheet", { enumerable: true, get: function () { return dataSheet_1.readSheet; } });
|
|
463
|
+
Object.defineProperty(exports, "readTabularFile", { enumerable: true, get: function () { return dataSheet_1.readTabularFile; } });
|
|
@@ -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,5 @@
|
|
|
1
|
-
import type { DataCaller, DataDeleteImpact, DataResult, DataSchema, DataTable, DataTableCopy } from './dataTypes';
|
|
1
|
+
import type { DataCaller, DataDeleteImpact, DataFileLinkChange, DataFileLinks, DataFileLinksReplaced, DataResult, DataSchema, DataTable, DataTableCopy, DataTableSync } from './dataTypes';
|
|
2
|
+
import type { SheetSyncArgs } from './dataEngine';
|
|
2
3
|
import type { DataQuery } from './dataQueries';
|
|
3
4
|
import type { DataTrigger, DataTriggerWithSecret, SavedTrigger } from './dataTriggers';
|
|
4
5
|
export type ExportFormat = 'jsonl' | 'csv';
|
|
@@ -45,6 +46,7 @@ export interface DatabaseInfo {
|
|
|
45
46
|
name: string;
|
|
46
47
|
label: string | null;
|
|
47
48
|
columns: number;
|
|
49
|
+
rows: number;
|
|
48
50
|
}[];
|
|
49
51
|
copy: DataTableCopy | null;
|
|
50
52
|
}
|
|
@@ -109,6 +111,10 @@ export interface ProjectDatabaseRpc {
|
|
|
109
111
|
}>;
|
|
110
112
|
describe(caller: DataCaller, args?: unknown): R<unknown>;
|
|
111
113
|
query(caller: DataCaller, args: unknown): R<unknown>;
|
|
114
|
+
eventRow(caller: DataCaller, args: {
|
|
115
|
+
table: string;
|
|
116
|
+
id?: number;
|
|
117
|
+
}): R<Record<string, unknown> | null>;
|
|
112
118
|
write(caller: DataCaller, args: unknown): R<{
|
|
113
119
|
ok: true;
|
|
114
120
|
results: unknown[];
|
|
@@ -117,6 +123,19 @@ export interface ProjectDatabaseRpc {
|
|
|
117
123
|
table: string;
|
|
118
124
|
ids?: number[];
|
|
119
125
|
}): R<DataDeleteImpact>;
|
|
126
|
+
fileLinks(caller: DataCaller, args: {
|
|
127
|
+
uris: string[];
|
|
128
|
+
}): R<DataFileLinks>;
|
|
129
|
+
replaceFileLinks(caller: DataCaller, args: {
|
|
130
|
+
changes: DataFileLinkChange[];
|
|
131
|
+
}): R<DataFileLinksReplaced>;
|
|
132
|
+
syncRows(caller: DataCaller, args: SheetSyncArgs): R<DataTableSync>;
|
|
133
|
+
recordSyncFailure(caller: DataCaller, args: {
|
|
134
|
+
table: string;
|
|
135
|
+
error: string;
|
|
136
|
+
title?: string | null;
|
|
137
|
+
version?: string | null;
|
|
138
|
+
}): R<DataTableSync | null>;
|
|
120
139
|
history(caller: DataCaller, args: {
|
|
121
140
|
table: string;
|
|
122
141
|
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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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ImportCell } from './dataImport';
|
|
2
|
+
export declare const DATA_SPREADSHEET_MIME: RegExp;
|
|
3
|
+
export declare const DATA_CSV_MIME: RegExp;
|
|
4
|
+
export declare const isTabularMimeType: (mimeType: string | null | undefined) => boolean;
|
|
5
|
+
export interface SheetJs {
|
|
6
|
+
read(data: ArrayBuffer, options: Record<string, unknown>): {
|
|
7
|
+
SheetNames: string[];
|
|
8
|
+
Sheets: Record<string, unknown>;
|
|
9
|
+
};
|
|
10
|
+
utils: {
|
|
11
|
+
sheet_to_json<T>(sheet: unknown, options: Record<string, unknown>): T[];
|
|
12
|
+
decode_range(ref: string): {
|
|
13
|
+
s: {
|
|
14
|
+
r: number;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface TabularFile {
|
|
20
|
+
headers: string[];
|
|
21
|
+
rows: ImportCell[][];
|
|
22
|
+
lines: number[];
|
|
23
|
+
}
|
|
24
|
+
export declare const cellFromSheet: (cell: unknown) => ImportCell;
|
|
25
|
+
export declare const readSheet: (XLSX: SheetJs, bytes: ArrayBuffer, uri: string, sheetName?: string | null) => TabularFile;
|
|
26
|
+
export declare const readCsvText: (text: string) => TabularFile;
|
|
27
|
+
export declare const readTabularFile: (file: {
|
|
28
|
+
bytes: ArrayBuffer;
|
|
29
|
+
mimeType: string | null;
|
|
30
|
+
uri: string;
|
|
31
|
+
sheet?: string | null;
|
|
32
|
+
loadSheetJs: () => Promise<SheetJs>;
|
|
33
|
+
}) => Promise<TabularFile>;
|
|
34
|
+
//# sourceMappingURL=dataSheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataSheet.d.ts","sourceRoot":"","sources":["../src/dataSheet.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,eAAO,MAAM,qBAAqB,QACmB,CAAC;AACtD,eAAO,MAAM,aAAa,QAAmC,CAAC;AAG9D,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,GAAG,IAAI,GAAG,SAAS,YAEG,CAAC;AAGzE,MAAM,WAAW,OAAO;IACtB,IAAI,CACF,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B;QACD,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACjC,CAAC;IACF,KAAK,EAAE;QACL,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACxE,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;YAAE,CAAC,EAAE;gBAAE,CAAC,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAC;KACjD,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC;IAErB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAOD,eAAO,MAAM,aAAa,GAAI,MAAM,OAAO,KAAG,UAa7C,CAAC;AAIF,eAAO,MAAM,SAAS,GACpB,MAAM,OAAO,EACb,OAAO,WAAW,EAClB,KAAK,MAAM,EACX,YAAY,MAAM,GAAG,IAAI,KACxB,WAuCF,CAAC;AAGF,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,WAO1C,CAAC;AAKF,eAAO,MAAM,eAAe,GAAU,MAAM;IAC1C,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACrC,KAAG,OAAO,CAAC,WAAW,CAqBtB,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readTabularFile = exports.readCsvText = exports.readSheet = exports.cellFromSheet = exports.isTabularMimeType = exports.DATA_CSV_MIME = exports.DATA_SPREADSHEET_MIME = void 0;
|
|
4
|
+
// Reading a spreadsheet or CSV from the project's knowledge into header and
|
|
5
|
+
// rows, for data-admin's import and a table's sheet sync alike. SheetJS is
|
|
6
|
+
// passed in, so each worker loads it only when a file needs it.
|
|
7
|
+
const dataCsv_1 = require("./dataCsv");
|
|
8
|
+
const dataTypes_1 = require("./dataTypes");
|
|
9
|
+
exports.DATA_SPREADSHEET_MIME = /spreadsheetml|ms-excel|opendocument\.spreadsheet/i;
|
|
10
|
+
exports.DATA_CSV_MIME = /csv|text\/plain|tab-separated/i;
|
|
11
|
+
// Whether a knowledge item can be a table's source.
|
|
12
|
+
const isTabularMimeType = (mimeType) => !!mimeType &&
|
|
13
|
+
(exports.DATA_SPREADSHEET_MIME.test(mimeType) || exports.DATA_CSV_MIME.test(mimeType));
|
|
14
|
+
exports.isTabularMimeType = isTabularMimeType;
|
|
15
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
16
|
+
// A spreadsheet's own date as the text the database reads, as the
|
|
17
|
+
// dashboard's import does: a date alone when it has no time, else a
|
|
18
|
+
// wall-clock time.
|
|
19
|
+
const cellFromSheet = (cell) => {
|
|
20
|
+
if (cell instanceof Date) {
|
|
21
|
+
const date = `${cell.getFullYear()}-${pad(cell.getMonth() + 1)}-${pad(cell.getDate())}`;
|
|
22
|
+
if (!cell.getHours() && !cell.getMinutes() && !cell.getSeconds()) {
|
|
23
|
+
return date;
|
|
24
|
+
}
|
|
25
|
+
return `${date}T${pad(cell.getHours())}:${pad(cell.getMinutes())}:${pad(cell.getSeconds())}`;
|
|
26
|
+
}
|
|
27
|
+
return typeof cell === 'string' ||
|
|
28
|
+
typeof cell === 'number' ||
|
|
29
|
+
typeof cell === 'boolean'
|
|
30
|
+
? cell
|
|
31
|
+
: null;
|
|
32
|
+
};
|
|
33
|
+
exports.cellFromSheet = cellFromSheet;
|
|
34
|
+
// One sheet of an Excel or OpenDocument file: the first unless named.
|
|
35
|
+
// Blank lines are left out.
|
|
36
|
+
const readSheet = (XLSX, bytes, uri, sheetName) => {
|
|
37
|
+
// Only the sheet being read is parsed: a workbook unpacks to many times
|
|
38
|
+
// its size, and a worker has 128 MiB.
|
|
39
|
+
const book = XLSX.read(bytes, {
|
|
40
|
+
cellDates: true,
|
|
41
|
+
dense: true,
|
|
42
|
+
sheets: sheetName ?? 0
|
|
43
|
+
});
|
|
44
|
+
const name = sheetName ?? book.SheetNames[0];
|
|
45
|
+
const sheet = name ? book.Sheets[name] : undefined;
|
|
46
|
+
if (!sheet) {
|
|
47
|
+
throw new dataTypes_1.DataError(`${uri} has no sheet "${sheetName}". Sheets: ${book.SheetNames.join(', ')}.`, 'not_found');
|
|
48
|
+
}
|
|
49
|
+
const all = XLSX.utils.sheet_to_json(sheet, {
|
|
50
|
+
header: 1,
|
|
51
|
+
raw: true,
|
|
52
|
+
defval: null,
|
|
53
|
+
blankrows: true
|
|
54
|
+
});
|
|
55
|
+
// The sheet's range may start below row 1.
|
|
56
|
+
const ref = sheet['!ref'];
|
|
57
|
+
const firstLine = ref ? XLSX.utils.decode_range(ref).s.r + 1 : 1;
|
|
58
|
+
const [header = [], ...body] = all;
|
|
59
|
+
const rows = [];
|
|
60
|
+
const lines = [];
|
|
61
|
+
body.forEach((row, i) => {
|
|
62
|
+
const cells = row.map(exports.cellFromSheet);
|
|
63
|
+
if (cells.every(c => c === null || c === ''))
|
|
64
|
+
return;
|
|
65
|
+
rows.push(cells);
|
|
66
|
+
lines.push(firstLine + 1 + i);
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
headers: header.map(h => (h === null ? '' : String(h))),
|
|
70
|
+
rows,
|
|
71
|
+
lines
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
exports.readSheet = readSheet;
|
|
75
|
+
// A CSV's text, with each row's line as a sheet's would be.
|
|
76
|
+
const readCsvText = (text) => {
|
|
77
|
+
const parsed = (0, dataCsv_1.parseCsv)(text);
|
|
78
|
+
return {
|
|
79
|
+
headers: parsed.headers,
|
|
80
|
+
rows: parsed.rows,
|
|
81
|
+
lines: parsed.lines
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
exports.readCsvText = readCsvText;
|
|
85
|
+
// A stored file, read by its type: a spreadsheet through SheetJS (loaded
|
|
86
|
+
// only then), anything else as CSV text. Over DATA_SHEET_MAX_BYTES it isn't
|
|
87
|
+
// read at all.
|
|
88
|
+
const readTabularFile = async (file) => {
|
|
89
|
+
if (file.bytes.byteLength > dataTypes_1.DATA_SHEET_MAX_BYTES) {
|
|
90
|
+
throw new dataTypes_1.DataError(`${file.uri} is over ${dataTypes_1.DATA_SHEET_MAX_BYTES / (1024 * 1024)} MB.`, 'too_large');
|
|
91
|
+
}
|
|
92
|
+
if (file.mimeType && exports.DATA_SPREADSHEET_MIME.test(file.mimeType)) {
|
|
93
|
+
return (0, exports.readSheet)(await file.loadSheetJs(), file.bytes, file.uri, file.sheet);
|
|
94
|
+
}
|
|
95
|
+
if (!file.mimeType || exports.DATA_CSV_MIME.test(file.mimeType)) {
|
|
96
|
+
return (0, exports.readCsvText)(new TextDecoder().decode(file.bytes));
|
|
97
|
+
}
|
|
98
|
+
throw new dataTypes_1.DataError(`${file.uri} is ${file.mimeType}; a table reads CSV and Excel files.`);
|
|
99
|
+
};
|
|
100
|
+
exports.readTabularFile = readTabularFile;
|
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
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { DataCaller, DataSchema, DataTable } from './dataTypes';
|
|
2
2
|
import type { SqlRunner } from './dataEngine';
|
|
3
|
-
export declare const DATA_TRIGGER_EVENTS: readonly ["insert", "update", "delete"];
|
|
3
|
+
export declare const DATA_TRIGGER_EVENTS: readonly ["insert", "update", "delete", "time"];
|
|
4
4
|
export type DataTriggerEvent = (typeof DATA_TRIGGER_EVENTS)[number];
|
|
5
|
+
export declare const DATA_CHANGE_EVENTS: readonly ["insert", "update", "delete"];
|
|
6
|
+
export declare const DATA_TIME_SCAN_MS = 300000;
|
|
7
|
+
export declare const DATA_TIME_MIN_MINUTES = 5;
|
|
8
|
+
export declare const DATA_TIME_MAX_MINUTES = 43200;
|
|
9
|
+
export declare const DATA_MAX_TIME_TRIGGERS = 10;
|
|
10
|
+
export declare const DATA_TIME_EVENTS_PER_SCAN = 100;
|
|
11
|
+
export declare const DATA_TIME_ROWS_PER_SCAN = 1000;
|
|
12
|
+
export declare const DATA_TIME_EVENTS_PER_DAY = 2000;
|
|
5
13
|
export declare const DATA_TRIGGER_ACTIONS: readonly ["function", "webhook", "chat", "email", "customer"];
|
|
6
14
|
export type DataTriggerActionType = (typeof DATA_TRIGGER_ACTIONS)[number];
|
|
7
15
|
export declare const DATA_MAX_TRIGGERS = 50;
|
|
@@ -54,11 +62,16 @@ export type DataTriggerAction = {
|
|
|
54
62
|
text: string;
|
|
55
63
|
template?: DataTriggerTemplate;
|
|
56
64
|
};
|
|
65
|
+
export interface DataTriggerSchedule {
|
|
66
|
+
column: string;
|
|
67
|
+
minutes: number;
|
|
68
|
+
}
|
|
57
69
|
export interface DataTriggerInput {
|
|
58
70
|
name?: string;
|
|
59
71
|
description?: string | null;
|
|
60
72
|
table: string;
|
|
61
73
|
on: DataTriggerEvent;
|
|
74
|
+
after?: DataTriggerSchedule | null;
|
|
62
75
|
when?: DataTriggerCondition | null;
|
|
63
76
|
enabled?: boolean;
|
|
64
77
|
replace?: boolean;
|
|
@@ -86,6 +99,7 @@ export interface DataTrigger {
|
|
|
86
99
|
description: string | null;
|
|
87
100
|
table: string;
|
|
88
101
|
on: DataTriggerEvent;
|
|
102
|
+
after: DataTriggerSchedule | null;
|
|
89
103
|
when: DataTriggerCondition | null;
|
|
90
104
|
action: DataTriggerAction;
|
|
91
105
|
enabled: boolean;
|
|
@@ -112,8 +126,11 @@ export interface DataTriggerEventMessage {
|
|
|
112
126
|
actor: string | null;
|
|
113
127
|
depth: number;
|
|
114
128
|
at: string;
|
|
129
|
+
dueAt?: string;
|
|
115
130
|
truncated?: true;
|
|
131
|
+
participantId?: string;
|
|
116
132
|
error?: string;
|
|
133
|
+
turnedOff?: true;
|
|
117
134
|
}
|
|
118
135
|
/**
|
|
119
136
|
* Whether a change matches a condition. A missing side counts as all null:
|
|
@@ -128,12 +145,28 @@ export declare const conditionMatches: (when: DataTriggerCondition | null | unde
|
|
|
128
145
|
* senders send it as text.
|
|
129
146
|
*/
|
|
130
147
|
export declare const renderTriggerText: (text: string, row: Record<string, unknown> | null) => string;
|
|
148
|
+
export interface DataTriggerCustomerMessage {
|
|
149
|
+
text: string;
|
|
150
|
+
template: {
|
|
151
|
+
name: string;
|
|
152
|
+
language: string;
|
|
153
|
+
params: string[];
|
|
154
|
+
} | null;
|
|
155
|
+
}
|
|
156
|
+
export declare const renderCustomerMessage: (action: {
|
|
157
|
+
text: string;
|
|
158
|
+
template?: DataTriggerTemplate;
|
|
159
|
+
}, row: Record<string, unknown> | null) => DataTriggerCustomerMessage;
|
|
160
|
+
export declare const normaliseCustomerAction: (schema: DataSchema, tableName: string, value: unknown) => Extract<DataTriggerAction, {
|
|
161
|
+
type: "customer";
|
|
162
|
+
}>;
|
|
131
163
|
interface NormalisedTrigger {
|
|
132
164
|
name: string;
|
|
133
165
|
defaultName: boolean;
|
|
134
166
|
description: string | null;
|
|
135
167
|
table: DataTable;
|
|
136
168
|
on: DataTriggerEvent;
|
|
169
|
+
after: DataTriggerSchedule | null;
|
|
137
170
|
when: DataTriggerCondition | null;
|
|
138
171
|
action: DataTriggerAction;
|
|
139
172
|
enabled: boolean | null;
|
|
@@ -173,6 +206,13 @@ export declare const changeCaptureTriggers: (table: Pick<DataTable, "id" | "name
|
|
|
173
206
|
sql: string;
|
|
174
207
|
}[];
|
|
175
208
|
export declare const ensureChangeCapture: (runner: SqlRunner, table: DataTable) => void;
|
|
209
|
+
/**
|
|
210
|
+
* A row as a trigger event carries it, read from the table: `id`, or the
|
|
211
|
+
* newest row. Null when there is none. A test send and a run whose event
|
|
212
|
+
* was too large to carry its row build their message from it, so it reads
|
|
213
|
+
* as it does for the event, system fields and the customer included.
|
|
214
|
+
*/
|
|
215
|
+
export declare const readEventRow: (runner: SqlRunner, schema: DataSchema, tableName: string, id?: number) => Record<string, unknown> | null;
|
|
176
216
|
/**
|
|
177
217
|
* Turns the changes a write captured into events, inside the write's
|
|
178
218
|
* transaction. A trigger never matches the writes of a run it started
|
|
@@ -188,9 +228,9 @@ export declare const deleteOutbox: (runner: SqlRunner, throughSeq: number) => vo
|
|
|
188
228
|
export declare const outboxSize: (runner: SqlRunner) => number;
|
|
189
229
|
export declare const clearOutbox: (runner: SqlRunner, before: string) => number;
|
|
190
230
|
/**
|
|
191
|
-
* The triggers whose condition
|
|
192
|
-
* is refused while any does, since they are only checked
|
|
193
|
-
* would quietly stop matching.
|
|
231
|
+
* The triggers whose condition, {{field}} texts or time column name a
|
|
232
|
+
* column. Dropping it is refused while any does, since they are only checked
|
|
233
|
+
* when saved and would quietly stop matching.
|
|
194
234
|
*/
|
|
195
235
|
export declare const triggersUsingColumn: (runner: SqlRunner, tableId: number, column: string) => string[];
|
|
196
236
|
/**
|
|
@@ -199,5 +239,27 @@ export declare const triggersUsingColumn: (runner: SqlRunner, tableId: number, c
|
|
|
199
239
|
* file until it is changed to match. Returns the triggers changed.
|
|
200
240
|
*/
|
|
201
241
|
export declare const renameColumnInTriggers: (runner: SqlRunner, tableId: number, from: string, to: string) => string[];
|
|
242
|
+
export declare const timeTriggersCountingFrom: (runner: SqlRunner, tableId: number, column: string) => string[];
|
|
243
|
+
/**
|
|
244
|
+
* Indexes the columns time triggers count from, and drops the ones no time
|
|
245
|
+
* trigger uses any more. A column the table already indexes (filterable or
|
|
246
|
+
* unique) needs nothing more. Cheap, so every scan runs it too: a table
|
|
247
|
+
* rebuilt for a column change loses the index and gets it back.
|
|
248
|
+
*/
|
|
249
|
+
export declare const syncTimeIndexes: (runner: SqlRunner) => void;
|
|
250
|
+
export declare const hasTimeTriggers: (runner: SqlRunner) => boolean;
|
|
251
|
+
export interface TimeScanResult {
|
|
252
|
+
events: number;
|
|
253
|
+
disabled: {
|
|
254
|
+
name: string;
|
|
255
|
+
reason: string;
|
|
256
|
+
}[];
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* One scan: for each enabled time trigger, the rows that came due since its
|
|
260
|
+
* last scan, matching its `when`, not fired for that due time before, become
|
|
261
|
+
* events in the outbox. One transaction, so a crash fires nothing twice.
|
|
262
|
+
*/
|
|
263
|
+
export declare const scanTimeTriggers: (runner: SqlRunner, schema: DataSchema, now?: Date) => TimeScanResult;
|
|
202
264
|
export {};
|
|
203
265
|
//# sourceMappingURL=dataTriggers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataTriggers.d.ts","sourceRoot":"","sources":["../src/dataTriggers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dataTriggers.d.ts","sourceRoot":"","sources":["../src/dataTriggers.ts"],"names":[],"mappings":"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"}
|