@tier0/sdk-v2 0.1.0 → 0.2.2
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/LICENSE +21 -21
- package/README.md +13 -11
- package/dist/cjs/app-identity-contract.generated.js.map +1 -1
- package/dist/cjs/capabilities.js.map +1 -1
- package/dist/cjs/cloud-server.js.map +1 -1
- package/dist/cjs/cloud-transport.d.ts +21 -0
- package/dist/cjs/cloud-transport.js +81 -1
- package/dist/cjs/cloud-transport.js.map +1 -1
- package/dist/cjs/controls.js.map +1 -1
- package/dist/cjs/data/bootstrap.d.ts +4 -0
- package/dist/cjs/data/bootstrap.js +15 -6
- package/dist/cjs/data/bootstrap.js.map +1 -1
- package/dist/cjs/data/call.d.ts +26 -9
- package/dist/cjs/data/call.js +179 -14
- package/dist/cjs/data/call.js.map +1 -1
- package/dist/cjs/data/client.d.ts +44 -2
- package/dist/cjs/data/client.js +87 -4
- package/dist/cjs/data/client.js.map +1 -1
- package/dist/cjs/data/collection.d.ts +151 -14
- package/dist/cjs/data/collection.js +213 -50
- package/dist/cjs/data/collection.js.map +1 -1
- package/dist/cjs/data/context.d.ts +4 -2
- package/dist/cjs/data/context.js +14 -3
- package/dist/cjs/data/context.js.map +1 -1
- package/dist/cjs/data/define.d.ts +9 -1
- package/dist/cjs/data/define.js.map +1 -1
- package/dist/cjs/data/error.d.ts +30 -12
- package/dist/cjs/data/error.js +61 -63
- package/dist/cjs/data/error.js.map +1 -1
- package/dist/cjs/data/index.d.ts +6 -3
- package/dist/cjs/data/index.js +7 -1
- package/dist/cjs/data/index.js.map +1 -1
- package/dist/cjs/data/schema.d.ts +7 -1
- package/dist/cjs/data/schema.js +54 -4
- package/dist/cjs/data/schema.js.map +1 -1
- package/dist/cjs/data/subscribe.d.ts +108 -0
- package/dist/cjs/data/subscribe.js +270 -0
- package/dist/cjs/data/subscribe.js.map +1 -0
- package/dist/cjs/mq/broker.js.map +1 -1
- package/dist/cjs/mq/client.js.map +1 -1
- package/dist/cjs/mq/index.js.map +1 -1
- package/dist/cjs/mq/types.js.map +1 -1
- package/dist/cjs/runtime-context.js.map +1 -1
- package/dist/cjs/runtime-env.js.map +1 -1
- package/dist/cjs/uns-v2/client.d.ts +90 -12
- package/dist/cjs/uns-v2/client.js +238 -63
- package/dist/cjs/uns-v2/client.js.map +1 -1
- package/dist/cjs/uns-v2/codec.js.map +1 -1
- package/dist/cjs/uns-v2/generated.d.ts +9619 -6923
- package/dist/cjs/uns-v2/generated.js +124 -119
- package/dist/cjs/uns-v2/generated.js.map +1 -1
- package/dist/cjs/uns-v2/index.js.map +1 -1
- package/dist/cjs/uns-v2/sse.d.ts +20 -0
- package/dist/cjs/uns-v2/sse.js +65 -0
- package/dist/cjs/uns-v2/sse.js.map +1 -0
- package/dist/esm/app-identity-contract.generated.js.map +1 -1
- package/dist/esm/capabilities.js.map +1 -1
- package/dist/esm/cloud-server.js.map +1 -1
- package/dist/esm/cloud-transport.d.ts +21 -0
- package/dist/esm/cloud-transport.js +81 -1
- package/dist/esm/cloud-transport.js.map +1 -1
- package/dist/esm/controls.js.map +1 -1
- package/dist/esm/data/bootstrap.d.ts +4 -0
- package/dist/esm/data/bootstrap.js +14 -5
- package/dist/esm/data/bootstrap.js.map +1 -1
- package/dist/esm/data/call.d.ts +26 -9
- package/dist/esm/data/call.js +177 -13
- package/dist/esm/data/call.js.map +1 -1
- package/dist/esm/data/client.d.ts +44 -2
- package/dist/esm/data/client.js +89 -7
- package/dist/esm/data/client.js.map +1 -1
- package/dist/esm/data/collection.d.ts +151 -14
- package/dist/esm/data/collection.js +212 -49
- package/dist/esm/data/collection.js.map +1 -1
- package/dist/esm/data/context.d.ts +4 -2
- package/dist/esm/data/context.js +13 -3
- package/dist/esm/data/context.js.map +1 -1
- package/dist/esm/data/define.d.ts +9 -1
- package/dist/esm/data/define.js.map +1 -1
- package/dist/esm/data/error.d.ts +30 -12
- package/dist/esm/data/error.js +61 -63
- package/dist/esm/data/error.js.map +1 -1
- package/dist/esm/data/index.d.ts +6 -3
- package/dist/esm/data/index.js +3 -1
- package/dist/esm/data/index.js.map +1 -1
- package/dist/esm/data/schema.d.ts +7 -1
- package/dist/esm/data/schema.js +54 -4
- package/dist/esm/data/schema.js.map +1 -1
- package/dist/esm/data/subscribe.d.ts +108 -0
- package/dist/esm/data/subscribe.js +265 -0
- package/dist/esm/data/subscribe.js.map +1 -0
- package/dist/esm/mq/broker.js.map +1 -1
- package/dist/esm/mq/client.js.map +1 -1
- package/dist/esm/mq/index.js.map +1 -1
- package/dist/esm/mq/types.js.map +1 -1
- package/dist/esm/runtime-context.js.map +1 -1
- package/dist/esm/runtime-env.js.map +1 -1
- package/dist/esm/uns-v2/client.d.ts +90 -12
- package/dist/esm/uns-v2/client.js +236 -63
- package/dist/esm/uns-v2/client.js.map +1 -1
- package/dist/esm/uns-v2/codec.js.map +1 -1
- package/dist/esm/uns-v2/generated.d.ts +9619 -6923
- package/dist/esm/uns-v2/generated.js +123 -118
- package/dist/esm/uns-v2/generated.js.map +1 -1
- package/dist/esm/uns-v2/index.js.map +1 -1
- package/dist/esm/uns-v2/sse.d.ts +20 -0
- package/dist/esm/uns-v2/sse.js +60 -0
- package/dist/esm/uns-v2/sse.js.map +1 -0
- package/package.json +29 -16
- package/skills/tier0-sdk-v2/SKILL.md +14 -14
- package/skills/{tier0-sdk-v2-data → tier0-sdk-v2/tier0-sdk-v2-data}/SKILL.md +3 -2
- package/skills/{tier0-sdk-v2-data → tier0-sdk-v2/tier0-sdk-v2-data}/references/consistency.md +3 -3
- package/skills/{tier0-sdk-v2-data → tier0-sdk-v2/tier0-sdk-v2-data}/references/errors.md +23 -10
- package/skills/{tier0-sdk-v2-data → tier0-sdk-v2/tier0-sdk-v2-data}/references/modeling.md +36 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/read-write.md +172 -0
- package/skills/{tier0-sdk-v2-mq → tier0-sdk-v2/tier0-sdk-v2-mq}/references/quickstart.md +1 -1
- package/skills/{tier0-sdk-v2-source → tier0-sdk-v2/tier0-sdk-v2-source}/SKILL.md +3 -3
- package/skills/{tier0-sdk-v2-source → tier0-sdk-v2/tier0-sdk-v2-source}/references/create.md +3 -6
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/delete.md +39 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/state.md +36 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/update.md +80 -0
- package/skills/{tier0-sdk-v2-stream → tier0-sdk-v2/tier0-sdk-v2-stream}/SKILL.md +6 -6
- package/skills/{tier0-sdk-v2-stream → tier0-sdk-v2/tier0-sdk-v2-stream}/references/create.md +15 -14
- package/skills/{tier0-sdk-v2-stream → tier0-sdk-v2/tier0-sdk-v2-stream}/references/deploy.md +11 -9
- package/skills/{tier0-sdk-v2-stream → tier0-sdk-v2/tier0-sdk-v2-stream}/references/lifecycle.md +2 -1
- package/skills/{tier0-sdk-v2-stream → tier0-sdk-v2/tier0-sdk-v2-stream}/references/update.md +5 -6
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md +55 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/create.md +57 -0
- package/skills/{tier0-sdk-v2-uns → tier0-sdk-v2/tier0-sdk-v2-uns}/references/data-workflows.md +3 -7
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/delete.md +53 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/namespace.md +38 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/read.md +34 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/restore.md +39 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/update.md +62 -0
- package/skills/tier0-sdk-v2-data/references/read-write.md +0 -72
- package/skills/tier0-sdk-v2-source/references/delete.md +0 -47
- package/skills/tier0-sdk-v2-source/references/state.md +0 -37
- package/skills/tier0-sdk-v2-source/references/update.md +0 -61
- package/skills/tier0-sdk-v2-uns/SKILL.md +0 -53
- package/skills/tier0-sdk-v2-uns/references/create.md +0 -85
- package/skills/tier0-sdk-v2-uns/references/delete.md +0 -69
- package/skills/tier0-sdk-v2-uns/references/namespace.md +0 -75
- package/skills/tier0-sdk-v2-uns/references/read.md +0 -32
- package/skills/tier0-sdk-v2-uns/references/restore.md +0 -41
- package/skills/tier0-sdk-v2-uns/references/update.md +0 -86
- /package/skills/{tier0-sdk-v2-agent → tier0-sdk-v2/tier0-sdk-v2-agent}/SKILL.md +0 -0
- /package/skills/{tier0-sdk-v2-agent → tier0-sdk-v2/tier0-sdk-v2-agent}/references/results.md +0 -0
- /package/skills/{tier0-sdk-v2-controls → tier0-sdk-v2/tier0-sdk-v2-controls}/SKILL.md +0 -0
- /package/skills/{tier0-sdk-v2-data → tier0-sdk-v2/tier0-sdk-v2-data}/references/schema-evolution.md +0 -0
- /package/skills/{tier0-sdk-v2-files → tier0-sdk-v2/tier0-sdk-v2-files}/SKILL.md +0 -0
- /package/skills/{tier0-sdk-v2-files → tier0-sdk-v2/tier0-sdk-v2-files}/references/delete.md +0 -0
- /package/skills/{tier0-sdk-v2-files → tier0-sdk-v2/tier0-sdk-v2-files}/references/download.md +0 -0
- /package/skills/{tier0-sdk-v2-files → tier0-sdk-v2/tier0-sdk-v2-files}/references/multipart.md +0 -0
- /package/skills/{tier0-sdk-v2-files → tier0-sdk-v2/tier0-sdk-v2-files}/references/upload.md +0 -0
- /package/skills/{tier0-sdk-v2-files → tier0-sdk-v2/tier0-sdk-v2-files}/references/url.md +0 -0
- /package/skills/{tier0-sdk-v2-members → tier0-sdk-v2/tier0-sdk-v2-members}/SKILL.md +0 -0
- /package/skills/{tier0-sdk-v2-members → tier0-sdk-v2/tier0-sdk-v2-members}/references/app-members.md +0 -0
- /package/skills/{tier0-sdk-v2-members → tier0-sdk-v2/tier0-sdk-v2-members}/references/platform-members.md +0 -0
- /package/skills/{tier0-sdk-v2-mq → tier0-sdk-v2/tier0-sdk-v2-mq}/SKILL.md +0 -0
- /package/skills/{tier0-sdk-v2-notifications → tier0-sdk-v2/tier0-sdk-v2-notifications}/SKILL.md +0 -0
- /package/skills/{tier0-sdk-v2-notifications → tier0-sdk-v2/tier0-sdk-v2-notifications}/references/get.md +0 -0
- /package/skills/{tier0-sdk-v2-notifications → tier0-sdk-v2/tier0-sdk-v2-notifications}/references/send.md +0 -0
- /package/skills/{tier0-sdk-v2-source → tier0-sdk-v2/tier0-sdk-v2-source}/references/changes.md +0 -0
- /package/skills/{tier0-sdk-v2-source → tier0-sdk-v2/tier0-sdk-v2-source}/references/protocols.md +0 -0
- /package/skills/{tier0-sdk-v2-source → tier0-sdk-v2/tier0-sdk-v2-source}/references/read.md +0 -0
- /package/skills/{tier0-sdk-v2-stream → tier0-sdk-v2/tier0-sdk-v2-stream}/references/delete.md +0 -0
- /package/skills/{tier0-sdk-v2-stream → tier0-sdk-v2/tier0-sdk-v2-stream}/references/read.md +0 -0
- /package/skills/{tier0-sdk-v2-system → tier0-sdk-v2/tier0-sdk-v2-system}/SKILL.md +0 -0
- /package/skills/{tier0-sdk-v2-system → tier0-sdk-v2/tier0-sdk-v2-system}/references/info.md +0 -0
- /package/skills/{tier0-sdk-v2-system → tier0-sdk-v2/tier0-sdk-v2-system}/references/whoami.md +0 -0
package/dist/cjs/data/context.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.runWithRequestContext = runWithRequestContext;
|
|
4
4
|
exports.runAsApp = runAsApp;
|
|
5
5
|
exports.currentDataSubject = currentDataSubject;
|
|
6
|
+
exports.currentSignal = currentSignal;
|
|
6
7
|
/**
|
|
7
8
|
* Request context for the data layer.
|
|
8
9
|
*
|
|
@@ -12,6 +13,10 @@ exports.currentDataSubject = currentDataSubject;
|
|
|
12
13
|
* forwards it only while serving that request: the App's request entry point
|
|
13
14
|
* opens the context with `runWithRequestContext`, and ensure, seed writes and
|
|
14
15
|
* `runAsApp(...)` background work never carry it.
|
|
16
|
+
*
|
|
17
|
+
* Given the `Request` itself, the context also carries its abort signal: when
|
|
18
|
+
* the caller goes away, data calls still waiting for a request slot are
|
|
19
|
+
* dropped unsent and those in flight are cancelled.
|
|
15
20
|
*/
|
|
16
21
|
const node_async_hooks_1 = require("node:async_hooks");
|
|
17
22
|
const cloud_transport_js_1 = require("../cloud-transport.js");
|
|
@@ -19,10 +24,12 @@ const cloud_transport_js_1 = require("../cloud-transport.js");
|
|
|
19
24
|
const STORAGE_KEY = Symbol.for('tier0.sdk-v2.data.request-context');
|
|
20
25
|
const globalStore = globalThis;
|
|
21
26
|
const storage = (globalStore[STORAGE_KEY] ??= new node_async_hooks_1.AsyncLocalStorage());
|
|
22
|
-
/** Runs `fn` as part of the business request
|
|
23
|
-
function runWithRequestContext(
|
|
27
|
+
/** Runs `fn` as part of the business request given (or only its headers, without abort). */
|
|
28
|
+
function runWithRequestContext(request, fn) {
|
|
29
|
+
const headers = request instanceof Headers ? request : request.headers;
|
|
30
|
+
const signal = request instanceof Headers ? undefined : request.signal;
|
|
24
31
|
const dataSubject = headers.get(cloud_transport_js_1.UNS_V2_APP_DATA_SUBJECT_HEADER)?.trim() || undefined;
|
|
25
|
-
return storage.run(dataSubject ? { dataSubject } : {}, fn);
|
|
32
|
+
return storage.run({ ...(dataSubject ? { dataSubject } : {}), ...(signal ? { signal } : {}) }, fn);
|
|
26
33
|
}
|
|
27
34
|
/**
|
|
28
35
|
* Runs `fn` as the App itself, outside any employee's request: use it for
|
|
@@ -36,4 +43,8 @@ function runAsApp(fn) {
|
|
|
36
43
|
function currentDataSubject() {
|
|
37
44
|
return storage.getStore()?.dataSubject;
|
|
38
45
|
}
|
|
46
|
+
/** The abort signal of the request being served, if it was given. */
|
|
47
|
+
function currentSignal() {
|
|
48
|
+
return storage.getStore()?.signal;
|
|
49
|
+
}
|
|
39
50
|
//# sourceMappingURL=context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/data/context.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/data/context.ts"],"names":[],"mappings":";;AA8BA,sDAKC;AAOD,4BAEC;AAGD,gDAEC;AAGD,sCAEC;AAtDD;;;;;;;;;;;;;GAaG;AACH,uDAAqD;AACrD,8DAAuE;AAOvE,kEAAkE;AAClE,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;AACpE,MAAM,WAAW,GAAG,UAEnB,CAAC;AACF,MAAM,OAAO,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,IAAI,oCAAiB,EAAyB,CAAC,CAAC;AAE9F,4FAA4F;AAC5F,SAAgB,qBAAqB,CAAI,OAA0B,EAAE,EAAW;IAC9E,MAAM,OAAO,GAAG,OAAO,YAAY,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACvE,MAAM,MAAM,GAAG,OAAO,YAAY,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACvE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,mDAA8B,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IACrF,OAAO,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACrG,CAAC;AAED;;;;GAIG;AACH,SAAgB,QAAQ,CAAI,EAAW;IACrC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,4DAA4D;AAC5D,SAAgB,kBAAkB;IAChC,OAAO,OAAO,CAAC,QAAQ,EAAE,EAAE,WAAW,CAAC;AACzC,CAAC;AAED,qEAAqE;AACrE,SAAgB,aAAa;IAC3B,OAAO,OAAO,CAAC,QAAQ,EAAE,EAAE,MAAM,CAAC;AACpC,CAAC","sourcesContent":["/**\n * Request context for the data layer.\n *\n * The Tier0 App Gateway signs the current employee into\n * `X-Tier0-App-Data-Subject` on each business request. UNS uses it to narrow\n * App-key access to that employee (data rules, record leases). The data layer\n * forwards it only while serving that request: the App's request entry point\n * opens the context with `runWithRequestContext`, and ensure, seed writes and\n * `runAsApp(...)` background work never carry it.\n *\n * Given the `Request` itself, the context also carries its abort signal: when\n * the caller goes away, data calls still waiting for a request slot are\n * dropped unsent and those in flight are cancelled.\n */\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { UNS_V2_APP_DATA_SUBJECT_HEADER } from '../cloud-transport.js';\n\ninterface RequestContext {\n dataSubject?: string;\n signal?: AbortSignal;\n}\n\n// One store per process, shared across dev-server module reloads.\nconst STORAGE_KEY = Symbol.for('tier0.sdk-v2.data.request-context');\nconst globalStore = globalThis as typeof globalThis & {\n [STORAGE_KEY]?: AsyncLocalStorage<RequestContext | null>;\n};\nconst storage = (globalStore[STORAGE_KEY] ??= new AsyncLocalStorage<RequestContext | null>());\n\n/** Runs `fn` as part of the business request given (or only its headers, without abort). */\nexport function runWithRequestContext<T>(request: Request | Headers, fn: () => T): T {\n const headers = request instanceof Headers ? request : request.headers;\n const signal = request instanceof Headers ? undefined : request.signal;\n const dataSubject = headers.get(UNS_V2_APP_DATA_SUBJECT_HEADER)?.trim() || undefined;\n return storage.run({ ...(dataSubject ? { dataSubject } : {}), ...(signal ? { signal } : {}) }, fn);\n}\n\n/**\n * Runs `fn` as the App itself, outside any employee's request: use it for\n * work that outlives or is detached from the request (timers, queues, fire-\n * and-forget follow-ups). Its data calls carry no data subject.\n */\nexport function runAsApp<T>(fn: () => T): T {\n return storage.run(null, fn);\n}\n\n/** The data subject of the request being served, if any. */\nexport function currentDataSubject(): string | undefined {\n return storage.getStore()?.dataSubject;\n}\n\n/** The abort signal of the request being served, if it was given. */\nexport function currentSignal(): AbortSignal | undefined {\n return storage.getStore()?.signal;\n}\n"]}
|
|
@@ -18,7 +18,7 @@ export declare const MAX_COLLECTIONS = 64;
|
|
|
18
18
|
export declare const MAX_DESCRIPTION_LENGTH = 512;
|
|
19
19
|
/** Seeds are inserted in atomic chunks of 200 during the first request; keep them a baseline, not a data import. */
|
|
20
20
|
export declare const MAX_SEED_DOCUMENTS = 1000;
|
|
21
|
-
/** Same shape as
|
|
21
|
+
/** Same shape as collection metadata indexes, limited to record indexes. */
|
|
22
22
|
export interface IndexSpec {
|
|
23
23
|
/** Business field path without `data.`, e.g. `code` or `customer.id`. */
|
|
24
24
|
path?: string;
|
|
@@ -27,6 +27,14 @@ export interface IndexSpec {
|
|
|
27
27
|
unique?: boolean;
|
|
28
28
|
/** `btree` (default) or `gin` for one object/array path; GIN cannot be unique. */
|
|
29
29
|
kind?: 'btree' | 'gin';
|
|
30
|
+
/**
|
|
31
|
+
* TTL index: UNS physically deletes a record this many seconds
|
|
32
|
+
* (60–31536000) after the instant in `path`, an integer field of Unix
|
|
33
|
+
* milliseconds. At most one per collection, on a single non-unique `path`. Expired
|
|
34
|
+
* records cannot be restored. ensure may add a TTL or lengthen it;
|
|
35
|
+
* shortening or removing it takes schema:replace.
|
|
36
|
+
*/
|
|
37
|
+
expireAfterSeconds?: number;
|
|
30
38
|
}
|
|
31
39
|
/** System metadata of a stored record. Times are Unix milliseconds. */
|
|
32
40
|
export interface RecordMeta {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../../src/data/define.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../../src/data/define.ts"],"names":[],"mappings":";;;AA6EA,4CA2BC;AA3FD,0DAA0D;AAC7C,QAAA,aAAa,GAAG,+BAA+B,CAAC;AAC7D,uFAAuF;AAC1E,QAAA,eAAe,GAAG,EAAE,CAAC;AAClC,wDAAwD;AAC3C,QAAA,sBAAsB,GAAG,GAAG,CAAC;AAC1C,oHAAoH;AACvG,QAAA,kBAAkB,GAAG,IAAI,CAAC;AAyDvC,SAAgB,gBAAgB,CAA6B,UAM5D;IACC,IAAI,CAAC,qBAAa,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,qBAAqB,UAAU,CAAC,KAAK,gBAAgB,qBAAa,yDAAyD,CAC5H,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,CAAC,WAAW,IAAI,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,8BAAsB,EAAE,CAAC;QAC1F,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,CAAC,KAAK,iCAAiC,8BAAsB,cAAc,CAAC,CAAC;IACxH,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,0BAAkB,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CACb,eAAe,UAAU,CAAC,KAAK,cAAc,0BAAkB,wBAAwB,UAAU,CAAC,IAAI,CAAC,MAAM,iEAAiE,CAC/K,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;QACvD,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Collection declarations — the single source of truth for App data.\n *\n * An App declares every collection with `defineCollection(...)` and passes the\n * list to `createDataClient({ collections })`. The client ensures that list in\n * one batch on first data access: a missing collection is created, a\n * declaration wider than storage widens it, and nothing is ever narrowed.\n *\n * This module is pure (Zod types only) so declarations, API input schemas and\n * build-time checks can import it without pulling in the runtime client.\n */\nimport type { z } from 'zod';\n\n/** Collection alias: unique per App, case-insensitive. */\nexport const ALIAS_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,62}$/;\n/** UNS: one ensure takes 1–64 declarations, and an App owns at most 64 collections. */\nexport const MAX_COLLECTIONS = 64;\n/** UNS: collection description length in characters. */\nexport const MAX_DESCRIPTION_LENGTH = 512;\n/** Seeds are inserted in atomic chunks of 200 during the first request; keep them a baseline, not a data import. */\nexport const MAX_SEED_DOCUMENTS = 1000;\n\n/** Same shape as collection metadata indexes, limited to record indexes. */\nexport interface IndexSpec {\n /** Business field path without `data.`, e.g. `code` or `customer.id`. */\n path?: string;\n /** Compound index, at most 3 paths. Mutually exclusive with `path`. */\n paths?: string[];\n unique?: boolean;\n /** `btree` (default) or `gin` for one object/array path; GIN cannot be unique. */\n kind?: 'btree' | 'gin';\n /**\n * TTL index: UNS physically deletes a record this many seconds\n * (60–31536000) after the instant in `path`, an integer field of Unix\n * milliseconds. At most one per collection, on a single non-unique `path`. Expired\n * records cannot be restored. ensure may add a TTL or lengthen it;\n * shortening or removing it takes schema:replace.\n */\n expireAfterSeconds?: number;\n}\n\n/** System metadata of a stored record. Times are Unix milliseconds. */\nexport interface RecordMeta {\n revision: number;\n createdAt: number;\n updatedAt: number;\n}\n\nexport type CollectionSchema = z.ZodObject;\n\n/** A seed document: a full record plus the fixed `_id` it is inserted with. */\nexport type SeedDoc<S extends CollectionSchema> = z.input<S> & { _id: string };\n\nexport interface CollectionDefinition<S extends CollectionSchema = CollectionSchema> {\n readonly alias: string;\n /** Zod 4 object schema of the record body (no `_id` / `_meta`). */\n readonly schema: S;\n readonly indexes: readonly IndexSpec[];\n readonly description?: string;\n /**\n * Baseline records, written only when ensure reports this collection as\n * `created`. Never re-applied to an existing collection.\n */\n readonly seed?: readonly SeedDoc<S>[];\n}\n\n/** A stored record as services read it: `{ _id, ...fields, _meta }`. */\nexport type Doc<C extends CollectionDefinition> = z.output<C['schema']> & {\n _id: string;\n _meta: RecordMeta;\n};\n\n/** A record to insert: the schema input plus an optional caller-chosen `_id`. */\nexport type NewDoc<C extends CollectionDefinition> = z.input<C['schema']> & {\n _id?: string;\n};\n\nexport function defineCollection<S extends CollectionSchema>(definition: {\n alias: string;\n schema: S;\n indexes?: IndexSpec[];\n description?: string;\n seed?: SeedDoc<S>[];\n}): CollectionDefinition<S> {\n if (!ALIAS_PATTERN.test(definition.alias)) {\n throw new Error(\n `Collection alias \"${definition.alias}\" must match ${ALIAS_PATTERN} (letters, digits, \"_\" or \"-\", starting with a letter).`,\n );\n }\n if (definition.description && [...definition.description].length > MAX_DESCRIPTION_LENGTH) {\n throw new Error(`Collection \"${definition.alias}\": description is longer than ${MAX_DESCRIPTION_LENGTH} characters.`);\n }\n if (definition.seed && definition.seed.length > MAX_SEED_DOCUMENTS) {\n throw new Error(\n `Collection \"${definition.alias}\": at most ${MAX_SEED_DOCUMENTS} seed documents (got ${definition.seed.length}). Seeds are a baseline written on creation, not a bulk import.`,\n );\n }\n return Object.freeze({\n alias: definition.alias,\n schema: definition.schema,\n indexes: Object.freeze([...(definition.indexes ?? [])]),\n ...(definition.description ? { description: definition.description } : {}),\n ...(definition.seed ? { seed: Object.freeze([...definition.seed]) } : {}),\n });\n}\n"]}
|
package/dist/cjs/data/error.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* `ZodError`; programming or platform errors, such as invalid client options or
|
|
8
8
|
* a malformed data subject from the gateway, throw `TypeError`.
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import type { UnsV2Error, UnsV2Execution, UnsV2Retry } from '../uns-v2/client.js';
|
|
11
11
|
/**
|
|
12
12
|
* Stable `data.reason` codes UNS adds when it refuses App data access; the
|
|
13
13
|
* top-level code stays FORBIDDEN / NOT_FOUND. Only whole-request errors carry
|
|
@@ -31,9 +31,24 @@ export declare class DataError extends Error {
|
|
|
31
31
|
/** HTTP status UNS answered with; 0 when no response arrived. */
|
|
32
32
|
readonly upstreamStatus: number;
|
|
33
33
|
readonly requestId?: string;
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
/**
|
|
35
|
+
* How far the failed request got: `notStarted` / `rolledBack` changed
|
|
36
|
+
* nothing, `committed` took effect, `unknown` (writes only) may have.
|
|
37
|
+
* Data-layer refusals raised before sending are `notStarted`.
|
|
38
|
+
*/
|
|
39
|
+
readonly execution: UnsV2Execution;
|
|
40
|
+
/** Whether the same call may be repeated later, and after how long. The data layer already retried it. */
|
|
41
|
+
readonly retry: UnsV2Retry;
|
|
42
|
+
/** `execution === "unknown"`: a write may have landed. Read back before writing again. */
|
|
36
43
|
readonly outcomeUnknown: boolean;
|
|
44
|
+
/** Requests sent for this call, retries included; 0 when nothing was sent. */
|
|
45
|
+
readonly attempts: number;
|
|
46
|
+
/**
|
|
47
|
+
* The idempotency key the write was sent with (generated unless the caller
|
|
48
|
+
* gave one). After `outcomeUnknown`, sending the same write with this key
|
|
49
|
+
* again cannot apply it twice.
|
|
50
|
+
*/
|
|
51
|
+
readonly idempotencyKey?: string;
|
|
37
52
|
/** The `data` object of the UNS error envelope, or data-layer details. */
|
|
38
53
|
readonly details: Record<string, unknown>;
|
|
39
54
|
constructor(init: {
|
|
@@ -43,18 +58,21 @@ export declare class DataError extends Error {
|
|
|
43
58
|
reason?: string;
|
|
44
59
|
upstreamStatus?: number;
|
|
45
60
|
requestId?: string;
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
execution?: UnsV2Execution;
|
|
62
|
+
retry?: UnsV2Retry;
|
|
63
|
+
attempts?: number;
|
|
64
|
+
idempotencyKey?: string;
|
|
48
65
|
details?: Record<string, unknown>;
|
|
49
66
|
cause?: unknown;
|
|
50
67
|
});
|
|
51
68
|
}
|
|
52
69
|
/**
|
|
53
|
-
* Maps an upstream UNS status to the status the App answers its own
|
|
54
|
-
* with. Credential failures are the platform's problem, not the user's
|
|
55
|
-
* session, so a 401 from UNS becomes 502 instead of looking like a logout
|
|
56
|
-
*
|
|
70
|
+
* Maps an upstream UNS status and code to the status the App answers its own
|
|
71
|
+
* caller with. Credential failures are the platform's problem, not the user's
|
|
72
|
+
* session, so a 401 from UNS becomes 502 instead of looking like a logout;
|
|
73
|
+
* platform states (App not ready yet, a dependency down, the App key changed
|
|
74
|
+
* mid-request) become 503 instead of looking like a denied action or a conflict.
|
|
57
75
|
*/
|
|
58
|
-
export declare function appStatus(upstream: number,
|
|
59
|
-
/** Translates a failed UNS call of the SDK client
|
|
60
|
-
export declare function toDataError(error: UnsV2Error): DataError;
|
|
76
|
+
export declare function appStatus(upstream: number, code?: string): number;
|
|
77
|
+
/** Translates a failed UNS call of the SDK client after `attempts` requests, sent with `idempotencyKey`. */
|
|
78
|
+
export declare function toDataError(error: UnsV2Error, attempts?: number, idempotencyKey?: string): DataError;
|
package/dist/cjs/data/error.js
CHANGED
|
@@ -3,16 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DataError = exports.ACCESS_REASONS = void 0;
|
|
4
4
|
exports.appStatus = appStatus;
|
|
5
5
|
exports.toDataError = toDataError;
|
|
6
|
-
/**
|
|
7
|
-
* Runtime failures of a data call, missing credentials included, are a
|
|
8
|
-
* `DataError`. The SDK's UNS client does the HTTP exchange; its `UnsV2Error`
|
|
9
|
-
* (kept as `cause`) is translated here, and the data layer raises its own codes
|
|
10
|
-
* (BATCH_LIMIT_EXCEEDED, WRITE_ERRORS, ...). `status` is the HTTP status the App
|
|
11
|
-
* should answer its own caller with. Writes that fail validation throw
|
|
12
|
-
* `ZodError`; programming or platform errors, such as invalid client options or
|
|
13
|
-
* a malformed data subject from the gateway, throw `TypeError`.
|
|
14
|
-
*/
|
|
15
|
-
const client_js_1 = require("../uns-v2/client.js");
|
|
16
6
|
/**
|
|
17
7
|
* Stable `data.reason` codes UNS adds when it refuses App data access; the
|
|
18
8
|
* top-level code stays FORBIDDEN / NOT_FOUND. Only whole-request errors carry
|
|
@@ -36,9 +26,24 @@ class DataError extends Error {
|
|
|
36
26
|
/** HTTP status UNS answered with; 0 when no response arrived. */
|
|
37
27
|
upstreamStatus;
|
|
38
28
|
requestId;
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
/**
|
|
30
|
+
* How far the failed request got: `notStarted` / `rolledBack` changed
|
|
31
|
+
* nothing, `committed` took effect, `unknown` (writes only) may have.
|
|
32
|
+
* Data-layer refusals raised before sending are `notStarted`.
|
|
33
|
+
*/
|
|
34
|
+
execution;
|
|
35
|
+
/** Whether the same call may be repeated later, and after how long. The data layer already retried it. */
|
|
36
|
+
retry;
|
|
37
|
+
/** `execution === "unknown"`: a write may have landed. Read back before writing again. */
|
|
41
38
|
outcomeUnknown;
|
|
39
|
+
/** Requests sent for this call, retries included; 0 when nothing was sent. */
|
|
40
|
+
attempts;
|
|
41
|
+
/**
|
|
42
|
+
* The idempotency key the write was sent with (generated unless the caller
|
|
43
|
+
* gave one). After `outcomeUnknown`, sending the same write with this key
|
|
44
|
+
* again cannot apply it twice.
|
|
45
|
+
*/
|
|
46
|
+
idempotencyKey;
|
|
42
47
|
/** The `data` object of the UNS error envelope, or data-layer details. */
|
|
43
48
|
details;
|
|
44
49
|
constructor(init) {
|
|
@@ -49,24 +54,28 @@ class DataError extends Error {
|
|
|
49
54
|
this.reason = init.reason;
|
|
50
55
|
this.upstreamStatus = init.upstreamStatus ?? 0;
|
|
51
56
|
this.requestId = init.requestId;
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
57
|
+
this.execution = init.execution ?? 'notStarted';
|
|
58
|
+
this.retry = init.retry ?? { safe: false };
|
|
59
|
+
this.outcomeUnknown = this.execution === 'unknown';
|
|
60
|
+
this.attempts = init.attempts ?? 0;
|
|
61
|
+
this.idempotencyKey = init.idempotencyKey;
|
|
54
62
|
this.details = init.details ?? {};
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
65
|
exports.DataError = DataError;
|
|
66
|
+
/** Platform states the App's caller cannot fix: they answer 503 whatever UNS answered. */
|
|
67
|
+
const PLATFORM_CODES = new Set(['APP_NOT_READY', 'DEPENDENCY_UNAVAILABLE', 'CREDENTIAL_CHANGED', 'OUTCOME_UNKNOWN', 'TEMPORARILY_UNAVAILABLE']);
|
|
58
68
|
/**
|
|
59
|
-
* Maps an upstream UNS status to the status the App answers its own
|
|
60
|
-
* with. Credential failures are the platform's problem, not the user's
|
|
61
|
-
* session, so a 401 from UNS becomes 502 instead of looking like a logout
|
|
62
|
-
*
|
|
69
|
+
* Maps an upstream UNS status and code to the status the App answers its own
|
|
70
|
+
* caller with. Credential failures are the platform's problem, not the user's
|
|
71
|
+
* session, so a 401 from UNS becomes 502 instead of looking like a logout;
|
|
72
|
+
* platform states (App not ready yet, a dependency down, the App key changed
|
|
73
|
+
* mid-request) become 503 instead of looking like a denied action or a conflict.
|
|
63
74
|
*/
|
|
64
|
-
function appStatus(upstream,
|
|
75
|
+
function appStatus(upstream, code = '') {
|
|
65
76
|
if (upstream === 401)
|
|
66
77
|
return 502;
|
|
67
|
-
|
|
68
|
-
// e.g. FORBIDDEN "hosted App is not ready" right after an import.
|
|
69
|
-
if (upstream === 403 && retryable)
|
|
78
|
+
if (PLATFORM_CODES.has(code))
|
|
70
79
|
return 503;
|
|
71
80
|
if (upstream === 400 || upstream === 403 || upstream === 404 || upstream === 409 || upstream === 413 || upstream === 422 || upstream === 429) {
|
|
72
81
|
return upstream;
|
|
@@ -84,6 +93,10 @@ const CODE_HINTS = {
|
|
|
84
93
|
APP_GRANT_REVOKED: "A workspace admin revoked this App's access to the collection; it is not re-granted automatically. Ask the admin to restore the grant.",
|
|
85
94
|
INDEX_QUOTA_EXCEEDED: 'The workspace index quota (200, counting every index that physically exists) is exhausted. Remove unused indexes through the tier0 MCP.',
|
|
86
95
|
COLLECTION_TOO_LARGE: 'archive / restore handle at most 2000 records; stop using a large collection in code instead of archiving it.',
|
|
96
|
+
OVERLOADED: "This workspace's data requests are over their concurrency share; the data layer already waited and retried. Batch page reads with data.queryBatch and avoid per-record loops.",
|
|
97
|
+
APP_NOT_READY: 'The platform is still preparing this App (e.g. right after an import); retry shortly.',
|
|
98
|
+
QUERY_TIMEOUT: 'Narrow the query: add an indexed condition, a smaller limit or maxCount.',
|
|
99
|
+
OUTCOME_UNKNOWN: 'The write may have committed; read the record back before writing again.',
|
|
87
100
|
};
|
|
88
101
|
/** `APP_QUOTA_EXCEEDED` per `data.resource`; each per-App limit is 64. */
|
|
89
102
|
const QUOTA_HINTS = {
|
|
@@ -93,9 +106,11 @@ const QUOTA_HINTS = {
|
|
|
93
106
|
};
|
|
94
107
|
/** SDK transport failures: no UNS answer to map, so the data layer names them. */
|
|
95
108
|
const TRANSPORT_FAILURES = {
|
|
96
|
-
UNS_V2_TRANSPORT_TIMEOUT: { code: 'DATA_TIMEOUT', status: 503,
|
|
97
|
-
UNS_V2_TRANSPORT_ERROR: { code: 'DATA_UNREACHABLE', status: 503,
|
|
98
|
-
|
|
109
|
+
UNS_V2_TRANSPORT_TIMEOUT: { code: 'DATA_TIMEOUT', status: 503, message: 'UNS did not answer in time' },
|
|
110
|
+
UNS_V2_TRANSPORT_ERROR: { code: 'DATA_UNREACHABLE', status: 503, message: 'Cannot reach the Tier0 data service' },
|
|
111
|
+
// The business request was aborted while the call was in flight (499: client closed request).
|
|
112
|
+
UNS_V2_TRANSPORT_ABORTED: { code: 'DATA_ABORTED', status: 499, message: 'The data call was aborted' },
|
|
113
|
+
UNS_V2_PROTOCOL_ERROR: { code: 'DATA_BAD_RESPONSE', status: 502, message: 'UNS answered with an invalid response' },
|
|
99
114
|
};
|
|
100
115
|
function codeHint(code, details) {
|
|
101
116
|
if (code === 'APP_QUOTA_EXCEEDED') {
|
|
@@ -107,49 +122,43 @@ function codeHint(code, details) {
|
|
|
107
122
|
function isObject(value) {
|
|
108
123
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
109
124
|
}
|
|
110
|
-
/** Translates a failed UNS call of the SDK client
|
|
111
|
-
function toDataError(error) {
|
|
112
|
-
const
|
|
125
|
+
/** Translates a failed UNS call of the SDK client after `attempts` requests, sent with `idempotencyKey`. */
|
|
126
|
+
function toDataError(error, attempts = 1, idempotencyKey) {
|
|
127
|
+
const common = {
|
|
128
|
+
upstreamStatus: error.status,
|
|
129
|
+
requestId: error.requestId,
|
|
130
|
+
execution: error.execution,
|
|
131
|
+
retry: error.retry,
|
|
132
|
+
attempts,
|
|
133
|
+
idempotencyKey,
|
|
134
|
+
cause: error,
|
|
135
|
+
};
|
|
136
|
+
const unknown = error.outcomeUnknown ? '; the write outcome is unknown' : '';
|
|
113
137
|
// An ingress or load balancer answers 502/503/504 without the UNS envelope during
|
|
114
|
-
// rolling releases and pod restarts
|
|
115
|
-
//
|
|
116
|
-
//
|
|
138
|
+
// rolling releases and pod restarts, like any unavailable upstream. UNS v2 routes
|
|
139
|
+
// answer every other error with the envelope (401/403/429 included), so other
|
|
140
|
+
// unenveloped responses stay DATA_BAD_RESPONSE.
|
|
117
141
|
if (error.code === 'UNS_V2_PROTOCOL_ERROR' && (error.status === 502 || error.status === 503 || error.status === 504)) {
|
|
118
142
|
return new DataError({
|
|
119
|
-
|
|
143
|
+
...common,
|
|
144
|
+
message: `The Tier0 data gateway answered ${error.operation} with HTTP ${error.status}${unknown}.`,
|
|
120
145
|
status: 503,
|
|
121
146
|
code: `HTTP_${error.status}`,
|
|
122
|
-
upstreamStatus: error.status,
|
|
123
|
-
retryable: true,
|
|
124
|
-
outcomeUnknown,
|
|
125
|
-
cause: error,
|
|
126
147
|
});
|
|
127
148
|
}
|
|
128
149
|
const transport = TRANSPORT_FAILURES[error.code];
|
|
129
150
|
if (transport) {
|
|
130
|
-
return new DataError({
|
|
131
|
-
message: `${transport.message} (${error.operation})${outcomeUnknown ? '; the write outcome is unknown' : ''}.`,
|
|
132
|
-
status: transport.status,
|
|
133
|
-
code: transport.code,
|
|
134
|
-
upstreamStatus: error.status,
|
|
135
|
-
retryable: transport.retryable,
|
|
136
|
-
outcomeUnknown,
|
|
137
|
-
cause: error,
|
|
138
|
-
});
|
|
151
|
+
return new DataError({ ...common, message: `${transport.message} (${error.operation})${unknown}.`, status: transport.status, code: transport.code });
|
|
139
152
|
}
|
|
140
153
|
const httpStatus = error.status ?? 0;
|
|
141
154
|
const data = isObject(error.data) ? error.data : {};
|
|
142
155
|
// Only `data.reason` is a code; `error.reason` repeats the message text.
|
|
143
156
|
const reason = typeof data.reason === 'string' ? data.reason : undefined;
|
|
144
|
-
const retryable = error.retryable || httpStatus === 503 || httpStatus === 504;
|
|
145
157
|
const code = error.code;
|
|
146
158
|
const msg = error.message;
|
|
147
|
-
const hint = codeHint(code, data);
|
|
159
|
+
const hint = codeHint(code, data) ?? error.repair;
|
|
148
160
|
let message = `${msg} (${code})`;
|
|
149
|
-
if (
|
|
150
|
-
message = `${msg} (${code}). The platform is still preparing this App; retry shortly.`;
|
|
151
|
-
}
|
|
152
|
-
else if (reason === exports.ACCESS_REASONS.permissionMissing) {
|
|
161
|
+
if (reason === exports.ACCESS_REASONS.permissionMissing) {
|
|
153
162
|
message =
|
|
154
163
|
data.missingPermission === 'uns.delete'
|
|
155
164
|
? `Deleting records requires the App key to hold uns.delete, and this App's key does not (${code}). ` +
|
|
@@ -168,17 +177,6 @@ function toDataError(error) {
|
|
|
168
177
|
else if (hint) {
|
|
169
178
|
message = `${message} ${hint}`;
|
|
170
179
|
}
|
|
171
|
-
return new DataError({
|
|
172
|
-
message,
|
|
173
|
-
status: appStatus(httpStatus, retryable),
|
|
174
|
-
code,
|
|
175
|
-
reason,
|
|
176
|
-
upstreamStatus: httpStatus,
|
|
177
|
-
requestId: error.requestId,
|
|
178
|
-
retryable,
|
|
179
|
-
outcomeUnknown,
|
|
180
|
-
details: data,
|
|
181
|
-
cause: error,
|
|
182
|
-
});
|
|
180
|
+
return new DataError({ ...common, message, status: appStatus(httpStatus, code), code, reason, upstreamStatus: httpStatus, details: data });
|
|
183
181
|
}
|
|
184
182
|
//# sourceMappingURL=error.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../../src/data/error.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Runtime failures of a data call, missing credentials included, are a\n * `DataError`. The SDK's UNS client does the HTTP exchange; its `UnsV2Error`\n * (kept as `cause`) is translated here, and the data layer raises its own codes\n * (BATCH_LIMIT_EXCEEDED, WRITE_ERRORS, ...). `status` is the HTTP status the App\n * should answer its own caller with. Writes that fail validation throw\n * `ZodError`; programming or platform errors, such as invalid client options or\n * a malformed data subject from the gateway, throw `TypeError`.\n */\nimport { UnsV2OutcomeUnknownError, type UnsV2Error } from '../uns-v2/client.js';\n\n/**\n * Stable `data.reason` codes UNS adds when it refuses App data access; the\n * top-level code stays FORBIDDEN / NOT_FOUND. Only whole-request errors carry\n * them, never per-item results of a batch or transaction.\n */\nexport const ACCESS_REASONS = {\n /** 403: the collection exists, but this App's grant does not cover it or the operation. */\n notGranted: 'COLLECTION_NOT_GRANTED',\n /** 403 or 404: the collection is gone (hard-deleted or archived). */\n notFound: 'COLLECTION_NOT_FOUND',\n /** 403: the grant covers the operation, the App key lacks `data.missingPermission`. */\n permissionMissing: 'APP_PERMISSION_MISSING',\n} as const;\n\nexport class DataError extends Error {\n /** HTTP status the App should answer with (see `appStatus`). */\n readonly status: number;\n /** UNS error code, e.g. `DUPLICATE_KEY`, or a data-layer code. */\n readonly code: string;\n /** Stable `data.reason` code, e.g. `COLLECTION_NOT_FOUND` (see ACCESS_REASONS). */\n readonly reason?: string;\n /** HTTP status UNS answered with; 0 when no response arrived. */\n readonly upstreamStatus: number;\n readonly requestId?: string;\n readonly retryable: boolean;\n /** A write may have reached UNS: reconcile before replaying it with a new idempotency key. */\n readonly outcomeUnknown: boolean;\n /** The `data` object of the UNS error envelope, or data-layer details. */\n readonly details: Record<string, unknown>;\n\n constructor(init: {\n message: string;\n status: number;\n code: string;\n reason?: string;\n upstreamStatus?: number;\n requestId?: string;\n retryable?: boolean;\n outcomeUnknown?: boolean;\n details?: Record<string, unknown>;\n cause?: unknown;\n }) {\n super(init.message, init.cause === undefined ? undefined : { cause: init.cause });\n this.name = 'DataError';\n this.status = init.status;\n this.code = init.code;\n this.reason = init.reason;\n this.upstreamStatus = init.upstreamStatus ?? 0;\n this.requestId = init.requestId;\n this.retryable = init.retryable ?? false;\n this.outcomeUnknown = init.outcomeUnknown ?? false;\n this.details = init.details ?? {};\n }\n}\n\n/**\n * Maps an upstream UNS status to the status the App answers its own caller\n * with. Credential failures are the platform's problem, not the user's\n * session, so a 401 from UNS becomes 502 instead of looking like a logout,\n * and a retryable 403 becomes 503 instead of looking like a denied action.\n */\nexport function appStatus(upstream: number, retryable = false): number {\n if (upstream === 401) return 502;\n // A retryable refusal is a platform state, not the caller's permission:\n // e.g. FORBIDDEN \"hosted App is not ready\" right after an import.\n if (upstream === 403 && retryable) return 503;\n if (upstream === 400 || upstream === 403 || upstream === 404 || upstream === 409 || upstream === 413 || upstream === 422 || upstream === 429) {\n return upstream;\n }\n if (upstream === 502 || upstream === 503 || upstream === 504) return 503;\n if (upstream >= 500) return 502;\n return upstream >= 400 ? 400 : 502;\n}\n\nconst CODE_HINTS: Record<string, string> = {\n UPSERT_REQUIRES_UNIQUE_INDEX:\n 'An upsert filter must contain `_id` or every field of a unique index that is already ready; a newly declared unique index may still be building.',\n DUPLICATE_KEY:\n 'A unique index already holds this value. (From restore: an active record took the value meanwhile; nothing was restored.)',\n VERSION_CONFLICT: 'The record changed since it was read; reload it and retry with the new revision.',\n APP_GRANT_REVOKED:\n \"A workspace admin revoked this App's access to the collection; it is not re-granted automatically. Ask the admin to restore the grant.\",\n INDEX_QUOTA_EXCEEDED:\n 'The workspace index quota (200, counting every index that physically exists) is exhausted. Remove unused indexes through the tier0 MCP.',\n COLLECTION_TOO_LARGE:\n 'archive / restore handle at most 2000 records; stop using a large collection in code instead of archiving it.',\n};\n\n/** `APP_QUOTA_EXCEEDED` per `data.resource`; each per-App limit is 64. */\nconst QUOTA_HINTS: Record<string, string> = {\n collections: 'This App owns 64 active collections. Archive unused ones through the tier0 MCP.',\n indexes: \"This App's collections hold 64 indexes. Drop unused indexes from the declarations, then apply that with schema:replace through the tier0 MCP.\",\n archivedCollections:\n 'This App keeps 64 archived collections. Restore one, or ask a workspace admin to clean up archived collections.',\n};\n\n/** SDK transport failures: no UNS answer to map, so the data layer names them. */\nconst TRANSPORT_FAILURES: Record<string, { code: string; status: number; retryable: boolean; message: string }> = {\n UNS_V2_TRANSPORT_TIMEOUT: { code: 'DATA_TIMEOUT', status: 503, retryable: true, message: 'UNS did not answer in time' },\n UNS_V2_TRANSPORT_ERROR: { code: 'DATA_UNREACHABLE', status: 503, retryable: true, message: 'Cannot reach the Tier0 data service' },\n UNS_V2_PROTOCOL_ERROR: { code: 'DATA_BAD_RESPONSE', status: 502, retryable: false, message: 'UNS answered with an invalid response' },\n};\n\nfunction codeHint(code: string, details: Record<string, unknown>): string | undefined {\n if (code === 'APP_QUOTA_EXCEEDED') {\n const resource = typeof details.resource === 'string' ? details.resource : '';\n return QUOTA_HINTS[resource] ?? 'This App reached a collection/index quota. Remove unused collections or indexes through the tier0 MCP.';\n }\n return CODE_HINTS[code];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Translates a failed UNS call of the SDK client. */\nexport function toDataError(error: UnsV2Error): DataError {\n const outcomeUnknown = error instanceof UnsV2OutcomeUnknownError;\n // An ingress or load balancer answers 502/503/504 without the UNS envelope during\n // rolling releases and pod restarts: retryable, like any unavailable upstream.\n // UNS v2 routes answer every other error with the envelope (401/403/429 included),\n // so other unenveloped responses stay DATA_BAD_RESPONSE.\n if (error.code === 'UNS_V2_PROTOCOL_ERROR' && (error.status === 502 || error.status === 503 || error.status === 504)) {\n return new DataError({\n message: `The Tier0 data gateway answered ${error.operation} with HTTP ${error.status}; retry shortly${outcomeUnknown ? ' (the write outcome is unknown)' : ''}.`,\n status: 503,\n code: `HTTP_${error.status}`,\n upstreamStatus: error.status,\n retryable: true,\n outcomeUnknown,\n cause: error,\n });\n }\n const transport = TRANSPORT_FAILURES[error.code];\n if (transport) {\n return new DataError({\n message: `${transport.message} (${error.operation})${outcomeUnknown ? '; the write outcome is unknown' : ''}.`,\n status: transport.status,\n code: transport.code,\n upstreamStatus: error.status,\n retryable: transport.retryable,\n outcomeUnknown,\n cause: error,\n });\n }\n\n const httpStatus = error.status ?? 0;\n const data = isObject(error.data) ? error.data : {};\n // Only `data.reason` is a code; `error.reason` repeats the message text.\n const reason = typeof data.reason === 'string' ? data.reason : undefined;\n const retryable = error.retryable || httpStatus === 503 || httpStatus === 504;\n const code = error.code;\n const msg = error.message;\n const hint = codeHint(code, data);\n let message = `${msg} (${code})`;\n if (httpStatus === 403 && retryable) {\n message = `${msg} (${code}). The platform is still preparing this App; retry shortly.`;\n } else if (reason === ACCESS_REASONS.permissionMissing) {\n message =\n data.missingPermission === 'uns.delete'\n ? `Deleting records requires the App key to hold uns.delete, and this App's key does not (${code}). ` +\n 'Model removal as a status change such as `archived`, or ask a workspace admin to grant uns.delete.'\n : `The App key lacks ${typeof data.missingPermission === 'string' ? data.missingPermission : 'a permission'} for this operation (${code}); ask a workspace admin.`;\n } else if (reason === ACCESS_REASONS.notGranted) {\n message = `${message} This App's grant does not cover the collection or operation; ask a workspace admin to restore the grant.`;\n } else if (reason === ACCESS_REASONS.notFound) {\n message = `${message} The collection was archived or deleted; the data layer ensures the declared collections again.`;\n } else if (httpStatus === 401) {\n message = `Tier0 rejected the App credential for ${error.operation} (${code}). The platform injects TIER0_API_KEY; do not replace it.`;\n } else if (hint) {\n message = `${message} ${hint}`;\n }\n\n return new DataError({\n message,\n status: appStatus(httpStatus, retryable),\n code,\n reason,\n upstreamStatus: httpStatus,\n requestId: error.requestId,\n retryable,\n outcomeUnknown,\n details: data,\n cause: error,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../../src/data/error.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Runtime failures of a data call, missing credentials included, are a\n * `DataError`. The SDK's UNS client does the HTTP exchange; its `UnsV2Error`\n * (kept as `cause`) is translated here, and the data layer raises its own codes\n * (BATCH_LIMIT_EXCEEDED, WRITE_ERRORS, ...). `status` is the HTTP status the App\n * should answer its own caller with. Writes that fail validation throw\n * `ZodError`; programming or platform errors, such as invalid client options or\n * a malformed data subject from the gateway, throw `TypeError`.\n */\nimport type { UnsV2Error, UnsV2Execution, UnsV2Retry } from '../uns-v2/client.js';\n\n/**\n * Stable `data.reason` codes UNS adds when it refuses App data access; the\n * top-level code stays FORBIDDEN / NOT_FOUND. Only whole-request errors carry\n * them, never per-item results of a batch or transaction.\n */\nexport const ACCESS_REASONS = {\n /** 403: the collection exists, but this App's grant does not cover it or the operation. */\n notGranted: 'COLLECTION_NOT_GRANTED',\n /** 403 or 404: the collection is gone (hard-deleted or archived). */\n notFound: 'COLLECTION_NOT_FOUND',\n /** 403: the grant covers the operation, the App key lacks `data.missingPermission`. */\n permissionMissing: 'APP_PERMISSION_MISSING',\n} as const;\n\nexport class DataError extends Error {\n /** HTTP status the App should answer with (see `appStatus`). */\n readonly status: number;\n /** UNS error code, e.g. `DUPLICATE_KEY`, or a data-layer code. */\n readonly code: string;\n /** Stable `data.reason` code, e.g. `COLLECTION_NOT_FOUND` (see ACCESS_REASONS). */\n readonly reason?: string;\n /** HTTP status UNS answered with; 0 when no response arrived. */\n readonly upstreamStatus: number;\n readonly requestId?: string;\n /**\n * How far the failed request got: `notStarted` / `rolledBack` changed\n * nothing, `committed` took effect, `unknown` (writes only) may have.\n * Data-layer refusals raised before sending are `notStarted`.\n */\n readonly execution: UnsV2Execution;\n /** Whether the same call may be repeated later, and after how long. The data layer already retried it. */\n readonly retry: UnsV2Retry;\n /** `execution === \"unknown\"`: a write may have landed. Read back before writing again. */\n readonly outcomeUnknown: boolean;\n /** Requests sent for this call, retries included; 0 when nothing was sent. */\n readonly attempts: number;\n /**\n * The idempotency key the write was sent with (generated unless the caller\n * gave one). After `outcomeUnknown`, sending the same write with this key\n * again cannot apply it twice.\n */\n readonly idempotencyKey?: string;\n /** The `data` object of the UNS error envelope, or data-layer details. */\n readonly details: Record<string, unknown>;\n\n constructor(init: {\n message: string;\n status: number;\n code: string;\n reason?: string;\n upstreamStatus?: number;\n requestId?: string;\n execution?: UnsV2Execution;\n retry?: UnsV2Retry;\n attempts?: number;\n idempotencyKey?: string;\n details?: Record<string, unknown>;\n cause?: unknown;\n }) {\n super(init.message, init.cause === undefined ? undefined : { cause: init.cause });\n this.name = 'DataError';\n this.status = init.status;\n this.code = init.code;\n this.reason = init.reason;\n this.upstreamStatus = init.upstreamStatus ?? 0;\n this.requestId = init.requestId;\n this.execution = init.execution ?? 'notStarted';\n this.retry = init.retry ?? { safe: false };\n this.outcomeUnknown = this.execution === 'unknown';\n this.attempts = init.attempts ?? 0;\n this.idempotencyKey = init.idempotencyKey;\n this.details = init.details ?? {};\n }\n}\n\n/** Platform states the App's caller cannot fix: they answer 503 whatever UNS answered. */\nconst PLATFORM_CODES = new Set(['APP_NOT_READY', 'DEPENDENCY_UNAVAILABLE', 'CREDENTIAL_CHANGED', 'OUTCOME_UNKNOWN', 'TEMPORARILY_UNAVAILABLE']);\n\n/**\n * Maps an upstream UNS status and code to the status the App answers its own\n * caller with. Credential failures are the platform's problem, not the user's\n * session, so a 401 from UNS becomes 502 instead of looking like a logout;\n * platform states (App not ready yet, a dependency down, the App key changed\n * mid-request) become 503 instead of looking like a denied action or a conflict.\n */\nexport function appStatus(upstream: number, code = ''): number {\n if (upstream === 401) return 502;\n if (PLATFORM_CODES.has(code)) return 503;\n if (upstream === 400 || upstream === 403 || upstream === 404 || upstream === 409 || upstream === 413 || upstream === 422 || upstream === 429) {\n return upstream;\n }\n if (upstream === 502 || upstream === 503 || upstream === 504) return 503;\n if (upstream >= 500) return 502;\n return upstream >= 400 ? 400 : 502;\n}\n\nconst CODE_HINTS: Record<string, string> = {\n UPSERT_REQUIRES_UNIQUE_INDEX:\n 'An upsert filter must contain `_id` or every field of a unique index that is already ready; a newly declared unique index may still be building.',\n DUPLICATE_KEY:\n 'A unique index already holds this value. (From restore: an active record took the value meanwhile; nothing was restored.)',\n VERSION_CONFLICT: 'The record changed since it was read; reload it and retry with the new revision.',\n APP_GRANT_REVOKED:\n \"A workspace admin revoked this App's access to the collection; it is not re-granted automatically. Ask the admin to restore the grant.\",\n INDEX_QUOTA_EXCEEDED:\n 'The workspace index quota (200, counting every index that physically exists) is exhausted. Remove unused indexes through the tier0 MCP.',\n COLLECTION_TOO_LARGE:\n 'archive / restore handle at most 2000 records; stop using a large collection in code instead of archiving it.',\n OVERLOADED:\n \"This workspace's data requests are over their concurrency share; the data layer already waited and retried. Batch page reads with data.queryBatch and avoid per-record loops.\",\n APP_NOT_READY: 'The platform is still preparing this App (e.g. right after an import); retry shortly.',\n QUERY_TIMEOUT: 'Narrow the query: add an indexed condition, a smaller limit or maxCount.',\n OUTCOME_UNKNOWN: 'The write may have committed; read the record back before writing again.',\n};\n\n/** `APP_QUOTA_EXCEEDED` per `data.resource`; each per-App limit is 64. */\nconst QUOTA_HINTS: Record<string, string> = {\n collections: 'This App owns 64 active collections. Archive unused ones through the tier0 MCP.',\n indexes: \"This App's collections hold 64 indexes. Drop unused indexes from the declarations, then apply that with schema:replace through the tier0 MCP.\",\n archivedCollections:\n 'This App keeps 64 archived collections. Restore one, or ask a workspace admin to clean up archived collections.',\n};\n\n/** SDK transport failures: no UNS answer to map, so the data layer names them. */\nconst TRANSPORT_FAILURES: Record<string, { code: string; status: number; message: string }> = {\n UNS_V2_TRANSPORT_TIMEOUT: { code: 'DATA_TIMEOUT', status: 503, message: 'UNS did not answer in time' },\n UNS_V2_TRANSPORT_ERROR: { code: 'DATA_UNREACHABLE', status: 503, message: 'Cannot reach the Tier0 data service' },\n // The business request was aborted while the call was in flight (499: client closed request).\n UNS_V2_TRANSPORT_ABORTED: { code: 'DATA_ABORTED', status: 499, message: 'The data call was aborted' },\n UNS_V2_PROTOCOL_ERROR: { code: 'DATA_BAD_RESPONSE', status: 502, message: 'UNS answered with an invalid response' },\n};\n\nfunction codeHint(code: string, details: Record<string, unknown>): string | undefined {\n if (code === 'APP_QUOTA_EXCEEDED') {\n const resource = typeof details.resource === 'string' ? details.resource : '';\n return QUOTA_HINTS[resource] ?? 'This App reached a collection/index quota. Remove unused collections or indexes through the tier0 MCP.';\n }\n return CODE_HINTS[code];\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Translates a failed UNS call of the SDK client after `attempts` requests, sent with `idempotencyKey`. */\nexport function toDataError(error: UnsV2Error, attempts = 1, idempotencyKey?: string): DataError {\n const common = {\n upstreamStatus: error.status,\n requestId: error.requestId,\n execution: error.execution,\n retry: error.retry,\n attempts,\n idempotencyKey,\n cause: error,\n };\n const unknown = error.outcomeUnknown ? '; the write outcome is unknown' : '';\n // An ingress or load balancer answers 502/503/504 without the UNS envelope during\n // rolling releases and pod restarts, like any unavailable upstream. UNS v2 routes\n // answer every other error with the envelope (401/403/429 included), so other\n // unenveloped responses stay DATA_BAD_RESPONSE.\n if (error.code === 'UNS_V2_PROTOCOL_ERROR' && (error.status === 502 || error.status === 503 || error.status === 504)) {\n return new DataError({\n ...common,\n message: `The Tier0 data gateway answered ${error.operation} with HTTP ${error.status}${unknown}.`,\n status: 503,\n code: `HTTP_${error.status}`,\n });\n }\n const transport = TRANSPORT_FAILURES[error.code];\n if (transport) {\n return new DataError({ ...common, message: `${transport.message} (${error.operation})${unknown}.`, status: transport.status, code: transport.code });\n }\n\n const httpStatus = error.status ?? 0;\n const data = isObject(error.data) ? error.data : {};\n // Only `data.reason` is a code; `error.reason` repeats the message text.\n const reason = typeof data.reason === 'string' ? data.reason : undefined;\n const code = error.code;\n const msg = error.message;\n const hint = codeHint(code, data) ?? error.repair;\n let message = `${msg} (${code})`;\n if (reason === ACCESS_REASONS.permissionMissing) {\n message =\n data.missingPermission === 'uns.delete'\n ? `Deleting records requires the App key to hold uns.delete, and this App's key does not (${code}). ` +\n 'Model removal as a status change such as `archived`, or ask a workspace admin to grant uns.delete.'\n : `The App key lacks ${typeof data.missingPermission === 'string' ? data.missingPermission : 'a permission'} for this operation (${code}); ask a workspace admin.`;\n } else if (reason === ACCESS_REASONS.notGranted) {\n message = `${message} This App's grant does not cover the collection or operation; ask a workspace admin to restore the grant.`;\n } else if (reason === ACCESS_REASONS.notFound) {\n message = `${message} The collection was archived or deleted; the data layer ensures the declared collections again.`;\n } else if (httpStatus === 401) {\n message = `Tier0 rejected the App credential for ${error.operation} (${code}). The platform injects TIER0_API_KEY; do not replace it.`;\n } else if (hint) {\n message = `${message} ${hint}`;\n }\n\n return new DataError({ ...common, message, status: appStatus(httpStatus, code), code, reason, upstreamStatus: httpStatus, details: data });\n}\n"]}
|
package/dist/cjs/data/index.d.ts
CHANGED
|
@@ -10,11 +10,14 @@
|
|
|
10
10
|
* Client code imports declarations and types from `@tier0/sdk-v2/data/define`.
|
|
11
11
|
*/
|
|
12
12
|
export { createDataClient } from './client.js';
|
|
13
|
-
export
|
|
13
|
+
export { MAX_BATCH_QUERIES } from './client.js';
|
|
14
|
+
export type { BatchQueries, BatchResults, DataClient, DataClientConfig, SettledBatchResults, TransactAction, TransactResult, TransactResultItem, TransactStep } from './client.js';
|
|
14
15
|
export type { DataEnvironment, EnsureConflict, EnsureNote, EnsureResult, EnsureState, EnsureWarning, Logger } from './bootstrap.js';
|
|
15
|
-
export { MAX_ATOMIC_ITEMS } from './collection.js';
|
|
16
|
-
export type { BulkOperation, Collection, Cursor, FindOneAndOptions, FindOptions, FindPageOptions, Projection, Update, UpdateOptions, WithMeta } from './collection.js';
|
|
16
|
+
export { MAX_ATOMIC_ITEMS, MAX_GET_IDS } from './collection.js';
|
|
17
|
+
export type { BatchQuery, BulkOperation, CappedCount, Collection, CollectionQueries, Cursor, DeepPartial, FoundPage, ValueCount, FindOneAndOptions, FindOptions, FindPageOptions, InsertOneOptions, Projection, Update, UpdateOptions, WithMeta } from './collection.js';
|
|
17
18
|
export { currentDataSubject, runAsApp, runWithRequestContext } from './context.js';
|
|
19
|
+
export { redactRestricted, SUBSCRIBE_IDLE_TIMEOUT_MS } from './subscribe.js';
|
|
20
|
+
export type { ChangeEvent, CollectionChange, RecordChange, SubscribeOptions, SubscriptionEvent } from './subscribe.js';
|
|
18
21
|
export { ACCESS_REASONS, DataError } from './error.js';
|
|
19
22
|
export * from './declarations.js';
|
|
20
23
|
export { toSortPairs } from './sort.js';
|
package/dist/cjs/data/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.toSortPairs = exports.DataError = exports.ACCESS_REASONS = exports.runWithRequestContext = exports.runAsApp = exports.currentDataSubject = exports.MAX_ATOMIC_ITEMS = exports.createDataClient = void 0;
|
|
17
|
+
exports.toSortPairs = exports.DataError = exports.ACCESS_REASONS = exports.SUBSCRIBE_IDLE_TIMEOUT_MS = exports.redactRestricted = exports.runWithRequestContext = exports.runAsApp = exports.currentDataSubject = exports.MAX_GET_IDS = exports.MAX_ATOMIC_ITEMS = exports.MAX_BATCH_QUERIES = exports.createDataClient = void 0;
|
|
18
18
|
/**
|
|
19
19
|
* `@tier0/sdk-v2/data` — server-only App data layer over Tier0 UNS collections.
|
|
20
20
|
*
|
|
@@ -28,12 +28,18 @@ exports.toSortPairs = exports.DataError = exports.ACCESS_REASONS = exports.runWi
|
|
|
28
28
|
*/
|
|
29
29
|
var client_js_1 = require("./client.js");
|
|
30
30
|
Object.defineProperty(exports, "createDataClient", { enumerable: true, get: function () { return client_js_1.createDataClient; } });
|
|
31
|
+
var client_js_2 = require("./client.js");
|
|
32
|
+
Object.defineProperty(exports, "MAX_BATCH_QUERIES", { enumerable: true, get: function () { return client_js_2.MAX_BATCH_QUERIES; } });
|
|
31
33
|
var collection_js_1 = require("./collection.js");
|
|
32
34
|
Object.defineProperty(exports, "MAX_ATOMIC_ITEMS", { enumerable: true, get: function () { return collection_js_1.MAX_ATOMIC_ITEMS; } });
|
|
35
|
+
Object.defineProperty(exports, "MAX_GET_IDS", { enumerable: true, get: function () { return collection_js_1.MAX_GET_IDS; } });
|
|
33
36
|
var context_js_1 = require("./context.js");
|
|
34
37
|
Object.defineProperty(exports, "currentDataSubject", { enumerable: true, get: function () { return context_js_1.currentDataSubject; } });
|
|
35
38
|
Object.defineProperty(exports, "runAsApp", { enumerable: true, get: function () { return context_js_1.runAsApp; } });
|
|
36
39
|
Object.defineProperty(exports, "runWithRequestContext", { enumerable: true, get: function () { return context_js_1.runWithRequestContext; } });
|
|
40
|
+
var subscribe_js_1 = require("./subscribe.js");
|
|
41
|
+
Object.defineProperty(exports, "redactRestricted", { enumerable: true, get: function () { return subscribe_js_1.redactRestricted; } });
|
|
42
|
+
Object.defineProperty(exports, "SUBSCRIBE_IDLE_TIMEOUT_MS", { enumerable: true, get: function () { return subscribe_js_1.SUBSCRIBE_IDLE_TIMEOUT_MS; } });
|
|
37
43
|
var error_js_1 = require("./error.js");
|
|
38
44
|
Object.defineProperty(exports, "ACCESS_REASONS", { enumerable: true, get: function () { return error_js_1.ACCESS_REASONS; } });
|
|
39
45
|
Object.defineProperty(exports, "DataError", { enumerable: true, get: function () { return error_js_1.DataError; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/data/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;GAUG;AACH,yCAA+C;AAAtC,6GAAA,gBAAgB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/data/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;GAUG;AACH,yCAA+C;AAAtC,6GAAA,gBAAgB,OAAA;AACzB,yCAAgD;AAAvC,8GAAA,iBAAiB,OAAA;AAG1B,iDAAgE;AAAvD,iHAAA,gBAAgB,OAAA;AAAE,4GAAA,WAAW,OAAA;AAEtC,2CAAmF;AAA1E,gHAAA,kBAAkB,OAAA;AAAE,sGAAA,QAAQ,OAAA;AAAE,mHAAA,qBAAqB,OAAA;AAC5D,+CAA6E;AAApE,gHAAA,gBAAgB,OAAA;AAAE,yHAAA,yBAAyB,OAAA;AAEpD,uCAAuD;AAA9C,0GAAA,cAAc,OAAA;AAAE,qGAAA,SAAS,OAAA;AAClC,oDAAkC;AAClC,qCAAwC;AAA/B,sGAAA,WAAW,OAAA","sourcesContent":["/**\n * `@tier0/sdk-v2/data` — server-only App data layer over Tier0 UNS collections.\n *\n * import { createDataClient, defineCollection } from '@tier0/sdk-v2/data';\n *\n * const data = createDataClient({ collections: [workOrders] });\n * const open = await data.collection(workOrders).find({ status: 'OPEN' }, { limit: 50 }).toArray();\n *\n * Declarations are ensured in one batch on first access. Requires `zod` 4.\n * Client code imports declarations and types from `@tier0/sdk-v2/data/define`.\n */\nexport { createDataClient } from './client.js';\nexport { MAX_BATCH_QUERIES } from './client.js';\nexport type { BatchQueries, BatchResults, DataClient, DataClientConfig, SettledBatchResults, TransactAction, TransactResult, TransactResultItem, TransactStep } from './client.js';\nexport type { DataEnvironment, EnsureConflict, EnsureNote, EnsureResult, EnsureState, EnsureWarning, Logger } from './bootstrap.js';\nexport { MAX_ATOMIC_ITEMS, MAX_GET_IDS } from './collection.js';\nexport type { BatchQuery, BulkOperation, CappedCount, Collection, CollectionQueries, Cursor, DeepPartial, FoundPage, ValueCount, FindOneAndOptions, FindOptions, FindPageOptions, InsertOneOptions, Projection, Update, UpdateOptions, WithMeta } from './collection.js';\nexport { currentDataSubject, runAsApp, runWithRequestContext } from './context.js';\nexport { redactRestricted, SUBSCRIBE_IDLE_TIMEOUT_MS } from './subscribe.js';\nexport type { ChangeEvent, CollectionChange, RecordChange, SubscribeOptions, SubscriptionEvent } from './subscribe.js';\nexport { ACCESS_REASONS, DataError } from './error.js';\nexport * from './declarations.js';\nexport { toSortPairs } from './sort.js';\nexport type { Filter, Sort, SortDirection, SortPairs } from './sort.js';\n"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* UNS stores one closed JSON-schema subset per collection: `type`,
|
|
5
5
|
* `properties`, `required`, `additionalProperties: false`, `items`, `enum`,
|
|
6
|
-
* `minimum`, `maximum`, `title`, `description`. `toRecordSchema` converts the
|
|
6
|
+
* `minimum`, `maximum`, declared `format`, `title`, `description`. `toRecordSchema` converts the
|
|
7
7
|
* `z.toJSONSchema` output into exactly that subset and rejects every other
|
|
8
8
|
* keyword with a concrete replacement, so a declaration that cannot be stored
|
|
9
9
|
* fails when it is compiled (an App can compile its declarations at build
|
|
@@ -15,6 +15,8 @@ export type RecordSchemaType = 'object' | 'array' | 'string' | 'number' | 'integ
|
|
|
15
15
|
export type EnumValue = string | number | boolean;
|
|
16
16
|
export interface RecordSchema {
|
|
17
17
|
type: RecordSchemaType;
|
|
18
|
+
/** Display annotation; does not add range/date checks or convert stored values. */
|
|
19
|
+
format?: 'int32' | 'float' | 'double' | 'date-time';
|
|
18
20
|
title?: string;
|
|
19
21
|
description?: string;
|
|
20
22
|
properties?: Record<string, RecordSchema>;
|
|
@@ -30,6 +32,7 @@ export interface NormalizedIndex {
|
|
|
30
32
|
paths?: string[];
|
|
31
33
|
unique?: true;
|
|
32
34
|
kind?: 'gin';
|
|
35
|
+
expireAfterSeconds?: number;
|
|
33
36
|
}
|
|
34
37
|
/** One ensure item, exactly as it is sent to `/uns/app/collections/ensure`. */
|
|
35
38
|
export interface CompiledCollection {
|
|
@@ -56,6 +59,9 @@ export declare const SCHEMA_LIMITS: {
|
|
|
56
59
|
readonly description: 2048;
|
|
57
60
|
readonly indexes: 16;
|
|
58
61
|
readonly indexPaths: 3;
|
|
62
|
+
readonly ttlIndexes: 1;
|
|
63
|
+
readonly minExpireAfterSeconds: 60;
|
|
64
|
+
readonly maxExpireAfterSeconds: 31536000;
|
|
59
65
|
};
|
|
60
66
|
type JsonNode = Record<string, unknown>;
|
|
61
67
|
/** Raw `z.toJSONSchema` output; exported for the snapshot tests. */
|