@ganju/utils 0.0.21 → 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/data.d.ts +4 -4
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +16 -2
- package/dist/dataApi.d.ts +32 -2
- package/dist/dataApi.d.ts.map +1 -1
- package/dist/dataApi.js +11 -1
- package/dist/dataCompiler.d.ts +1 -0
- package/dist/dataCompiler.d.ts.map +1 -1
- package/dist/dataCompiler.js +3 -2
- package/dist/dataEngine.d.ts +17 -1
- package/dist/dataEngine.d.ts.map +1 -1
- package/dist/dataEngine.js +368 -10
- package/dist/dataImport.d.ts +3 -0
- package/dist/dataImport.d.ts.map +1 -1
- package/dist/dataImport.js +12 -2
- package/dist/dataRpc.d.ts +9 -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/dataTriggers.d.ts +43 -4
- package/dist/dataTriggers.d.ts.map +1 -1
- package/dist/dataTriggers.js +401 -19
- package/dist/dataTypes.d.ts +23 -0
- package/dist/dataTypes.d.ts.map +1 -1
- package/dist/dataTypes.js +15 -1
- package/dist/index.d.ts +35 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/localizeDataError.d.ts.map +1 -1
- package/dist/localizeDataError.js +45 -1
- package/dist/schema.d.ts +33 -4
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +26 -3
- package/dist/untrustedContent.d.ts +7 -0
- package/dist/untrustedContent.d.ts.map +1 -1
- package/dist/untrustedContent.js +13 -1
- package/package.json +1 -1
- package/src/data.ts +19 -3
- package/src/dataApi.ts +14 -2
- package/src/dataCompiler.ts +4 -1
- package/src/dataEngine.ts +485 -10
- package/src/dataImport.ts +16 -1
- package/src/dataRpc.ts +10 -1
- package/src/dataSheet.ts +147 -0
- package/src/dataTriggers.ts +528 -19
- package/src/dataTypes.ts +46 -0
- package/src/index.ts +4 -0
- package/src/localizeDataError.ts +82 -1
- package/src/schema.ts +27 -3
- package/src/untrustedContent.ts +15 -0
package/src/data.ts
CHANGED
|
@@ -65,9 +65,12 @@ export {
|
|
|
65
65
|
writeReachesCopy,
|
|
66
66
|
assertActor,
|
|
67
67
|
assertWritable,
|
|
68
|
+
assertNotSynced,
|
|
69
|
+
syncRows,
|
|
70
|
+
recordSyncFailure,
|
|
68
71
|
exportRows
|
|
69
72
|
} from './dataEngine';
|
|
70
|
-
export type { SqlRow, SqlRunner } from './dataEngine';
|
|
73
|
+
export type { SqlRow, SqlRunner, SheetSyncArgs } from './dataEngine';
|
|
71
74
|
export { adviseIndexes, adviceDoubled } from './dataIndexAdvice';
|
|
72
75
|
export type {
|
|
73
76
|
IndexAdviceCandidate,
|
|
@@ -118,6 +121,7 @@ export {
|
|
|
118
121
|
export type { DataToolDefinition, DataAdminAction } from './dataTools';
|
|
119
122
|
export {
|
|
120
123
|
DATA_TRIGGER_EVENTS,
|
|
124
|
+
DATA_CHANGE_EVENTS,
|
|
121
125
|
DATA_TRIGGER_ACTIONS,
|
|
122
126
|
DATA_MAX_TRIGGERS,
|
|
123
127
|
DATA_TRIGGER_MAX_DEPTH,
|
|
@@ -125,6 +129,12 @@ export {
|
|
|
125
129
|
DATA_TRIGGER_MAX_RATE,
|
|
126
130
|
DATA_OUTBOX_BATCH,
|
|
127
131
|
DATA_TRIGGER_MAX_MESSAGE_BYTES,
|
|
132
|
+
DATA_TIME_SCAN_MS,
|
|
133
|
+
DATA_TIME_MIN_MINUTES,
|
|
134
|
+
DATA_TIME_MAX_MINUTES,
|
|
135
|
+
DATA_MAX_TIME_TRIGGERS,
|
|
136
|
+
DATA_TIME_EVENTS_PER_SCAN,
|
|
137
|
+
DATA_TIME_EVENTS_PER_DAY,
|
|
128
138
|
utf8Bytes,
|
|
129
139
|
conditionMatches,
|
|
130
140
|
renderTriggerText,
|
|
@@ -144,7 +154,11 @@ export {
|
|
|
144
154
|
outboxSize,
|
|
145
155
|
clearOutbox,
|
|
146
156
|
triggersUsingColumn,
|
|
147
|
-
renameColumnInTriggers
|
|
157
|
+
renameColumnInTriggers,
|
|
158
|
+
timeTriggersCountingFrom,
|
|
159
|
+
syncTimeIndexes,
|
|
160
|
+
hasTimeTriggers,
|
|
161
|
+
scanTimeTriggers
|
|
148
162
|
} from './dataTriggers';
|
|
149
163
|
export type {
|
|
150
164
|
DataTrigger,
|
|
@@ -155,8 +169,10 @@ export type {
|
|
|
155
169
|
DataTriggerEvent,
|
|
156
170
|
DataTriggerEventMessage,
|
|
157
171
|
DataTriggerInput,
|
|
172
|
+
DataTriggerSchedule,
|
|
158
173
|
DataTriggerTemplate,
|
|
159
174
|
DataTriggerTest,
|
|
160
175
|
DataTriggerWithSecret,
|
|
161
|
-
SavedTrigger
|
|
176
|
+
SavedTrigger,
|
|
177
|
+
TimeScanResult
|
|
162
178
|
} from './dataTriggers';
|
package/src/dataApi.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface DataApiRoute {
|
|
|
27
27
|
query?: z.ZodObject;
|
|
28
28
|
// What a 200/201 answers with, in a sentence.
|
|
29
29
|
returns: string;
|
|
30
|
-
status?: 200 | 201;
|
|
30
|
+
status?: 200 | 201 | 202;
|
|
31
31
|
// Answers with a file instead of JSON.
|
|
32
32
|
file?: boolean;
|
|
33
33
|
}
|
|
@@ -179,9 +179,21 @@ export const DATA_API_ROUTES = {
|
|
|
179
179
|
path: '/table/:table',
|
|
180
180
|
tag: 'Tables',
|
|
181
181
|
summary: 'Rename a table or change its settings',
|
|
182
|
+
description:
|
|
183
|
+
"`source` (`{ uri, sheet?, key }`) keeps the table's rows in step with a spreadsheet or CSV in the project's knowledge, matched by `key`, a unique column: the sheet wins, and row writes to the table are refused until `source` is set back to null. It syncs when the file changes and from `POST …/sync`; `sync` on the table says how the last one went.",
|
|
182
184
|
body: DATA_TABLE_PATCH,
|
|
183
185
|
returns: '{ table }'
|
|
184
186
|
},
|
|
187
|
+
syncTable: {
|
|
188
|
+
method: 'post',
|
|
189
|
+
path: '/table/:table/sync',
|
|
190
|
+
tag: 'Tables',
|
|
191
|
+
summary: 'Sync a table from its sheet now',
|
|
192
|
+
description:
|
|
193
|
+
"Queues a sync of a table that has a `source`: a Google Drive or OneDrive file is fetched again first if it changed. New keys are inserted, rows that differ updated (actor `system:sheet-sync`, so triggers fire), rows whose key is gone deleted. A sheet that doesn't fit (a missing key column, a repeated key, a value a column won't take) changes nothing; the table's `sync` says why.",
|
|
194
|
+
returns: '{ queued: true }',
|
|
195
|
+
status: 202
|
|
196
|
+
},
|
|
185
197
|
dropTable: {
|
|
186
198
|
method: 'delete',
|
|
187
199
|
path: '/table/:table',
|
|
@@ -347,7 +359,7 @@ export const DATA_API_ROUTES = {
|
|
|
347
359
|
tag: 'Triggers',
|
|
348
360
|
summary: 'Save a trigger',
|
|
349
361
|
description:
|
|
350
|
-
'Runs one action when rows of `table` are inserted, updated or deleted, and `when` holds: `{ "status": { "changedTo": "READY" } }` fires on the transition only; `changedFrom`, `changed: true` and `equals` test a column too, and `all` / `any` combine them. The action is one of `function` (a function of this project, given `{ event, table, row, previous, actor, eventId, triggerId }`), `webhook` (an https URL, sent a POST signed in `x-ganju-signature`), `chat` (`{ channelId, chatId, text }`), `email` (`{ to, subject, text }`) or `customer` (`{ text, template? }`, to the row\'s customer on a customer-scoped table). Texts take `{{field}}` from the row, inserted as plain text. Saving under an existing name replaces it, unless `replace` is false; with no `name`, it always creates a new trigger, named from the table, event and action and numbered past those taken. Left out, `enabled` keeps a saved trigger on or off as it was. A new webhook answers with its signing `secret`, shown this once. An `email` goes to the organization\'s members; any other address is sent a link to confirm first, and those still waiting come back as `confirming`. Delivery is at least once: every event carries an `eventId`.',
|
|
362
|
+
'Runs one action when rows of `table` are inserted, updated or deleted, and `when` holds: `{ "status": { "changedTo": "READY" } }` fires on the transition only; `changedFrom`, `changed: true` and `equals` test a column too, and `all` / `any` combine them. With `"on": "time"` it fires instead once a row comes due, with nothing written: `after` is `{ column, minutes }`, the column `created_at`, `updated_at` or a date or datetime column (a date counts from midnight in the database\'s time zone) and `minutes` 5 to 43,200, negative on a date or datetime for before it. Its `when` tests `equals` only, read when the row comes due; rows already due when it is saved don\'t fire, and each row fires once per due time (an `updated_at` trigger again after the next change). Due rows are looked for every 5 minutes, up to 100 events per trigger per scan; a database holds up to 10 time triggers, and the database\'s time triggers share 2,000 events a day (UTC): past that, each time trigger with another row due that day is turned off and the organization\'s admins are emailed. A time trigger is also turned off when its runs are paused (the plan no longer includes Data, or the month\'s trigger runs reached the plan\'s limit). The action is one of `function` (a function of this project, given `{ event, table, row, previous, actor, eventId, triggerId, dueAt? }`), `webhook` (an https URL, sent a POST signed in `x-ganju-signature`), `chat` (`{ channelId, chatId, text }`), `email` (`{ to, subject, text }`) or `customer` (`{ text, template? }`, to the row\'s customer on a customer-scoped table). Texts take `{{field}}` from the row, inserted as plain text. Saving under an existing name replaces it, unless `replace` is false; with no `name`, it always creates a new trigger, named from the table, event and action and numbered past those taken. Left out, `enabled` keeps a saved trigger on or off as it was. A new webhook answers with its signing `secret`, shown this once. An `email` goes to the organization\'s members; any other address is sent a link to confirm first, and those still waiting come back as `confirming`. Delivery is at least once: every event carries an `eventId`.',
|
|
351
363
|
body: DATA_TRIGGER_INPUT,
|
|
352
364
|
returns: '{ trigger, secret?, confirming? }',
|
|
353
365
|
status: 201
|
package/src/dataCompiler.ts
CHANGED
|
@@ -194,7 +194,10 @@ const LOCAL_DATETIME =
|
|
|
194
194
|
// "2026-10-21T15:00:00" with no offset, read as a wall-clock time in
|
|
195
195
|
// `timeZone` (UTC without one). `new Date()` would read it in the server's
|
|
196
196
|
// zone: UTC on Workers, the developer's own zone on a laptop.
|
|
197
|
-
const localDatetime = (
|
|
197
|
+
export const localDatetime = (
|
|
198
|
+
value: string,
|
|
199
|
+
timeZone?: string
|
|
200
|
+
): Date | null => {
|
|
198
201
|
const m = LOCAL_DATETIME.exec(value.trim());
|
|
199
202
|
if (!m) return null;
|
|
200
203
|
const [year, month, day, hour, minute, second] = m
|