@ikas/component-cli 1.4.0-beta.43 → 1.4.0-beta.45
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/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +5 -168
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +301 -3
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/create-design-tokens.d.ts +7 -0
- package/dist/commands/create-design-tokens.d.ts.map +1 -0
- package/dist/commands/create-design-tokens.js +127 -0
- package/dist/commands/create-design-tokens.js.map +1 -0
- package/dist/commands/create-global-variable.d.ts +3 -0
- package/dist/commands/create-global-variable.d.ts.map +1 -0
- package/dist/commands/create-global-variable.js +53 -0
- package/dist/commands/create-global-variable.js.map +1 -0
- package/dist/commands/delete-theme-globals.d.ts +4 -0
- package/dist/commands/delete-theme-globals.d.ts.map +1 -0
- package/dist/commands/delete-theme-globals.js +48 -0
- package/dist/commands/delete-theme-globals.js.map +1 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +61 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/list-theme-globals.d.ts +3 -0
- package/dist/commands/list-theme-globals.d.ts.map +1 -0
- package/dist/commands/list-theme-globals.js +22 -0
- package/dist/commands/list-theme-globals.js.map +1 -0
- package/dist/commands/update-global-variable.d.ts +3 -0
- package/dist/commands/update-global-variable.d.ts.map +1 -0
- package/dist/commands/update-global-variable.js +47 -0
- package/dist/commands/update-global-variable.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -8
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/compile.d.ts +4 -1
- package/dist/utils/compile.d.ts.map +1 -1
- package/dist/utils/compile.js +500 -40
- package/dist/utils/compile.js.map +1 -1
- package/dist/utils/component-helpers.d.ts +23 -1
- package/dist/utils/component-helpers.d.ts.map +1 -1
- package/dist/utils/component-helpers.js +94 -15
- package/dist/utils/component-helpers.js.map +1 -1
- package/dist/utils/editor-action-client.d.ts +1 -1
- package/dist/utils/editor-action-client.d.ts.map +1 -1
- package/dist/utils/editor-action-client.js.map +1 -1
- package/dist/utils/websocket-server.d.ts +53 -3
- package/dist/utils/websocket-server.d.ts.map +1 -1
- package/dist/utils/websocket-server.js +34 -0
- package/dist/utils/websocket-server.js.map +1 -1
- package/package.json +1 -1
- package/dist/commands/create.d.ts +0 -4
- package/dist/commands/create.d.ts.map +0 -1
- package/dist/commands/create.js +0 -228
- package/dist/commands/create.js.map +0 -1
- package/dist/commands/get-available-values.d.ts +0 -3
- package/dist/commands/get-available-values.d.ts.map +0 -1
- package/dist/commands/get-available-values.js +0 -49
- package/dist/commands/get-available-values.js.map +0 -1
- package/dist/commands/proxy.d.ts +0 -39
- package/dist/commands/proxy.d.ts.map +0 -1
- package/dist/commands/proxy.js +0 -210
- package/dist/commands/proxy.js.map +0 -1
- package/dist/commands/set-dynamic-value.d.ts +0 -3
- package/dist/commands/set-dynamic-value.d.ts.map +0 -1
- package/dist/commands/set-dynamic-value.js +0 -54
- package/dist/commands/set-dynamic-value.js.map +0 -1
- package/dist/commands/update-section-props.d.ts +0 -3
- package/dist/commands/update-section-props.d.ts.map +0 -1
- package/dist/commands/update-section-props.js +0 -43
- package/dist/commands/update-section-props.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmIpC,wBAAgB,kBAAkB,IAAI,OAAO,CAK5C"}
|
package/dist/commands/build.js
CHANGED
|
@@ -2,175 +2,12 @@ import { Command } from "commander";
|
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import ora from "ora";
|
|
4
4
|
import * as fs from "fs";
|
|
5
|
-
import * as os from "os";
|
|
6
5
|
import * as path from "path";
|
|
7
|
-
import * as esbuild from "esbuild";
|
|
8
6
|
import { execSync } from "child_process";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
// pragma and break rendering. See utils/compile.ts for the full rationale.
|
|
14
|
-
const PREACT_JSX_SHIM = path.join(os.tmpdir(), "ikas-preact-jsx-shim.mjs");
|
|
15
|
-
fs.writeFileSync(PREACT_JSX_SHIM, 'export{h as __ikas_h,Fragment as __ikas_Fragment}from"preact";\n');
|
|
16
|
-
async function compileComponent(componentId, entryPath, stylesPath) {
|
|
17
|
-
const componentDir = path.dirname(path.resolve(process.cwd(), entryPath));
|
|
18
|
-
try {
|
|
19
|
-
// Build server bundle (for SSR with preact-render-to-string)
|
|
20
|
-
const serverResult = await esbuild.build({
|
|
21
|
-
entryPoints: [path.resolve(process.cwd(), entryPath)],
|
|
22
|
-
bundle: true,
|
|
23
|
-
format: "esm",
|
|
24
|
-
platform: "node",
|
|
25
|
-
target: "node18",
|
|
26
|
-
write: false,
|
|
27
|
-
external: [
|
|
28
|
-
"preact",
|
|
29
|
-
"preact/hooks",
|
|
30
|
-
"preact-render-to-string",
|
|
31
|
-
"mobx",
|
|
32
|
-
"@ikas/bp-storefront",
|
|
33
|
-
"@ikas/bp-storefront-models",
|
|
34
|
-
"@ikas/bp-storefront-config",
|
|
35
|
-
"@ikas/bp-storefront-api"
|
|
36
|
-
],
|
|
37
|
-
plugins: [ikasComponentUtilsPlugin()],
|
|
38
|
-
jsx: "transform",
|
|
39
|
-
jsxFactory: "__ikas_h",
|
|
40
|
-
jsxFragment: "__ikas_Fragment",
|
|
41
|
-
inject: [PREACT_JSX_SHIM],
|
|
42
|
-
tsconfigRaw: {
|
|
43
|
-
compilerOptions: {
|
|
44
|
-
jsx: "react",
|
|
45
|
-
jsxFactory: "__ikas_h",
|
|
46
|
-
jsxFragmentFactory: "__ikas_Fragment"
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
minify: true,
|
|
50
|
-
sourcemap: false,
|
|
51
|
-
});
|
|
52
|
-
// Build client bundle (for hydration)
|
|
53
|
-
const clientResult = await esbuild.build({
|
|
54
|
-
entryPoints: [path.resolve(process.cwd(), entryPath)],
|
|
55
|
-
bundle: true,
|
|
56
|
-
format: "esm",
|
|
57
|
-
platform: "browser",
|
|
58
|
-
target: "es2020",
|
|
59
|
-
write: false,
|
|
60
|
-
external: [
|
|
61
|
-
"preact",
|
|
62
|
-
"preact/hooks",
|
|
63
|
-
"mobx",
|
|
64
|
-
"@ikas/bp-storefront",
|
|
65
|
-
"@ikas/bp-storefront-models",
|
|
66
|
-
"@ikas/bp-storefront-config"
|
|
67
|
-
],
|
|
68
|
-
plugins: [ikasComponentUtilsPlugin()],
|
|
69
|
-
jsx: "transform",
|
|
70
|
-
jsxFactory: "__ikas_h",
|
|
71
|
-
jsxFragment: "__ikas_Fragment",
|
|
72
|
-
inject: [PREACT_JSX_SHIM],
|
|
73
|
-
tsconfigRaw: {
|
|
74
|
-
compilerOptions: {
|
|
75
|
-
jsx: "react",
|
|
76
|
-
jsxFactory: "__ikas_h",
|
|
77
|
-
jsxFragmentFactory: "__ikas_Fragment"
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
minify: true,
|
|
81
|
-
sourcemap: false,
|
|
82
|
-
});
|
|
83
|
-
// Read and scope CSS (with import resolution)
|
|
84
|
-
const cssPath = path.resolve(process.cwd(), stylesPath);
|
|
85
|
-
let css = "";
|
|
86
|
-
if (fs.existsSync(cssPath)) {
|
|
87
|
-
const rawCss = fs.readFileSync(cssPath, "utf-8");
|
|
88
|
-
css = resolveCssImports(rawCss, cssPath);
|
|
89
|
-
}
|
|
90
|
-
// Scope CSS with component ID prefix
|
|
91
|
-
const scopedCss = scopeCSS(css, componentId);
|
|
92
|
-
return {
|
|
93
|
-
success: true,
|
|
94
|
-
serverJs: serverResult.outputFiles[0]?.text || "",
|
|
95
|
-
clientJs: clientResult.outputFiles[0]?.text || "",
|
|
96
|
-
scopedCss
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
return {
|
|
101
|
-
success: false,
|
|
102
|
-
serverJs: "",
|
|
103
|
-
clientJs: "",
|
|
104
|
-
scopedCss: "",
|
|
105
|
-
error: error instanceof Error ? error.message : String(error)
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
function scopeCSS(css, componentId) {
|
|
110
|
-
// Add a scoping class to all selectors
|
|
111
|
-
const scopeClass = `cc_${componentId.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
112
|
-
// Simple CSS scoping - prepend scope class to each rule
|
|
113
|
-
// This is a basic implementation; a production version would use a proper CSS parser
|
|
114
|
-
const lines = css.split("\n");
|
|
115
|
-
const scopedLines = [];
|
|
116
|
-
let inMediaQuery = false;
|
|
117
|
-
let keyframesDepth = 0;
|
|
118
|
-
for (const line of lines) {
|
|
119
|
-
const trimmed = line.trim();
|
|
120
|
-
// Skip empty lines
|
|
121
|
-
if (!trimmed) {
|
|
122
|
-
scopedLines.push(line);
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
// Handle @media queries
|
|
126
|
-
if (trimmed.startsWith("@media")) {
|
|
127
|
-
inMediaQuery = true;
|
|
128
|
-
scopedLines.push(line);
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
// Handle @keyframes
|
|
132
|
-
if (trimmed.startsWith("@keyframes") || trimmed.startsWith("@-webkit-keyframes")) {
|
|
133
|
-
keyframesDepth = 1;
|
|
134
|
-
scopedLines.push(line);
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
// Inside @keyframes: track brace depth, pass lines through unscoped
|
|
138
|
-
if (keyframesDepth > 0) {
|
|
139
|
-
for (const ch of trimmed) {
|
|
140
|
-
if (ch === "{")
|
|
141
|
-
keyframesDepth++;
|
|
142
|
-
else if (ch === "}")
|
|
143
|
-
keyframesDepth--;
|
|
144
|
-
}
|
|
145
|
-
scopedLines.push(line);
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
// Handle closing braces for @media
|
|
149
|
-
if (trimmed === "}" && inMediaQuery) {
|
|
150
|
-
inMediaQuery = false;
|
|
151
|
-
scopedLines.push(line);
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
// Skip lines that don't contain selectors
|
|
155
|
-
if (!trimmed.includes("{") || trimmed.startsWith("@")) {
|
|
156
|
-
scopedLines.push(line);
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
// Scope the selector
|
|
160
|
-
const [selector, rest] = line.split("{");
|
|
161
|
-
if (selector && rest !== undefined) {
|
|
162
|
-
const scopedSelector = selector
|
|
163
|
-
.split(",")
|
|
164
|
-
.map((s) => `.${scopeClass} ${s.trim()}`)
|
|
165
|
-
.join(", ");
|
|
166
|
-
scopedLines.push(`${scopedSelector} {${rest}`);
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
scopedLines.push(line);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return scopedLines.join("\n");
|
|
173
|
-
}
|
|
7
|
+
// Single-source the per-component compile pipeline (esbuild config, externals, CSS
|
|
8
|
+
// scoping) from utils/compile.ts. This command previously carried its own copy, which
|
|
9
|
+
// is how the CSS-scoping fix could land in one place and not the other — keep it shared.
|
|
10
|
+
import { compileComponent } from "../utils/compile.js";
|
|
174
11
|
function runTypeCheck() {
|
|
175
12
|
const spinner = ora("Type checking with TypeScript...").start();
|
|
176
13
|
try {
|
|
@@ -216,7 +53,7 @@ async function buildComponents(options) {
|
|
|
216
53
|
// Build each component
|
|
217
54
|
for (const component of config.components) {
|
|
218
55
|
const spinner = ora(`Building ${component.name}...`).start();
|
|
219
|
-
const result = await compileComponent(component.
|
|
56
|
+
const result = await compileComponent(component.entry, component.styles, component.id);
|
|
220
57
|
if (result.success) {
|
|
221
58
|
// Write output files
|
|
222
59
|
const componentOutDir = path.join(outputPath, component.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4yDpC,wBAAgB,mBAAmB,IAAI,OAAO,CA4Q7C"}
|
package/dist/commands/config.js
CHANGED
|
@@ -2,6 +2,16 @@ import { Command } from "commander";
|
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as path from "path";
|
|
4
4
|
import { PROP_TYPES, toPascalCase, generateTypesFile, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, generateComponentId, generateUniqueId, updateBarrelExport, findPropGroup, collectPropGroupIds, movePropGroupInTree, validateFilteredComponentIds, } from "../utils/component-helpers.js";
|
|
5
|
+
import { runEditorAction, printResultAndExit, printErrorAndExit } from "../utils/editor-action-client.js";
|
|
6
|
+
async function listLocales(port) {
|
|
7
|
+
try {
|
|
8
|
+
const result = await runEditorAction("list-locales", {}, port ? { port } : {});
|
|
9
|
+
printResultAndExit(result);
|
|
10
|
+
}
|
|
11
|
+
catch (e) {
|
|
12
|
+
printErrorAndExit(e);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
5
15
|
function loadConfig() {
|
|
6
16
|
const configPath = path.resolve(process.cwd(), "ikas.config.json");
|
|
7
17
|
if (!fs.existsSync(configPath)) {
|
|
@@ -234,6 +244,14 @@ async function parsePropsFlag(propsJson, config, configPath) {
|
|
|
234
244
|
}));
|
|
235
245
|
process.exit(1);
|
|
236
246
|
}
|
|
247
|
+
// Validate LINK / LIST_OF_LINK defaultValue shape (reject JSON strings and legacy { href })
|
|
248
|
+
if ((propType === "LINK" || propType === "LIST_OF_LINK") && r.defaultValue !== undefined) {
|
|
249
|
+
const linkError = validateLinkDefaultValue(propType, r.defaultValue, r.name);
|
|
250
|
+
if (linkError) {
|
|
251
|
+
console.log(JSON.stringify({ success: false, error: linkError }));
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
237
255
|
// Auto-generate displayName if omitted
|
|
238
256
|
const displayName = typeof r.displayName === "string" && r.displayName
|
|
239
257
|
? r.displayName
|
|
@@ -489,14 +507,22 @@ async function addProp(ref, options) {
|
|
|
489
507
|
process.exit(1);
|
|
490
508
|
}
|
|
491
509
|
}
|
|
510
|
+
const parsedDefaultValue = options.defaultValue !== undefined ? parseDefaultValue(options.defaultValue, propType) : undefined;
|
|
511
|
+
if ((propType === "LINK" || propType === "LIST_OF_LINK") && parsedDefaultValue !== undefined) {
|
|
512
|
+
const linkError = validateLinkDefaultValue(propType, parsedDefaultValue, options.name);
|
|
513
|
+
if (linkError) {
|
|
514
|
+
console.log(JSON.stringify({ success: false, error: linkError }));
|
|
515
|
+
process.exit(1);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
492
518
|
const newProp = {
|
|
493
519
|
name: options.name,
|
|
494
520
|
displayName: options.displayName,
|
|
495
521
|
type: propType,
|
|
496
522
|
required: options.required ?? false,
|
|
497
523
|
...(options.description ? { description: options.description } : {}),
|
|
498
|
-
...(
|
|
499
|
-
? { defaultValue:
|
|
524
|
+
...(parsedDefaultValue !== undefined
|
|
525
|
+
? { defaultValue: parsedDefaultValue }
|
|
500
526
|
: {}),
|
|
501
527
|
...(options.group ? { groupId: options.group } : {}),
|
|
502
528
|
...(options.typeId ? { typeId: options.typeId } : {}),
|
|
@@ -530,10 +556,70 @@ function parseDefaultValue(value, propType) {
|
|
|
530
556
|
return Number(value);
|
|
531
557
|
case "BOOLEAN":
|
|
532
558
|
return value === "true";
|
|
559
|
+
case "LINK":
|
|
560
|
+
case "LIST_OF_LINK":
|
|
561
|
+
// The --default-value flag arrives as a string; LINK values must be stored as a
|
|
562
|
+
// typed object. Parse it here; if it is not valid JSON, return the raw string so
|
|
563
|
+
// validateLinkDefaultValue can report a precise error.
|
|
564
|
+
try {
|
|
565
|
+
return JSON.parse(value);
|
|
566
|
+
}
|
|
567
|
+
catch {
|
|
568
|
+
return value;
|
|
569
|
+
}
|
|
533
570
|
default:
|
|
534
571
|
return value;
|
|
535
572
|
}
|
|
536
573
|
}
|
|
574
|
+
const VALID_LINK_TYPES = ["PAGE", "EXTERNAL", "FILE"];
|
|
575
|
+
const LINK_SHAPE_HELP = 'A link must be an object: { "linkType": "EXTERNAL", "label": "Text", "externalLink": "https://...", "subLinks": [] } ' +
|
|
576
|
+
'for external links, or { "linkType": "PAGE", "label": "Text", "pageType": "INDEX", "subLinks": [] } for store pages. ' +
|
|
577
|
+
"Do NOT pass a JSON string or a { label, href } shape.";
|
|
578
|
+
// Returns the index of the first array element that fails `fn`, as an error string, or null.
|
|
579
|
+
const firstError = (arr, fn) => arr.reduce((acc, item, index) => acc ?? fn(item, index), null);
|
|
580
|
+
const validateSingleLink = (link, propName, path) => {
|
|
581
|
+
const where = `defaultValue for prop "${propName}"${path}`;
|
|
582
|
+
if (typeof link === "string") {
|
|
583
|
+
return `${where} is a JSON string but must be an object. ${LINK_SHAPE_HELP}`;
|
|
584
|
+
}
|
|
585
|
+
if (!link || typeof link !== "object" || Array.isArray(link)) {
|
|
586
|
+
return `${where} must be a link object. ${LINK_SHAPE_HELP}`;
|
|
587
|
+
}
|
|
588
|
+
const l = link;
|
|
589
|
+
if ("href" in l && !("linkType" in l)) {
|
|
590
|
+
return `${where} uses a legacy { href } shape without "linkType". Use "linkType" + "externalLink"/"pageType" instead. ${LINK_SHAPE_HELP}`;
|
|
591
|
+
}
|
|
592
|
+
if (typeof l.linkType !== "string" || !VALID_LINK_TYPES.includes(l.linkType)) {
|
|
593
|
+
return `${where} must have a valid "linkType" (one of ${VALID_LINK_TYPES.join(", ")}). ${LINK_SHAPE_HELP}`;
|
|
594
|
+
}
|
|
595
|
+
if (l.subLinks !== undefined && !Array.isArray(l.subLinks)) {
|
|
596
|
+
return `${where}: "subLinks" must be an array (use [] when there are none).`;
|
|
597
|
+
}
|
|
598
|
+
if (Array.isArray(l.subLinks)) {
|
|
599
|
+
return firstError(l.subLinks, (sl, i) => validateSingleLink(sl, propName, `${path}.subLinks[${i}]`));
|
|
600
|
+
}
|
|
601
|
+
return null;
|
|
602
|
+
};
|
|
603
|
+
// Validates a LINK / LIST_OF_LINK defaultValue. Returns an error message, or null if valid.
|
|
604
|
+
// These defaults are a frequent source of bad data: agents tend to pass a JSON string or a
|
|
605
|
+
// legacy { label, href } shape. Rejecting them at authoring time keeps malformed link values
|
|
606
|
+
// out of published themes.
|
|
607
|
+
function validateLinkDefaultValue(propType, value, propName) {
|
|
608
|
+
if (value === undefined || value === null)
|
|
609
|
+
return null;
|
|
610
|
+
if (propType === "LINK") {
|
|
611
|
+
return validateSingleLink(value, propName, "");
|
|
612
|
+
}
|
|
613
|
+
// LIST_OF_LINK
|
|
614
|
+
if (typeof value === "string") {
|
|
615
|
+
return `defaultValue for prop "${propName}" is a JSON string but must be an object { "links": [...] }. ${LINK_SHAPE_HELP}`;
|
|
616
|
+
}
|
|
617
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || !Array.isArray(value.links)) {
|
|
618
|
+
return `defaultValue for prop "${propName}" must be an object with a "links" array: { "links": [ <link>, ... ] }. ${LINK_SHAPE_HELP}`;
|
|
619
|
+
}
|
|
620
|
+
const links = value.links;
|
|
621
|
+
return firstError(links, (link, i) => validateSingleLink(link, propName, `.links[${i}]`));
|
|
622
|
+
}
|
|
537
623
|
function updateProp(ref, options) {
|
|
538
624
|
const { config, configPath } = loadConfig();
|
|
539
625
|
const component = resolveComponent(config, ref);
|
|
@@ -567,7 +653,15 @@ function updateProp(ref, options) {
|
|
|
567
653
|
prop.description = options.description || undefined;
|
|
568
654
|
}
|
|
569
655
|
if (options.defaultValue !== undefined) {
|
|
570
|
-
|
|
656
|
+
const parsed = parseDefaultValue(options.defaultValue, prop.type);
|
|
657
|
+
if (prop.type === "LINK" || prop.type === "LIST_OF_LINK") {
|
|
658
|
+
const linkError = validateLinkDefaultValue(prop.type, parsed, prop.name);
|
|
659
|
+
if (linkError) {
|
|
660
|
+
console.log(JSON.stringify({ success: false, error: linkError }));
|
|
661
|
+
process.exit(1);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
prop.defaultValue = parsed;
|
|
571
665
|
}
|
|
572
666
|
if (options.group !== undefined) {
|
|
573
667
|
if (options.group === "" || options.group === "none") {
|
|
@@ -908,6 +1002,156 @@ function updateComponent(ref, options) {
|
|
|
908
1002
|
...(component.isFooter ? { isFooter: true } : {}),
|
|
909
1003
|
}));
|
|
910
1004
|
}
|
|
1005
|
+
// Upsert a per-locale translation row in `list` by locale, applying only the
|
|
1006
|
+
// provided fields. Studio keeps one translation per locale, so this matches by
|
|
1007
|
+
// locale rather than appending. A row left with no content (all label fields
|
|
1008
|
+
// empty) is not persisted — a new one is skipped, an existing one is pruned —
|
|
1009
|
+
// so we never write a meaningless `{id, locale}` row. Returns the row, or null
|
|
1010
|
+
// when nothing meaningful remains.
|
|
1011
|
+
function upsertTranslation(list, locale, fields) {
|
|
1012
|
+
const existing = list.find((t) => t.locale === locale);
|
|
1013
|
+
const target = existing ?? { id: generateUniqueId(), locale };
|
|
1014
|
+
if (fields.displayName !== undefined)
|
|
1015
|
+
target.displayName = fields.displayName || undefined;
|
|
1016
|
+
if (fields.description !== undefined)
|
|
1017
|
+
target.description = fields.description || undefined;
|
|
1018
|
+
if (fields.name !== undefined)
|
|
1019
|
+
target.name = fields.name || undefined;
|
|
1020
|
+
if (!target.displayName && !target.description && !target.name) {
|
|
1021
|
+
if (existing)
|
|
1022
|
+
list.splice(list.indexOf(existing), 1);
|
|
1023
|
+
return null;
|
|
1024
|
+
}
|
|
1025
|
+
if (!existing)
|
|
1026
|
+
list.push(target);
|
|
1027
|
+
return target;
|
|
1028
|
+
}
|
|
1029
|
+
function setPropTranslation(ref, options) {
|
|
1030
|
+
const { config, configPath } = loadConfig();
|
|
1031
|
+
const component = resolveComponent(config, ref);
|
|
1032
|
+
const prop = component.props.find((p) => p.name === options.prop);
|
|
1033
|
+
if (!prop) {
|
|
1034
|
+
console.log(JSON.stringify({
|
|
1035
|
+
success: false,
|
|
1036
|
+
error: `Prop "${options.prop}" not found on component "${component.name}". Available: ${component.props.map((p) => p.name).join(", ")}`,
|
|
1037
|
+
}));
|
|
1038
|
+
process.exit(1);
|
|
1039
|
+
}
|
|
1040
|
+
if (options.displayName === undefined && options.description === undefined) {
|
|
1041
|
+
console.log(JSON.stringify({
|
|
1042
|
+
success: false,
|
|
1043
|
+
error: "Nothing to set: provide --displayName and/or --description.",
|
|
1044
|
+
}));
|
|
1045
|
+
process.exit(1);
|
|
1046
|
+
}
|
|
1047
|
+
if (!prop.translations)
|
|
1048
|
+
prop.translations = [];
|
|
1049
|
+
const row = upsertTranslation(prop.translations, options.locale, {
|
|
1050
|
+
displayName: options.displayName,
|
|
1051
|
+
description: options.description,
|
|
1052
|
+
});
|
|
1053
|
+
if (prop.translations.length === 0)
|
|
1054
|
+
prop.translations = undefined;
|
|
1055
|
+
saveConfig(configPath, config);
|
|
1056
|
+
console.log(JSON.stringify({
|
|
1057
|
+
success: true,
|
|
1058
|
+
componentName: component.name,
|
|
1059
|
+
prop: prop.name,
|
|
1060
|
+
translation: row,
|
|
1061
|
+
}));
|
|
1062
|
+
}
|
|
1063
|
+
function setGroupTranslation(ref, options) {
|
|
1064
|
+
const { config, configPath } = loadConfig();
|
|
1065
|
+
const component = resolveComponent(config, ref);
|
|
1066
|
+
if (!component.propGroups || component.propGroups.length === 0) {
|
|
1067
|
+
console.log(JSON.stringify({ success: false, error: `No prop groups on component "${component.name}".` }));
|
|
1068
|
+
process.exit(1);
|
|
1069
|
+
}
|
|
1070
|
+
const found = findPropGroup(component.propGroups, options.group);
|
|
1071
|
+
if (!found) {
|
|
1072
|
+
console.log(JSON.stringify({
|
|
1073
|
+
success: false,
|
|
1074
|
+
error: `Prop group "${options.group}" not found on component "${component.name}". Available: ${Array.from(collectPropGroupIds(component.propGroups)).join(", ")}`,
|
|
1075
|
+
}));
|
|
1076
|
+
process.exit(1);
|
|
1077
|
+
}
|
|
1078
|
+
if (options.name === undefined && options.description === undefined) {
|
|
1079
|
+
console.log(JSON.stringify({
|
|
1080
|
+
success: false,
|
|
1081
|
+
error: "Nothing to set: provide --name and/or --description.",
|
|
1082
|
+
}));
|
|
1083
|
+
process.exit(1);
|
|
1084
|
+
}
|
|
1085
|
+
if (!found.group.translations)
|
|
1086
|
+
found.group.translations = [];
|
|
1087
|
+
const row = upsertTranslation(found.group.translations, options.locale, {
|
|
1088
|
+
name: options.name,
|
|
1089
|
+
description: options.description,
|
|
1090
|
+
});
|
|
1091
|
+
if (found.group.translations.length === 0)
|
|
1092
|
+
found.group.translations = undefined;
|
|
1093
|
+
saveConfig(configPath, config);
|
|
1094
|
+
console.log(JSON.stringify({
|
|
1095
|
+
success: true,
|
|
1096
|
+
componentName: component.name,
|
|
1097
|
+
group: found.group.id,
|
|
1098
|
+
translation: row,
|
|
1099
|
+
}));
|
|
1100
|
+
}
|
|
1101
|
+
function removePropTranslation(ref, options) {
|
|
1102
|
+
const { config, configPath } = loadConfig();
|
|
1103
|
+
const component = resolveComponent(config, ref);
|
|
1104
|
+
const prop = component.props.find((p) => p.name === options.prop);
|
|
1105
|
+
if (!prop) {
|
|
1106
|
+
console.log(JSON.stringify({
|
|
1107
|
+
success: false,
|
|
1108
|
+
error: `Prop "${options.prop}" not found on component "${component.name}". Available: ${component.props.map((p) => p.name).join(", ")}`,
|
|
1109
|
+
}));
|
|
1110
|
+
process.exit(1);
|
|
1111
|
+
}
|
|
1112
|
+
const before = prop.translations?.length ?? 0;
|
|
1113
|
+
if (prop.translations) {
|
|
1114
|
+
prop.translations = prop.translations.filter((t) => t.locale !== options.locale);
|
|
1115
|
+
if (prop.translations.length === 0)
|
|
1116
|
+
prop.translations = undefined;
|
|
1117
|
+
}
|
|
1118
|
+
saveConfig(configPath, config);
|
|
1119
|
+
console.log(JSON.stringify({
|
|
1120
|
+
success: true,
|
|
1121
|
+
componentName: component.name,
|
|
1122
|
+
prop: prop.name,
|
|
1123
|
+
removed: before - (prop.translations?.length ?? 0),
|
|
1124
|
+
}));
|
|
1125
|
+
}
|
|
1126
|
+
function removeGroupTranslation(ref, options) {
|
|
1127
|
+
const { config, configPath } = loadConfig();
|
|
1128
|
+
const component = resolveComponent(config, ref);
|
|
1129
|
+
if (!component.propGroups || component.propGroups.length === 0) {
|
|
1130
|
+
console.log(JSON.stringify({ success: false, error: `No prop groups on component "${component.name}".` }));
|
|
1131
|
+
process.exit(1);
|
|
1132
|
+
}
|
|
1133
|
+
const found = findPropGroup(component.propGroups, options.group);
|
|
1134
|
+
if (!found) {
|
|
1135
|
+
console.log(JSON.stringify({
|
|
1136
|
+
success: false,
|
|
1137
|
+
error: `Prop group "${options.group}" not found on component "${component.name}". Available: ${Array.from(collectPropGroupIds(component.propGroups)).join(", ")}`,
|
|
1138
|
+
}));
|
|
1139
|
+
process.exit(1);
|
|
1140
|
+
}
|
|
1141
|
+
const before = found.group.translations?.length ?? 0;
|
|
1142
|
+
if (found.group.translations) {
|
|
1143
|
+
found.group.translations = found.group.translations.filter((t) => t.locale !== options.locale);
|
|
1144
|
+
if (found.group.translations.length === 0)
|
|
1145
|
+
found.group.translations = undefined;
|
|
1146
|
+
}
|
|
1147
|
+
saveConfig(configPath, config);
|
|
1148
|
+
console.log(JSON.stringify({
|
|
1149
|
+
success: true,
|
|
1150
|
+
componentName: component.name,
|
|
1151
|
+
group: found.group.id,
|
|
1152
|
+
removed: before - (found.group.translations?.length ?? 0),
|
|
1153
|
+
}));
|
|
1154
|
+
}
|
|
911
1155
|
function listComponents() {
|
|
912
1156
|
const { config } = loadConfig();
|
|
913
1157
|
const components = config.components.map((c) => ({
|
|
@@ -1250,6 +1494,53 @@ export function createConfigCommand() {
|
|
|
1250
1494
|
.action((options) => {
|
|
1251
1495
|
movePropGroup({ id: options.componentId, name: options.component }, options);
|
|
1252
1496
|
});
|
|
1497
|
+
config
|
|
1498
|
+
.command("set-prop-translation")
|
|
1499
|
+
.description("Add or update a per-locale translation for a prop's label/description. " +
|
|
1500
|
+
"Seeded into the editor on first import of a new component or a newly added prop; " +
|
|
1501
|
+
"studio-owned translations for already-imported props are not overwritten.")
|
|
1502
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1503
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1504
|
+
.requiredOption("--prop <propName>", "Prop name to translate")
|
|
1505
|
+
.requiredOption("--locale <locale>", "Target locale (e.g. de, fr, en)")
|
|
1506
|
+
.option("--displayName <text>", "Translated display name")
|
|
1507
|
+
.option("--description <text>", "Translated description")
|
|
1508
|
+
.action((options) => {
|
|
1509
|
+
setPropTranslation({ id: options.componentId, name: options.component }, options);
|
|
1510
|
+
});
|
|
1511
|
+
config
|
|
1512
|
+
.command("set-group-translation")
|
|
1513
|
+
.description("Add or update a per-locale translation for a prop group's name/description. " +
|
|
1514
|
+
"Seeded into the editor only for groups studio has not seen yet (studio wins otherwise).")
|
|
1515
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1516
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1517
|
+
.requiredOption("--group <groupId>", "Prop group id (local, as in ikas.config.json)")
|
|
1518
|
+
.requiredOption("--locale <locale>", "Target locale (e.g. de, fr, en)")
|
|
1519
|
+
.option("--name <text>", "Translated group name")
|
|
1520
|
+
.option("--description <text>", "Translated description")
|
|
1521
|
+
.action((options) => {
|
|
1522
|
+
setGroupTranslation({ id: options.componentId, name: options.component }, options);
|
|
1523
|
+
});
|
|
1524
|
+
config
|
|
1525
|
+
.command("remove-prop-translation")
|
|
1526
|
+
.description("Remove a prop's translation for a given locale")
|
|
1527
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1528
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1529
|
+
.requiredOption("--prop <propName>", "Prop name")
|
|
1530
|
+
.requiredOption("--locale <locale>", "Locale to remove")
|
|
1531
|
+
.action((options) => {
|
|
1532
|
+
removePropTranslation({ id: options.componentId, name: options.component }, options);
|
|
1533
|
+
});
|
|
1534
|
+
config
|
|
1535
|
+
.command("remove-group-translation")
|
|
1536
|
+
.description("Remove a prop group's translation for a given locale")
|
|
1537
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1538
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1539
|
+
.requiredOption("--group <groupId>", "Prop group id (local, as in ikas.config.json)")
|
|
1540
|
+
.requiredOption("--locale <locale>", "Locale to remove")
|
|
1541
|
+
.action((options) => {
|
|
1542
|
+
removeGroupTranslation({ id: options.componentId, name: options.component }, options);
|
|
1543
|
+
});
|
|
1253
1544
|
config
|
|
1254
1545
|
.command("list-components")
|
|
1255
1546
|
.description("List all components and their props (with canonical ids for use with --id flags)")
|
|
@@ -1269,6 +1560,13 @@ export function createConfigCommand() {
|
|
|
1269
1560
|
.action(async (options) => {
|
|
1270
1561
|
await listTypes(options.componentType);
|
|
1271
1562
|
});
|
|
1563
|
+
config
|
|
1564
|
+
.command("list-locales")
|
|
1565
|
+
.description("List the editor's configured locales — the ONLY valid --locale values for set-prop-translation / set-group-translation. Run this before adding translations; never invent a locale. (Requires a running dev server with the editor connected.)")
|
|
1566
|
+
.option("--port <port>", "Dev server WebSocket port", "5201")
|
|
1567
|
+
.action(async (options) => {
|
|
1568
|
+
await listLocales(options.port ? parseInt(options.port, 10) : undefined);
|
|
1569
|
+
});
|
|
1272
1570
|
config
|
|
1273
1571
|
.command("add-enum")
|
|
1274
1572
|
.description("Create a custom enum type (offline, no editor needed)")
|