@jskit-ai/crud-server-generator 0.1.73 → 0.1.75

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,7 +1,7 @@
1
1
  export default Object.freeze({
2
2
  packageVersion: 1,
3
3
  packageId: "@jskit-ai/crud-server-generator",
4
- version: "0.1.73",
4
+ version: "0.1.75",
5
5
  kind: "generator",
6
6
  description: "CRUD server generator with routes, actions, and persistence scaffolding.",
7
7
  options: {
@@ -160,14 +160,14 @@ export default Object.freeze({
160
160
  mutations: {
161
161
  dependencies: {
162
162
  runtime: {
163
- "@jskit-ai/auth-core": "0.1.64",
164
- "@jskit-ai/crud-core": "0.1.73",
165
- "@jskit-ai/database-runtime": "0.1.65",
166
- "@jskit-ai/http-runtime": "0.1.64",
167
- "@jskit-ai/json-rest-api-core": "0.1.10",
168
- "@jskit-ai/kernel": "0.1.65",
169
- "@jskit-ai/realtime": "0.1.64",
170
- "@jskit-ai/resource-crud-core": "0.1.10",
163
+ "@jskit-ai/auth-core": "0.1.66",
164
+ "@jskit-ai/crud-core": "0.1.75",
165
+ "@jskit-ai/database-runtime": "0.1.67",
166
+ "@jskit-ai/http-runtime": "0.1.66",
167
+ "@jskit-ai/json-rest-api-core": "0.1.12",
168
+ "@jskit-ai/kernel": "0.1.67",
169
+ "@jskit-ai/realtime": "0.1.66",
170
+ "@jskit-ai/resource-crud-core": "0.1.12",
171
171
  "@local/${option:namespace|kebab}": "file:packages/${option:namespace|kebab}"
172
172
  },
173
173
  dev: {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/crud-server-generator",
3
- "version": "0.1.73",
3
+ "version": "0.1.75",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
@@ -13,12 +13,12 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@babel/parser": "^7.29.2",
16
- "@jskit-ai/crud-core": "0.1.73",
17
- "@jskit-ai/database-runtime": "0.1.65",
18
- "@jskit-ai/http-runtime": "0.1.64",
19
- "@jskit-ai/json-rest-api-core": "0.1.10",
20
- "@jskit-ai/kernel": "0.1.65",
21
- "@jskit-ai/resource-crud-core": "0.1.10",
16
+ "@jskit-ai/crud-core": "0.1.75",
17
+ "@jskit-ai/database-runtime": "0.1.67",
18
+ "@jskit-ai/http-runtime": "0.1.66",
19
+ "@jskit-ai/json-rest-api-core": "0.1.12",
20
+ "@jskit-ai/kernel": "0.1.67",
21
+ "@jskit-ai/resource-crud-core": "0.1.12",
22
22
  "recast": "^0.23.11"
23
23
  }
24
24
  }
@@ -1036,6 +1036,8 @@ function renderJsonRestSchemaPropertyLines(columns = [], { fieldContractEntries
1036
1036
  }
1037
1037
 
1038
1038
  function renderJsonRestSearchSchemaLines(columns = []) {
1039
+ const exactFilterKeys = new Set();
1040
+ const exactFilterLines = [];
1039
1041
  const searchableStringKeys = (Array.isArray(columns) ? columns : [])
1040
1042
  .filter((column) =>
1041
1043
  normalizeText(column?.typeKind).toLowerCase() === "string" &&
@@ -1051,6 +1053,29 @@ function renderJsonRestSearchSchemaLines(columns = []) {
1051
1053
  ' id: { type: "id", actualField: "id" },'
1052
1054
  ];
1053
1055
 
1056
+ for (const column of Array.isArray(columns) ? columns : []) {
1057
+ const key = normalizeText(column?.key);
1058
+ if (
1059
+ !key ||
1060
+ exactFilterKeys.has(key) ||
1061
+ column?.isOwnerColumn === true ||
1062
+ column?.isIdColumn === true ||
1063
+ column?.isCreatedAtColumn === true ||
1064
+ column?.isUpdatedAtColumn === true ||
1065
+ column?.isForeignIdColumn !== true
1066
+ ) {
1067
+ continue;
1068
+ }
1069
+
1070
+ const actualField = normalizeText(column?.name) || key;
1071
+ exactFilterKeys.add(key);
1072
+ exactFilterLines.push(
1073
+ ` ${renderObjectPropertyKey(key)}: { type: "id", actualField: ${JSON.stringify(actualField)}, filterOperator: "=" },`
1074
+ );
1075
+ }
1076
+
1077
+ lines.push(...exactFilterLines);
1078
+
1054
1079
  if (searchableStringKeys.length > 0) {
1055
1080
  lines.push(
1056
1081
  ` q: { type: "string", oneOf: ${JSON.stringify(searchableStringKeys)}, filterOperator: "like", splitBy: " ", matchAll: true },`
@@ -557,6 +557,10 @@ test("buildReplacementsFromSnapshot renders inline field relation metadata from
557
557
  replacements.__JSKIT_CRUD_RESOURCE_SCHEMA_PROPERTIES__,
558
558
  /relation: \{ kind: "lookup", namespace: "customer-categories", valueKey: "id" \}.*belongsTo: "customerCategories".*as: "vet".*ui: \{ formControl: "autocomplete" \}/s
559
559
  );
560
+ assert.match(
561
+ replacements.__JSKIT_CRUD_RESOURCE_SEARCH_SCHEMA_LINES__,
562
+ /vetId: \{ type: "id", actualField: "vet_id", filterOperator: "=" \}/
563
+ );
560
564
  assert.match(replacements.__JSKIT_CRUD_MIGRATION_FOREIGN_KEY_LINES__, /table\.foreign\(\["vet_id"\]/);
561
565
  });
562
566
 
@@ -273,6 +273,78 @@ test("template list action strips workspaceSlug before calling the service", asy
273
273
  });
274
274
  });
275
275
 
276
+ test("template write actions strip workspaceSlug before calling the service", async () => {
277
+ const actions = createActions({ surface: "admin" });
278
+ const createAction = actions.find((action) => action.id === "crud.customers.create");
279
+ const updateAction = actions.find((action) => action.id === "crud.customers.update");
280
+ const calls = [];
281
+
282
+ await createAction.execute(
283
+ {
284
+ workspaceSlug: "acme",
285
+ name: "Merc"
286
+ },
287
+ { visibilityContext: { visibility: "workspace", scopeOwnerId: "7" } },
288
+ {
289
+ customersService: {
290
+ async createDocument(payload, options) {
291
+ calls.push({ kind: "create", payload, options });
292
+ return { kind: "document", value: { data: { id: "1" } } };
293
+ }
294
+ }
295
+ }
296
+ );
297
+
298
+ await updateAction.execute(
299
+ {
300
+ workspaceSlug: "acme",
301
+ recordId: "7",
302
+ name: "Changed"
303
+ },
304
+ { visibilityContext: { visibility: "workspace", scopeOwnerId: "7" } },
305
+ {
306
+ customersService: {
307
+ async patchDocumentById(recordId, patch, options) {
308
+ calls.push({ kind: "update", recordId, patch, options });
309
+ return { kind: "document", value: { data: { id: recordId } } };
310
+ }
311
+ }
312
+ }
313
+ );
314
+
315
+ assert.deepEqual(calls, [
316
+ {
317
+ kind: "create",
318
+ payload: {
319
+ name: "Merc"
320
+ },
321
+ options: {
322
+ context: {
323
+ visibilityContext: {
324
+ visibility: "workspace",
325
+ scopeOwnerId: "7"
326
+ }
327
+ }
328
+ }
329
+ },
330
+ {
331
+ kind: "update",
332
+ recordId: "7",
333
+ patch: {
334
+ name: "Changed"
335
+ },
336
+ options: {
337
+ context: {
338
+ visibilityContext: {
339
+ visibility: "workspace",
340
+ scopeOwnerId: "7"
341
+ }
342
+ }
343
+ }
344
+ }
345
+ ]);
346
+ });
347
+
276
348
  test("template createActions omits workspace validators for non-workspace generation", () => {
277
349
  const actions = createNonWorkspaceActions({ surface: "home" });
278
350