@stdout-design/cli 0.1.1 → 0.1.2
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.mjs +16 -99
- package/dist/schema.mjs +1 -1
- package/package.json +15 -22
- package/dist/cache-BdS9VgtQ.mjs +0 -22
- package/dist/dev-DoEMJ8Qi.mjs +0 -25
- package/dist/dist-CZVUmY-d.mjs +0 -590
- package/dist/dist-Dm76-R-V.mjs +0 -1187
- package/dist/init-CfgXE-J9.mjs +0 -195
- package/dist/lint-CacX6_Ob.mjs +0 -7
- package/dist/render-BhTeMXMX.mjs +0 -120
- package/dist/validation-CMTs74Vm-C3_d2dBv.mjs +0 -14
package/dist/init-CfgXE-J9.mjs
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
-
//#region src/commands/init.ts
|
|
5
|
-
const getConfigTemplate = () => `import type { StudioConfig } from "@stdout-design/cli";
|
|
6
|
-
|
|
7
|
-
const config: StudioConfig = {
|
|
8
|
-
defaultPreset: "instagram-square",
|
|
9
|
-
locales: ["en", "ar"],
|
|
10
|
-
outDir: "./out",
|
|
11
|
-
presets: [
|
|
12
|
-
{ height: 1080, id: "instagram-square", platform: "instagram", width: 1080 },
|
|
13
|
-
{ height: 1200, id: "x-card", platform: "x", width: 1200 },
|
|
14
|
-
],
|
|
15
|
-
templates: {
|
|
16
|
-
"bento-feature": {
|
|
17
|
-
componentPath: "./templates/bento-feature",
|
|
18
|
-
description: "Apple-style bento feature card.",
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export default config;
|
|
24
|
-
`;
|
|
25
|
-
const getBentoFeatureTemplate = () => `import { defineSchema } from "@stdout-design/cli/schema";
|
|
26
|
-
import { createElement, css, text } from "takumi-js";
|
|
27
|
-
import type { TakumiNode } from "takumi-js";
|
|
28
|
-
|
|
29
|
-
interface Props {
|
|
30
|
-
title?: string;
|
|
31
|
-
description?: string;
|
|
32
|
-
accent?: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const propsSchema = defineSchema({
|
|
36
|
-
title: { type: "string", default: "Featured App", description: "Headline text" },
|
|
37
|
-
description: { type: "string", default: "A beautiful description goes here.", description: "Subtitle text" },
|
|
38
|
-
accent: { type: "string", default: "#6366f1", description: "Accent color" },
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
export default (props: Props): TakumiNode => {
|
|
42
|
-
const { title = "Featured App", description = "", accent = "#6366f1" } = props;
|
|
43
|
-
|
|
44
|
-
return createElement("div", {
|
|
45
|
-
style: css({
|
|
46
|
-
alignItems: "center",
|
|
47
|
-
background: "#0a0a0b",
|
|
48
|
-
borderRadius: 24,
|
|
49
|
-
display: "flex",
|
|
50
|
-
flexDirection: "column",
|
|
51
|
-
height: "100%",
|
|
52
|
-
justifyContent: "center",
|
|
53
|
-
padding: 48,
|
|
54
|
-
width: "100%",
|
|
55
|
-
}),
|
|
56
|
-
children: [
|
|
57
|
-
createElement("div", {
|
|
58
|
-
style: css({
|
|
59
|
-
background: accent,
|
|
60
|
-
borderRadius: 12,
|
|
61
|
-
height: 64,
|
|
62
|
-
marginBottom: 24,
|
|
63
|
-
width: 64,
|
|
64
|
-
}),
|
|
65
|
-
}),
|
|
66
|
-
createElement("h1", {
|
|
67
|
-
style: css({
|
|
68
|
-
color: "#ffffff",
|
|
69
|
-
fontFamily: "Inter",
|
|
70
|
-
fontSize: 42,
|
|
71
|
-
fontWeight: 700,
|
|
72
|
-
margin: 0,
|
|
73
|
-
textAlign: "center",
|
|
74
|
-
}),
|
|
75
|
-
children: [text(title)],
|
|
76
|
-
}),
|
|
77
|
-
description ? createElement("p", {
|
|
78
|
-
style: css({
|
|
79
|
-
color: "#a1a1aa",
|
|
80
|
-
fontFamily: "Inter",
|
|
81
|
-
fontSize: 18,
|
|
82
|
-
marginTop: 16,
|
|
83
|
-
textAlign: "center",
|
|
84
|
-
}),
|
|
85
|
-
children: [text(description)],
|
|
86
|
-
}) : null,
|
|
87
|
-
],
|
|
88
|
-
});
|
|
89
|
-
};
|
|
90
|
-
`;
|
|
91
|
-
const scaffold = async (dir, options) => {
|
|
92
|
-
if (!existsSync(dir)) await mkdir(dir, { recursive: true });
|
|
93
|
-
const configPath = path.resolve(dir, "studio.config.ts");
|
|
94
|
-
if (existsSync(configPath)) {
|
|
95
|
-
console.log("studio.config.ts already exists — skipping scaffold.");
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
if (options.templates.length > 0) await mkdir(path.resolve(dir, "templates"), { recursive: true });
|
|
99
|
-
if (options.locales.length > 0) await mkdir(path.resolve(dir, "locales"), { recursive: true });
|
|
100
|
-
await writeFile(configPath, getConfigTemplate());
|
|
101
|
-
const pkgJson = {
|
|
102
|
-
name: path.basename(dir),
|
|
103
|
-
private: true,
|
|
104
|
-
type: "module",
|
|
105
|
-
dependencies: { "takumi-js": "^2.0.2" }
|
|
106
|
-
};
|
|
107
|
-
await writeFile(path.resolve(dir, "package.json"), JSON.stringify(pkgJson, null, 2));
|
|
108
|
-
const writes = [];
|
|
109
|
-
for (const template of options.templates) if (template === "bento-feature") {
|
|
110
|
-
const templatesDir = path.resolve(dir, "templates");
|
|
111
|
-
writes.push(writeFile(path.resolve(templatesDir, "bento-feature.tsx"), getBentoFeatureTemplate()));
|
|
112
|
-
}
|
|
113
|
-
for (const locale of options.locales) {
|
|
114
|
-
const localesDir = path.resolve(dir, "locales");
|
|
115
|
-
if (locale === "en") writes.push(writeFile(path.resolve(localesDir, "en.json"), JSON.stringify({ title: "Featured App" }, null, 2)));
|
|
116
|
-
if (locale === "ar") writes.push(writeFile(path.resolve(localesDir, "ar.json"), JSON.stringify({ title: "التطبيق المميز" }, null, 2)));
|
|
117
|
-
}
|
|
118
|
-
await Promise.all(writes);
|
|
119
|
-
console.log(`Scaffolded studio project in ${dir}`);
|
|
120
|
-
console.log("");
|
|
121
|
-
console.log("Next steps:");
|
|
122
|
-
console.log(` cd ${dir}`);
|
|
123
|
-
console.log(" studio dev");
|
|
124
|
-
if (options.install) {
|
|
125
|
-
console.log("");
|
|
126
|
-
console.log("Installing dependencies...");
|
|
127
|
-
const { spawnSync } = await import("node:child_process");
|
|
128
|
-
spawnSync("bun", ["install"], {
|
|
129
|
-
cwd: dir,
|
|
130
|
-
stdio: "inherit"
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
const init = async (projectDir, options) => {
|
|
135
|
-
const dir = path.resolve(projectDir ?? process.cwd());
|
|
136
|
-
if (options?.yes) {
|
|
137
|
-
await scaffold(dir, {
|
|
138
|
-
install: true,
|
|
139
|
-
locales: ["en", "ar"],
|
|
140
|
-
templates: ["bento-feature"]
|
|
141
|
-
});
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const { intro, confirm, multiselect, outro, cancel, isCancel } = await import("@clack/prompts");
|
|
145
|
-
intro("Studio Init");
|
|
146
|
-
if (existsSync(path.resolve(dir, "studio.config.ts"))) {
|
|
147
|
-
console.log("studio.config.ts already exists — skipping scaffold.");
|
|
148
|
-
outro("Done");
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
const selectedTemplates = await multiselect({
|
|
152
|
-
message: "Which templates would you like to scaffold?",
|
|
153
|
-
options: [{
|
|
154
|
-
hint: "Apple-style feature card",
|
|
155
|
-
label: "Bento Feature",
|
|
156
|
-
value: "bento-feature"
|
|
157
|
-
}]
|
|
158
|
-
});
|
|
159
|
-
if (isCancel(selectedTemplates)) {
|
|
160
|
-
cancel("Cancelled.");
|
|
161
|
-
process.exit(0);
|
|
162
|
-
}
|
|
163
|
-
const templates = selectedTemplates;
|
|
164
|
-
const selectedLocales = await multiselect({
|
|
165
|
-
message: "Which locales would you like to include?",
|
|
166
|
-
options: [{
|
|
167
|
-
label: "English",
|
|
168
|
-
value: "en"
|
|
169
|
-
}, {
|
|
170
|
-
label: "Arabic",
|
|
171
|
-
value: "ar"
|
|
172
|
-
}]
|
|
173
|
-
});
|
|
174
|
-
if (isCancel(selectedLocales)) {
|
|
175
|
-
cancel("Cancelled.");
|
|
176
|
-
process.exit(0);
|
|
177
|
-
}
|
|
178
|
-
const locales = selectedLocales;
|
|
179
|
-
const shouldInstall = await confirm({
|
|
180
|
-
initialValue: true,
|
|
181
|
-
message: "Install dependencies?"
|
|
182
|
-
});
|
|
183
|
-
if (isCancel(shouldInstall)) {
|
|
184
|
-
cancel("Cancelled.");
|
|
185
|
-
process.exit(0);
|
|
186
|
-
}
|
|
187
|
-
await scaffold(dir, {
|
|
188
|
-
install: shouldInstall,
|
|
189
|
-
locales,
|
|
190
|
-
templates
|
|
191
|
-
});
|
|
192
|
-
outro("Done");
|
|
193
|
-
};
|
|
194
|
-
//#endregion
|
|
195
|
-
export { init };
|
package/dist/lint-CacX6_Ob.mjs
DELETED
package/dist/render-BhTeMXMX.mjs
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { r as formatManifestSummary } from "./index.mjs";
|
|
2
|
-
import { r as zodToJsonSchemaShape } from "./validation-CMTs74Vm-C3_d2dBv.mjs";
|
|
3
|
-
import { a as importTemplateForBatch, d as runBatch, n as ErrorCode, o as loadConfig, t as AppError } from "./dist-Dm76-R-V.mjs";
|
|
4
|
-
//#region src/lib/prop-parser.ts
|
|
5
|
-
const coerceValue = (value, type, _items) => {
|
|
6
|
-
switch (type) {
|
|
7
|
-
case "number": {
|
|
8
|
-
const n = Number(value);
|
|
9
|
-
return Number.isNaN(n) ? value : n;
|
|
10
|
-
}
|
|
11
|
-
case "boolean":
|
|
12
|
-
if (value === "true" || value === "1") return true;
|
|
13
|
-
if (value === "false" || value === "0") return false;
|
|
14
|
-
return value;
|
|
15
|
-
case "array":
|
|
16
|
-
if (value.startsWith("[") && value.endsWith("]")) try {
|
|
17
|
-
return JSON.parse(value);
|
|
18
|
-
} catch {
|
|
19
|
-
return value.split(",").map((s) => s.trim());
|
|
20
|
-
}
|
|
21
|
-
return value.split(",").map((s) => s.trim());
|
|
22
|
-
default: return value;
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
const parsePropArgs = (args, schema) => {
|
|
26
|
-
const props = {};
|
|
27
|
-
const properties = schema.properties ?? {};
|
|
28
|
-
for (const arg of args) {
|
|
29
|
-
const eqIndex = arg.indexOf("=");
|
|
30
|
-
if (eqIndex === -1) {
|
|
31
|
-
props[arg] = true;
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
const key = arg.slice(0, eqIndex);
|
|
35
|
-
const value = arg.slice(eqIndex + 1);
|
|
36
|
-
const field = properties[key];
|
|
37
|
-
props[key] = field ? coerceValue(value, field.type, field.items) : value;
|
|
38
|
-
}
|
|
39
|
-
return props;
|
|
40
|
-
};
|
|
41
|
-
const mergeDefaultProps = (schema, props) => {
|
|
42
|
-
const properties = schema.properties ?? {};
|
|
43
|
-
const merged = {};
|
|
44
|
-
for (const [key, field] of Object.entries(properties)) if (field.default !== void 0) merged[key] = field.default;
|
|
45
|
-
return {
|
|
46
|
-
...merged,
|
|
47
|
-
...props
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
//#endregion
|
|
51
|
-
//#region src/lib/suggest.ts
|
|
52
|
-
const levenshteinDistance = (a, b) => {
|
|
53
|
-
const aLen = a.length;
|
|
54
|
-
const bLen = b.length;
|
|
55
|
-
if (aLen === 0) return bLen;
|
|
56
|
-
if (bLen === 0) return aLen;
|
|
57
|
-
let prev = Array.from({ length: aLen + 1 }, (_, j) => j);
|
|
58
|
-
let curr = Array.from({ length: aLen + 1 }).fill(0);
|
|
59
|
-
for (let j = 1; j <= bLen; j += 1) {
|
|
60
|
-
curr[0] = j;
|
|
61
|
-
for (let i = 1; i <= aLen; i += 1) {
|
|
62
|
-
const cost = b[j - 1] === a[i - 1] ? 0 : 1;
|
|
63
|
-
curr[i] = Math.min((prev[i] ?? 0) + 1, (curr[i - 1] ?? 0) + 1, (prev[i - 1] ?? 0) + cost);
|
|
64
|
-
}
|
|
65
|
-
const tmp = prev;
|
|
66
|
-
prev = curr;
|
|
67
|
-
curr = tmp;
|
|
68
|
-
}
|
|
69
|
-
return prev[aLen] ?? 0;
|
|
70
|
-
};
|
|
71
|
-
const suggestClosest = (input, candidates, maxDistance = 3) => {
|
|
72
|
-
let best;
|
|
73
|
-
let bestDistance = Infinity;
|
|
74
|
-
for (const candidate of candidates) {
|
|
75
|
-
const dist = levenshteinDistance(input.toLowerCase(), candidate.toLowerCase());
|
|
76
|
-
if (dist < bestDistance && dist <= maxDistance) {
|
|
77
|
-
bestDistance = dist;
|
|
78
|
-
best = candidate;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return best;
|
|
82
|
-
};
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region src/commands/render.ts
|
|
85
|
-
const render = async (templateId, propArgs, options) => {
|
|
86
|
-
const rootDir = process.cwd();
|
|
87
|
-
const config = await loadConfig(rootDir);
|
|
88
|
-
const templateEntry = config.templates[templateId];
|
|
89
|
-
if (!templateEntry) {
|
|
90
|
-
const suggestions = suggestClosest(templateId, Object.keys(config.templates));
|
|
91
|
-
const hint = suggestions ? ` Did you mean "${suggestions}"?` : "";
|
|
92
|
-
throw new AppError(ErrorCode.TEMPLATE_NOT_FOUND, `Template "${templateId}" not found in studio.config.ts.${hint}`, {
|
|
93
|
-
availableTemplates: Object.keys(config.templates),
|
|
94
|
-
templateId
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
const { module } = await importTemplateForBatch(rootDir, templateEntry.componentPath, templateId);
|
|
98
|
-
const schema = zodToJsonSchemaShape(module.propsSchema);
|
|
99
|
-
const mergedProps = mergeDefaultProps(schema, parsePropArgs(propArgs, schema));
|
|
100
|
-
const presetIds = options.preset ? options.preset.split(",").map((s) => s.trim()) : config.presets.map((p) => p.id);
|
|
101
|
-
const localeIds = options.locale ? options.locale.split(",").map((s) => s.trim()) : void 0;
|
|
102
|
-
const outDir = options.outDir ?? config.outDir ?? "out";
|
|
103
|
-
const { manifest } = await runBatch({
|
|
104
|
-
baseProps: mergedProps,
|
|
105
|
-
concurrency: Number(options.concurrency ?? "4"),
|
|
106
|
-
dataFile: options.data,
|
|
107
|
-
failFast: options.failFast,
|
|
108
|
-
locales: localeIds,
|
|
109
|
-
outDir,
|
|
110
|
-
presets: presetIds,
|
|
111
|
-
rootDir,
|
|
112
|
-
rows: options.data ? void 0 : [{}],
|
|
113
|
-
templateId
|
|
114
|
-
});
|
|
115
|
-
if (options.json) console.log(JSON.stringify(manifest, null, 2));
|
|
116
|
-
else console.log(formatManifestSummary(manifest));
|
|
117
|
-
if (manifest.failed.length > 0) process.exit(1);
|
|
118
|
-
};
|
|
119
|
-
//#endregion
|
|
120
|
-
export { render };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
//#region ../core/dist/validation-CMTs74Vm.mjs
|
|
3
|
-
/** Identity helper purely for inference ergonomics at the template definition site. */
|
|
4
|
-
const defineSchema = (schema) => schema;
|
|
5
|
-
const isZodObject = (schema) => {
|
|
6
|
-
if (typeof schema !== "object" || schema === null) return false;
|
|
7
|
-
return schema.type === "object";
|
|
8
|
-
};
|
|
9
|
-
const zodToJsonSchemaShape = (schema) => {
|
|
10
|
-
if (typeof schema !== "object" || !schema || !("shape" in schema)) return {};
|
|
11
|
-
return z.toJSONSchema(schema);
|
|
12
|
-
};
|
|
13
|
-
//#endregion
|
|
14
|
-
export { isZodObject as n, zodToJsonSchemaShape as r, defineSchema as t };
|