@tier0/sdk-v2 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/NOTICE.md +7 -0
- package/README.md +201 -2
- package/dist/cjs/app-identity-contract.generated.d.ts +22 -0
- package/dist/cjs/app-identity-contract.generated.js +51 -0
- package/dist/cjs/app-identity-contract.generated.js.map +1 -0
- package/dist/cjs/capabilities.d.ts +54 -0
- package/dist/cjs/capabilities.js +134 -0
- package/dist/cjs/capabilities.js.map +1 -0
- package/dist/cjs/client.d.ts +604 -0
- package/dist/cjs/client.js +35 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/cloud-server.d.ts +31 -0
- package/dist/cjs/cloud-server.js +114 -0
- package/dist/cjs/cloud-server.js.map +1 -0
- package/dist/cjs/cloud-transport.d.ts +46 -0
- package/dist/cjs/cloud-transport.js +192 -0
- package/dist/cjs/cloud-transport.js.map +1 -0
- package/dist/cjs/controls.d.ts +93 -0
- package/dist/cjs/controls.js +169 -0
- package/dist/cjs/controls.js.map +1 -0
- package/dist/cjs/data/bootstrap.d.ts +66 -0
- package/dist/cjs/data/bootstrap.js +282 -0
- package/dist/cjs/data/bootstrap.js.map +1 -0
- package/dist/cjs/data/call.d.ts +16 -0
- package/dist/cjs/data/call.js +51 -0
- package/dist/cjs/data/call.js.map +1 -0
- package/dist/cjs/data/client.d.ts +92 -0
- package/dist/cjs/data/client.js +102 -0
- package/dist/cjs/data/client.js.map +1 -0
- package/dist/cjs/data/collection.d.ts +238 -0
- package/dist/cjs/data/collection.js +441 -0
- package/dist/cjs/data/collection.js.map +1 -0
- package/dist/cjs/data/context.d.ts +10 -0
- package/dist/cjs/data/context.js +39 -0
- package/dist/cjs/data/context.js.map +1 -0
- package/dist/cjs/data/declarations.d.ts +11 -0
- package/dist/cjs/data/declarations.js +18 -0
- package/dist/cjs/data/declarations.js.map +1 -0
- package/dist/cjs/data/define.d.ts +69 -0
- package/dist/cjs/data/define.js +31 -0
- package/dist/cjs/data/define.js.map +1 -0
- package/dist/cjs/data/error.d.ts +60 -0
- package/dist/cjs/data/error.js +184 -0
- package/dist/cjs/data/error.js.map +1 -0
- package/dist/cjs/data/index.d.ts +21 -0
- package/dist/cjs/data/index.js +43 -0
- package/dist/cjs/data/index.js.map +1 -0
- package/dist/cjs/data/schema.d.ts +82 -0
- package/dist/cjs/data/schema.js +607 -0
- package/dist/cjs/data/schema.js.map +1 -0
- package/dist/cjs/data/sort.d.ts +8 -0
- package/dist/cjs/data/sort.js +21 -0
- package/dist/cjs/data/sort.js.map +1 -0
- package/dist/cjs/files.d.ts +67 -0
- package/dist/cjs/files.js +119 -0
- package/dist/cjs/files.js.map +1 -0
- package/dist/cjs/framework-scope.d.ts +1 -0
- package/dist/cjs/framework-scope.js +14 -0
- package/dist/cjs/framework-scope.js.map +1 -0
- package/dist/cjs/index.d.ts +14 -0
- package/dist/cjs/index.js +33 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/mq/broker.d.ts +65 -0
- package/dist/cjs/mq/broker.js +115 -0
- package/dist/cjs/mq/broker.js.map +1 -0
- package/dist/cjs/mq/client.d.ts +37 -0
- package/dist/cjs/mq/client.js +321 -0
- package/dist/cjs/mq/client.js.map +1 -0
- package/dist/cjs/mq/index.d.ts +5 -0
- package/dist/cjs/mq/index.js +11 -0
- package/dist/cjs/mq/index.js.map +1 -0
- package/dist/cjs/mq/types.d.ts +48 -0
- package/dist/cjs/mq/types.js +3 -0
- package/dist/cjs/mq/types.js.map +1 -0
- package/dist/cjs/openapi/api.generated.d.ts +820 -0
- package/dist/cjs/openapi/api.generated.js +607 -0
- package/dist/cjs/openapi/api.generated.js.map +1 -0
- package/dist/cjs/openapi/client.d.ts +56 -0
- package/dist/cjs/openapi/client.js +219 -0
- package/dist/cjs/openapi/client.js.map +1 -0
- package/dist/cjs/openapi/codecs.generated.d.ts +2234 -0
- package/dist/cjs/openapi/codecs.generated.js +6 -0
- package/dist/cjs/openapi/codecs.generated.js.map +1 -0
- package/dist/cjs/openapi/index.d.ts +5 -0
- package/dist/cjs/openapi/index.js +12 -0
- package/dist/cjs/openapi/index.js.map +1 -0
- package/dist/cjs/openapi/types.generated.d.ts +3227 -0
- package/dist/cjs/openapi/types.generated.js +3 -0
- package/dist/cjs/openapi/types.generated.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/react.d.ts +9 -0
- package/dist/cjs/react.js +16 -0
- package/dist/cjs/react.js.map +1 -0
- package/dist/cjs/runtime-context.d.ts +9 -0
- package/dist/cjs/runtime-context.js +25 -0
- package/dist/cjs/runtime-context.js.map +1 -0
- package/dist/cjs/runtime-env.d.ts +1 -0
- package/dist/cjs/runtime-env.js +18 -0
- package/dist/cjs/runtime-env.js.map +1 -0
- package/dist/cjs/source.d.ts +39 -0
- package/dist/cjs/source.js +29 -0
- package/dist/cjs/source.js.map +1 -0
- package/dist/cjs/stream.d.ts +40 -0
- package/dist/cjs/stream.js +33 -0
- package/dist/cjs/stream.js.map +1 -0
- package/dist/cjs/uns-v2/client.d.ts +54 -0
- package/dist/cjs/uns-v2/client.js +177 -0
- package/dist/cjs/uns-v2/client.js.map +1 -0
- package/dist/cjs/uns-v2/codec.d.ts +11 -0
- package/dist/cjs/uns-v2/codec.js +290 -0
- package/dist/cjs/uns-v2/codec.js.map +1 -0
- package/dist/cjs/uns-v2/data-client.d.ts +10 -0
- package/dist/cjs/uns-v2/data-client.js +18 -0
- package/dist/cjs/uns-v2/data-client.js.map +1 -0
- package/dist/cjs/uns-v2/generated.d.ts +15551 -0
- package/dist/cjs/uns-v2/generated.js +139 -0
- package/dist/cjs/uns-v2/generated.js.map +1 -0
- package/dist/cjs/uns-v2/index.d.ts +5 -0
- package/dist/cjs/uns-v2/index.js +24 -0
- package/dist/cjs/uns-v2/index.js.map +1 -0
- package/dist/cjs/vue.d.ts +9 -0
- package/dist/cjs/vue.js +39 -0
- package/dist/cjs/vue.js.map +1 -0
- package/dist/esm/app-identity-contract.generated.d.ts +22 -0
- package/dist/esm/app-identity-contract.generated.js +48 -0
- package/dist/esm/app-identity-contract.generated.js.map +1 -0
- package/dist/esm/capabilities.d.ts +54 -0
- package/dist/esm/capabilities.js +129 -0
- package/dist/esm/capabilities.js.map +1 -0
- package/dist/esm/client.d.ts +604 -0
- package/dist/esm/client.js +32 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/cloud-server.d.ts +31 -0
- package/dist/esm/cloud-server.js +109 -0
- package/dist/esm/cloud-server.js.map +1 -0
- package/dist/esm/cloud-transport.d.ts +46 -0
- package/dist/esm/cloud-transport.js +187 -0
- package/dist/esm/cloud-transport.js.map +1 -0
- package/dist/esm/controls.d.ts +93 -0
- package/dist/esm/controls.js +163 -0
- package/dist/esm/controls.js.map +1 -0
- package/dist/esm/data/bootstrap.d.ts +66 -0
- package/dist/esm/data/bootstrap.js +277 -0
- package/dist/esm/data/bootstrap.js.map +1 -0
- package/dist/esm/data/call.d.ts +16 -0
- package/dist/esm/data/call.js +47 -0
- package/dist/esm/data/call.js.map +1 -0
- package/dist/esm/data/client.d.ts +92 -0
- package/dist/esm/data/client.js +99 -0
- package/dist/esm/data/client.js.map +1 -0
- package/dist/esm/data/collection.d.ts +238 -0
- package/dist/esm/data/collection.js +434 -0
- package/dist/esm/data/collection.js.map +1 -0
- package/dist/esm/data/context.d.ts +10 -0
- package/dist/esm/data/context.js +34 -0
- package/dist/esm/data/context.js.map +1 -0
- package/dist/esm/data/declarations.d.ts +11 -0
- package/dist/esm/data/declarations.js +10 -0
- package/dist/esm/data/declarations.js.map +1 -0
- package/dist/esm/data/define.d.ts +69 -0
- package/dist/esm/data/define.js +27 -0
- package/dist/esm/data/define.js.map +1 -0
- package/dist/esm/data/error.d.ts +60 -0
- package/dist/esm/data/error.js +178 -0
- package/dist/esm/data/error.js.map +1 -0
- package/dist/esm/data/index.d.ts +21 -0
- package/dist/esm/data/index.js +18 -0
- package/dist/esm/data/index.js.map +1 -0
- package/dist/esm/data/schema.d.ts +82 -0
- package/dist/esm/data/schema.js +596 -0
- package/dist/esm/data/schema.js.map +1 -0
- package/dist/esm/data/sort.d.ts +8 -0
- package/dist/esm/data/sort.js +18 -0
- package/dist/esm/data/sort.js.map +1 -0
- package/dist/esm/files.d.ts +67 -0
- package/dist/esm/files.js +113 -0
- package/dist/esm/files.js.map +1 -0
- package/dist/esm/framework-scope.d.ts +1 -0
- package/dist/esm/framework-scope.js +11 -0
- package/dist/esm/framework-scope.js.map +1 -0
- package/dist/esm/index.d.ts +14 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/mq/broker.d.ts +65 -0
- package/dist/esm/mq/broker.js +109 -0
- package/dist/esm/mq/broker.js.map +1 -0
- package/dist/esm/mq/client.d.ts +37 -0
- package/dist/esm/mq/client.js +314 -0
- package/dist/esm/mq/client.js.map +1 -0
- package/dist/esm/mq/index.d.ts +5 -0
- package/dist/esm/mq/index.js +3 -0
- package/dist/esm/mq/index.js.map +1 -0
- package/dist/esm/mq/types.d.ts +48 -0
- package/dist/esm/mq/types.js +2 -0
- package/dist/esm/mq/types.js.map +1 -0
- package/dist/esm/openapi/api.generated.d.ts +820 -0
- package/dist/esm/openapi/api.generated.js +603 -0
- package/dist/esm/openapi/api.generated.js.map +1 -0
- package/dist/esm/openapi/client.d.ts +56 -0
- package/dist/esm/openapi/client.js +210 -0
- package/dist/esm/openapi/client.js.map +1 -0
- package/dist/esm/openapi/codecs.generated.d.ts +2234 -0
- package/dist/esm/openapi/codecs.generated.js +3 -0
- package/dist/esm/openapi/codecs.generated.js.map +1 -0
- package/dist/esm/openapi/index.d.ts +5 -0
- package/dist/esm/openapi/index.js +3 -0
- package/dist/esm/openapi/index.js.map +1 -0
- package/dist/esm/openapi/types.generated.d.ts +3227 -0
- package/dist/esm/openapi/types.generated.js +2 -0
- package/dist/esm/openapi/types.generated.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/react.d.ts +9 -0
- package/dist/esm/react.js +12 -0
- package/dist/esm/react.js.map +1 -0
- package/dist/esm/runtime-context.d.ts +9 -0
- package/dist/esm/runtime-context.js +22 -0
- package/dist/esm/runtime-context.js.map +1 -0
- package/dist/esm/runtime-env.d.ts +1 -0
- package/dist/esm/runtime-env.js +15 -0
- package/dist/esm/runtime-env.js.map +1 -0
- package/dist/esm/source.d.ts +39 -0
- package/dist/esm/source.js +25 -0
- package/dist/esm/source.js.map +1 -0
- package/dist/esm/stream.d.ts +40 -0
- package/dist/esm/stream.js +29 -0
- package/dist/esm/stream.js.map +1 -0
- package/dist/esm/uns-v2/client.d.ts +54 -0
- package/dist/esm/uns-v2/client.js +170 -0
- package/dist/esm/uns-v2/client.js.map +1 -0
- package/dist/esm/uns-v2/codec.d.ts +11 -0
- package/dist/esm/uns-v2/codec.js +284 -0
- package/dist/esm/uns-v2/codec.js.map +1 -0
- package/dist/esm/uns-v2/data-client.d.ts +10 -0
- package/dist/esm/uns-v2/data-client.js +14 -0
- package/dist/esm/uns-v2/data-client.js.map +1 -0
- package/dist/esm/uns-v2/generated.d.ts +15551 -0
- package/dist/esm/uns-v2/generated.js +136 -0
- package/dist/esm/uns-v2/generated.js.map +1 -0
- package/dist/esm/uns-v2/index.d.ts +5 -0
- package/dist/esm/uns-v2/index.js +5 -0
- package/dist/esm/uns-v2/index.js.map +1 -0
- package/dist/esm/vue.d.ts +9 -0
- package/dist/esm/vue.js +36 -0
- package/dist/esm/vue.js.map +1 -0
- package/docs/acceptance-2026-10-22.md +88 -0
- package/package.json +242 -4
- package/skills/tier0-sdk-v2/SKILL.md +66 -0
- package/skills/tier0-sdk-v2/references/integration.md +72 -0
- package/skills/tier0-sdk-v2-agent/SKILL.md +73 -0
- package/skills/tier0-sdk-v2-agent/references/results.md +45 -0
- package/skills/tier0-sdk-v2-controls/SKILL.md +63 -0
- package/skills/tier0-sdk-v2-data/SKILL.md +57 -0
- package/skills/tier0-sdk-v2-data/references/consistency.md +70 -0
- package/skills/tier0-sdk-v2-data/references/errors.md +69 -0
- package/skills/tier0-sdk-v2-data/references/modeling.md +77 -0
- package/skills/tier0-sdk-v2-data/references/read-write.md +72 -0
- package/skills/tier0-sdk-v2-data/references/schema-evolution.md +36 -0
- package/skills/tier0-sdk-v2-files/SKILL.md +85 -0
- package/skills/tier0-sdk-v2-files/references/delete.md +22 -0
- package/skills/tier0-sdk-v2-files/references/download.md +49 -0
- package/skills/tier0-sdk-v2-files/references/multipart.md +42 -0
- package/skills/tier0-sdk-v2-files/references/upload.md +27 -0
- package/skills/tier0-sdk-v2-files/references/url.md +22 -0
- package/skills/tier0-sdk-v2-members/SKILL.md +56 -0
- package/skills/tier0-sdk-v2-members/references/app-members.md +41 -0
- package/skills/tier0-sdk-v2-members/references/platform-members.md +56 -0
- package/skills/tier0-sdk-v2-mq/SKILL.md +78 -0
- package/skills/tier0-sdk-v2-mq/references/quickstart.md +69 -0
- package/skills/tier0-sdk-v2-notifications/SKILL.md +42 -0
- package/skills/tier0-sdk-v2-notifications/references/get.md +34 -0
- package/skills/tier0-sdk-v2-notifications/references/send.md +72 -0
- package/skills/tier0-sdk-v2-source/SKILL.md +38 -0
- package/skills/tier0-sdk-v2-source/references/changes.md +40 -0
- package/skills/tier0-sdk-v2-source/references/create.md +63 -0
- package/skills/tier0-sdk-v2-source/references/delete.md +47 -0
- package/skills/tier0-sdk-v2-source/references/protocols.md +36 -0
- package/skills/tier0-sdk-v2-source/references/read.md +34 -0
- package/skills/tier0-sdk-v2-source/references/state.md +37 -0
- package/skills/tier0-sdk-v2-source/references/update.md +61 -0
- package/skills/tier0-sdk-v2-stream/SKILL.md +43 -0
- package/skills/tier0-sdk-v2-stream/references/create.md +55 -0
- package/skills/tier0-sdk-v2-stream/references/delete.md +35 -0
- package/skills/tier0-sdk-v2-stream/references/deploy.md +63 -0
- package/skills/tier0-sdk-v2-stream/references/lifecycle.md +25 -0
- package/skills/tier0-sdk-v2-stream/references/read.md +35 -0
- package/skills/tier0-sdk-v2-stream/references/update.md +35 -0
- package/skills/tier0-sdk-v2-system/SKILL.md +64 -0
- package/skills/tier0-sdk-v2-system/references/info.md +23 -0
- package/skills/tier0-sdk-v2-system/references/whoami.md +21 -0
- package/skills/tier0-sdk-v2-uns/SKILL.md +53 -0
- package/skills/tier0-sdk-v2-uns/references/create.md +85 -0
- package/skills/tier0-sdk-v2-uns/references/data-workflows.md +73 -0
- package/skills/tier0-sdk-v2-uns/references/delete.md +69 -0
- package/skills/tier0-sdk-v2-uns/references/namespace.md +75 -0
- package/skills/tier0-sdk-v2-uns/references/read.md +32 -0
- package/skills/tier0-sdk-v2-uns/references/restore.md +41 -0
- package/skills/tier0-sdk-v2-uns/references/update.md +86 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_DATA_TIMEOUT_MS = void 0;
|
|
4
|
+
exports.createDataCall = createDataCall;
|
|
5
|
+
/**
|
|
6
|
+
* One UNS call of the data layer. The SDK's UNS client resolves host and key,
|
|
7
|
+
* sends the request and checks the envelope; this binds the employee data
|
|
8
|
+
* subject of the current call and turns every failure into a `DataError`.
|
|
9
|
+
*/
|
|
10
|
+
const client_js_1 = require("../openapi/client.js");
|
|
11
|
+
const client_js_2 = require("../uns-v2/client.js");
|
|
12
|
+
const error_js_1 = require("./error.js");
|
|
13
|
+
/** UNS statements time out at 15 s, so a data call waits no longer by default. */
|
|
14
|
+
exports.DEFAULT_DATA_TIMEOUT_MS = 15_000;
|
|
15
|
+
function createDataCall(config) {
|
|
16
|
+
const http = new client_js_1.HttpClient(config);
|
|
17
|
+
const resolve = () => http;
|
|
18
|
+
const transport = { transportTimeoutMs: config.transportTimeoutMs ?? exports.DEFAULT_DATA_TIMEOUT_MS };
|
|
19
|
+
const app = new client_js_2.UnsV2ClientCore(resolve, transport);
|
|
20
|
+
function assertConfigured() {
|
|
21
|
+
let problem;
|
|
22
|
+
try {
|
|
23
|
+
http.getBaseURL();
|
|
24
|
+
if (!http.getApiKey()?.trim())
|
|
25
|
+
problem = 'TIER0_API_KEY is not set';
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
problem = error instanceof Error ? error.message : String(error);
|
|
29
|
+
}
|
|
30
|
+
if (problem) {
|
|
31
|
+
throw new error_js_1.DataError({
|
|
32
|
+
message: `${problem}. The platform injects TIER0_API_HOST and TIER0_API_KEY in Preview and deployments; for local development set them before starting the App.`,
|
|
33
|
+
status: 503,
|
|
34
|
+
code: 'DATA_NOT_CONFIGURED',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return async function call(operation, request, options = {}) {
|
|
39
|
+
assertConfigured();
|
|
40
|
+
// The SDK binds a data subject to one client; App-level calls use the shared one without it.
|
|
41
|
+
const core = options.dataSubject ? new client_js_2.UnsV2ClientCore(resolve, { ...transport, unsV2AppDataSubject: options.dataSubject }) : app;
|
|
42
|
+
try {
|
|
43
|
+
const response = await core.call(operation, request);
|
|
44
|
+
return response.data;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw error instanceof client_js_2.UnsV2Error ? (0, error_js_1.toDataError)(error) : error;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call.js","sourceRoot":"","sources":["../../../src/data/call.ts"],"names":[],"mappings":";;;AAqBA,wCAkCC;AAvDD;;;;GAIG;AACH,oDAAqE;AACrE,mDAAkE;AAElE,yCAAoD;AAEpD,kFAAkF;AACrE,QAAA,uBAAuB,GAAG,MAAM,CAAC;AAU9C,SAAgB,cAAc,CAAC,MAAoB;IACjD,MAAM,IAAI,GAAG,IAAI,sBAAU,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;IAC3B,MAAM,SAAS,GAAG,EAAE,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,+BAAuB,EAAE,CAAC;IAC/F,MAAM,GAAG,GAAG,IAAI,2BAAe,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAEpD,SAAS,gBAAgB;QACvB,IAAI,OAA2B,CAAC;QAChC,IAAI,CAAC;YACH,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE;gBAAE,OAAO,GAAG,0BAA0B,CAAC;QACtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,IAAI,oBAAS,CAAC;gBAClB,OAAO,EAAE,GAAG,OAAO,6IAA6I;gBAChK,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE,qBAAqB;aAC5B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,KAAK,UAAU,IAAI,CAAI,SAA6B,EAAE,OAAgC,EAAE,UAAuB,EAAE;QACtH,gBAAgB,EAAE,CAAC;QACnB,6FAA6F;QAC7F,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,2BAAe,CAAC,OAAO,EAAE,EAAE,GAAG,SAAS,EAAE,mBAAmB,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAClI,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAyC,CAAC,CAAC;YACvF,OAAO,QAAQ,CAAC,IAAS,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,YAAY,sBAAU,CAAC,CAAC,CAAC,IAAA,sBAAW,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACjE,CAAC;IACH,CAAC,CAAC;AACJ,CAAC","sourcesContent":["/**\n * One UNS call of the data layer. The SDK's UNS client resolves host and key,\n * sends the request and checks the envelope; this binds the employee data\n * subject of the current call and turns every failure into a `DataError`.\n */\nimport { HttpClient, type ClientConfig } from '../openapi/client.js';\nimport { UnsV2ClientCore, UnsV2Error } from '../uns-v2/client.js';\nimport type { UnsV2OperationName, UnsV2Request } from '../uns-v2/generated.js';\nimport { DataError, toDataError } from './error.js';\n\n/** UNS statements time out at 15 s, so a data call waits no longer by default. */\nexport const DEFAULT_DATA_TIMEOUT_MS = 15_000;\n\nexport interface CallOptions {\n /** Employee assertion forwarded from the current business request. */\n dataSubject?: string;\n}\n\n/** Sends one operation and resolves with the envelope's `data`. */\nexport type DataCall = <T>(operation: UnsV2OperationName, request: Record<string, unknown>, options?: CallOptions) => Promise<T>;\n\nexport function createDataCall(config: ClientConfig): DataCall {\n const http = new HttpClient(config);\n const resolve = () => http;\n const transport = { transportTimeoutMs: config.transportTimeoutMs ?? DEFAULT_DATA_TIMEOUT_MS };\n const app = new UnsV2ClientCore(resolve, transport);\n\n function assertConfigured() {\n let problem: string | undefined;\n try {\n http.getBaseURL();\n if (!http.getApiKey()?.trim()) problem = 'TIER0_API_KEY is not set';\n } catch (error) {\n problem = error instanceof Error ? error.message : String(error);\n }\n if (problem) {\n throw new DataError({\n message: `${problem}. The platform injects TIER0_API_HOST and TIER0_API_KEY in Preview and deployments; for local development set them before starting the App.`,\n status: 503,\n code: 'DATA_NOT_CONFIGURED',\n });\n }\n }\n\n return async function call<T>(operation: UnsV2OperationName, request: Record<string, unknown>, options: CallOptions = {}): Promise<T> {\n assertConfigured();\n // The SDK binds a data subject to one client; App-level calls use the shared one without it.\n const core = options.dataSubject ? new UnsV2ClientCore(resolve, { ...transport, unsV2AppDataSubject: options.dataSubject }) : app;\n try {\n const response = await core.call(operation, request as UnsV2Request<typeof operation>);\n return response.data as T;\n } catch (error) {\n throw error instanceof UnsV2Error ? toDataError(error) : error;\n }\n };\n}\n"]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data client factory: collection handles, cross-collection transactions and
|
|
3
|
+
* the shared bootstrap. An App builds one client per process from its
|
|
4
|
+
* collection declarations; tests build their own with a mock `fetch`.
|
|
5
|
+
*/
|
|
6
|
+
import type { z } from 'zod';
|
|
7
|
+
import type { ClientConfig } from '../openapi/client.js';
|
|
8
|
+
import { type DataEnvironment, type EnsureState, type Logger } from './bootstrap.js';
|
|
9
|
+
import { Collection, type WithMeta } from './collection.js';
|
|
10
|
+
import { type CollectionDefinition } from './define.js';
|
|
11
|
+
import { type Filter, type Sort } from './sort.js';
|
|
12
|
+
export type TransactAction = 'record.create' | 'record.check' | 'record.read' | 'record.update' | 'record.modify' | 'record.replace' | 'record.delete' | 'record.query';
|
|
13
|
+
/** One `recordTransactionExecute` item; `collection` is a declaration or alias instead of a collection ID. */
|
|
14
|
+
export interface TransactStep {
|
|
15
|
+
opId: string;
|
|
16
|
+
action: TransactAction;
|
|
17
|
+
collection: CollectionDefinition | string;
|
|
18
|
+
id?: string | {
|
|
19
|
+
ref: string;
|
|
20
|
+
};
|
|
21
|
+
filter?: Filter;
|
|
22
|
+
data?: Record<string, unknown>;
|
|
23
|
+
update?: Record<string, unknown>;
|
|
24
|
+
upsert?: boolean;
|
|
25
|
+
expectedRevision?: number;
|
|
26
|
+
dependsOn?: string[];
|
|
27
|
+
bindings?: {
|
|
28
|
+
path: string;
|
|
29
|
+
ref: string;
|
|
30
|
+
resultPath: string;
|
|
31
|
+
}[];
|
|
32
|
+
selection?: 'exactOne' | 'first';
|
|
33
|
+
sort?: Sort;
|
|
34
|
+
returnDocument?: 'before' | 'after';
|
|
35
|
+
exists?: boolean;
|
|
36
|
+
operations?: Record<string, unknown>[];
|
|
37
|
+
conditions?: Filter[];
|
|
38
|
+
/** `record.query`: rows to bind from; `expectCount` asserts the match count before `limit`. */
|
|
39
|
+
query?: {
|
|
40
|
+
filter?: Filter;
|
|
41
|
+
sort?: Sort;
|
|
42
|
+
limit?: number;
|
|
43
|
+
expectCount?: {
|
|
44
|
+
min?: number;
|
|
45
|
+
max?: number;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
arrayFilters?: Record<string, unknown>[];
|
|
49
|
+
}
|
|
50
|
+
export interface TransactResultItem {
|
|
51
|
+
opId: string;
|
|
52
|
+
action: string;
|
|
53
|
+
id: string;
|
|
54
|
+
status: string;
|
|
55
|
+
collectionId?: string;
|
|
56
|
+
revision?: number;
|
|
57
|
+
/** Before/after snapshot when requested, as a flat document. */
|
|
58
|
+
document?: WithMeta<Record<string, unknown>>;
|
|
59
|
+
data?: unknown;
|
|
60
|
+
query?: unknown;
|
|
61
|
+
error?: unknown;
|
|
62
|
+
}
|
|
63
|
+
export interface TransactResult {
|
|
64
|
+
status: string;
|
|
65
|
+
results: TransactResultItem[];
|
|
66
|
+
}
|
|
67
|
+
/** Credentials as for `createClient`; `transportTimeoutMs` defaults to 15 s here, the UNS statement timeout. */
|
|
68
|
+
export interface DataClientConfig extends ClientConfig {
|
|
69
|
+
collections: readonly CollectionDefinition[];
|
|
70
|
+
/** Defaults to "deployed" when NODE_ENV is production, otherwise "preview". */
|
|
71
|
+
environment?: DataEnvironment;
|
|
72
|
+
logger?: Logger;
|
|
73
|
+
}
|
|
74
|
+
export interface DataClient {
|
|
75
|
+
/** Typed handle for a declaration listed in `collections`. */
|
|
76
|
+
collection<C extends CollectionDefinition>(definition: C): Collection<z.output<C['schema']>, z.input<C['schema']>>;
|
|
77
|
+
/** Handle by alias, typed by the caller. */
|
|
78
|
+
collection<T extends object = Record<string, unknown>>(alias: string): Collection<T>;
|
|
79
|
+
/**
|
|
80
|
+
* Atomic multi-record, multi-collection write (`recordTransactionExecute`, sync),
|
|
81
|
+
* at most 200 steps. Steps can depend on each other (`dependsOn`) and bind
|
|
82
|
+
* earlier results (`bindings`). This is not a Mongo session: everything is
|
|
83
|
+
* sent at once.
|
|
84
|
+
*/
|
|
85
|
+
transact(steps: readonly TransactStep[], options?: {
|
|
86
|
+
dryRun?: boolean;
|
|
87
|
+
idempotencyKey?: string;
|
|
88
|
+
}): Promise<TransactResult>;
|
|
89
|
+
/** Ensures every declaration now (normally lazy on first access). */
|
|
90
|
+
ensure(): Promise<EnsureState>;
|
|
91
|
+
}
|
|
92
|
+
export declare function createDataClient(config: DataClientConfig): DataClient;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDataClient = createDataClient;
|
|
4
|
+
const runtime_env_js_1 = require("../runtime-env.js");
|
|
5
|
+
const bootstrap_js_1 = require("./bootstrap.js");
|
|
6
|
+
const call_js_1 = require("./call.js");
|
|
7
|
+
const collection_js_1 = require("./collection.js");
|
|
8
|
+
const context_js_1 = require("./context.js");
|
|
9
|
+
const define_js_1 = require("./define.js");
|
|
10
|
+
const error_js_1 = require("./error.js");
|
|
11
|
+
const schema_js_1 = require("./schema.js");
|
|
12
|
+
const sort_js_1 = require("./sort.js");
|
|
13
|
+
function createDataClient(config) {
|
|
14
|
+
const call = (0, call_js_1.createDataCall)(config);
|
|
15
|
+
const environment = config.environment ?? ((0, runtime_env_js_1.getEnvVar)('NODE_ENV') === 'production' ? 'deployed' : 'preview');
|
|
16
|
+
const declared = [...config.collections];
|
|
17
|
+
if (declared.length > define_js_1.MAX_COLLECTIONS) {
|
|
18
|
+
throw new Error(`An App declares at most ${define_js_1.MAX_COLLECTIONS} collections; got ${declared.length}.`);
|
|
19
|
+
}
|
|
20
|
+
const seen = new Set();
|
|
21
|
+
for (const definition of declared) {
|
|
22
|
+
const key = definition.alias.toLowerCase();
|
|
23
|
+
if (seen.has(key))
|
|
24
|
+
throw new Error(`Collection alias "${definition.alias}" is declared twice (aliases are case-insensitive).`);
|
|
25
|
+
seen.add(key);
|
|
26
|
+
}
|
|
27
|
+
const bootstrap = (0, bootstrap_js_1.createBootstrap)({ call, collections: declared, environment, logger: config.logger ?? console });
|
|
28
|
+
const runtime = {
|
|
29
|
+
call,
|
|
30
|
+
resolve: (target) => bootstrap.resolve(lookup(target)),
|
|
31
|
+
recover: bootstrap.recover,
|
|
32
|
+
subject: context_js_1.currentDataSubject,
|
|
33
|
+
};
|
|
34
|
+
const handles = new Map();
|
|
35
|
+
function lookup(target) {
|
|
36
|
+
if (typeof target === 'string') {
|
|
37
|
+
const found = declared.find((definition) => definition.alias.toLowerCase() === target.toLowerCase());
|
|
38
|
+
if (!found)
|
|
39
|
+
throw new Error(`Collection "${target}" is not declared in this data client's collections.`);
|
|
40
|
+
return found;
|
|
41
|
+
}
|
|
42
|
+
if (!declared.includes(target)) {
|
|
43
|
+
throw new Error(`Collection "${target.alias}" is declared but missing from the \`collections\` passed to createDataClient.`);
|
|
44
|
+
}
|
|
45
|
+
return target;
|
|
46
|
+
}
|
|
47
|
+
function collection(target) {
|
|
48
|
+
const definition = lookup(target);
|
|
49
|
+
let handle = handles.get(definition);
|
|
50
|
+
if (!handle) {
|
|
51
|
+
handle = new collection_js_1.Collection(definition, runtime);
|
|
52
|
+
handles.set(definition, handle);
|
|
53
|
+
}
|
|
54
|
+
return handle;
|
|
55
|
+
}
|
|
56
|
+
async function transact(steps, options = {}) {
|
|
57
|
+
(0, collection_js_1.assertAtomicBatch)('data.transact', steps.length);
|
|
58
|
+
// Steps resolve their collection IDs inside the recovered call, so a retry uses fresh IDs.
|
|
59
|
+
const result = await bootstrap.recover(() => sendTransaction(steps, options));
|
|
60
|
+
const results = (result.results ?? []).map(({ document, ...item }) => ({
|
|
61
|
+
...item,
|
|
62
|
+
...(document ? { document: (0, collection_js_1.toDoc)(document) } : {}),
|
|
63
|
+
}));
|
|
64
|
+
const expected = options.dryRun ? 'validated' : 'committed';
|
|
65
|
+
if (result.status !== expected) {
|
|
66
|
+
const failed = results.filter((item) => item.error);
|
|
67
|
+
throw new error_js_1.DataError({
|
|
68
|
+
message: `Transaction ${result.status}: ${failed.map((item) => `${item.opId} ${JSON.stringify(item.error)}`).join('; ') || 'no step committed'}`,
|
|
69
|
+
status: 409,
|
|
70
|
+
code: 'TRANSACTION_FAILED',
|
|
71
|
+
details: { status: result.status, results },
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return { status: result.status, results };
|
|
75
|
+
}
|
|
76
|
+
async function sendTransaction(steps, options) {
|
|
77
|
+
const items = await Promise.all(steps.map(async ({ collection: target, sort, query, ...step }) => {
|
|
78
|
+
const definition = lookup(target);
|
|
79
|
+
const item = { ...step, collectionId: await bootstrap.resolve(definition) };
|
|
80
|
+
if (sort)
|
|
81
|
+
item.sort = (0, sort_js_1.toSortPairs)(sort);
|
|
82
|
+
if (query)
|
|
83
|
+
item.query = { ...query, ...(query.sort ? { sort: (0, sort_js_1.toSortPairs)(query.sort) } : {}) };
|
|
84
|
+
if (step.data) {
|
|
85
|
+
// Fields bound to earlier results are filled by UNS at commit; everything literal validates now.
|
|
86
|
+
const bound = (step.bindings ?? []).flatMap((binding) => (binding.path.startsWith('data.') ? [binding.path.slice(5).split('.')[0]] : []));
|
|
87
|
+
item.data = (0, schema_js_1.validateStepData)(definition, step.data, bound);
|
|
88
|
+
}
|
|
89
|
+
if (step.update)
|
|
90
|
+
item.update = (0, schema_js_1.validateUpdate)(definition, step.update);
|
|
91
|
+
return item;
|
|
92
|
+
}));
|
|
93
|
+
return call('recordTransactionExecute', {
|
|
94
|
+
items,
|
|
95
|
+
mode: 'sync',
|
|
96
|
+
...(options.dryRun ? { dryRun: true } : {}),
|
|
97
|
+
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
98
|
+
}, { dataSubject: (0, context_js_1.currentDataSubject)() });
|
|
99
|
+
}
|
|
100
|
+
return { collection: collection, transact, ensure: bootstrap.ensure };
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/data/client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Data client factory: collection handles, cross-collection transactions and\n * the shared bootstrap. An App builds one client per process from its\n * collection declarations; tests build their own with a mock `fetch`.\n */\nimport type { z } from 'zod';\nimport type { ClientConfig } from '../openapi/client.js';\nimport { getEnvVar } from '../runtime-env.js';\nimport { createBootstrap, type DataEnvironment, type EnsureState, type Logger } from './bootstrap.js';\nimport { createDataCall } from './call.js';\nimport { assertAtomicBatch, Collection, toDoc, type UnsRecord, type WithMeta } from './collection.js';\nimport { currentDataSubject } from './context.js';\nimport { MAX_COLLECTIONS, type CollectionDefinition } from './define.js';\nimport { DataError } from './error.js';\nimport { validateStepData, validateUpdate } from './schema.js';\nimport { toSortPairs, type Filter, type Sort } from './sort.js';\n\nexport type TransactAction =\n | 'record.create'\n | 'record.check'\n | 'record.read'\n | 'record.update'\n | 'record.modify'\n | 'record.replace'\n | 'record.delete'\n | 'record.query';\n\n/** One `recordTransactionExecute` item; `collection` is a declaration or alias instead of a collection ID. */\nexport interface TransactStep {\n opId: string;\n action: TransactAction;\n collection: CollectionDefinition | string;\n id?: string | { ref: string };\n filter?: Filter;\n data?: Record<string, unknown>;\n update?: Record<string, unknown>;\n upsert?: boolean;\n expectedRevision?: number;\n dependsOn?: string[];\n bindings?: { path: string; ref: string; resultPath: string }[];\n selection?: 'exactOne' | 'first';\n sort?: Sort;\n returnDocument?: 'before' | 'after';\n exists?: boolean;\n operations?: Record<string, unknown>[];\n conditions?: Filter[];\n /** `record.query`: rows to bind from; `expectCount` asserts the match count before `limit`. */\n query?: { filter?: Filter; sort?: Sort; limit?: number; expectCount?: { min?: number; max?: number } };\n arrayFilters?: Record<string, unknown>[];\n}\n\nexport interface TransactResultItem {\n opId: string;\n action: string;\n id: string;\n status: string;\n collectionId?: string;\n revision?: number;\n /** Before/after snapshot when requested, as a flat document. */\n document?: WithMeta<Record<string, unknown>>;\n data?: unknown;\n query?: unknown;\n error?: unknown;\n}\n\nexport interface TransactResult {\n status: string;\n results: TransactResultItem[];\n}\n\n/** Credentials as for `createClient`; `transportTimeoutMs` defaults to 15 s here, the UNS statement timeout. */\nexport interface DataClientConfig extends ClientConfig {\n collections: readonly CollectionDefinition[];\n /** Defaults to \"deployed\" when NODE_ENV is production, otherwise \"preview\". */\n environment?: DataEnvironment;\n logger?: Logger;\n}\n\nexport interface DataClient {\n /** Typed handle for a declaration listed in `collections`. */\n collection<C extends CollectionDefinition>(definition: C): Collection<z.output<C['schema']>, z.input<C['schema']>>;\n /** Handle by alias, typed by the caller. */\n collection<T extends object = Record<string, unknown>>(alias: string): Collection<T>;\n /**\n * Atomic multi-record, multi-collection write (`recordTransactionExecute`, sync),\n * at most 200 steps. Steps can depend on each other (`dependsOn`) and bind\n * earlier results (`bindings`). This is not a Mongo session: everything is\n * sent at once.\n */\n transact(steps: readonly TransactStep[], options?: { dryRun?: boolean; idempotencyKey?: string }): Promise<TransactResult>;\n /** Ensures every declaration now (normally lazy on first access). */\n ensure(): Promise<EnsureState>;\n}\n\nexport function createDataClient(config: DataClientConfig): DataClient {\n const call = createDataCall(config);\n const environment = config.environment ?? (getEnvVar('NODE_ENV') === 'production' ? 'deployed' : 'preview');\n const declared = [...config.collections];\n if (declared.length > MAX_COLLECTIONS) {\n throw new Error(`An App declares at most ${MAX_COLLECTIONS} collections; got ${declared.length}.`);\n }\n const seen = new Set<string>();\n for (const definition of declared) {\n const key = definition.alias.toLowerCase();\n if (seen.has(key)) throw new Error(`Collection alias \"${definition.alias}\" is declared twice (aliases are case-insensitive).`);\n seen.add(key);\n }\n\n const bootstrap = createBootstrap({ call, collections: declared, environment, logger: config.logger ?? console });\n const runtime = {\n call,\n resolve: (target: CollectionDefinition | string) => bootstrap.resolve(lookup(target)),\n recover: bootstrap.recover,\n subject: currentDataSubject,\n };\n const handles = new Map<CollectionDefinition, Collection<object>>();\n\n function lookup(target: CollectionDefinition | string): CollectionDefinition {\n if (typeof target === 'string') {\n const found = declared.find((definition) => definition.alias.toLowerCase() === target.toLowerCase());\n if (!found) throw new Error(`Collection \"${target}\" is not declared in this data client's collections.`);\n return found;\n }\n if (!declared.includes(target)) {\n throw new Error(`Collection \"${target.alias}\" is declared but missing from the \\`collections\\` passed to createDataClient.`);\n }\n return target;\n }\n\n function collection(target: CollectionDefinition | string) {\n const definition = lookup(target);\n let handle = handles.get(definition);\n if (!handle) {\n handle = new Collection<object>(definition, runtime);\n handles.set(definition, handle);\n }\n return handle;\n }\n\n async function transact(\n steps: readonly TransactStep[],\n options: { dryRun?: boolean; idempotencyKey?: string } = {},\n ): Promise<TransactResult> {\n assertAtomicBatch('data.transact', steps.length);\n // Steps resolve their collection IDs inside the recovered call, so a retry uses fresh IDs.\n const result = await bootstrap.recover(() => sendTransaction(steps, options));\n const results = (result.results ?? []).map(({ document, ...item }) => ({\n ...item,\n ...(document ? { document: toDoc<Record<string, unknown>>(document) } : {}),\n }));\n const expected = options.dryRun ? 'validated' : 'committed';\n if (result.status !== expected) {\n const failed = results.filter((item) => item.error);\n throw new DataError({\n message: `Transaction ${result.status}: ${failed.map((item) => `${item.opId} ${JSON.stringify(item.error)}`).join('; ') || 'no step committed'}`,\n status: 409,\n code: 'TRANSACTION_FAILED',\n details: { status: result.status, results },\n });\n }\n return { status: result.status, results };\n }\n\n async function sendTransaction(steps: readonly TransactStep[], options: { dryRun?: boolean; idempotencyKey?: string }) {\n const items = await Promise.all(\n steps.map(async ({ collection: target, sort, query, ...step }) => {\n const definition = lookup(target);\n const item: Record<string, unknown> = { ...step, collectionId: await bootstrap.resolve(definition) };\n if (sort) item.sort = toSortPairs(sort);\n if (query) item.query = { ...query, ...(query.sort ? { sort: toSortPairs(query.sort) } : {}) };\n if (step.data) {\n // Fields bound to earlier results are filled by UNS at commit; everything literal validates now.\n const bound = (step.bindings ?? []).flatMap((binding) => (binding.path.startsWith('data.') ? [binding.path.slice(5).split('.')[0]] : []));\n item.data = validateStepData(definition, step.data, bound);\n }\n if (step.update) item.update = validateUpdate(definition, step.update);\n return item;\n }),\n );\n return call<{ status: string; results?: (Omit<TransactResultItem, 'document'> & { document?: UnsRecord })[] }>(\n 'recordTransactionExecute',\n {\n items,\n mode: 'sync',\n ...(options.dryRun ? { dryRun: true } : {}),\n ...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),\n },\n { dataSubject: currentDataSubject() },\n );\n }\n\n return { collection: collection as DataClient['collection'], transact, ensure: bootstrap.ensure };\n}\n"]}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import type { DataCall } from './call.js';
|
|
2
|
+
import type { CollectionDefinition, RecordMeta } from './define.js';
|
|
3
|
+
import { type Filter, type Sort, type SortPairs } from './sort.js';
|
|
4
|
+
/** UNS page limit for find / aggregate / distinct. */
|
|
5
|
+
export declare const MAX_PAGE_SIZE = 200;
|
|
6
|
+
/**
|
|
7
|
+
* UNS commits at most 200 items in one synchronous atomic batch
|
|
8
|
+
* (insertMany, bulkWrite, data.transact).
|
|
9
|
+
*/
|
|
10
|
+
export declare const MAX_ATOMIC_ITEMS = 200;
|
|
11
|
+
export type WithMeta<T> = T & {
|
|
12
|
+
_id: string;
|
|
13
|
+
_meta: RecordMeta;
|
|
14
|
+
};
|
|
15
|
+
export type Projection = Record<string, 0 | 1 | boolean>;
|
|
16
|
+
export type Update = Record<string, unknown>;
|
|
17
|
+
export interface UnsRecord {
|
|
18
|
+
id: string;
|
|
19
|
+
data: Record<string, unknown>;
|
|
20
|
+
revision: number;
|
|
21
|
+
createdAt: number;
|
|
22
|
+
updatedAt: number;
|
|
23
|
+
}
|
|
24
|
+
/** Position of the next page: an opaque cursor or a 1-based offset page number. */
|
|
25
|
+
type PageToken = string | number;
|
|
26
|
+
interface Page<T> {
|
|
27
|
+
items: T[];
|
|
28
|
+
/** Token of the following page; null when this was the last one. */
|
|
29
|
+
next: PageToken | null;
|
|
30
|
+
}
|
|
31
|
+
/** Runtime services a collection handle needs from its client. */
|
|
32
|
+
export interface CollectionRuntime {
|
|
33
|
+
call: DataCall;
|
|
34
|
+
/** Collection ID of a declaration or declared alias, ensuring all declarations first. */
|
|
35
|
+
resolve(target: CollectionDefinition | string): Promise<string>;
|
|
36
|
+
/** Runs a call, re-ensuring and retrying once when its collection ID went stale (see bootstrap). */
|
|
37
|
+
recover<R>(fn: () => Promise<R>, options?: {
|
|
38
|
+
retry?: boolean;
|
|
39
|
+
}): Promise<R>;
|
|
40
|
+
/** Data subject of the request being served. */
|
|
41
|
+
subject(): string | undefined;
|
|
42
|
+
}
|
|
43
|
+
/** Rejects batches UNS would refuse, before anything is sent. */
|
|
44
|
+
export declare function assertAtomicBatch(operation: string, count: number): void;
|
|
45
|
+
export declare function toDoc<T>(record: UnsRecord): WithMeta<T>;
|
|
46
|
+
/**
|
|
47
|
+
* Async-iterable result set. Pages hold at most 200 items; the page source
|
|
48
|
+
* decides whether the next page is reached by cursor or by offset page number.
|
|
49
|
+
*/
|
|
50
|
+
export declare class Cursor<T> implements AsyncIterable<T> {
|
|
51
|
+
private readonly fetchPage;
|
|
52
|
+
private sortSpec?;
|
|
53
|
+
private limitCount?;
|
|
54
|
+
private projection?;
|
|
55
|
+
private started;
|
|
56
|
+
constructor(fetchPage: (state: {
|
|
57
|
+
token: PageToken | null;
|
|
58
|
+
size: number;
|
|
59
|
+
sort?: SortPairs;
|
|
60
|
+
projection?: Projection;
|
|
61
|
+
}) => Promise<Page<T>>, options?: {
|
|
62
|
+
sort?: Sort;
|
|
63
|
+
limit?: number;
|
|
64
|
+
projection?: Projection;
|
|
65
|
+
});
|
|
66
|
+
private assertNotStarted;
|
|
67
|
+
sort(sort: Sort): this;
|
|
68
|
+
/** Total number of documents to return (pages are fetched ≤200 at a time). */
|
|
69
|
+
limit(count: number): this;
|
|
70
|
+
project(projection: Projection): this;
|
|
71
|
+
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
72
|
+
toArray(): Promise<T[]>;
|
|
73
|
+
}
|
|
74
|
+
export interface FindOptions {
|
|
75
|
+
sort?: Sort;
|
|
76
|
+
limit?: number;
|
|
77
|
+
projection?: Projection;
|
|
78
|
+
}
|
|
79
|
+
export interface FindPageOptions {
|
|
80
|
+
sort?: Sort;
|
|
81
|
+
/** 1-based page number. */
|
|
82
|
+
page?: number;
|
|
83
|
+
/** At most 200. */
|
|
84
|
+
pageSize?: number;
|
|
85
|
+
projection?: Projection;
|
|
86
|
+
}
|
|
87
|
+
export interface UpdateOptions {
|
|
88
|
+
upsert?: boolean;
|
|
89
|
+
/** Reject the write with VERSION_CONFLICT unless the record is at this revision. */
|
|
90
|
+
expectedRevision?: number;
|
|
91
|
+
sort?: Sort;
|
|
92
|
+
arrayFilters?: Record<string, unknown>[];
|
|
93
|
+
idempotencyKey?: string;
|
|
94
|
+
}
|
|
95
|
+
export interface FindOneAndOptions extends UpdateOptions {
|
|
96
|
+
returnDocument?: 'before' | 'after';
|
|
97
|
+
projection?: Projection;
|
|
98
|
+
}
|
|
99
|
+
export type BulkOperation = {
|
|
100
|
+
insertOne: {
|
|
101
|
+
document: Record<string, unknown>;
|
|
102
|
+
};
|
|
103
|
+
} | {
|
|
104
|
+
updateOne: {
|
|
105
|
+
filter: Filter;
|
|
106
|
+
update: Update;
|
|
107
|
+
upsert?: boolean;
|
|
108
|
+
sort?: Sort;
|
|
109
|
+
};
|
|
110
|
+
} | {
|
|
111
|
+
replaceOne: {
|
|
112
|
+
filter: Filter;
|
|
113
|
+
replacement: Record<string, unknown>;
|
|
114
|
+
upsert?: boolean;
|
|
115
|
+
sort?: Sort;
|
|
116
|
+
};
|
|
117
|
+
} | {
|
|
118
|
+
deleteOne: {
|
|
119
|
+
filter: Filter;
|
|
120
|
+
sort?: Sort;
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
export declare class Collection<T extends object = Record<string, unknown>, TInput extends object = T> {
|
|
124
|
+
readonly definition: CollectionDefinition;
|
|
125
|
+
private readonly runtime;
|
|
126
|
+
constructor(definition: CollectionDefinition, runtime: CollectionRuntime);
|
|
127
|
+
get alias(): string;
|
|
128
|
+
/**
|
|
129
|
+
* One call with stale-ID recovery. A call continuing a cursor or
|
|
130
|
+
* resumeAfter token of the old collection is not retried: the token means
|
|
131
|
+
* nothing to a recreated collection.
|
|
132
|
+
*/
|
|
133
|
+
private post;
|
|
134
|
+
private send;
|
|
135
|
+
find(filter?: Filter, options?: FindOptions): Cursor<WithMeta<T>>;
|
|
136
|
+
findOne(filter?: Filter, options?: Omit<FindOptions, 'limit'>): Promise<WithMeta<T> | null>;
|
|
137
|
+
/**
|
|
138
|
+
* One numbered page plus the total match count, for paged list screens.
|
|
139
|
+
* Uses `recordAggregatePipeline` offset paging.
|
|
140
|
+
*/
|
|
141
|
+
findPage(filter?: Filter, options?: FindPageOptions): Promise<{
|
|
142
|
+
items: WithMeta<T>[];
|
|
143
|
+
total: number;
|
|
144
|
+
page: number;
|
|
145
|
+
pageSize: number;
|
|
146
|
+
}>;
|
|
147
|
+
countDocuments(filter?: Filter): Promise<number>;
|
|
148
|
+
/** Distinct values of a field (every page). */
|
|
149
|
+
distinct(field: string, filter?: Filter): Promise<unknown[]>;
|
|
150
|
+
/**
|
|
151
|
+
* Runs a pipeline (`$match`, `$sort`, `$group`, `$project`, `$set`,
|
|
152
|
+
* `$lookup`, `$unwind`, `$skip`, `$limit`, `$count`). `$sort` accepts
|
|
153
|
+
* `{ field: 1 | -1 }`; `$lookup` takes `from` (a declared collection or
|
|
154
|
+
* alias of this App) instead of a collection ID. Rows are whatever the
|
|
155
|
+
* pipeline outputs, not wrapped records.
|
|
156
|
+
*
|
|
157
|
+
* Pipelines of only `$match` / `$sort` page by cursor; any other stage pages
|
|
158
|
+
* by offset (UNS rejects cursors for transformed results). The `$exists`,
|
|
159
|
+
* `$distinct` and `$frequencies` stages are listed in the UNS schema but not
|
|
160
|
+
* executed by the record pipeline; use `countDocuments`, `distinct` or `$group`.
|
|
161
|
+
*/
|
|
162
|
+
aggregate<R = Record<string, unknown>>(pipeline: Record<string, unknown>[]): Cursor<R>;
|
|
163
|
+
private aggregatePage;
|
|
164
|
+
/** Converts Mongo-style `$sort` objects and resolves `$lookup.from`, recursively. */
|
|
165
|
+
private prepareStages;
|
|
166
|
+
insertOne(document: TInput & {
|
|
167
|
+
_id?: string;
|
|
168
|
+
}, options?: {
|
|
169
|
+
idempotencyKey?: string;
|
|
170
|
+
}): Promise<{
|
|
171
|
+
insertedId: string;
|
|
172
|
+
}>;
|
|
173
|
+
/** Inserts up to 200 documents atomically (all or none). */
|
|
174
|
+
insertMany(documents: readonly (TInput & {
|
|
175
|
+
_id?: string;
|
|
176
|
+
})[], options?: {
|
|
177
|
+
idempotencyKey?: string;
|
|
178
|
+
}): Promise<{
|
|
179
|
+
insertedCount: number;
|
|
180
|
+
insertedIds: string[];
|
|
181
|
+
}>;
|
|
182
|
+
updateOne(filter: Filter, update: Update, options?: UpdateOptions): Promise<{
|
|
183
|
+
matchedCount: number;
|
|
184
|
+
modifiedCount: number;
|
|
185
|
+
upsertedId: string | null;
|
|
186
|
+
}>;
|
|
187
|
+
/**
|
|
188
|
+
* Updates every match like Mongo's updateMany: documents commit one by one
|
|
189
|
+
* (not atomically), following `resumeAfter` until every match is processed.
|
|
190
|
+
* A failure stops the run and reports the counts already committed. For
|
|
191
|
+
* all-or-nothing multi-document changes use `data.transact` (≤200 items).
|
|
192
|
+
*/
|
|
193
|
+
updateMany(filter: Filter, update: Update, options?: Pick<UpdateOptions, 'arrayFilters'>): Promise<{
|
|
194
|
+
matchedCount: number;
|
|
195
|
+
modifiedCount: number;
|
|
196
|
+
}>;
|
|
197
|
+
/**
|
|
198
|
+
* Replaces the whole body. Fields written by another App version and not in
|
|
199
|
+
* this declaration are lost — prefer `updateOne` with `$set`.
|
|
200
|
+
*/
|
|
201
|
+
replaceOne(filter: Filter, replacement: TInput, options?: Omit<UpdateOptions, 'arrayFilters'>): Promise<{
|
|
202
|
+
matchedCount: number;
|
|
203
|
+
modifiedCount: number;
|
|
204
|
+
upsertedId: string | null;
|
|
205
|
+
}>;
|
|
206
|
+
/** Soft-deletes one record; requires `uns.delete` on the App key. */
|
|
207
|
+
deleteOne(filter: Filter, options?: Pick<UpdateOptions, 'expectedRevision' | 'sort' | 'idempotencyKey'>): Promise<{
|
|
208
|
+
deletedCount: number;
|
|
209
|
+
}>;
|
|
210
|
+
/**
|
|
211
|
+
* Soft-deletes every match, one document at a time like Mongo's deleteMany
|
|
212
|
+
* (not atomic), following `resumeAfter`; requires `uns.delete` on the App key.
|
|
213
|
+
*/
|
|
214
|
+
deleteMany(filter: Filter): Promise<{
|
|
215
|
+
deletedCount: number;
|
|
216
|
+
}>;
|
|
217
|
+
/**
|
|
218
|
+
* Atomic read-modify-write. A state transition puts the expected state in
|
|
219
|
+
* the filter: `findOneAndUpdate({ _id, status: "DRAFT" }, { $set: { status: "SUBMITTED" } })`
|
|
220
|
+
* returns null when another request moved the record first.
|
|
221
|
+
*/
|
|
222
|
+
findOneAndUpdate(filter: Filter, update: Update, options?: FindOneAndOptions): Promise<WithMeta<T> | null>;
|
|
223
|
+
findOneAndReplace(filter: Filter, replacement: TInput, options?: Omit<FindOneAndOptions, 'arrayFilters'>): Promise<WithMeta<T> | null>;
|
|
224
|
+
findOneAndDelete(filter: Filter, options?: Pick<FindOneAndOptions, 'expectedRevision' | 'sort' | 'projection' | 'idempotencyKey'>): Promise<WithMeta<T> | null>;
|
|
225
|
+
/** Up to 200 mixed single-record writes in one atomic call (insertOne / updateOne / replaceOne / deleteOne). */
|
|
226
|
+
bulkWrite(operations: readonly BulkOperation[], options?: {
|
|
227
|
+
idempotencyKey?: string;
|
|
228
|
+
}): Promise<{
|
|
229
|
+
insertedCount: number;
|
|
230
|
+
matchedCount: number;
|
|
231
|
+
modifiedCount: number;
|
|
232
|
+
deletedCount: number;
|
|
233
|
+
upsertedCount: number;
|
|
234
|
+
insertedIds: Record<number, string>;
|
|
235
|
+
upsertedIds: Record<number, string>;
|
|
236
|
+
}>;
|
|
237
|
+
}
|
|
238
|
+
export {};
|