@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.
- package/dist/index.js +68 -30
- 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
|
-
|
|
2295
|
-
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
2579
|
-
|
|
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
|
|
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, {
|
|
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))
|
|
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.
|
|
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.
|
|
31
|
+
"@cmssy/core": "19.6.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^20.0.0",
|