pipework 0.132.0 → 0.133.0
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/CHANGELOG.md +4 -0
- package/REFERENCE.md +10 -0
- package/dist/data/write/audit/final-select.d.ts.map +1 -1
- package/dist/data/write/audit/final-select.js +4 -1
- package/dist/data/write/audit/final-select.js.map +1 -1
- package/dist/data/write/audit/verb-insert.d.ts.map +1 -1
- package/dist/data/write/audit/verb-insert.js +2 -1
- package/dist/data/write/audit/verb-insert.js.map +1 -1
- package/dist/data/write/conflict.d.ts +8 -0
- package/dist/data/write/conflict.d.ts.map +1 -0
- package/dist/data/write/conflict.js +39 -0
- package/dist/data/write/conflict.js.map +1 -0
- package/dist/data/write/execute.d.ts.map +1 -1
- package/dist/data/write/execute.js +40 -8
- package/dist/data/write/execute.js.map +1 -1
- package/dist/data/write/insert.d.ts +10 -0
- package/dist/data/write/insert.d.ts.map +1 -1
- package/dist/data/write/insert.js +18 -0
- package/dist/data/write/insert.js.map +1 -1
- package/dist/data/write/state.d.ts +5 -0
- package/dist/data/write/state.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.133.0
|
|
4
|
+
|
|
5
|
+
- **Added: `pipe.insert(T).values(...).onConflictDoNothing({ target? })`** (#636). An insert leaves a row that conflicts with an existing one and writes the rest, so two writers creating the same keyed row no longer need a savepoint and a check of Postgres's error code. `target` is field keys; without it a conflict on any unique or exclusion constraint is skipped. `.returning()` yields only the rows written. Under `@touches`, each row written gets its `create` audit row and a skipped row gets none (no read-touch row either). When a traced insert skips at least one row, an `external:pipework.insert.conflict` step under the open step records `{ table, target, attempted, written, skipped }`.
|
|
6
|
+
|
|
3
7
|
## 0.132.0
|
|
4
8
|
|
|
5
9
|
- **Added: a low-balance line per tenant, its state readable, and the crossing inside the operation's transaction** (#634). Each tenant can set its own line with `credits.setLowBalanceLine(line)` / `setLowBalanceLineFor(tenantId, line)`; `null` goes back to `lowBalanceThreshold`, which stays the default for tenants that set none. The line is read in each operation's transaction, so a change applies to the next operation, and a change that puts the current balance under the new line counts as a crossing. Changes are audited (`CreditAccount` `set_low_balance_line`, with before and after) into the open trace step. `credits.lowBalance()` / `lowBalanceFor(tenantId)` return `{ line, source, available, below }` for any tenant member. New `onLowBalanceCrossed({ tenantId, available, line })` is awaited inside the transaction of the operation that crossed, in a Flow with the operation's tenant where `pipe()` is that transaction, so what the app writes commits or rolls back with it; if it throws, the operation rolls back. `onLowBalance` still fires as before, now against each tenant's line. `expire()` now signals a crossing too. Upgrading: generate a migration — the new `credit_account` table joins the credits tables.
|
package/REFERENCE.md
CHANGED
|
@@ -787,6 +787,16 @@ Pipework-owned UPDATE builder — the only consumer-facing way to update pipewor
|
|
|
787
787
|
|
|
788
788
|
Pipework-owned INSERT builder — the only consumer-facing way to insert into pipework-managed tables (Q8). A list of any size is split into statements under Postgres's parameter limit, in one transaction.
|
|
789
789
|
|
|
790
|
+
`.onConflictDoNothing({ target? })` inserts the rows that do not conflict and leaves the rows that do. `target` is field keys; without it any unique or exclusion conflict is skipped, and an empty `target` or an unknown key throws. `.returning()` yields only the rows written, so a fully skipped insert returns `[]`.
|
|
791
|
+
|
|
792
|
+
```ts
|
|
793
|
+
// two writers, one keyed row: the second resolves without error and the row keeps the first's values
|
|
794
|
+
await pipe.insert(Item).values({ key: 'a', other: 'first' }).onConflictDoNothing({ target: ['key'] })
|
|
795
|
+
await pipe.insert(Item).values({ key: 'a', other: 'second' }).onConflictDoNothing({ target: ['key'] })
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
Under `@touches` each row written gets its `create` audit row and a skipped row gets none (no read-touch row either). When at least one row is skipped in a traced flow, one `external:pipework.insert.conflict` step is recorded under the open step with `{ table, target, attempted, written, skipped }` (summed across chunks); nothing is recorded when every row is written.
|
|
799
|
+
|
|
790
800
|
### `pipe.delete`
|
|
791
801
|
|
|
792
802
|
Pipework-owned DELETE builder — the only consumer-facing way to delete from pipework-managed tables (Q8).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"final-select.d.ts","sourceRoot":"","sources":["../../../../src/data/write/audit/final-select.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,GAAG,
|
|
1
|
+
{"version":3,"file":"final-select.d.ts","sourceRoot":"","sources":["../../../../src/data/write/audit/final-select.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,GAAG,CAmB1E;AAED,sGAAsG;AACtG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAIxE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAA;CAAE,CAEhH"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Builds the final SELECT of the CTE statement — the row(s) the caller sees.
|
|
2
2
|
// Mirrors the shape `vanilla DML` would have produced for the same `returning`:
|
|
3
|
-
// no `returning` → no rows; `returning('all')` → SELECT *; per-key projection
|
|
3
|
+
// no `returning` → no rows (one placeholder row per written row under onConflict); `returning('all')` → SELECT *; per-key projection
|
|
4
4
|
// → aliased column list. Reads from the verb's post-image CTE (`inserted` /
|
|
5
5
|
// `updated` / `deleted` / `upserted`).
|
|
6
6
|
import { sql } from '../../db/sql.js';
|
|
@@ -10,6 +10,9 @@ export function buildFinalSelect(state, sourceCte) {
|
|
|
10
10
|
const source = quoteIdentifier(sourceCte, 'CTE alias');
|
|
11
11
|
const returning = state.returning ?? null;
|
|
12
12
|
if (returning === null) {
|
|
13
|
+
// Under onConflictDoNothing the rows written are counted from the rows returned.
|
|
14
|
+
if (state.onConflict !== undefined)
|
|
15
|
+
return sql.raw(`SELECT 1 FROM ${source}`);
|
|
13
16
|
return sql.raw(`SELECT 1 FROM ${source} WHERE FALSE`);
|
|
14
17
|
}
|
|
15
18
|
if (returning === 'all') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"final-select.js","sourceRoot":"","sources":["../../../../src/data/write/audit/final-select.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gFAAgF;AAChF,
|
|
1
|
+
{"version":3,"file":"final-select.js","sourceRoot":"","sources":["../../../../src/data/write/audit/final-select.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gFAAgF;AAChF,qIAAqI;AACrI,4EAA4E;AAC5E,uCAAuC;AAEvC,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAIrD,MAAM,UAAU,gBAAgB,CAAC,KAAiB,EAAE,SAAiB;IACnE,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IACtD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,IAAI,CAAA;IACzC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,iFAAiF;QACjF,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;YAAE,OAAO,GAAG,CAAC,GAAG,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAA;QAC7E,OAAO,GAAG,CAAC,GAAG,CAAC,iBAAiB,MAAM,cAAc,CAAC,CAAA;IACvD,CAAC;IACD,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,GAAG,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAA;IAC3C,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAA;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QACxB,MAAM,QAAQ,GAAG,eAAe,CAAC,kBAAkB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAA;QACzF,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;QACnD,OAAO,GAAG,MAAM,IAAI,QAAQ,OAAO,KAAK,EAAE,CAAA;IAC5C,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACb,OAAO,GAAG,CAAC,GAAG,CAAC,UAAU,IAAI,SAAS,MAAM,EAAE,CAAC,CAAA;AACjD,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,KAAc;IAC9D,MAAM,IAAI,GAAI,KAAmC,EAAE,IAAI,CAAA;IACvD,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC5D,OAAO,YAAY,CAAC,KAAK,CAAC,CAAA;AAC5B,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,YAAY,IAAI,KAAK,CAAA;AAC7E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verb-insert.d.ts","sourceRoot":"","sources":["../../../../src/data/write/audit/verb-insert.ts"],"names":[],"mappings":"AAOA,OAAO,EAAwC,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"verb-insert.d.ts","sourceRoot":"","sources":["../../../../src/data/write/audit/verb-insert.ts"],"names":[],"mappings":"AAOA,OAAO,EAAwC,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAIjG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAG7C,KAAK,KAAK,GAAG,GAAG,CAAA;AAEhB,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,kBAAkB,GAAG,GAAG,CAkB7F"}
|
|
@@ -7,11 +7,12 @@ import { buildTraceSafeProjection } from './projection.js';
|
|
|
7
7
|
import { buildAuditInserts, buildEntityIdExpr } from './audit-select.js';
|
|
8
8
|
import { AUDIT_COLUMNS_SQL } from './audit-columns.js';
|
|
9
9
|
import { buildFinalSelect } from './final-select.js';
|
|
10
|
+
import { applyOnConflict } from '../conflict.js';
|
|
10
11
|
export function compileInsertAudit(db, state, ctx) {
|
|
11
12
|
// `.getSQL()` strips the auto-paren drizzle adds around SQLWrapper builders
|
|
12
13
|
// when they are templated — we add explicit parens at the CTE boundary so
|
|
13
14
|
// the WITH clause keeps a uniform shape across verbs.
|
|
14
|
-
const inner = db.insert(state.table).values(state.values ?? []).returning().getSQL();
|
|
15
|
+
const inner = applyOnConflict(db.insert(state.table).values(state.values ?? []), state).returning().getSQL();
|
|
15
16
|
const after = buildTraceSafeProjection(state.table, 'inserted') ?? sql `NULL::jsonb`;
|
|
16
17
|
const auditSelect = buildAuditInserts(ctx, sql `FROM inserted`, buildEntityIdExpr(state.table, 'inserted'), sql `NULL::jsonb`, after);
|
|
17
18
|
const finalSelect = buildFinalSelect(state, 'inserted');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verb-insert.js","sourceRoot":"","sources":["../../../../src/data/write/audit/verb-insert.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yEAAyE;AACzE,sEAAsE;AACtE,qBAAqB;AAErB,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AACrC,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAA2B,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"verb-insert.js","sourceRoot":"","sources":["../../../../src/data/write/audit/verb-insert.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yEAAyE;AACzE,sEAAsE;AACtE,qBAAqB;AAErB,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AACrC,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAA2B,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAOhD,MAAM,UAAU,kBAAkB,CAAC,EAAS,EAAE,KAAiB,EAAE,GAAuB;IACtF,4EAA4E;IAC5E,0EAA0E;IAC1E,sDAAsD;IACtD,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,CAAA;IAC5G,MAAM,KAAK,GAAG,wBAAwB,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,GAAG,CAAA,aAAa,CAAA;IACnF,MAAM,WAAW,GAAG,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAA,eAAe,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,GAAG,CAAA,aAAa,EAAE,KAAK,CAAC,CAAA;IACnI,MAAM,WAAW,GAAG,gBAAgB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IAEvD,OAAO,GAAG,CAAA;wBACY,KAAK;;oCAEO,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACtD,WAAW;;;MAGb,WAAW;GACd,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WriteState } from './state.js';
|
|
2
|
+
type AnyChain = any;
|
|
3
|
+
/** Applies the state's `ON CONFLICT DO NOTHING` to an insert chain; the chain is returned unchanged when the state has none. */
|
|
4
|
+
export declare function applyOnConflict(q: AnyChain, state: WriteState): AnyChain;
|
|
5
|
+
/** Records the rows an `onConflictDoNothing` insert skipped; nothing when none were. */
|
|
6
|
+
export declare function reportSkipped(state: WriteState, written: number): void;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=conflict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.d.ts","sourceRoot":"","sources":["../../../src/data/write/conflict.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG5C,KAAK,QAAQ,GAAG,GAAG,CAAA;AAEnB,gIAAgI;AAChI,wBAAgB,eAAe,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,QAAQ,CAgBxE;AAED,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAatE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// `ON CONFLICT DO NOTHING` on `pipe.insert`: the target lookup shared by the
|
|
2
|
+
// vanilla and audited paths, and the trace event naming the rows left alone.
|
|
3
|
+
import { event } from '../../trace/external/record.js';
|
|
4
|
+
/** Applies the state's `ON CONFLICT DO NOTHING` to an insert chain; the chain is returned unchanged when the state has none. */
|
|
5
|
+
export function applyOnConflict(q, state) {
|
|
6
|
+
const onConflict = state.onConflict;
|
|
7
|
+
if (onConflict === undefined)
|
|
8
|
+
return q;
|
|
9
|
+
if (onConflict.target === undefined)
|
|
10
|
+
return q.onConflictDoNothing();
|
|
11
|
+
const target = onConflict.target.map(key => {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- DefinedTable columns are indexed by field key; the lookup is validated here
|
|
13
|
+
const col = state.table[key];
|
|
14
|
+
if (col === undefined) {
|
|
15
|
+
throw new Error(`pipe.insert: onConflictDoNothing target "${key}" is not a field of "${state.table.$name}". ` +
|
|
16
|
+
`Use a field key declared on the table.`);
|
|
17
|
+
}
|
|
18
|
+
return col;
|
|
19
|
+
});
|
|
20
|
+
return q.onConflictDoNothing({ target });
|
|
21
|
+
}
|
|
22
|
+
/** Records the rows an `onConflictDoNothing` insert skipped; nothing when none were. */
|
|
23
|
+
export function reportSkipped(state, written) {
|
|
24
|
+
if (state.onConflict === undefined)
|
|
25
|
+
return;
|
|
26
|
+
const attempted = state.values?.length ?? 0;
|
|
27
|
+
if (written >= attempted)
|
|
28
|
+
return;
|
|
29
|
+
event('pipework.insert.conflict', {
|
|
30
|
+
capture: {
|
|
31
|
+
table: state.table.$name,
|
|
32
|
+
target: state.onConflict.target ?? null,
|
|
33
|
+
attempted,
|
|
34
|
+
written,
|
|
35
|
+
skipped: attempted - written,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=conflict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.js","sourceRoot":"","sources":["../../../src/data/write/conflict.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6EAA6E;AAE7E,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAA;AAMtD,gIAAgI;AAChI,MAAM,UAAU,eAAe,CAAC,CAAW,EAAE,KAAiB;IAC5D,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAA;IACnC,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,CAAC,CAAA;IACtC,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC,mBAAmB,EAAE,CAAA;IACnE,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;QACzC,6IAA6I;QAC7I,MAAM,GAAG,GAAI,KAAK,CAAC,KAAa,CAAC,GAAG,CAAC,CAAA;QACrC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,4CAA4C,GAAG,wBAAwB,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK;gBAC7F,wCAAwC,CACzC,CAAA;QACH,CAAC;QACD,OAAO,GAAc,CAAA;IACvB,CAAC,CAAC,CAAA;IACF,OAAO,CAAC,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;AAC1C,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,aAAa,CAAC,KAAiB,EAAE,OAAe;IAC9D,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;QAAE,OAAM;IAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAA;IAC3C,IAAI,OAAO,IAAI,SAAS;QAAE,OAAM;IAChC,KAAK,CAAC,0BAA0B,EAAE;QAChC,OAAO,EAAE;YACP,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK;YACxB,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI;YACvC,SAAS;YACT,OAAO;YACP,OAAO,EAAE,SAAS,GAAG,OAAO;SAC7B;KACF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/data/write/execute.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/data/write/execute.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AA0B5C,wBAAsB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CA0CtE"}
|
|
@@ -20,6 +20,7 @@ import { touchesForTable } from './audit/touch-match.js';
|
|
|
20
20
|
import { decodeReturning } from './audit/decode-returning.js';
|
|
21
21
|
import { resolveActorId } from './audit/actor.js';
|
|
22
22
|
import { getTableColumns } from '../query/index.js';
|
|
23
|
+
import { applyOnConflict, reportSkipped } from './conflict.js';
|
|
23
24
|
/**
|
|
24
25
|
* postgres.js refuses a statement with more than 65,534 parameters. A bulk
|
|
25
26
|
* insert/upsert is split so each statement binds at most this many, counting
|
|
@@ -61,6 +62,8 @@ export async function executeWrite(state) {
|
|
|
61
62
|
const rows = await rawDb.execute(stmt);
|
|
62
63
|
for (const touch of matched)
|
|
63
64
|
stepCtx.markWrote(touch);
|
|
65
|
+
if (state.onConflict !== undefined)
|
|
66
|
+
reportSkipped(state, Array.isArray(rows) ? rows.length : 0);
|
|
64
67
|
return decodeReturning(state, rows);
|
|
65
68
|
}
|
|
66
69
|
}
|
|
@@ -106,29 +109,40 @@ async function executeChunkedWrite(state, size) {
|
|
|
106
109
|
const allValues = state.values ?? [];
|
|
107
110
|
const collectsRows = state.returning !== undefined && state.returning !== null;
|
|
108
111
|
const collected = [];
|
|
112
|
+
let written = 0;
|
|
109
113
|
const dbName = state.table.$options.database;
|
|
110
114
|
const runChunks = async () => {
|
|
111
115
|
for (let i = 0; i < allValues.length; i += size) {
|
|
112
116
|
const chunkState = { ...state, values: allValues.slice(i, i + size) };
|
|
113
117
|
const db = pipe(dbName);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
if (state.verb === 'insert') {
|
|
119
|
+
const out = await runInsert(db, chunkState);
|
|
120
|
+
written += out.written;
|
|
121
|
+
if (collectsRows && Array.isArray(out.result))
|
|
122
|
+
for (const row of out.result)
|
|
123
|
+
collected.push(row);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const rows = await executeUpsert(db, chunkState);
|
|
127
|
+
if (collectsRows && Array.isArray(rows))
|
|
128
|
+
for (const row of rows)
|
|
129
|
+
collected.push(row);
|
|
130
|
+
}
|
|
120
131
|
}
|
|
121
132
|
};
|
|
122
133
|
if (dbName === undefined)
|
|
123
134
|
await pipe.transaction(runChunks);
|
|
124
135
|
else
|
|
125
136
|
await pipe.transaction(dbName, runChunks);
|
|
137
|
+
if (state.verb === 'insert')
|
|
138
|
+
reportSkipped(state, written);
|
|
126
139
|
return collectsRows ? collected : undefined;
|
|
127
140
|
}
|
|
128
141
|
async function executeChunkedAuditWrite(state, ctx, chunkValueSize) {
|
|
129
142
|
const allValues = state.values ?? [];
|
|
130
143
|
const collectsRows = state.returning !== undefined && state.returning !== null;
|
|
131
144
|
const collected = [];
|
|
145
|
+
let written = 0;
|
|
132
146
|
const dbName = state.table.$options.database;
|
|
133
147
|
// `pipe.transaction` opens a transaction when none is active and a
|
|
134
148
|
// savepoint when nested — so chunked execution is atomic in both call sites
|
|
@@ -141,6 +155,8 @@ async function executeChunkedAuditWrite(state, ctx, chunkValueSize) {
|
|
|
141
155
|
const stmt = compileAuditWrite(scoped, chunkState, ctx);
|
|
142
156
|
const rawDb = pipeRaw(dbName);
|
|
143
157
|
const rows = await rawDb.execute(stmt);
|
|
158
|
+
if (Array.isArray(rows))
|
|
159
|
+
written += rows.length;
|
|
144
160
|
if (collectsRows && Array.isArray(rows)) {
|
|
145
161
|
for (const row of rows)
|
|
146
162
|
collected.push(row);
|
|
@@ -155,6 +171,8 @@ async function executeChunkedAuditWrite(state, ctx, chunkValueSize) {
|
|
|
155
171
|
}
|
|
156
172
|
for (const touch of ctx.touches)
|
|
157
173
|
ctx.step.markWrote(touch);
|
|
174
|
+
if (state.onConflict !== undefined)
|
|
175
|
+
reportSkipped(state, written);
|
|
158
176
|
return collectsRows ? decodeReturning(state, collected) : undefined;
|
|
159
177
|
}
|
|
160
178
|
async function executeUpdate(db, state) {
|
|
@@ -164,8 +182,22 @@ async function executeUpdate(db, state) {
|
|
|
164
182
|
return runWithReturning(q, state.returning);
|
|
165
183
|
}
|
|
166
184
|
async function executeInsert(db, state) {
|
|
167
|
-
const
|
|
168
|
-
|
|
185
|
+
const out = await runInsert(db, state);
|
|
186
|
+
reportSkipped(state, out.written);
|
|
187
|
+
return out.result;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* One insert statement. Under `onConflictDoNothing` the rows written are the
|
|
191
|
+
* rows the statement returns, so it asks for them when the caller did not; the
|
|
192
|
+
* caller still gets what it asked for.
|
|
193
|
+
*/
|
|
194
|
+
async function runInsert(db, state) {
|
|
195
|
+
const q = applyOnConflict(db.insert(state.table).values(state.values ?? []), state);
|
|
196
|
+
if (state.onConflict === undefined)
|
|
197
|
+
return { result: await runWithReturning(q, state.returning), written: 0 };
|
|
198
|
+
const rows = await runWithReturning(q, state.returning ?? 'all');
|
|
199
|
+
const caller = state.returning === undefined || state.returning === null;
|
|
200
|
+
return { result: caller ? [] : rows, written: rows.length };
|
|
169
201
|
}
|
|
170
202
|
async function executeDelete(db, state) {
|
|
171
203
|
let q = db.delete(state.table);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/data/write/execute.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,wEAAwE;AACxE,2EAA2E;AAC3E,+EAA+E;AAC/E,mFAAmF;AACnF,uCAAuC;AACvC,EAAE;AACF,yEAAyE;AACzE,yDAAyD;AACzD,yEAAyE;AACzE,yEAAyE;AACzE,4EAA4E;AAC5E,uEAAuE;AACvE,2CAA2C;AAI3C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/data/write/execute.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,16 @@ export declare class InsertBuilder<T extends PgTable, TResult = unknown> impleme
|
|
|
6
6
|
private readonly state;
|
|
7
7
|
constructor(state: WriteState);
|
|
8
8
|
values(rows: InsertValues<T> | ReadonlyArray<InsertValues<T>>): InsertBuilder<T, TResult>;
|
|
9
|
+
/**
|
|
10
|
+
* Leaves a row that conflicts with an existing one and inserts the rest.
|
|
11
|
+
* Without `target`, any unique or exclusion constraint conflict is skipped.
|
|
12
|
+
* `.returning()` yields only the rows written, so a fully skipped insert
|
|
13
|
+
* returns `[]`. Under `@touches`, a skipped row gets no audit row; a traced
|
|
14
|
+
* flow records an `external:pipework.insert.conflict` step with the counts.
|
|
15
|
+
*/
|
|
16
|
+
onConflictDoNothing(options?: {
|
|
17
|
+
target?: readonly (keyof T['$inferSelect'] & string)[];
|
|
18
|
+
}): InsertBuilder<T, TResult>;
|
|
9
19
|
returning(): InsertBuilder<T, Record<string, unknown>[]>;
|
|
10
20
|
returning<TShape extends Record<string, unknown>>(shape: TShape): InsertBuilder<T, Record<string, unknown>[]>;
|
|
11
21
|
then<TFulfilled = TResult, TRejected = never>(onfulfilled?: ((value: TResult) => TFulfilled | PromiseLike<TFulfilled>) | null, onrejected?: ((reason: unknown) => TRejected | PromiseLike<TRejected>) | null): PromiseLike<TFulfilled | TRejected>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insert.d.ts","sourceRoot":"","sources":["../../../src/data/write/insert.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG/C,qBAAa,aAAa,CAAC,CAAC,SAAS,OAAO,EAAE,OAAO,GAAG,OAAO,CAAE,YAAW,WAAW,CAAC,OAAO,CAAC;IAClF,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,UAAU;IAE9C,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC;IAQzF,SAAS,IAAI,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACxD,SAAS,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAM7G,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,SAAS,GAAG,KAAK,EAC1C,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,EAC/E,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,GAC5E,WAAW,CAAC,UAAU,GAAG,SAAS,CAAC;CAGvC;AAED,gGAAgG;AAEhG,wBAAgB,MAAM,CAAC,CAAC,SAAS,YAAY,CAAC,GAAG,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,GAAG,CAAC,CAE7F"}
|
|
1
|
+
{"version":3,"file":"insert.d.ts","sourceRoot":"","sources":["../../../src/data/write/insert.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG/C,qBAAa,aAAa,CAAC,CAAC,SAAS,OAAO,EAAE,OAAO,GAAG,OAAO,CAAE,YAAW,WAAW,CAAC,OAAO,CAAC;IAClF,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,UAAU;IAE9C,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC;IAQzF;;;;;;OAMG;IACH,mBAAmB,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC,EAAE,CAAA;KAAE,GAAG,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC;IAcpH,SAAS,IAAI,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACxD,SAAS,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAM7G,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,SAAS,GAAG,KAAK,EAC1C,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,EAC/E,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,GAC5E,WAAW,CAAC,UAAU,GAAG,SAAS,CAAC;CAGvC;AAED,gGAAgG;AAEhG,wBAAgB,MAAM,CAAC,CAAC,SAAS,YAAY,CAAC,GAAG,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,GAAG,CAAC,CAE7F"}
|
|
@@ -13,6 +13,24 @@ export class InsertBuilder {
|
|
|
13
13
|
values: normalized,
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Leaves a row that conflicts with an existing one and inserts the rest.
|
|
18
|
+
* Without `target`, any unique or exclusion constraint conflict is skipped.
|
|
19
|
+
* `.returning()` yields only the rows written, so a fully skipped insert
|
|
20
|
+
* returns `[]`. Under `@touches`, a skipped row gets no audit row; a traced
|
|
21
|
+
* flow records an `external:pipework.insert.conflict` step with the counts.
|
|
22
|
+
*/
|
|
23
|
+
onConflictDoNothing(options) {
|
|
24
|
+
const target = options?.target;
|
|
25
|
+
if (target !== undefined && target.length === 0) {
|
|
26
|
+
throw new Error('pipe.insert onConflictDoNothing target must not be empty. ' +
|
|
27
|
+
'Pass the field keys of the unique constraint, or omit target to skip a conflict on any constraint.');
|
|
28
|
+
}
|
|
29
|
+
return new InsertBuilder({
|
|
30
|
+
...this.state,
|
|
31
|
+
onConflict: target === undefined ? { action: 'nothing' } : { action: 'nothing', target: target },
|
|
32
|
+
});
|
|
33
|
+
}
|
|
16
34
|
returning(shape) {
|
|
17
35
|
const returning = shape === undefined ? 'all' : shape;
|
|
18
36
|
return new InsertBuilder({ ...this.state, returning });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insert.js","sourceRoot":"","sources":["../../../src/data/write/insert.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4DAA4D;AAM5D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,OAAO,aAAa;IACK;IAA7B,YAA6B,KAAiB;QAAjB,UAAK,GAAL,KAAK,CAAY;IAAG,CAAC;IAElD,MAAM,CAAC,IAAsD;QAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QACtD,OAAO,IAAI,aAAa,CAAa;YACnC,GAAG,IAAI,CAAC,KAAK;YACb,MAAM,EAAE,UAAoD;SAC7D,CAAC,CAAA;IACJ,CAAC;IAID,SAAS,CAAC,KAA+B;QACvC,MAAM,SAAS,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAc,CAAC,CAAC,CAAC,KAAK,CAAA;QAC9D,OAAO,IAAI,aAAa,CAA+B,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;IACtF,CAAC;IAED,IAAI,CACF,WAA+E,EAC/E,UAA6E;QAE7E,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAA6C,EAAE,UAAU,CAAwC,CAAA;IACxI,CAAC;CACF;AAED,gGAAgG;AAChG,8DAA8D;AAC9D,MAAM,UAAU,MAAM,CAAwC,KAAQ;IACpE,OAAO,IAAI,aAAa,CAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;AACjE,CAAC"}
|
|
1
|
+
{"version":3,"file":"insert.js","sourceRoot":"","sources":["../../../src/data/write/insert.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4DAA4D;AAM5D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,OAAO,aAAa;IACK;IAA7B,YAA6B,KAAiB;QAAjB,UAAK,GAAL,KAAK,CAAY;IAAG,CAAC;IAElD,MAAM,CAAC,IAAsD;QAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QACtD,OAAO,IAAI,aAAa,CAAa;YACnC,GAAG,IAAI,CAAC,KAAK;YACb,MAAM,EAAE,UAAoD;SAC7D,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;OAMG;IACH,mBAAmB,CAAC,OAAoE;QACtF,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,CAAA;QAC9B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CACb,4DAA4D;gBAC5D,oGAAoG,CACrG,CAAA;QACH,CAAC;QACD,OAAO,IAAI,aAAa,CAAa;YACnC,GAAG,IAAI,CAAC,KAAK;YACb,UAAU,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAA2B,EAAE;SACtH,CAAC,CAAA;IACJ,CAAC;IAID,SAAS,CAAC,KAA+B;QACvC,MAAM,SAAS,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAc,CAAC,CAAC,CAAC,KAAK,CAAA;QAC9D,OAAO,IAAI,aAAa,CAA+B,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;IACtF,CAAC;IAED,IAAI,CACF,WAA+E,EAC/E,UAA6E;QAE7E,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAA6C,EAAE,UAAU,CAAwC,CAAA;IACxI,CAAC;CACF;AAED,gGAAgG;AAChG,8DAA8D;AAC9D,MAAM,UAAU,MAAM,CAAwC,KAAQ;IACpE,OAAO,IAAI,aAAa,CAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;AACjE,CAAC"}
|
|
@@ -21,6 +21,11 @@ export interface WriteState {
|
|
|
21
21
|
readonly where?: SQL;
|
|
22
22
|
/** Conflict-target columns for `upsert`. */
|
|
23
23
|
readonly onConflictColumns?: readonly string[];
|
|
24
|
+
/** `ON CONFLICT DO NOTHING` for `insert`; `target` is field keys, absent for the bare clause. */
|
|
25
|
+
readonly onConflict?: {
|
|
26
|
+
readonly action: 'nothing';
|
|
27
|
+
readonly target?: readonly string[];
|
|
28
|
+
};
|
|
24
29
|
/** What `RETURNING` should produce. `null` (default) emits no RETURNING. */
|
|
25
30
|
readonly returning?: ReturningShape;
|
|
26
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/data/write/state.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEnE,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAEjE;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,GAAG,IAAI,CAAA;AAEnE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IAExB,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,CAAA;IACjC,4CAA4C;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtC,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACxD,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,GAAG,CAAA;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9C,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAA;CACpC;AAED,yFAAyF;AACzF,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/data/write/state.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEnE,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAEjE;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,GAAG,IAAI,CAAA;AAEnE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IAExB,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,CAAA;IACjC,4CAA4C;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtC,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACxD,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,GAAG,CAAA;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9C,iGAAiG;IACjG,QAAQ,CAAC,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAA;IACzF,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAA;CACpC;AAED,yFAAyF;AACzF,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA"}
|