@nsp-labs/agnostic-sdk 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -9,6 +9,15 @@ and pass the runtime OpenAPI schema check.
9
9
 
10
10
  ## Unreleased
11
11
 
12
+ ## 1.5.0 - 2026-09-06
13
+
14
+ ### Added
15
+
16
+ - `data.table(name).records.query` for projected JSON pages and nested filters
17
+ without URL array encoding; `data.batchQuery` for bounded independent pages.
18
+ - Updated runtime OpenAPI schema and exact public manifest. New methods require
19
+ the additive query/batch-query Runtime API; existing methods are unchanged.
20
+
12
21
  ## 1.4.0 - 2026-09-02
13
22
 
14
23
  ### Added
package/README.md CHANGED
@@ -8,6 +8,19 @@ environment + runtime token` and does not expose control-plane resources.
8
8
  npm install @nsp-labs/agnostic-sdk
9
9
  ```
10
10
 
11
+ ## Projected and Batch Reads (1.5.0)
12
+
13
+ `data.table(name).records.query({ fields: ['title'], filter, limit, cursor })`
14
+ reads only requested technical fields plus id. JSON filters support the existing
15
+ 50-value `in` budget without URL-array encoding. Omit `fields` for full records.
16
+ Changing fields or conditions requires a new cursor chain.
17
+
18
+ `data.batchQuery([{ tableName: 'orders', query: { fields: ['status'], limit: 50 } }])`
19
+ returns `{ results: [...] }` in request order, with independent page cursors.
20
+ Limits: 20 queries, 1000 requested rows total, default 50 rows/query. One failed
21
+ query fails the batch; reads are not a transactional snapshot. Requires the
22
+ additive query/batch-query Runtime API and `data.read`. Old methods are unchanged.
23
+
11
24
  ## Context
12
25
 
13
26
  Inside managed runtime, context is resolved automatically:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nsp-labs/agnostic-sdk",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Server-side Runtime SDK for Agnostic project services, workers, automations, and trusted local scripts.",
5
5
  "license": "ISC",
6
6
  "type": "commonjs",
@@ -38,6 +38,40 @@ export interface paths {
38
38
  patch?: never;
39
39
  trace?: never;
40
40
  };
41
+ "/api/v1/runtime/data/tables/{tableName}/records/query": {
42
+ parameters: {
43
+ query?: never;
44
+ header?: never;
45
+ path?: never;
46
+ cookie?: never;
47
+ };
48
+ get?: never;
49
+ put?: never;
50
+ /** Read one projected Data page using a JSON query */
51
+ post: operations["runtimeDataQueryRecords"];
52
+ delete?: never;
53
+ options?: never;
54
+ head?: never;
55
+ patch?: never;
56
+ trace?: never;
57
+ };
58
+ "/api/v1/runtime/data/records/batch-query": {
59
+ parameters: {
60
+ query?: never;
61
+ header?: never;
62
+ path?: never;
63
+ cookie?: never;
64
+ };
65
+ get?: never;
66
+ put?: never;
67
+ /** Read bounded independent Data pages in the runtime scope */
68
+ post: operations["runtimeDataBatchQueryRecords"];
69
+ delete?: never;
70
+ options?: never;
71
+ head?: never;
72
+ patch?: never;
73
+ trace?: never;
74
+ };
41
75
  "/api/v1/runtime/data/tables/{tableName}/records/aggregate": {
42
76
  parameters: {
43
77
  query?: never;
@@ -835,6 +869,55 @@ export interface components {
835
869
  capabilities: string[];
836
870
  actor?: components["schemas"]["RuntimeActorMetadataDto"] | null;
837
871
  };
872
+ RuntimeDataBatchQueryDto: {
873
+ /** @description Independent read-only pages; sum of requested page limits must not exceed 1000 (default 50 per page). */
874
+ queries: components["schemas"]["RuntimeDataBatchQueryItemDto"][];
875
+ };
876
+ RuntimeDataBatchQueryItemDto: {
877
+ /** @example orders */
878
+ tableName: string;
879
+ query: components["schemas"]["RuntimeDataQueryDto"];
880
+ };
881
+ RuntimeDataBatchResultDto: {
882
+ /** @description Pages in request order, each with its own cursor. Not a transactional snapshot. Any failed query fails the whole request. */
883
+ results: components["schemas"]["DataRecordsListDto"][];
884
+ };
885
+ RuntimeDataQueryDto: {
886
+ /** @example 50 */
887
+ limit?: number;
888
+ /**
889
+ * @description Opaque versioned pagination cursor bound to this exact query. Legacy offset cursors are temporarily accepted.
890
+ * @example k1.b3BhcXVlLWl2.b3BhcXVlLXBheWxvYWQ.b3BhcXVlLXRhZw
891
+ */
892
+ cursor?: string;
893
+ /**
894
+ * @description Search text applied across searchable text columns
895
+ * @example alex
896
+ */
897
+ q?: string;
898
+ /** @example created_at:desc */
899
+ sort?: string;
900
+ /**
901
+ * @example {
902
+ * "id": {
903
+ * "in": [
904
+ * "record-a",
905
+ * "record-b"
906
+ * ]
907
+ * }
908
+ * }
909
+ */
910
+ filter?: {
911
+ [key: string]: unknown;
912
+ };
913
+ /**
914
+ * @description Technical field names to read. Record id is always included. Omit for all fields.
915
+ * @example [
916
+ * "title"
917
+ * ]
918
+ */
919
+ fields?: string[];
920
+ };
838
921
  RuntimeStartWorkflowDto: {
839
922
  /**
840
923
  * @example {
@@ -1070,6 +1153,82 @@ export interface operations {
1070
1153
  };
1071
1154
  };
1072
1155
  };
1156
+ runtimeDataQueryRecords: {
1157
+ parameters: {
1158
+ query?: never;
1159
+ header?: never;
1160
+ path: {
1161
+ tableName: string;
1162
+ };
1163
+ cookie?: never;
1164
+ };
1165
+ requestBody: {
1166
+ content: {
1167
+ "application/json": components["schemas"]["RuntimeDataQueryDto"];
1168
+ };
1169
+ };
1170
+ responses: {
1171
+ 200: {
1172
+ headers: {
1173
+ [name: string]: unknown;
1174
+ };
1175
+ content: {
1176
+ "application/json": components["schemas"]["DataRecordsListDto"];
1177
+ };
1178
+ };
1179
+ /** @description Invalid runtime token */
1180
+ 401: {
1181
+ headers: {
1182
+ [name: string]: unknown;
1183
+ };
1184
+ content?: never;
1185
+ };
1186
+ /** @description Missing runtime capability */
1187
+ 403: {
1188
+ headers: {
1189
+ [name: string]: unknown;
1190
+ };
1191
+ content?: never;
1192
+ };
1193
+ };
1194
+ };
1195
+ runtimeDataBatchQueryRecords: {
1196
+ parameters: {
1197
+ query?: never;
1198
+ header?: never;
1199
+ path?: never;
1200
+ cookie?: never;
1201
+ };
1202
+ requestBody: {
1203
+ content: {
1204
+ "application/json": components["schemas"]["RuntimeDataBatchQueryDto"];
1205
+ };
1206
+ };
1207
+ responses: {
1208
+ 200: {
1209
+ headers: {
1210
+ [name: string]: unknown;
1211
+ };
1212
+ content: {
1213
+ "application/json": components["schemas"]["RuntimeDataBatchResultDto"];
1214
+ };
1215
+ };
1216
+ /** @description Invalid runtime token */
1217
+ 401: {
1218
+ headers: {
1219
+ [name: string]: unknown;
1220
+ };
1221
+ content?: never;
1222
+ };
1223
+ /** @description Missing runtime capability */
1224
+ 403: {
1225
+ headers: {
1226
+ [name: string]: unknown;
1227
+ };
1228
+ content?: never;
1229
+ };
1230
+ };
1231
+ };
1073
1232
  runtimeDataAggregateRecords: {
1074
1233
  parameters: {
1075
1234
  query?: never;
package/src/index.d.ts CHANGED
@@ -2,4 +2,4 @@ export { AgnosticRuntime, RuntimeAppAuthNamespace, RuntimeContextNamespace, Runt
2
2
  export { normalizeApiUrl, resolveRuntimeContext } from './lib/context';
3
3
  export { AgnosticRuntimeError } from './lib/errors';
4
4
  export { AGNOSTIC_RUNTIME_SDK_MANIFEST, type AgnosticRuntimeSdkManifest, } from './lib/manifest';
5
- export type { AgnosticRuntimeConfig, RuntimeAggregateMetric, RuntimeAggregateOperation, RuntimeAggregateOrderBy, RuntimeAggregateRecordsInput, RuntimeAggregateRecordsResult, RuntimeAggregateRow, ResolvedRuntimeContext, RuntimeActorMetadata, RuntimeActorType, RuntimeAnonymousClaimFileHandle, RuntimeAnonymousClaimInput, RuntimeAnonymousClaimResult, RuntimeAppAuthActor, RuntimeAppAuthCachePolicy, RuntimeAppAuthRequestLike, RuntimeAppAuthSession, RuntimeAppAuthSessionClaims, RuntimeAppAuthUserClaims, RuntimeAppAuthUserResult, RuntimeCreateRecordInput, RuntimeCreateFileUploadInput, RuntimeDataField, RuntimeDataViewState, RuntimeIdentityContext, RuntimeFileAccessMode, RuntimeFileDownloadUrl, RuntimeFileObject, RuntimeFileObjectStatus, RuntimeFileUploadCompletion, RuntimeFileUploadGrant, RuntimeListRecordsOptions, RuntimeListWindowOptions, RuntimeRecord, RuntimeRecordMutation, RuntimeRecordsList, RuntimeRequestOptions, RuntimeRowData, RuntimeRowValue, RuntimeTableWindow, RuntimeUpdateRecordInput, RuntimeWorkflowRun, RuntimeWorkflowStepRun, RuntimeWorkflowWaitOptions, WorkflowRunStatus, } from './lib/types';
5
+ export type { RuntimeQueryRecordsInput, RuntimeBatchQueryItem, RuntimeBatchQueryResult, AgnosticRuntimeConfig, RuntimeAggregateMetric, RuntimeAggregateOperation, RuntimeAggregateOrderBy, RuntimeAggregateRecordsInput, RuntimeAggregateRecordsResult, RuntimeAggregateRow, ResolvedRuntimeContext, RuntimeActorMetadata, RuntimeActorType, RuntimeAnonymousClaimFileHandle, RuntimeAnonymousClaimInput, RuntimeAnonymousClaimResult, RuntimeAppAuthActor, RuntimeAppAuthCachePolicy, RuntimeAppAuthRequestLike, RuntimeAppAuthSession, RuntimeAppAuthSessionClaims, RuntimeAppAuthUserClaims, RuntimeAppAuthUserResult, RuntimeCreateRecordInput, RuntimeCreateFileUploadInput, RuntimeDataField, RuntimeDataViewState, RuntimeIdentityContext, RuntimeFileAccessMode, RuntimeFileDownloadUrl, RuntimeFileObject, RuntimeFileObjectStatus, RuntimeFileUploadCompletion, RuntimeFileUploadGrant, RuntimeListRecordsOptions, RuntimeListWindowOptions, RuntimeRecord, RuntimeRecordMutation, RuntimeRecordsList, RuntimeRequestOptions, RuntimeRowData, RuntimeRowValue, RuntimeTableWindow, RuntimeUpdateRecordInput, RuntimeWorkflowRun, RuntimeWorkflowStepRun, RuntimeWorkflowWaitOptions, WorkflowRunStatus, } from './lib/types';
@@ -9,7 +9,7 @@ export declare const AGNOSTIC_RUNTIME_SDK_MANIFEST: Readonly<{
9
9
  readonly schema: "agnostic_runtime_sdk_manifest.v1";
10
10
  readonly package: Readonly<{
11
11
  name: "@nsp-labs/agnostic-sdk";
12
- version: "1.4.0";
12
+ version: "1.5.0";
13
13
  factory: "createAgnosticRuntime";
14
14
  runtime: "server_only";
15
15
  }>;
@@ -23,7 +23,7 @@ export declare const AGNOSTIC_RUNTIME_SDK_MANIFEST: Readonly<{
23
23
  readonly namespaces: Readonly<{
24
24
  auth: readonly ("requireSession" | "getSession" | "requireScopes" | "getUser")[];
25
25
  context: readonly "get"[];
26
- data: readonly ("table(name).records.delete" | "table(name).records.list" | "table(name).records.aggregate" | "table(name).records.create" | "table(name).records.update" | "view(id).table.window")[];
26
+ data: readonly ("batchQuery" | "table(name).records.delete" | "table(name).records.query" | "table(name).records.list" | "table(name).records.aggregate" | "table(name).records.create" | "table(name).records.update" | "view(id).table.window")[];
27
27
  storage: readonly ("bucket(name).get" | "bucket(name).delete" | "bucket(name).createUpload" | "bucket(name).completeUpload" | "bucket(name).createDownloadUrl" | "bucket(name).anonymousUploads.claim")[];
28
28
  workflows: readonly ("start" | "getRun")[];
29
29
  workflowRuns: readonly ("get" | "wait" | "listSteps")[];
@@ -11,12 +11,13 @@ const AUTH_KEYS_LITERAL = [
11
11
  const AUTH_KEYS = AUTH_KEYS_LITERAL;
12
12
  const CONTEXT_KEYS_LITERAL = ['get'];
13
13
  const CONTEXT_KEYS = CONTEXT_KEYS_LITERAL;
14
- const DATA_NAMESPACE_KEYS_LITERAL = ['table', 'view'];
14
+ const DATA_NAMESPACE_KEYS_LITERAL = ['table', 'view', 'batchQuery'];
15
15
  const DATA_NAMESPACE_KEYS = DATA_NAMESPACE_KEYS_LITERAL;
16
16
  const DATA_TABLE_KEYS_LITERAL = ['records'];
17
17
  const DATA_TABLE_KEYS = DATA_TABLE_KEYS_LITERAL;
18
18
  const DATA_RECORD_KEYS_LITERAL = [
19
19
  'list',
20
+ 'query',
20
21
  'aggregate',
21
22
  'create',
22
23
  'update',
@@ -51,6 +52,7 @@ const NAMESPACES = Object.freeze({
51
52
  data: Object.freeze([
52
53
  ...DATA_RECORD_KEYS.map((method) => `${DATA_NAMESPACE_KEYS[0]}(name).${DATA_TABLE_KEYS[0]}.${method}`),
53
54
  ...DATA_VIEW_TABLE_KEYS.map((method) => `${DATA_NAMESPACE_KEYS[1]}(id).${DATA_VIEW_KEYS[0]}.${method}`),
55
+ DATA_NAMESPACE_KEYS[2],
54
56
  ]),
55
57
  storage: Object.freeze([
56
58
  ...STORAGE_BUCKET_KEYS.filter((method) => method !== 'anonymousUploads').map((method) => `${STORAGE_NAMESPACE_KEYS[0]}(name).${method}`),
@@ -68,7 +70,7 @@ const MANIFEST_CONTRACT = Object.freeze({
68
70
  schema: 'agnostic_runtime_sdk_manifest.v1',
69
71
  package: Object.freeze({
70
72
  name: '@nsp-labs/agnostic-sdk',
71
- version: '1.4.0',
73
+ version: '1.5.0',
72
74
  factory: 'createAgnosticRuntime',
73
75
  runtime: 'server_only',
74
76
  }),
@@ -1,5 +1,5 @@
1
1
  import { type RuntimeOpenApiClient } from './http-client';
2
- import type { AgnosticRuntimeConfig, ResolvedRuntimeContext, RuntimeAppAuthRequestLike, RuntimeAppAuthSession, RuntimeAppAuthUserResult, RuntimeAnonymousClaimInput, RuntimeAnonymousClaimResult, RuntimeAggregateRecordsInput, RuntimeAggregateRecordsResult, RuntimeCreateFileUploadInput, RuntimeCreateRecordInput, RuntimeIdentityContext, RuntimeFileDownloadUrl, RuntimeFileObject, RuntimeFileUploadCompletion, RuntimeFileUploadGrant, RuntimeListRecordsOptions, RuntimeListWindowOptions, RuntimeRecordMutation, RuntimeRecordsList, RuntimeRequestOptions, RuntimeRowData, RuntimeTableWindow, RuntimeUpdateRecordInput, RuntimeWorkflowRun, RuntimeWorkflowStepRun, RuntimeWorkflowWaitOptions } from './types';
2
+ import type { AgnosticRuntimeConfig, ResolvedRuntimeContext, RuntimeAppAuthRequestLike, RuntimeAppAuthSession, RuntimeAppAuthUserResult, RuntimeAnonymousClaimInput, RuntimeAnonymousClaimResult, RuntimeAggregateRecordsInput, RuntimeAggregateRecordsResult, RuntimeCreateFileUploadInput, RuntimeCreateRecordInput, RuntimeIdentityContext, RuntimeFileDownloadUrl, RuntimeFileObject, RuntimeFileUploadCompletion, RuntimeFileUploadGrant, RuntimeListRecordsOptions, RuntimeQueryRecordsInput, RuntimeBatchQueryItem, RuntimeBatchQueryResult, RuntimeListWindowOptions, RuntimeRecordMutation, RuntimeRecordsList, RuntimeRequestOptions, RuntimeRowData, RuntimeTableWindow, RuntimeUpdateRecordInput, RuntimeWorkflowRun, RuntimeWorkflowStepRun, RuntimeWorkflowWaitOptions } from './types';
3
3
  export declare class AgnosticRuntime {
4
4
  readonly auth: RuntimeAppAuthNamespace;
5
5
  readonly context: RuntimeContextNamespace;
@@ -31,6 +31,7 @@ export declare class RuntimeDataNamespace {
31
31
  constructor(openapi: RuntimeOpenApiClient);
32
32
  table(tableName: string): RuntimeDataTableClient;
33
33
  view(viewId: string): RuntimeDataViewClient;
34
+ batchQuery(queries: RuntimeBatchQueryItem[], options?: RuntimeRequestOptions): Promise<RuntimeBatchQueryResult>;
34
35
  }
35
36
  export declare class RuntimeStorageNamespace {
36
37
  private readonly openapi;
@@ -64,6 +65,7 @@ export declare class RuntimeDataRecordsClient {
64
65
  private readonly tableName;
65
66
  constructor(openapi: RuntimeOpenApiClient, tableName: string);
66
67
  list(query?: RuntimeListRecordsOptions, options?: RuntimeRequestOptions): Promise<RuntimeRecordsList>;
68
+ query(input?: RuntimeQueryRecordsInput, options?: RuntimeRequestOptions): Promise<RuntimeRecordsList>;
67
69
  aggregate(input: RuntimeAggregateRecordsInput, options?: RuntimeRequestOptions): Promise<RuntimeAggregateRecordsResult>;
68
70
  create(input: RuntimeCreateRecordInput | RuntimeRowData, options?: RuntimeRequestOptions): Promise<RuntimeRecordMutation>;
69
71
  update(recordId: string, input: RuntimeUpdateRecordInput | RuntimeRowData, options?: RuntimeRequestOptions): Promise<RuntimeRecordMutation>;
@@ -9,6 +9,8 @@ const APP_AUTH_VERIFY_SESSION_PATH = '/api/v1/runtime/app-auth/session/verify';
9
9
  const APP_AUTH_USER_PATH = '/api/v1/runtime/app-auth/users/{userId}';
10
10
  const AUTH_CONTEXT_PATH = '/api/v1/runtime/auth/context';
11
11
  const DATA_RECORDS_PATH = '/api/v1/runtime/data/tables/{tableName}/records';
12
+ const DATA_QUERY_PATH = '/api/v1/runtime/data/tables/{tableName}/records/query';
13
+ const DATA_BATCH_QUERY_PATH = '/api/v1/runtime/data/records/batch-query';
12
14
  const DATA_AGGREGATE_PATH = '/api/v1/runtime/data/tables/{tableName}/records/aggregate';
13
15
  const DATA_RECORD_PATH = '/api/v1/runtime/data/tables/{tableName}/records/{recordId}';
14
16
  const DATA_VIEW_WINDOW_PATH = '/api/v1/runtime/data/views/{viewId}/table/window';
@@ -138,6 +140,13 @@ class RuntimeDataNamespace {
138
140
  view(viewId) {
139
141
  return new RuntimeDataViewClient(this.openapi, viewId);
140
142
  }
143
+ async batchQuery(queries, options) {
144
+ const result = await this.openapi.POST(DATA_BATCH_QUERY_PATH, {
145
+ body: { queries },
146
+ headers: (0, http_client_1.runtimeRequestHeaders)(options),
147
+ });
148
+ return (0, http_client_1.unwrapRuntimeResult)(result, 'Failed to batch query data records');
149
+ }
141
150
  }
142
151
  exports.RuntimeDataNamespace = RuntimeDataNamespace;
143
152
  class RuntimeStorageNamespace {
@@ -232,6 +241,14 @@ class RuntimeDataRecordsClient {
232
241
  });
233
242
  return (0, http_client_1.unwrapRuntimeResult)(result, 'Failed to list data records');
234
243
  }
244
+ async query(input = {}, options) {
245
+ const result = await this.openapi.POST(DATA_QUERY_PATH, {
246
+ body: input,
247
+ headers: (0, http_client_1.runtimeRequestHeaders)(options),
248
+ params: { path: { tableName: this.tableName } },
249
+ });
250
+ return (0, http_client_1.unwrapRuntimeResult)(result, 'Failed to query data records');
251
+ }
235
252
  async aggregate(input, options) {
236
253
  const result = await this.openapi.POST(DATA_AGGREGATE_PATH, {
237
254
  body: input,
@@ -159,6 +159,18 @@ export interface RuntimeListRecordsOptions {
159
159
  sort?: string;
160
160
  }
161
161
  export type RuntimeAggregateOperation = 'count' | 'sum' | 'avg' | 'min' | 'max';
162
+ export interface RuntimeQueryRecordsInput extends RuntimeListRecordsOptions {
163
+ /** Technical names; id is always included. Omit to read all fields. */
164
+ fields?: string[];
165
+ }
166
+ export interface RuntimeBatchQueryItem {
167
+ tableName: string;
168
+ query: RuntimeQueryRecordsInput;
169
+ }
170
+ export interface RuntimeBatchQueryResult {
171
+ /** Independent pages, in request order; no shared transactional snapshot. */
172
+ results: RuntimeRecordsList[];
173
+ }
162
174
  export interface RuntimeAggregateMetric {
163
175
  operation: RuntimeAggregateOperation;
164
176
  field?: string;