@seliseblocks/client 0.1.0-beta.2 → 0.1.1

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.
@@ -1,5 +1,5 @@
1
1
  import { BlocksHttpClient } from "../http/http-client.js";
2
- import { BlocksDataCollection, BlocksDmsCreateFolderRequest, BlocksDmsListRequest, BlocksDmsUploadRequest, BlocksFileDeleteRequest, BlocksFileGetOptions, BlocksFileInfoListRequest, BlocksDataSchema, BlocksFileListRequest, BlocksFileUpdateAdditionalInfoRequest, BlocksFileUploadRequest, BlocksFolderDeleteRequest, BlocksGraphqlRequest, BlocksLocalStorageUploadRequest, BlocksPagedResult, BlocksRegexGenerateRequest, BlocksSchemaFieldValidationOptions, BlocksSchemaListOptions, BlocksSchemaValidationListOptions, BlocksUploadToUrlRequest } from "./types.js";
2
+ import { BlocksDataCollection, BlocksDataCollectionOptions, BlocksDmsCreateFolderRequest, BlocksDmsListRequest, BlocksDmsUploadRequest, BlocksFileDeleteRequest, BlocksFileGetOptions, BlocksFileInfoListRequest, BlocksDataSchema, BlocksFileListRequest, BlocksFileUpdateAdditionalInfoRequest, BlocksFileUploadRequest, BlocksFolderDeleteRequest, BlocksGraphqlRequest, BlocksLocalStorageUploadRequest, BlocksPagedResult, BlocksRegexGenerateRequest, BlocksSchemaFieldValidationOptions, BlocksSchemaListOptions, BlocksSchemaValidationListOptions, BlocksUploadToUrlRequest } from "./types.js";
3
3
  export declare class BlocksDataClient {
4
4
  private readonly http;
5
5
  constructor(http: BlocksHttpClient);
@@ -171,8 +171,8 @@ export declare class BlocksDataClient {
171
171
  };
172
172
  /**
173
173
  * What: creates CRUD helpers for a Data runtime collection.
174
- * Why: frontend code usually works with business collection names rather than hand-written URLs.
175
- * How: pass the exact collection name; returned helpers support list/get/create/update/delete and never add `ProjectKey`.
174
+ * Why: frontend code usually works with schema names rather than hand-written GraphQL operations.
175
+ * How: pass the exact schema name, such as `Product`; returned helpers call `/data/v4/gateway` and never add `ProjectKey`.
176
176
  */
177
- collection<T = Record<string, unknown>>(name: string): BlocksDataCollection<T>;
177
+ collection<T = Record<string, unknown>>(schemaName: string, options?: BlocksDataCollectionOptions): BlocksDataCollection<T>;
178
178
  }
@@ -241,51 +241,100 @@ export class BlocksDataClient {
241
241
  };
242
242
  /**
243
243
  * What: creates CRUD helpers for a Data runtime collection.
244
- * Why: frontend code usually works with business collection names rather than hand-written URLs.
245
- * How: pass the exact collection name; returned helpers support list/get/create/update/delete and never add `ProjectKey`.
244
+ * Why: frontend code usually works with schema names rather than hand-written GraphQL operations.
245
+ * How: pass the exact schema name, such as `Product`; returned helpers call `/data/v4/gateway` and never add `ProjectKey`.
246
246
  */
247
- collection(name) {
247
+ collection(schemaName, options = {}) {
248
+ assertGraphqlName(schemaName, "schemaName");
249
+ const listField = `get${schemaName}s`;
250
+ const createField = `insert${schemaName}`;
251
+ const updateField = `update${schemaName}`;
252
+ const deleteField = `delete${schemaName}`;
248
253
  return {
249
254
  /**
250
- * What: creates a collection item through `POST /data/v4/{collection}`.
255
+ * What: creates a schema-backed item through `POST /data/v4/gateway`.
251
256
  * Why: forms need a direct runtime create operation.
252
- * How: pass the item payload; Data validates it against the active collection schema.
257
+ * How: pass the item payload; Data validates it against the active schema's insert input.
253
258
  */
254
- create: (payload) => this.http.request(`${DATA_API}/${encodeURIComponent(name)}`, { body: payload }),
259
+ create: (payload) => this.graphql({
260
+ operationName: createField,
261
+ query: `mutation ${createField}($input: ${schemaName}InsertInput!) {
262
+ ${createField}(input: $input) {
263
+ acknowledged
264
+ itemId
265
+ message
266
+ totalImpactedData
267
+ }
268
+ }`,
269
+ variables: { input: payload }
270
+ }),
255
271
  /**
256
- * What: deletes a collection item through `DELETE /data/v4/{collection}/{itemId}`.
272
+ * What: deletes a schema-backed item through `POST /data/v4/gateway`.
257
273
  * Why: collection UIs need a runtime delete operation when allowed by permissions/rules.
258
- * How: pass the item id from Data.
274
+ * How: pass the item id from Data; the SDK sends a GraphQL `filter` on `ItemId`.
259
275
  */
260
- delete: (itemId) => this.http.request(`${DATA_API}/${encodeURIComponent(name)}/${encodeURIComponent(itemId)}`, {
261
- method: "DELETE"
276
+ delete: (itemId, deleteOptions = {}) => this.graphql({
277
+ operationName: deleteField,
278
+ query: `mutation ${deleteField}($filter: String, $input: ${schemaName}DeleteInput!) {
279
+ ${deleteField}(filter: $filter, input: $input) {
280
+ acknowledged
281
+ itemId
282
+ message
283
+ totalImpactedData
284
+ }
285
+ }`,
286
+ variables: {
287
+ filter: itemIdFilter(itemId),
288
+ input: { isHardDelete: deleteOptions.hardDelete ?? false }
289
+ }
262
290
  }),
263
291
  /**
264
- * What: reads one collection item through `GET /data/v4/{collection}/{itemId}`.
292
+ * What: reads one schema-backed item through `POST /data/v4/gateway`.
265
293
  * Why: detail pages need one runtime record by id.
266
- * How: pass the item id from Data.
294
+ * How: pass the item id from Data; the SDK queries `get{SchemaName}s` with an `ItemId` filter.
267
295
  */
268
- get: (itemId) => this.http.request(`${DATA_API}/${encodeURIComponent(name)}/${encodeURIComponent(itemId)}`),
296
+ get: (itemId, getOptions = {}) => this.graphql({
297
+ operationName: listField,
298
+ query: collectionListQuery(listField, selectionFor(getOptions.fields ?? options.fields)),
299
+ variables: {
300
+ input: {
301
+ filter: itemIdFilter(itemId),
302
+ pageNo: 1,
303
+ pageSize: 1
304
+ }
305
+ }
306
+ }),
269
307
  /**
270
- * What: lists collection items through `GET /data/v4/{collection}`.
308
+ * What: lists schema-backed items through `POST /data/v4/gateway`.
271
309
  * Why: tables, grids, and pickers need paged runtime records.
272
- * How: pass `pageNo`, `pageSize`, and optional query fields supported by the collection endpoint.
310
+ * How: pass `pageNo`, `pageSize`, optional `filter`/`sort`, and GraphQL fields to select.
273
311
  */
274
- list: (options) => this.http.request(`${DATA_API}/${encodeURIComponent(name)}`, {
275
- query: {
276
- PageNo: options?.pageNo ?? 1,
277
- PageSize: options?.pageSize ?? 20,
278
- ...options?.query
312
+ list: (listOptions) => this.graphql({
313
+ operationName: listField,
314
+ query: collectionListQuery(listField, selectionFor(listOptions?.fields ?? options.fields)),
315
+ variables: {
316
+ input: dynamicQueryInput(listOptions)
279
317
  }
280
318
  }),
281
319
  /**
282
- * What: updates a collection item through `PUT /data/v4/{collection}/{itemId}`.
320
+ * What: updates a schema-backed item through `POST /data/v4/gateway`.
283
321
  * Why: edit forms need a runtime update operation.
284
- * How: pass the item id and partial payload; Data applies its schema/rule validation.
322
+ * How: pass the item id and partial payload; the SDK sends a GraphQL `filter` on `ItemId`.
285
323
  */
286
- update: (itemId, payload) => this.http.request(`${DATA_API}/${encodeURIComponent(name)}/${encodeURIComponent(itemId)}`, {
287
- body: payload,
288
- method: "PUT"
324
+ update: (itemId, payload) => this.graphql({
325
+ operationName: updateField,
326
+ query: `mutation ${updateField}($filter: String, $input: ${schemaName}UpdateInput!) {
327
+ ${updateField}(filter: $filter, input: $input) {
328
+ acknowledged
329
+ itemId
330
+ message
331
+ totalImpactedData
332
+ }
333
+ }`,
334
+ variables: {
335
+ filter: itemIdFilter(itemId),
336
+ input: payload
337
+ }
289
338
  })
290
339
  };
291
340
  }
@@ -383,3 +432,50 @@ function withoutProjectKey(request) {
383
432
  delete record.ProjectKey;
384
433
  return record;
385
434
  }
435
+ function dynamicQueryInput(options) {
436
+ return {
437
+ filter: normalizeGraphqlJsonInput(options?.filter ?? options?.query),
438
+ pageNo: options?.pageNo ?? 1,
439
+ pageSize: options?.pageSize ?? 20,
440
+ sort: normalizeGraphqlJsonInput(options?.sort)
441
+ };
442
+ }
443
+ function collectionListQuery(fieldName, selection) {
444
+ return `query ${fieldName}($input: DynamicQueryInput) {
445
+ ${fieldName}(input: $input) {
446
+ items {
447
+ ${indent(selection, 6)}
448
+ }
449
+ totalCount
450
+ pageNo
451
+ pageSize
452
+ totalPages
453
+ hasNextPage
454
+ hasPreviousPage
455
+ }
456
+ }`;
457
+ }
458
+ function selectionFor(fields) {
459
+ const selected = fields?.length ? fields : ["ItemId"];
460
+ const unique = Array.from(new Set(["ItemId", ...selected]));
461
+ for (const field of unique)
462
+ assertGraphqlName(field, "field");
463
+ return unique.join("\n");
464
+ }
465
+ function itemIdFilter(itemId) {
466
+ return JSON.stringify({ ItemId: itemId });
467
+ }
468
+ function normalizeGraphqlJsonInput(value) {
469
+ if (value === undefined)
470
+ return undefined;
471
+ return typeof value === "string" ? value : JSON.stringify(value);
472
+ }
473
+ function assertGraphqlName(value, label) {
474
+ if (!/^[_A-Za-z][_0-9A-Za-z]*$/.test(value)) {
475
+ throw new Error(`Invalid Blocks Data GraphQL ${label}: ${value}`);
476
+ }
477
+ }
478
+ function indent(value, spaces) {
479
+ const pad = " ".repeat(spaces);
480
+ return value.split("\n").map((line) => `${pad}${line}`).join("\n");
481
+ }
@@ -9,14 +9,30 @@ export type BlocksPagedResult<T> = {
9
9
  message?: string | null;
10
10
  };
11
11
  export type BlocksDataListOptions = {
12
+ fields?: string[];
13
+ filter?: Record<string, unknown> | string;
12
14
  pageNo?: number;
13
15
  pageSize?: number;
16
+ /**
17
+ * Legacy convenience alias for the GraphQL DynamicQueryInput.Filter payload.
18
+ * Prefer `filter` for new code.
19
+ */
14
20
  query?: Record<string, boolean | number | string | undefined>;
21
+ sort?: Record<string, unknown> | string;
22
+ };
23
+ export type BlocksDataCollectionOptions = {
24
+ fields?: string[];
25
+ };
26
+ export type BlocksDataDeleteOptions = {
27
+ hardDelete?: boolean;
28
+ };
29
+ export type BlocksDataGetOptions = {
30
+ fields?: string[];
15
31
  };
16
32
  export type BlocksDataCollection<T = Record<string, unknown>> = {
17
33
  create(payload: Partial<T>): Promise<unknown>;
18
- delete(itemId: string): Promise<unknown>;
19
- get(itemId: string): Promise<unknown>;
34
+ delete(itemId: string, options?: BlocksDataDeleteOptions): Promise<unknown>;
35
+ get(itemId: string, options?: BlocksDataGetOptions): Promise<unknown>;
20
36
  list(options?: BlocksDataListOptions): Promise<unknown>;
21
37
  update(itemId: string, payload: Partial<T>): Promise<unknown>;
22
38
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seliseblocks/client",
3
- "version": "0.1.0-beta.2",
3
+ "version": "0.1.1",
4
4
  "description": "Framework-neutral TypeScript client SDK for SELISE Blocks frontend applications.",
5
5
  "license": "MIT",
6
6
  "type": "module",