@ghentcdh/crouton-api 0.0.1-alpha.61 → 0.0.1-alpha.69

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/dist/index.cjs CHANGED
@@ -70,7 +70,7 @@ __export(index_exports, {
70
70
  });
71
71
  module.exports = __toCommonJS(index_exports);
72
72
 
73
- // ../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.58.8_@types+node@26.4.0__@swc+core@1.16.1_@swc+he_53e7170f1cd8909962d4b3404cf3712f/node_modules/tsup/assets/cjs_shims.js
73
+ // ../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.58.8_@types+node@26.4.0__@swc+core@1.16.1_@swc+he_9a17c50ee76d0369ad0c28a18d209a0d/node_modules/tsup/assets/cjs_shims.js
74
74
  var getImportMetaUrl = /* @__PURE__ */ __name(() => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href, "getImportMetaUrl");
75
75
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
76
76
 
@@ -98,7 +98,8 @@ var RequestSchema = import_zod2.z.object({
98
98
  sort: import_zod2.z.string().optional().default("id"),
99
99
  sortDir: SortDirEnum.optional().default("asc"),
100
100
  // Filter is of the format key:value:operator (e.g. name:john:eq) operator is optional
101
- filter: StringOrArray().optional().default([])
101
+ filter: StringOrArray().optional().default([]),
102
+ q: import_zod2.z.string().optional()
102
103
  });
103
104
  var RequestSchemaWithOffset = RequestSchema.transform((schema) => {
104
105
  const { page, pageSize, sort } = schema;
@@ -160,6 +161,15 @@ var ResponseSchema = import_zod4.z.object({
160
161
  // ../crouton-core/src/lib/create-schema.ts
161
162
  var import_zod6 = require("zod");
162
163
 
164
+ // ../crouton-core/src/lib/schema.utils.ts
165
+ var isNullableProperty = /* @__PURE__ */ __name((property) => {
166
+ const prop = property;
167
+ if (!prop) return false;
168
+ if (Array.isArray(prop["type"]) && prop["type"].includes("null")) return true;
169
+ const anyOf = prop["anyOf"];
170
+ return Array.isArray(anyOf) && anyOf.some((s) => s?.["type"] === "null");
171
+ }, "isNullableProperty");
172
+
163
173
  // ../crouton-core/src/lib/layout/base.builder.ts
164
174
  var Builder = class {
165
175
  static {
@@ -1668,10 +1678,6 @@ var allowAdditionalProperties = /* @__PURE__ */ __name((schema) => {
1668
1678
  allowAdditionalProperties(schema["items"]);
1669
1679
  }
1670
1680
  }, "allowAdditionalProperties");
1671
- var isNullableProperty = /* @__PURE__ */ __name((prop) => {
1672
- const anyOf = prop?.["anyOf"];
1673
- return Array.isArray(anyOf) && anyOf.some((s) => s?.["type"] === "null");
1674
- }, "isNullableProperty");
1675
1681
  var dropNullableFromRequired = /* @__PURE__ */ __name((schema) => {
1676
1682
  if (schema["type"] !== "object") return;
1677
1683
  const props = schema["properties"];
@@ -1823,6 +1829,11 @@ var buildDetailLayout = /* @__PURE__ */ __name((detail) => {
1823
1829
  var defaultControlFormat = /* @__PURE__ */ __name((col) => {
1824
1830
  if (isObjectColumn(col)) return "object";
1825
1831
  if (isArrayColumn(col)) return "array";
1832
+ const typeName = columnTypeName(col.type);
1833
+ if (typeName === "number" || typeName === "integer") return typeName;
1834
+ const format = columnTypeToJsonSchema(col.type).format;
1835
+ if (format === "date") return "date";
1836
+ if (format === "date-time") return "dateTime";
1826
1837
  return "text";
1827
1838
  }, "defaultControlFormat");
1828
1839
  var buildFormControl = /* @__PURE__ */ __name((col) => {
@@ -2846,7 +2857,7 @@ var resolveLanguage = /* @__PURE__ */ __name((acceptLanguage, supported, default
2846
2857
  }, "resolveLanguage");
2847
2858
 
2848
2859
  // src/lib/crouton-api.module.ts
2849
- var import_common26 = require("@nestjs/common");
2860
+ var import_common27 = require("@nestjs/common");
2850
2861
  var import_core2 = require("@nestjs/core");
2851
2862
 
2852
2863
  // src/lib/crud/app-layout/app-layout.types.ts
@@ -3172,6 +3183,28 @@ var patchViewTitles = /* @__PURE__ */ __name((views, columnLabels) => {
3172
3183
  } : vc;
3173
3184
  });
3174
3185
  }
3186
+ const patchUiElements = /* @__PURE__ */ __name((elements) => {
3187
+ for (const el of elements) {
3188
+ if (!el || typeof el !== "object") continue;
3189
+ const element = el;
3190
+ const scope = element.scope;
3191
+ if (scope) {
3192
+ const match = /^#\/properties\/([^/]+)/.exec(scope);
3193
+ if (match) {
3194
+ const translated = columnLabels.get(match[1]);
3195
+ if (translated) {
3196
+ const opts = element.options;
3197
+ if (opts && typeof opts === "object") opts.label = translated;
3198
+ }
3199
+ }
3200
+ }
3201
+ const nested = element.elements;
3202
+ if (Array.isArray(nested)) patchUiElements(nested);
3203
+ }
3204
+ }, "patchUiElements");
3205
+ const uiSchema = patchedView.ui_schema;
3206
+ const uiElements = uiSchema?.elements;
3207
+ if (Array.isArray(uiElements)) patchUiElements(uiElements);
3175
3208
  patched[viewName] = patchedView;
3176
3209
  }
3177
3210
  return patched;
@@ -3732,7 +3765,10 @@ var isTableProcedureAction = /* @__PURE__ */ __name((action) => action.type !==
3732
3765
  var import_node_fs4 = require("fs");
3733
3766
  var import_node_module = require("module");
3734
3767
  var import_node_path5 = require("path");
3768
+ var import_node_url = require("url");
3769
+ var import_meta = {};
3735
3770
  var _require = (0, import_node_module.createRequire)(importMetaUrl ?? __filename);
3771
+ var IS_ESM = typeof import_meta !== "undefined" && typeof importMetaUrl === "string";
3736
3772
  var findModule = /* @__PURE__ */ __name((dir, name) => {
3737
3773
  for (const ext of [
3738
3774
  ".ts",
@@ -3750,6 +3786,9 @@ var importDefault = /* @__PURE__ */ __name(async (filePath, onError) => {
3750
3786
  const importPath = IS_DEV ? `${filePath}?t=${Date.now()}` : filePath;
3751
3787
  const mod = await import(importPath);
3752
3788
  return mod.default ?? mod;
3789
+ } else if (IS_ESM) {
3790
+ const mod = await import((0, import_node_url.pathToFileURL)(filePath).href);
3791
+ return mod.default ?? mod;
3753
3792
  } else {
3754
3793
  const mod = _require(filePath);
3755
3794
  return mod.default;
@@ -4373,8 +4412,16 @@ var ReadRepository = class {
4373
4412
  const subResources = this.config.subResources ?? [];
4374
4413
  const projection = this.projection("findAll");
4375
4414
  const vlCols = await resolveValueLabelColumns(this.config.route, this.config.valueLabelColumns, this.configRegistry);
4415
+ const filterWhere = this.buildWhere(params.filter);
4416
+ const searchWhere = this.buildSearchOrWhere(params.q);
4417
+ const where = filterWhere && searchWhere ? {
4418
+ AND: [
4419
+ filterWhere,
4420
+ searchWhere
4421
+ ]
4422
+ } : filterWhere ?? searchWhere;
4376
4423
  const query = {
4377
- where: this.buildWhere(params.filter),
4424
+ where,
4378
4425
  take: params.pageSize,
4379
4426
  skip: offsetOf(params),
4380
4427
  orderBy: this.safeSort(sanitizeValueLabelSort(params.sort, vlCols), params.sortDir)
@@ -4432,10 +4479,30 @@ var ReadRepository = class {
4432
4479
  const withCalc = await mergeCalculatedColumnsForRows(mapped, this.config.calculatedColumns ?? [], this.tableName, this.prisma, this.config.idField ?? "id");
4433
4480
  return withCalc;
4434
4481
  }
4435
- /** Count records matching the given filter strings. */
4436
- count(filter) {
4482
+ buildSearchOrWhere(q) {
4483
+ const lookup = this.config.lookup;
4484
+ const labels = lookup?.labels?.length ? lookup.labels : lookup?.label ? [
4485
+ lookup.label
4486
+ ] : void 0;
4487
+ if (!q || !labels?.length) return void 0;
4488
+ return {
4489
+ OR: labels.map((path) => buildNestedPath(path.split("."), {
4490
+ contains: q
4491
+ }))
4492
+ };
4493
+ }
4494
+ /** Count records matching the given filter strings and optional free-text search. */
4495
+ count(filter, q) {
4496
+ const filterWhere = this.buildWhere(filter);
4497
+ const searchWhere = this.buildSearchOrWhere(q);
4498
+ const where = filterWhere && searchWhere ? {
4499
+ AND: [
4500
+ filterWhere,
4501
+ searchWhere
4502
+ ]
4503
+ } : filterWhere ?? searchWhere;
4437
4504
  return this.prismaModel.count({
4438
- where: this.buildWhere(filter)
4505
+ where
4439
4506
  });
4440
4507
  }
4441
4508
  /**
@@ -4946,7 +5013,7 @@ var PrismaDataSourceAdapter = class {
4946
5013
  const reader = new ReadRepository(prismaModel, this, ctx.config, ctx.listSelect, ctx.oneSelect, ctx.configRegistry);
4947
5014
  const [data, count] = await Promise.all([
4948
5015
  reader.findAll(params, ctx.request),
4949
- reader.count(params.filter ?? [])
5016
+ reader.count(params.filter ?? [], params.q)
4950
5017
  ]);
4951
5018
  return {
4952
5019
  data,
@@ -4955,7 +5022,7 @@ var PrismaDataSourceAdapter = class {
4955
5022
  }
4956
5023
  async count(model, filter, ctx) {
4957
5024
  const reader = new ReadRepository(this.prismaModel(model), this, ctx.config, void 0, void 0, ctx.configRegistry);
4958
- return reader.count(filter);
5025
+ return reader.count(filter, ctx.q);
4959
5026
  }
4960
5027
  async findOne(model, id, ctx) {
4961
5028
  const prismaModel = this.prismaModel(model);
@@ -5275,14 +5342,10 @@ function isZodSchema(schema) {
5275
5342
  return schema instanceof import_zod40.ZodObject;
5276
5343
  }
5277
5344
  __name(isZodSchema, "isZodSchema");
5278
- var isNullableProperty2 = /* @__PURE__ */ __name((property) => {
5279
- const anyOf = property?.["anyOf"];
5280
- return Array.isArray(anyOf) && anyOf.some((s) => s?.["type"] === "null");
5281
- }, "isNullableProperty");
5282
5345
  var dropNullableFromRequired2 = /* @__PURE__ */ __name((jsonSchema) => {
5283
5346
  const { properties, required } = jsonSchema;
5284
5347
  if (!properties || !Array.isArray(required)) return;
5285
- jsonSchema.required = required.filter((key) => !isNullableProperty2(properties[key]));
5348
+ jsonSchema.required = required.filter((key) => !isNullableProperty(properties[key]));
5286
5349
  }, "dropNullableFromRequired");
5287
5350
  function toJsonSchema2(schema) {
5288
5351
  if (isZodSchema(schema)) {
@@ -5438,7 +5501,10 @@ function createCrudRepository(prisma, config, dataSources, configRegistry) {
5438
5501
  });
5439
5502
  return decorateFindAll2(data, request);
5440
5503
  }, "findAll"),
5441
- count: /* @__PURE__ */ __name((filter) => resolvedAdapter.count(adapterModelKey, filter, baseCtx), "count"),
5504
+ count: /* @__PURE__ */ __name((filter, q) => resolvedAdapter.count(adapterModelKey, filter, {
5505
+ ...baseCtx,
5506
+ q
5507
+ }), "count"),
5442
5508
  findOne: /* @__PURE__ */ __name(async (id, request) => {
5443
5509
  const row = await resolvedAdapter.findOne(adapterModelKey, id, ctx(request, "findOne", id));
5444
5510
  if (row === null || row === void 0) throw new import_common10.NotFoundException(`${config.name} with id ${id} not found`);
@@ -6172,19 +6238,10 @@ var ZodValidationPipe = class {
6172
6238
  };
6173
6239
 
6174
6240
  // src/lib/crud/operations/register-findall.ts
6175
- var _findAll = /* @__PURE__ */ __name(async (repo, params, q, lookupLabel, request) => {
6176
- const effectiveParams = {
6177
- ...params
6178
- };
6179
- if (q && lookupLabel) {
6180
- effectiveParams.filter = [
6181
- ...params.filter ?? [],
6182
- `${lookupLabel}:${q}`
6183
- ];
6184
- }
6185
- const { data, count } = repo.findAllWithCount ? await repo.findAllWithCount(effectiveParams, request) : await Promise.all([
6186
- repo.findAll(effectiveParams, request),
6187
- repo.count(effectiveParams.filter)
6241
+ var _findAll = /* @__PURE__ */ __name(async (repo, params, request) => {
6242
+ const { data, count } = repo.findAllWithCount ? await repo.findAllWithCount(params, request) : await Promise.all([
6243
+ repo.findAll(params, request),
6244
+ repo.count(params.filter ?? [], params.q)
6188
6245
  ]).then(([data2, count2]) => ({
6189
6246
  data: data2,
6190
6247
  count: count2
@@ -6223,9 +6280,8 @@ var defaultFindAll = /* @__PURE__ */ __name((ctx) => {
6223
6280
  if (!isOperationEnabled2(ctx.definition, "findAll")) return;
6224
6281
  if (isOperationExternal2(ctx.definition, "findAll")) return;
6225
6282
  const { config } = ctx;
6226
- const lookupLabel = config.lookup?.label;
6227
- const findAll = /* @__PURE__ */ __name(async function(params, q, req) {
6228
- return _findAll(this.repo, params, q, lookupLabel, req);
6283
+ const findAll = /* @__PURE__ */ __name(async function(params, req) {
6284
+ return _findAll(this.repo, params, req);
6229
6285
  }, "findAll");
6230
6286
  return {
6231
6287
  route: "",
@@ -6241,12 +6297,12 @@ var childFindAll = /* @__PURE__ */ __name((sub) => (ctx) => {
6241
6297
  if (!isOperationEnabled2(sub.operations, "findAll")) return;
6242
6298
  const { cls } = ctx;
6243
6299
  const methodName = `findAllBy_${sub.childRoute}`;
6244
- const findAll = /* @__PURE__ */ __name(async function(params, q, id, req) {
6300
+ const findAll = /* @__PURE__ */ __name(async function(params, id, req) {
6245
6301
  return findAllByParent(this.repo, id, sub.childRoute, params, req);
6246
6302
  }, "findAll");
6247
6303
  const decorators = /* @__PURE__ */ __name(() => {
6248
- (0, import_common17.Param)("id")(cls.prototype, methodName, 2);
6249
- (0, import_common17.Req)()(cls.prototype, methodName, 3);
6304
+ (0, import_common17.Param)("id")(cls.prototype, methodName, 1);
6305
+ (0, import_common17.Req)()(cls.prototype, methodName, 2);
6250
6306
  }, "decorators");
6251
6307
  return {
6252
6308
  name: sub.childRoute,
@@ -6267,8 +6323,7 @@ var registerFindAll = /* @__PURE__ */ __name((ctx, sub) => {
6267
6323
  const d = desc(cls, methodName);
6268
6324
  (0, import_common17.Get)(route)(cls.prototype, methodName, d);
6269
6325
  (0, import_common17.Query)(new ZodValidationPipe(RequestDtoNoOffset.schema))(cls.prototype, methodName, 0);
6270
- (0, import_common17.Query)("q")(cls.prototype, methodName, 1);
6271
- if (!sub) (0, import_common17.Req)()(cls.prototype, methodName, 2);
6326
+ if (!sub) (0, import_common17.Req)()(cls.prototype, methodName, 1);
6272
6327
  (0, import_swagger5.ApiOperation)({
6273
6328
  summary: `List all ${name}s`
6274
6329
  })(cls.prototype, methodName, d);
@@ -6950,12 +7005,23 @@ var defaultSchemas = /* @__PURE__ */ __name((ctx) => {
6950
7005
  var childSchemas = /* @__PURE__ */ __name((sub) => (ctx) => {
6951
7006
  if (!sub.views) return null;
6952
7007
  const { config, baseUrl } = ctx;
7008
+ const { route } = config;
6953
7009
  const schemasPayload = buildSubResourceViewsPayload(config, sub, baseUrl);
6954
7010
  return {
6955
7011
  route: `${sub.childRoute}/schemas`,
6956
7012
  methodName: `getSchemas_${sub.childRoute}`,
6957
7013
  name: sub.childRoute,
6958
7014
  schemasFn: /* @__PURE__ */ __name(async function() {
7015
+ const language = getRequestLanguage();
7016
+ if (IS_DEV || language) {
7017
+ const localizedParent = await this.configRegistry.getByRoute(route, language);
7018
+ if (localizedParent) {
7019
+ const localizedSub = (localizedParent.subResources ?? []).find((s) => s.childRoute === sub.childRoute);
7020
+ if (localizedSub) {
7021
+ return buildSubResourceViewsPayload(localizedParent, localizedSub, baseUrl) ?? schemasPayload;
7022
+ }
7023
+ }
7024
+ }
6959
7025
  return schemasPayload;
6960
7026
  }, "schemasFn"),
6961
7027
  decorators: /* @__PURE__ */ __name(() => {
@@ -8076,65 +8142,29 @@ var prismaGenerate = /* @__PURE__ */ __name(async (cwd, prismaConfig) => {
8076
8142
  ${stderr}`.trim()
8077
8143
  };
8078
8144
  }, "prismaGenerate");
8079
- var fixZodImports = /* @__PURE__ */ __name(async (zodOutputDir) => {
8080
- let fixed = 0;
8081
- const walk = /* @__PURE__ */ __name(async (dir) => {
8082
- let entries;
8083
- try {
8084
- entries = await (0, import_promises7.readdir)(dir, {
8085
- withFileTypes: true
8086
- });
8087
- } catch {
8088
- return;
8089
- }
8090
- for (const entry of entries) {
8091
- const full = (0, import_node_path15.join)(dir, entry.name);
8092
- if (entry.isDirectory()) {
8093
- await walk(full);
8094
- } else if (entry.name.endsWith(".ts")) {
8095
- const src = await (0, import_promises7.readFile)(full, "utf-8");
8096
- if (src.includes("z.") && !src.includes("from 'zod'") && !src.includes('from "zod"')) {
8097
- await (0, import_promises7.writeFile)(full, `import { z } from 'zod';
8098
- ${src}`, "utf-8");
8099
- fixed++;
8100
- }
8101
- }
8102
- }
8103
- }, "walk");
8104
- await walk(zodOutputDir);
8105
- return fixed;
8106
- }, "fixZodImports");
8107
8145
  var pullAndGenerate = /* @__PURE__ */ __name(async (input) => {
8108
- const { root, prismaConfigPath, schemaPath, zodOutputDir } = input;
8146
+ const { root, prismaConfigPath, schemaPath } = input;
8109
8147
  loadDotenv(root);
8110
8148
  const backupPath = await backupSchema(schemaPath);
8111
8149
  const dbPull = await prismaDbPull(root, prismaConfigPath);
8112
- if (!dbPull.ok) {
8113
- return {
8114
- ok: false,
8115
- backupPath,
8116
- dbPull
8117
- };
8118
- }
8150
+ if (!dbPull.ok) return {
8151
+ ok: false,
8152
+ backupPath,
8153
+ dbPull
8154
+ };
8119
8155
  const caseFormat = await prismaCaseFormat(root, schemaPath);
8120
8156
  const normalized = await normalizeSchema(schemaPath);
8121
- const normalizeResult = {
8122
- ok: true,
8123
- renamed: normalized.renamed
8124
- };
8125
8157
  const generate = await prismaGenerate(root, prismaConfigPath);
8126
- let zodImportsFixed;
8127
- if (generate.ok && zodOutputDir) {
8128
- zodImportsFixed = await fixZodImports(zodOutputDir);
8129
- }
8130
8158
  return {
8131
8159
  ok: true,
8132
8160
  backupPath,
8133
8161
  dbPull,
8134
8162
  caseFormat,
8135
- normalizeSchema: normalizeResult,
8136
- generate,
8137
- zodImportsFixed
8163
+ normalizeSchema: {
8164
+ ok: true,
8165
+ renamed: normalized.renamed
8166
+ },
8167
+ generate
8138
8168
  };
8139
8169
  }, "pullAndGenerate");
8140
8170
  var normalizeSchema = /* @__PURE__ */ __name(async (schemaPath, configDir) => {
@@ -8835,10 +8865,44 @@ var injectEnumValues2 = /* @__PURE__ */ __name((columns, enums) => {
8835
8865
  };
8836
8866
  const options = col.fieldInput.options ?? {};
8837
8867
  if (!("values" in options)) options.values = values;
8868
+ if (!("emitObject" in options)) options.emitObject = true;
8869
+ if (!("displayKey" in options)) options.displayKey = "label";
8838
8870
  col.fieldInput.options = options;
8839
8871
  }
8840
8872
  }, "injectEnumValues");
8841
8873
 
8874
+ // src/lib/crud/interceptors/no-cache.interceptor.ts
8875
+ var import_common25 = require("@nestjs/common");
8876
+ function _ts_decorate9(decorators, target, key, desc2) {
8877
+ var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
8878
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
8879
+ r = Reflect.decorate(decorators, target, key, desc2);
8880
+ } else {
8881
+ for (var i = decorators.length - 1; i >= 0; i--) {
8882
+ if (d = decorators[i]) {
8883
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
8884
+ }
8885
+ }
8886
+ }
8887
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
8888
+ }
8889
+ __name(_ts_decorate9, "_ts_decorate");
8890
+ var NoCacheInterceptor = class {
8891
+ static {
8892
+ __name(this, "NoCacheInterceptor");
8893
+ }
8894
+ intercept(context, next) {
8895
+ const response = context.switchToHttp().getResponse();
8896
+ response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
8897
+ response.setHeader("Pragma", "no-cache");
8898
+ response.setHeader("Expires", "0");
8899
+ return next.handle();
8900
+ }
8901
+ };
8902
+ NoCacheInterceptor = _ts_decorate9([
8903
+ (0, import_common25.Injectable)()
8904
+ ], NoCacheInterceptor);
8905
+
8842
8906
  // src/lib/crud/builder/schema.helpers.ts
8843
8907
  var pickByColumns = /* @__PURE__ */ __name((schema, columns, filter) => {
8844
8908
  if (!schema) return void 0;
@@ -9090,7 +9154,10 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
9090
9154
  // A custom child has no Prisma model. Leave it empty rather than
9091
9155
  // falling back to the column id, which would produce a bogus
9092
9156
  // `prisma[<column>]` lookup at query time.
9093
- childModel: childKind === "custom" ? "" : c.id,
9157
+ // Use the child resource's declared model name so plural column ids
9158
+ // (e.g. "books") resolve to the correct Prisma delegate (prisma.book).
9159
+ // ponytail: charAt toLowerCase is cheap; Prisma model names are always PascalCase
9160
+ childModel: childKind === "custom" ? "" : childJson?.model ? childJson.model.charAt(0).toLowerCase() + childJson.model.slice(1) : c.id,
9094
9161
  foreignKey: c.fieldInput?.foreignKey ?? `${parentModel}Id`,
9095
9162
  name: childJson?.name ?? childRoute,
9096
9163
  title: childJson?.title ?? childJson?.tag ?? childRoute,
@@ -9171,7 +9238,7 @@ var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, ac
9171
9238
  };
9172
9239
  }
9173
9240
  }
9174
- const lookup = buildLookup(enrichedColumns);
9241
+ const lookup = buildLookup(enrichedColumns, dirPath);
9175
9242
  const enrichedInclude = enrichIncludeWithSort2(json.include, enrichedColumns);
9176
9243
  const definition = buildResourceDefinitions2(schema, json.operations, enrichedColumns);
9177
9244
  return {
@@ -9228,15 +9295,26 @@ var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, ac
9228
9295
  ...pickExtensions2(json)
9229
9296
  };
9230
9297
  }, "fromJson");
9231
- var buildLookup = /* @__PURE__ */ __name((columns) => {
9298
+ var buildLookup = /* @__PURE__ */ __name((columns, dirPath) => {
9232
9299
  if (!columns) return void 0;
9233
9300
  const keyCol = columns.find((c) => c.idField);
9234
- const labelCol = columns.find((c) => c.showInLookup) ?? columns.find((c) => c.searchable);
9235
- if (!keyCol && !labelCol) return void 0;
9301
+ const searchCols = columns.filter((c) => c.showInLookup || c.searchable);
9302
+ if (!keyCol && !searchCols.length) return void 0;
9303
+ const labels = searchCols.map((col) => {
9304
+ if (col.fieldInput?.relationType === "manyToOne" && col.fieldInput?.resource && dirPath) {
9305
+ const relationName = col.id.replace(/Id$/, "");
9306
+ const child = resolveChildResource(col.fieldInput.resource, dirPath);
9307
+ const childColumns = child ? expandExtendColumns(child.json.columns, dirPath) : void 0;
9308
+ const displayCol = childColumns?.find((c) => !c.idField && !c.hiddenInTable);
9309
+ if (displayCol) return `${relationName}.${displayCol.id}`;
9310
+ }
9311
+ return col.id;
9312
+ });
9236
9313
  return {
9237
9314
  key: keyCol?.id ?? "id",
9238
- ...labelCol && {
9239
- label: labelCol.id
9315
+ ...labels.length && {
9316
+ label: labels[0],
9317
+ labels
9240
9318
  }
9241
9319
  };
9242
9320
  }, "buildLookup");
@@ -9527,12 +9605,12 @@ var FileSystemResourceConfigLoader = class extends ResourceConfigLoader2 {
9527
9605
  // src/lib/crud/status/status.service.ts
9528
9606
  var import_node_fs11 = require("fs");
9529
9607
  var import_node_path19 = require("path");
9530
- var import_node_url = require("url");
9608
+ var import_node_url2 = require("url");
9531
9609
  var CONNECTION_STRING_PATTERN = /(?:postgresql|postgres|mysql|mongodb|sqlserver|sqlite):\/\/[^\s"')]+/gi;
9532
9610
  var stripConnectionStrings = /* @__PURE__ */ __name((message) => message.replace(CONNECTION_STRING_PATTERN, "[REDACTED]"), "stripConnectionStrings");
9533
9611
  var getCroutonVersion = /* @__PURE__ */ __name(() => {
9534
9612
  try {
9535
- const startDir = typeof __dirname !== "undefined" ? __dirname : (0, import_node_path19.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
9613
+ const startDir = typeof __dirname !== "undefined" ? __dirname : (0, import_node_path19.dirname)((0, import_node_url2.fileURLToPath)(importMetaUrl));
9536
9614
  let dir = startDir;
9537
9615
  while (dir !== (0, import_node_path19.dirname)(dir)) {
9538
9616
  const pkgPath = (0, import_node_path19.join)(dir, "package.json");
@@ -9788,9 +9866,9 @@ var buildStatus = /* @__PURE__ */ __name(async (registry2, loadedConfigs, enumRe
9788
9866
  }, "buildStatus");
9789
9867
 
9790
9868
  // src/lib/crud/status/status.controller.ts
9791
- var import_common25 = require("@nestjs/common");
9869
+ var import_common26 = require("@nestjs/common");
9792
9870
  var import_swagger13 = require("@nestjs/swagger");
9793
- function _ts_decorate9(decorators, target, key, desc2) {
9871
+ function _ts_decorate10(decorators, target, key, desc2) {
9794
9872
  var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
9795
9873
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
9796
9874
  r = Reflect.decorate(decorators, target, key, desc2);
@@ -9803,7 +9881,7 @@ function _ts_decorate9(decorators, target, key, desc2) {
9803
9881
  }
9804
9882
  return c > 3 && r && Object.defineProperty(target, key, r), r;
9805
9883
  }
9806
- __name(_ts_decorate9, "_ts_decorate");
9884
+ __name(_ts_decorate10, "_ts_decorate");
9807
9885
  function _ts_metadata9(metadataKey, metadataValue) {
9808
9886
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
9809
9887
  return Reflect.metadata(metadataKey, metadataValue);
@@ -9826,8 +9904,8 @@ var createStatusController = /* @__PURE__ */ __name((enumRegistry, translationRe
9826
9904
  return buildStatus(this.dataSourceRegistry, configs, enumRegistry, translationRegistry);
9827
9905
  }
9828
9906
  };
9829
- _ts_decorate9([
9830
- (0, import_common25.Get)("status.json"),
9907
+ _ts_decorate10([
9908
+ (0, import_common26.Get)("status.json"),
9831
9909
  (0, import_swagger13.ApiOperation)({
9832
9910
  summary: "Crouton system status (db, resources, version)"
9833
9911
  }),
@@ -9839,8 +9917,8 @@ var createStatusController = /* @__PURE__ */ __name((enumRegistry, translationRe
9839
9917
  _ts_metadata9("design:paramtypes", []),
9840
9918
  _ts_metadata9("design:returntype", Promise)
9841
9919
  ], StatusController.prototype, "getStatus", null);
9842
- StatusController = _ts_decorate9([
9843
- (0, import_common25.Controller)(prefix ? `${prefix}/crouton` : "crouton"),
9920
+ StatusController = _ts_decorate10([
9921
+ (0, import_common26.Controller)(prefix ? `${prefix}/crouton` : "crouton"),
9844
9922
  (0, import_swagger13.ApiTags)("Status"),
9845
9923
  _ts_metadata9("design:type", Function),
9846
9924
  _ts_metadata9("design:paramtypes", [
@@ -9857,8 +9935,8 @@ var createStatusController = /* @__PURE__ */ __name((enumRegistry, translationRe
9857
9935
 
9858
9936
  // src/lib/crouton-api.module.ts
9859
9937
  var import_node_path20 = require("path");
9860
- var import_node_url2 = require("url");
9861
- function _ts_decorate10(decorators, target, key, desc2) {
9938
+ var import_node_url3 = require("url");
9939
+ function _ts_decorate11(decorators, target, key, desc2) {
9862
9940
  var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
9863
9941
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
9864
9942
  r = Reflect.decorate(decorators, target, key, desc2);
@@ -9871,7 +9949,7 @@ function _ts_decorate10(decorators, target, key, desc2) {
9871
9949
  }
9872
9950
  return c > 3 && r && Object.defineProperty(target, key, r), r;
9873
9951
  }
9874
- __name(_ts_decorate10, "_ts_decorate");
9952
+ __name(_ts_decorate11, "_ts_decorate");
9875
9953
  var CroutonApiModule = class _CroutonApiModule {
9876
9954
  static {
9877
9955
  __name(this, "CroutonApiModule");
@@ -9895,7 +9973,7 @@ var CroutonApiModule = class _CroutonApiModule {
9895
9973
  const dataSourceRegistry = new DataSourceRegistry(dataSources);
9896
9974
  const guardRegistry = new SecurityGuardRegistry(security?.guards ?? {});
9897
9975
  const moduleDefaultSecurity = security?.default;
9898
- const startDir = typeof __dirname !== "undefined" ? __dirname : (0, import_node_path20.dirname)((0, import_node_url2.fileURLToPath)(importMetaUrl));
9976
+ const startDir = typeof __dirname !== "undefined" ? __dirname : (0, import_node_path20.dirname)((0, import_node_url3.fileURLToPath)(importMetaUrl));
9899
9977
  const enumRegistry = loadEnumRegistry(startDir, config.enumsFile);
9900
9978
  const validConfigs = [];
9901
9979
  for (const c of configs) {
@@ -9980,6 +10058,10 @@ var CroutonApiModule = class _CroutonApiModule {
9980
10058
  ResourceConfigRegistry
9981
10059
  ],
9982
10060
  providers: [
10061
+ {
10062
+ provide: import_core2.APP_INTERCEPTOR,
10063
+ useClass: NoCacheInterceptor
10064
+ },
9983
10065
  {
9984
10066
  provide: import_core2.APP_FILTER,
9985
10067
  useClass: CroutonValidationExceptionFilter
@@ -10028,8 +10110,8 @@ var CroutonApiModule = class _CroutonApiModule {
10028
10110
  return _CroutonApiModule.forResources(configs, dataSources, loader, appConfig, config);
10029
10111
  }
10030
10112
  };
10031
- CroutonApiModule = _ts_decorate10([
10032
- (0, import_common26.Module)({
10113
+ CroutonApiModule = _ts_decorate11([
10114
+ (0, import_common27.Module)({
10033
10115
  controllers: [],
10034
10116
  providers: [],
10035
10117
  exports: []