@cmssy/cli 19.4.0 → 19.6.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.
Files changed (2) hide show
  1. package/dist/index.js +68 -30
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -2215,7 +2215,7 @@ async function runLink(options, deps) {
2215
2215
  // src/types-command.ts
2216
2216
  import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, readdirSync, writeFileSync as writeFileSync7 } from "fs";
2217
2217
  import { dirname as dirname4, relative, resolve as resolvePath } from "path";
2218
- import { DEFAULT_CMSSY_API_URL } from "@cmssy/core";
2218
+ import { DEFAULT_CMSSY_API_URL, createRetryingFetch } from "@cmssy/core";
2219
2219
 
2220
2220
  // src/model-types.ts
2221
2221
  var TEXTUAL = /* @__PURE__ */ new Set([
@@ -2243,7 +2243,12 @@ function propertyKey(key) {
2243
2243
  return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
2244
2244
  }
2245
2245
  function stringUnion(options) {
2246
- return options.map((option) => JSON.stringify(option)).join(" | ");
2246
+ return options.map((option) => JSON.stringify(option.value)).join(" | ");
2247
+ }
2248
+ function textIn(text, language) {
2249
+ if (!text) return null;
2250
+ if (language && text[language]?.trim()) return text[language];
2251
+ return Object.values(text).find((entry) => entry.trim()) ?? null;
2247
2252
  }
2248
2253
  function scalarType(field) {
2249
2254
  if (TEXTUAL.has(field.type)) {
@@ -2273,13 +2278,13 @@ function scalarType(field) {
2273
2278
  return "unknown";
2274
2279
  }
2275
2280
  }
2276
- function fieldType(field, depth) {
2281
+ function fieldType(field, depth, language) {
2277
2282
  if (field.type === "object") {
2278
- return field.fields?.length ? objectType(field.fields, depth) : "Record<string, unknown>";
2283
+ return field.fields?.length ? objectType(field.fields, depth, language) : "Record<string, unknown>";
2279
2284
  }
2280
2285
  if (field.type === "repeater" || field.type === "list") {
2281
2286
  if (field.itemFields?.length) {
2282
- return `Array<${objectType(field.itemFields, depth)}>`;
2287
+ return `Array<${objectType(field.itemFields, depth, language)}>`;
2283
2288
  }
2284
2289
  if (field.itemType) {
2285
2290
  const item = scalarType({ key: field.key, type: field.itemType });
@@ -2289,10 +2294,12 @@ function fieldType(field, depth) {
2289
2294
  }
2290
2295
  return scalarType(field);
2291
2296
  }
2292
- function docComment(field, pad) {
2297
+ function docComment(field, pad, language) {
2293
2298
  const parts = [];
2294
- if (field.label && field.label !== field.key) parts.push(field.label);
2295
- if (field.description) parts.push(field.description);
2299
+ const label = textIn(field.label, language);
2300
+ const description = textIn(field.description, language);
2301
+ if (label && label !== field.key) parts.push(label);
2302
+ if (description) parts.push(description);
2296
2303
  if (field.type === "relation" && field.relationTo) {
2297
2304
  parts.push(
2298
2305
  `Record id(s) from \`${field.relationTo.replace(/^model:/, "")}\`.`
@@ -2301,21 +2308,21 @@ function docComment(field, pad) {
2301
2308
  if (!parts.length) return [];
2302
2309
  return [`${pad}/** ${parts.join(" - ")} */`];
2303
2310
  }
2304
- function members(fields, depth) {
2311
+ function members(fields, depth, language) {
2305
2312
  const pad = INDENT.repeat(depth + 1);
2306
2313
  const lines = [];
2307
2314
  for (const field of fields) {
2308
2315
  if (field.hidden) continue;
2309
- lines.push(...docComment(field, pad));
2316
+ lines.push(...docComment(field, pad, language));
2310
2317
  const optional = field.required ? "" : "?";
2311
2318
  lines.push(
2312
- `${pad}${propertyKey(field.key)}${optional}: ${fieldType(field, depth + 1)};`
2319
+ `${pad}${propertyKey(field.key)}${optional}: ${fieldType(field, depth + 1, language)};`
2313
2320
  );
2314
2321
  }
2315
2322
  return lines;
2316
2323
  }
2317
- function objectType(fields, depth) {
2318
- const body = members(fields, depth);
2324
+ function objectType(fields, depth, language) {
2325
+ const body = members(fields, depth, language);
2319
2326
  if (!body.length) return "Record<string, unknown>";
2320
2327
  return ["{", ...body, `${INDENT.repeat(depth)}}`].join("\n");
2321
2328
  }
@@ -2330,7 +2337,9 @@ export type { CmssyLocalized, CmssyMedia, CmssyFile, CmssyRecordOf };`;
2330
2337
  function preambleImports() {
2331
2338
  const clause = /import type \{([^}]*)\} from "@cmssy\/core";/.exec(PREAMBLE);
2332
2339
  if (!clause?.[1]) return [];
2333
- return clause[1].split(",").map((entry) => entry.trim().split(/\s+as\s+/)[0]?.trim() ?? "").filter((name) => name.length > 0);
2340
+ return clause[1].split(",").map(
2341
+ (entry) => entry.trim().split(/\s+as\s+/)[0]?.trim() ?? ""
2342
+ ).filter((name) => name.length > 0);
2334
2343
  }
2335
2344
  function generateModelTypes(models, options) {
2336
2345
  const command = options.command ?? "npx @cmssy/cli types";
@@ -2361,7 +2370,7 @@ function generateModelTypes(models, options) {
2361
2370
  blocks.push(
2362
2371
  "",
2363
2372
  doc.join("\n"),
2364
- `export interface ${name}Data ${objectType(model.fields, 0)}`,
2373
+ `export interface ${name}Data ${objectType(model.fields, 0, options.language)}`,
2365
2374
  "",
2366
2375
  `export type ${name}Record = CmssyRecordOf<${name}Data>;`
2367
2376
  );
@@ -2425,12 +2434,13 @@ ${documents}
2425
2434
  // src/types-command.ts
2426
2435
  var DEFAULT_OUT = "cmssy/models.ts";
2427
2436
  var SITE_CONFIG_QUERY = `query CliSiteConfig($workspaceSlug: String!) {
2428
- public { siteConfig(workspaceSlug: $workspaceSlug) { workspaceId } }
2437
+ public { siteConfig(workspaceSlug: $workspaceSlug) { workspaceId defaultLanguage } }
2429
2438
  }`;
2430
- var DEFINITIONS_QUERY = `query CliModelDefinitions($workspaceId: String!) {
2439
+ var DEFINITIONS_PAGE = 4;
2440
+ var DEFINITIONS_QUERY = `query CliModelDefinitions($workspaceId: String!, $limit: Int!, $offset: Int!) {
2431
2441
  public {
2432
2442
  model {
2433
- definitions(workspaceId: $workspaceId) {
2443
+ definitions(workspaceId: $workspaceId, limit: $limit, offset: $offset) {
2434
2444
  slug
2435
2445
  name
2436
2446
  description
@@ -2444,7 +2454,10 @@ var DEFINITIONS_QUERY = `query CliModelDefinitions($workspaceId: String!) {
2444
2454
  localized
2445
2455
  multiple
2446
2456
  hidden
2447
- options
2457
+ options {
2458
+ value
2459
+ label
2460
+ }
2448
2461
  relationTo
2449
2462
  relationType
2450
2463
  fields
@@ -2473,9 +2486,10 @@ async function refusalReason(response) {
2473
2486
  return said.length > 0 ? said.join("; ") : void 0;
2474
2487
  }
2475
2488
  async function request(deps, endpoint, query, variables) {
2489
+ const doFetch = createRetryingFetch("build", deps.fetch, "cmssy types");
2476
2490
  let response;
2477
2491
  try {
2478
- response = await deps.fetch(endpoint, {
2492
+ response = await doFetch(endpoint, {
2479
2493
  method: "POST",
2480
2494
  headers: { "content-type": "application/json" },
2481
2495
  body: JSON.stringify({ query, variables })
@@ -2516,7 +2530,9 @@ function ancestors(from) {
2516
2530
  function exportedNames(declarations) {
2517
2531
  const source = declarations.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/^\s*\/\/.*$/gm, " ");
2518
2532
  const found = /* @__PURE__ */ new Set();
2519
- for (const [, clause] of source.matchAll(/export\s+(?:type\s+)?\{([^}]*)\}/g)) {
2533
+ for (const [, clause] of source.matchAll(
2534
+ /export\s+(?:type\s+)?\{([^}]*)\}/g
2535
+ )) {
2520
2536
  for (const entry of (clause ?? "").split(",")) {
2521
2537
  const parts = entry.trim().split(/\s+as\s+/);
2522
2538
  const name = (parts[1] ?? parts[0] ?? "").trim();
@@ -2575,8 +2591,16 @@ function describeDrift(previous, next) {
2575
2591
  if (added.length) lines.push(`+ ${label}: ${added.join(", ")}`);
2576
2592
  if (removed.length) lines.push(`- ${label}: ${removed.join(", ")}`);
2577
2593
  };
2578
- report("models", declared(body(previous), models), declared(body(next), models));
2579
- report("fields", declared(body(previous), fields), declared(body(next), fields));
2594
+ report(
2595
+ "models",
2596
+ declared(body(previous), models),
2597
+ declared(body(next), models)
2598
+ );
2599
+ report(
2600
+ "fields",
2601
+ declared(body(previous), fields),
2602
+ declared(body(next), fields)
2603
+ );
2580
2604
  return lines.length ? lines : ["the generated output differs"];
2581
2605
  }
2582
2606
  function resolve4(value, fromEnv, variable) {
@@ -2674,6 +2698,19 @@ function syncOperations(options, deps) {
2674
2698
  deps.log(` ${names.join(", ")}`);
2675
2699
  return 0;
2676
2700
  }
2701
+ async function readDefinitions(deps, endpoint, workspaceId) {
2702
+ const models = [];
2703
+ for (let offset = 0; ; offset += DEFINITIONS_PAGE) {
2704
+ const result = await request(deps, endpoint, DEFINITIONS_QUERY, {
2705
+ workspaceId,
2706
+ limit: DEFINITIONS_PAGE,
2707
+ offset
2708
+ });
2709
+ const page = result.public.model.definitions;
2710
+ models.push(...page);
2711
+ if (page.length < DEFINITIONS_PAGE) return models;
2712
+ }
2713
+ }
2677
2714
  async function runTypes(options, deps) {
2678
2715
  let operationsStatus = 0;
2679
2716
  try {
@@ -2694,8 +2731,7 @@ async function runTypes(options, deps) {
2694
2731
  "check the slugs under Settings \u2192 Headless"
2695
2732
  );
2696
2733
  }
2697
- const result = await request(deps, endpoint, DEFINITIONS_QUERY, { workspaceId });
2698
- const models = result.public.model.definitions;
2734
+ const models = await readDefinitions(deps, endpoint, workspaceId);
2699
2735
  if (models.length === 0) {
2700
2736
  deps.log(
2701
2737
  `cmssy: the "${workspace}" workspace has no models yet - nothing to generate`
@@ -2706,7 +2742,10 @@ async function runTypes(options, deps) {
2706
2742
  const outPath = resolvePath(deps.cwd, requested);
2707
2743
  const inside = relative(deps.cwd, outPath);
2708
2744
  const shown = inside && !inside.startsWith("..") ? inside : outPath;
2709
- const source = generateModelTypes(models, { workspace });
2745
+ const source = generateModelTypes(models, {
2746
+ workspace,
2747
+ language: site.public.siteConfig?.defaultLanguage
2748
+ });
2710
2749
  const gap = coreShapeGap(deps.cwd);
2711
2750
  if (gap) {
2712
2751
  deps.log(
@@ -2731,7 +2770,8 @@ async function runTypes(options, deps) {
2731
2770
  previous === null ? `cmssy: ${shown} is missing - run \`cmssy types\` and commit it` : `cmssy: ${shown} is out of date with the "${workspace}" workspace`
2732
2771
  );
2733
2772
  if (previous !== null) {
2734
- for (const line of describeDrift(previous, source)) deps.log(` ${line}`);
2773
+ for (const line of describeDrift(previous, source))
2774
+ deps.log(` ${line}`);
2735
2775
  }
2736
2776
  deps.log(" run `cmssy types` and commit the result");
2737
2777
  return 1;
@@ -2745,9 +2785,7 @@ async function runTypes(options, deps) {
2745
2785
  deps.log(
2746
2786
  `cmssy: wrote ${shown} - ${models.length} model${models.length === 1 ? "" : "s"}, ${fieldCount} field${fieldCount === 1 ? "" : "s"}`
2747
2787
  );
2748
- deps.log(
2749
- ` ${models.map((model) => model.slug).join(", ")}`
2750
- );
2788
+ deps.log(` ${models.map((model) => model.slug).join(", ")}`);
2751
2789
  return operationsStatus;
2752
2790
  } catch (error) {
2753
2791
  if (error instanceof CliError) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/cli",
3
- "version": "19.4.0",
3
+ "version": "19.6.0",
4
4
  "description": "The cmssy CLI: `cmssy init` wires cmssy into an existing Next.js, Astro or React Router app; `cmssy link` connects it to a workspace and verifies the editor wiring.",
5
5
  "keywords": [
6
6
  "cmssy",
@@ -28,7 +28,7 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "esbuild": "^0.27.7",
31
- "@cmssy/core": "19.4.0"
31
+ "@cmssy/core": "19.6.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/node": "^20.0.0",