cmssy-cli 0.12.3 → 0.13.1
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/config.d.ts +2 -0
- package/dist/cli.js +1 -1
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +20 -171
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/configure.js +2 -2
- package/dist/commands/configure.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +30 -279
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/package.d.ts.map +1 -1
- package/dist/commands/package.js +18 -43
- package/dist/commands/package.js.map +1 -1
- package/dist/utils/block-config.js +5 -0
- package/dist/utils/block-config.js.map +1 -1
- package/dist/utils/builder.d.ts +31 -0
- package/dist/utils/builder.d.ts.map +1 -0
- package/dist/utils/builder.js +135 -0
- package/dist/utils/builder.js.map +1 -0
- package/dist/utils/scanner.d.ts +34 -0
- package/dist/utils/scanner.d.ts.map +1 -0
- package/dist/utils/scanner.js +133 -0
- package/dist/utils/scanner.js.map +1 -0
- package/package.json +3 -2
package/config.d.ts
ADDED
package/dist/cli.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAOA,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,iBAgEvD"}
|
package/dist/commands/build.js
CHANGED
|
@@ -1,35 +1,41 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import { build as esbuild } from "esbuild";
|
|
3
|
-
import { execSync } from "child_process";
|
|
4
|
-
import fs from "fs-extra";
|
|
5
2
|
import ora from "ora";
|
|
6
3
|
import path from "path";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
4
|
+
import { loadConfig } from "../utils/cmssy-config.js";
|
|
5
|
+
import { scanResources } from "../utils/scanner.js";
|
|
6
|
+
import { buildResource } from "../utils/builder.js";
|
|
10
7
|
export async function buildCommand(options) {
|
|
11
8
|
const spinner = ora("Starting build...").start();
|
|
12
9
|
try {
|
|
13
10
|
const config = await loadConfig();
|
|
14
11
|
const framework = options.framework || config.framework;
|
|
15
|
-
// Scan for blocks and templates
|
|
16
|
-
const resources = await scanResources(
|
|
12
|
+
// Scan for blocks and templates (strict mode - throw errors)
|
|
13
|
+
const resources = await scanResources({
|
|
14
|
+
strict: true,
|
|
15
|
+
loadConfig: true,
|
|
16
|
+
validateSchema: true,
|
|
17
|
+
loadPreview: false,
|
|
18
|
+
requirePackageJson: true,
|
|
19
|
+
});
|
|
17
20
|
if (resources.length === 0) {
|
|
18
21
|
spinner.warn("No blocks or templates found");
|
|
19
22
|
process.exit(0);
|
|
20
23
|
}
|
|
21
24
|
spinner.text = `Building ${resources.length} resources...`;
|
|
22
25
|
const outDir = path.join(process.cwd(), config.build?.outDir || "public");
|
|
23
|
-
// Clean output directory
|
|
24
|
-
if (fs.existsSync(outDir)) {
|
|
25
|
-
fs.removeSync(outDir);
|
|
26
|
-
}
|
|
27
|
-
fs.mkdirSync(outDir, { recursive: true });
|
|
28
26
|
let successCount = 0;
|
|
29
27
|
let errorCount = 0;
|
|
30
28
|
for (const resource of resources) {
|
|
31
29
|
try {
|
|
32
|
-
await buildResource(resource,
|
|
30
|
+
await buildResource(resource, outDir, {
|
|
31
|
+
framework,
|
|
32
|
+
minify: config.build?.minify ?? true,
|
|
33
|
+
sourcemap: config.build?.sourcemap ?? true,
|
|
34
|
+
outputMode: "versioned",
|
|
35
|
+
generatePackageJson: true,
|
|
36
|
+
generateTypes: true,
|
|
37
|
+
strict: true,
|
|
38
|
+
});
|
|
33
39
|
successCount++;
|
|
34
40
|
console.log(chalk.green(` ✓ ${resource.packageJson.name}@${resource.packageJson.version}`));
|
|
35
41
|
}
|
|
@@ -52,161 +58,4 @@ export async function buildCommand(options) {
|
|
|
52
58
|
process.exit(1);
|
|
53
59
|
}
|
|
54
60
|
}
|
|
55
|
-
async function scanResources() {
|
|
56
|
-
const resources = [];
|
|
57
|
-
// Scan blocks
|
|
58
|
-
const blocksDir = path.join(process.cwd(), "blocks");
|
|
59
|
-
if (fs.existsSync(blocksDir)) {
|
|
60
|
-
const blockDirs = fs
|
|
61
|
-
.readdirSync(blocksDir, { withFileTypes: true })
|
|
62
|
-
.filter((dirent) => dirent.isDirectory())
|
|
63
|
-
.map((dirent) => dirent.name);
|
|
64
|
-
for (const blockName of blockDirs) {
|
|
65
|
-
const blockPath = path.join(blocksDir, blockName);
|
|
66
|
-
// Try loading block.config.ts
|
|
67
|
-
const blockConfig = await loadBlockConfig(blockPath);
|
|
68
|
-
if (!blockConfig) {
|
|
69
|
-
// Check if package.json has cmssy (old format)
|
|
70
|
-
const pkg = getPackageJson(blockPath);
|
|
71
|
-
if (pkg && pkg.cmssy) {
|
|
72
|
-
throw new Error(`Block "${blockName}" uses legacy package.json format.\n` +
|
|
73
|
-
`Please migrate to block.config.ts.\n` +
|
|
74
|
-
`Run: cmssy migrate ${blockName}\n` +
|
|
75
|
-
`Or see migration guide: https://cmssy.io/docs/migration`);
|
|
76
|
-
}
|
|
77
|
-
console.warn(chalk.yellow(`Warning: Skipping ${blockName} - no block.config.ts found`));
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
// Validate schema
|
|
81
|
-
const validation = await validateSchema(blockConfig.schema, blockPath);
|
|
82
|
-
if (!validation.valid) {
|
|
83
|
-
console.error(chalk.red(`\nValidation errors in ${blockName}:`));
|
|
84
|
-
validation.errors.forEach((err) => console.error(chalk.red(` - ${err}`)));
|
|
85
|
-
throw new Error(`Schema validation failed for ${blockName}`);
|
|
86
|
-
}
|
|
87
|
-
// Load package.json for name and version
|
|
88
|
-
const pkg = getPackageJson(blockPath);
|
|
89
|
-
if (!pkg || !pkg.name || !pkg.version) {
|
|
90
|
-
throw new Error(`Block "${blockName}" must have package.json with name and version`);
|
|
91
|
-
}
|
|
92
|
-
resources.push({
|
|
93
|
-
type: "block",
|
|
94
|
-
name: blockName,
|
|
95
|
-
path: blockPath,
|
|
96
|
-
packageJson: pkg,
|
|
97
|
-
blockConfig,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
// Scan templates
|
|
102
|
-
const templatesDir = path.join(process.cwd(), "templates");
|
|
103
|
-
if (fs.existsSync(templatesDir)) {
|
|
104
|
-
const templateDirs = fs
|
|
105
|
-
.readdirSync(templatesDir, { withFileTypes: true })
|
|
106
|
-
.filter((dirent) => dirent.isDirectory())
|
|
107
|
-
.map((dirent) => dirent.name);
|
|
108
|
-
for (const templateName of templateDirs) {
|
|
109
|
-
const templatePath = path.join(templatesDir, templateName);
|
|
110
|
-
// Try loading block.config.ts
|
|
111
|
-
const blockConfig = await loadBlockConfig(templatePath);
|
|
112
|
-
if (!blockConfig) {
|
|
113
|
-
// Check if package.json has cmssy (old format)
|
|
114
|
-
const pkg = getPackageJson(templatePath);
|
|
115
|
-
if (pkg && pkg.cmssy) {
|
|
116
|
-
throw new Error(`Template "${templateName}" uses legacy package.json format.\n` +
|
|
117
|
-
`Please migrate to block.config.ts.\n` +
|
|
118
|
-
`Run: cmssy migrate ${templateName}\n` +
|
|
119
|
-
`Or see migration guide: https://cmssy.io/docs/migration`);
|
|
120
|
-
}
|
|
121
|
-
console.warn(chalk.yellow(`Warning: Skipping ${templateName} - no block.config.ts found`));
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
// Validate schema
|
|
125
|
-
const validation = await validateSchema(blockConfig.schema, templatePath);
|
|
126
|
-
if (!validation.valid) {
|
|
127
|
-
console.error(chalk.red(`\nValidation errors in ${templateName}:`));
|
|
128
|
-
validation.errors.forEach((err) => console.error(chalk.red(` - ${err}`)));
|
|
129
|
-
throw new Error(`Schema validation failed for ${templateName}`);
|
|
130
|
-
}
|
|
131
|
-
// Load package.json for name and version
|
|
132
|
-
const pkg = getPackageJson(templatePath);
|
|
133
|
-
if (!pkg || !pkg.name || !pkg.version) {
|
|
134
|
-
throw new Error(`Template "${templateName}" must have package.json with name and version`);
|
|
135
|
-
}
|
|
136
|
-
resources.push({
|
|
137
|
-
type: "template",
|
|
138
|
-
name: templateName,
|
|
139
|
-
path: templatePath,
|
|
140
|
-
packageJson: pkg,
|
|
141
|
-
blockConfig,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return resources;
|
|
146
|
-
}
|
|
147
|
-
async function buildResource(resource, framework, outDir, config) {
|
|
148
|
-
const srcPath = path.join(resource.path, "src");
|
|
149
|
-
const entryPoint = framework === "react"
|
|
150
|
-
? path.join(srcPath, "index.tsx")
|
|
151
|
-
: path.join(srcPath, "index.ts");
|
|
152
|
-
if (!fs.existsSync(entryPoint)) {
|
|
153
|
-
throw new Error(`Entry point not found: ${entryPoint}`);
|
|
154
|
-
}
|
|
155
|
-
// Create versioned output directory
|
|
156
|
-
// Example: public/@vendor/blocks.hero/1.0.0/
|
|
157
|
-
const packageName = resource.packageJson.name;
|
|
158
|
-
const version = resource.packageJson.version;
|
|
159
|
-
const destDir = path.join(outDir, packageName, version);
|
|
160
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
161
|
-
// Build JavaScript
|
|
162
|
-
const outFile = path.join(destDir, "index.js");
|
|
163
|
-
await esbuild({
|
|
164
|
-
entryPoints: [entryPoint],
|
|
165
|
-
bundle: true,
|
|
166
|
-
format: "esm",
|
|
167
|
-
outfile: outFile,
|
|
168
|
-
jsx: "transform",
|
|
169
|
-
minify: config.build?.minify ?? true,
|
|
170
|
-
sourcemap: config.build?.sourcemap ?? true,
|
|
171
|
-
target: "es2020",
|
|
172
|
-
external: ["*.css"],
|
|
173
|
-
});
|
|
174
|
-
// Process CSS with PostCSS if exists
|
|
175
|
-
const cssPath = path.join(srcPath, "index.css");
|
|
176
|
-
if (fs.existsSync(cssPath)) {
|
|
177
|
-
const outCssFile = path.join(destDir, "index.css");
|
|
178
|
-
// Check if postcss.config.js exists (Tailwind enabled)
|
|
179
|
-
const postcssConfigPath = path.join(process.cwd(), "postcss.config.js");
|
|
180
|
-
if (fs.existsSync(postcssConfigPath)) {
|
|
181
|
-
// Use PostCSS to process CSS (includes Tailwind)
|
|
182
|
-
try {
|
|
183
|
-
execSync(`npx postcss "${cssPath}" -o "${outCssFile}"${config.build?.minify ? " --no-map" : ""}`, { stdio: "pipe", cwd: process.cwd() });
|
|
184
|
-
}
|
|
185
|
-
catch (error) {
|
|
186
|
-
console.warn(chalk.yellow(`Warning: PostCSS processing failed: ${error.message}`));
|
|
187
|
-
console.log(chalk.gray("Copying CSS as-is..."));
|
|
188
|
-
fs.copyFileSync(cssPath, outCssFile);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
// No PostCSS config - just copy CSS
|
|
193
|
-
fs.copyFileSync(cssPath, outCssFile);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
// Generate package.json with cmssy metadata from block.config.ts
|
|
197
|
-
if (resource.blockConfig) {
|
|
198
|
-
const cmssyMetadata = generatePackageJsonMetadata(resource.blockConfig, resource.type);
|
|
199
|
-
const outputPackageJson = {
|
|
200
|
-
...resource.packageJson,
|
|
201
|
-
cmssy: cmssyMetadata,
|
|
202
|
-
};
|
|
203
|
-
fs.writeFileSync(path.join(destDir, "package.json"), JSON.stringify(outputPackageJson, null, 2) + "\n");
|
|
204
|
-
// Generate TypeScript types
|
|
205
|
-
await generateTypes(resource.path, resource.blockConfig.schema);
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
// Fallback: copy package.json as-is (shouldn't happen after migration)
|
|
209
|
-
fs.copyFileSync(path.join(resource.path, "package.json"), path.join(destDir, "package.json"));
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
61
|
//# sourceMappingURL=build.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,7 +36,7 @@ export async function configureCommand(options) {
|
|
|
36
36
|
});
|
|
37
37
|
console.log(chalk.green("\n✓ Configuration saved to .env\n"));
|
|
38
38
|
console.log(chalk.cyan("Next steps:\n"));
|
|
39
|
-
console.log(chalk.white(" cmssy
|
|
40
|
-
console.log(chalk.white(" cmssy sync
|
|
39
|
+
console.log(chalk.white(" cmssy publish --all --marketplace # Publish to marketplace"));
|
|
40
|
+
console.log(chalk.white(" cmssy sync # Pull blocks from Cmssy\n"));
|
|
41
41
|
}
|
|
42
42
|
//# sourceMappingURL=configure.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../../src/commands/configure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAM5D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAyB;IAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAEzD,MAAM,cAAc,GAAG,UAAU,EAAE,CAAC;IAEpC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACpC;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,gBAAgB;YACzB,OAAO,EACL,OAAO,CAAC,MAAM;gBACd,cAAc,CAAC,MAAM;gBACrB,8BAA8B;SACjC;QACD;YACE,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,0CAA0C;YACnD,OAAO,EAAE,cAAc,CAAC,QAAQ,IAAI,SAAS;YAC7C,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;gBAClB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;oBAChC,OAAO,gCAAgC,CAAC;gBAC1C,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC7B,OAAO,+BAA+B,CAAC;gBACzC,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF;KACF,CAAC,CAAC;IAEH,eAAe;IACf,UAAU,CAAC;QACT,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../../src/commands/configure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAM5D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAyB;IAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAEzD,MAAM,cAAc,GAAG,UAAU,EAAE,CAAC;IAEpC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACpC;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,gBAAgB;YACzB,OAAO,EACL,OAAO,CAAC,MAAM;gBACd,cAAc,CAAC,MAAM;gBACrB,8BAA8B;SACjC;QACD;YACE,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,0CAA0C;YACnD,OAAO,EAAE,cAAc,CAAC,QAAQ,IAAI,SAAS;YAC7C,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;gBAClB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;oBAChC,OAAO,gCAAgC,CAAC;gBAC1C,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC7B,OAAO,+BAA+B,CAAC;gBACzC,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF;KACF,CAAC,CAAC;IAEH,eAAe;IACf,UAAU,CAAC;QACT,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAC9E,CAAC;IACF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAChF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAgBA,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAgBA,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAKD,wBAAsB,UAAU,CAAC,OAAO,EAAE,UAAU,iBAwXnD"}
|
package/dist/commands/dev.js
CHANGED
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import { exec
|
|
2
|
+
import { exec } from "child_process";
|
|
3
3
|
import chokidar from "chokidar";
|
|
4
|
-
import { build } from "esbuild";
|
|
5
4
|
import express from "express";
|
|
6
5
|
import fs from "fs-extra";
|
|
7
6
|
import { GraphQLClient } from "graphql-request";
|
|
8
7
|
import ora from "ora";
|
|
9
8
|
import path from "path";
|
|
10
9
|
import { fileURLToPath } from "url";
|
|
11
|
-
import { loadBlockConfig
|
|
12
|
-
import {
|
|
10
|
+
import { loadBlockConfig } from "../utils/block-config.js";
|
|
11
|
+
import { buildResource } from "../utils/builder.js";
|
|
12
|
+
import { loadConfig } from "../utils/cmssy-config.js";
|
|
13
13
|
import { loadConfig as loadEnvConfig } from "../utils/config.js";
|
|
14
|
+
import { scanResources } from "../utils/scanner.js";
|
|
14
15
|
import { generateTypes } from "../utils/type-generator.js";
|
|
15
16
|
export async function devCommand(options) {
|
|
16
17
|
const spinner = ora("Starting development server...").start();
|
|
17
18
|
try {
|
|
18
19
|
const config = await loadConfig();
|
|
19
20
|
const port = parseInt(options.port, 10);
|
|
20
|
-
// Scan for blocks and templates
|
|
21
|
-
const resources = await scanResources(
|
|
21
|
+
// Scan for blocks and templates (lenient mode - warnings only)
|
|
22
|
+
const resources = await scanResources({
|
|
23
|
+
strict: false,
|
|
24
|
+
loadConfig: true,
|
|
25
|
+
validateSchema: true,
|
|
26
|
+
loadPreview: true,
|
|
27
|
+
requirePackageJson: true,
|
|
28
|
+
});
|
|
22
29
|
if (resources.length === 0) {
|
|
23
30
|
spinner.warn("No blocks or templates found");
|
|
24
31
|
console.log(chalk.yellow("\nCreate your first block:\n"));
|
|
@@ -275,7 +282,7 @@ export async function devCommand(options) {
|
|
|
275
282
|
console.log(chalk.cyan(` Blocks (${blocks.length})`));
|
|
276
283
|
blocks.forEach((block) => {
|
|
277
284
|
const url = `/preview/block/${block.name}`;
|
|
278
|
-
console.log(chalk.white(` ● ${block.displayName.padEnd(20)} ${url}`));
|
|
285
|
+
console.log(chalk.white(` ● ${(block.displayName || block.name).padEnd(20)} ${url}`));
|
|
279
286
|
});
|
|
280
287
|
console.log("");
|
|
281
288
|
}
|
|
@@ -283,7 +290,7 @@ export async function devCommand(options) {
|
|
|
283
290
|
console.log(chalk.cyan(` Templates (${templates.length})`));
|
|
284
291
|
templates.forEach((template) => {
|
|
285
292
|
const url = `/preview/template/${template.name}`;
|
|
286
|
-
console.log(chalk.white(` ● ${template.displayName.padEnd(20)} ${url}`));
|
|
293
|
+
console.log(chalk.white(` ● ${(template.displayName || template.name).padEnd(20)} ${url}`));
|
|
287
294
|
});
|
|
288
295
|
console.log("");
|
|
289
296
|
}
|
|
@@ -298,165 +305,19 @@ export async function devCommand(options) {
|
|
|
298
305
|
process.exit(1);
|
|
299
306
|
}
|
|
300
307
|
}
|
|
301
|
-
async function scanResources() {
|
|
302
|
-
const resources = [];
|
|
303
|
-
// Scan blocks
|
|
304
|
-
const blocksDir = path.join(process.cwd(), "blocks");
|
|
305
|
-
if (fs.existsSync(blocksDir)) {
|
|
306
|
-
const blockDirs = fs
|
|
307
|
-
.readdirSync(blocksDir, { withFileTypes: true })
|
|
308
|
-
.filter((dirent) => dirent.isDirectory())
|
|
309
|
-
.map((dirent) => dirent.name);
|
|
310
|
-
for (const blockName of blockDirs) {
|
|
311
|
-
const blockPath = path.join(blocksDir, blockName);
|
|
312
|
-
// Try loading block.config.ts
|
|
313
|
-
const blockConfig = await loadBlockConfig(blockPath);
|
|
314
|
-
if (!blockConfig) {
|
|
315
|
-
// Check if package.json has cmssy (old format)
|
|
316
|
-
const pkg = getPackageJson(blockPath);
|
|
317
|
-
if (pkg && pkg.cmssy) {
|
|
318
|
-
console.warn(chalk.yellow(`Warning: Block "${blockName}" uses legacy package.json format. Run: cmssy migrate ${blockName}`));
|
|
319
|
-
}
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
// Validate schema
|
|
323
|
-
const validation = await validateSchema(blockConfig.schema, blockPath);
|
|
324
|
-
if (!validation.valid) {
|
|
325
|
-
console.warn(chalk.yellow(`\nValidation warnings in ${blockName}:`));
|
|
326
|
-
validation.errors.forEach((err) => console.warn(chalk.yellow(` - ${err}`)));
|
|
327
|
-
continue;
|
|
328
|
-
}
|
|
329
|
-
// Load package.json for name and version
|
|
330
|
-
const pkg = getPackageJson(blockPath);
|
|
331
|
-
if (!pkg || !pkg.name || !pkg.version) {
|
|
332
|
-
console.warn(chalk.yellow(`Warning: Block "${blockName}" must have package.json with name and version`));
|
|
333
|
-
continue;
|
|
334
|
-
}
|
|
335
|
-
const previewPath = path.join(blockPath, "preview.json");
|
|
336
|
-
const previewData = fs.existsSync(previewPath)
|
|
337
|
-
? fs.readJsonSync(previewPath)
|
|
338
|
-
: {};
|
|
339
|
-
resources.push({
|
|
340
|
-
type: "block",
|
|
341
|
-
name: blockName,
|
|
342
|
-
path: blockPath,
|
|
343
|
-
displayName: blockConfig.name || blockName,
|
|
344
|
-
description: blockConfig.description || pkg.description,
|
|
345
|
-
category: blockConfig.category,
|
|
346
|
-
previewData,
|
|
347
|
-
blockConfig,
|
|
348
|
-
packageJson: pkg,
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
// Scan templates
|
|
353
|
-
const templatesDir = path.join(process.cwd(), "templates");
|
|
354
|
-
if (fs.existsSync(templatesDir)) {
|
|
355
|
-
const templateDirs = fs
|
|
356
|
-
.readdirSync(templatesDir, { withFileTypes: true })
|
|
357
|
-
.filter((dirent) => dirent.isDirectory())
|
|
358
|
-
.map((dirent) => dirent.name);
|
|
359
|
-
for (const templateName of templateDirs) {
|
|
360
|
-
const templatePath = path.join(templatesDir, templateName);
|
|
361
|
-
// Try loading block.config.ts
|
|
362
|
-
const blockConfig = await loadBlockConfig(templatePath);
|
|
363
|
-
if (!blockConfig) {
|
|
364
|
-
// Check if package.json has cmssy (old format)
|
|
365
|
-
const pkg = getPackageJson(templatePath);
|
|
366
|
-
if (pkg && pkg.cmssy) {
|
|
367
|
-
console.warn(chalk.yellow(`Warning: Template "${templateName}" uses legacy package.json format. Run: cmssy migrate ${templateName}`));
|
|
368
|
-
}
|
|
369
|
-
continue;
|
|
370
|
-
}
|
|
371
|
-
// Validate schema
|
|
372
|
-
const validation = await validateSchema(blockConfig.schema, templatePath);
|
|
373
|
-
if (!validation.valid) {
|
|
374
|
-
console.warn(chalk.yellow(`\nValidation warnings in ${templateName}:`));
|
|
375
|
-
validation.errors.forEach((err) => console.warn(chalk.yellow(` - ${err}`)));
|
|
376
|
-
continue;
|
|
377
|
-
}
|
|
378
|
-
// Load package.json for name and version
|
|
379
|
-
const pkg = getPackageJson(templatePath);
|
|
380
|
-
if (!pkg || !pkg.name || !pkg.version) {
|
|
381
|
-
console.warn(chalk.yellow(`Warning: Template "${templateName}" must have package.json with name and version`));
|
|
382
|
-
continue;
|
|
383
|
-
}
|
|
384
|
-
const previewPath = path.join(templatePath, "preview.json");
|
|
385
|
-
const previewData = fs.existsSync(previewPath)
|
|
386
|
-
? fs.readJsonSync(previewPath)
|
|
387
|
-
: {};
|
|
388
|
-
resources.push({
|
|
389
|
-
type: "template",
|
|
390
|
-
name: templateName,
|
|
391
|
-
path: templatePath,
|
|
392
|
-
displayName: blockConfig.name || templateName,
|
|
393
|
-
description: blockConfig.description || pkg.description,
|
|
394
|
-
category: blockConfig.category,
|
|
395
|
-
previewData,
|
|
396
|
-
blockConfig,
|
|
397
|
-
packageJson: pkg,
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
return resources;
|
|
402
|
-
}
|
|
403
308
|
async function buildAllResources(resources, config) {
|
|
404
309
|
const devDir = path.join(process.cwd(), ".cmssy", "dev");
|
|
405
310
|
fs.ensureDirSync(devDir);
|
|
406
311
|
for (const resource of resources) {
|
|
407
|
-
await buildResource(resource,
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
async function buildResource(resource, config, outDir) {
|
|
411
|
-
const srcPath = path.join(resource.path, "src");
|
|
412
|
-
const entryPoint = config.framework === "react"
|
|
413
|
-
? path.join(srcPath, "index.tsx")
|
|
414
|
-
: path.join(srcPath, "index.ts");
|
|
415
|
-
if (!fs.existsSync(entryPoint)) {
|
|
416
|
-
console.warn(chalk.yellow(`Warning: Entry point not found for ${resource.name}`));
|
|
417
|
-
return;
|
|
418
|
-
}
|
|
419
|
-
const outFile = path.join(outDir, `${resource.type}.${resource.name}.js`);
|
|
420
|
-
try {
|
|
421
|
-
await build({
|
|
422
|
-
entryPoints: [entryPoint],
|
|
423
|
-
bundle: true,
|
|
424
|
-
format: "esm",
|
|
425
|
-
outfile: outFile,
|
|
426
|
-
jsx: "transform",
|
|
312
|
+
await buildResource(resource, devDir, {
|
|
313
|
+
framework: config.framework,
|
|
427
314
|
minify: false,
|
|
428
315
|
sourcemap: true,
|
|
429
|
-
|
|
430
|
-
|
|
316
|
+
outputMode: "flat",
|
|
317
|
+
generatePackageJson: false,
|
|
318
|
+
generateTypes: false, // Types are generated during scan
|
|
319
|
+
strict: false,
|
|
431
320
|
});
|
|
432
|
-
// Process CSS with PostCSS if exists
|
|
433
|
-
const cssPath = path.join(srcPath, "index.css");
|
|
434
|
-
if (fs.existsSync(cssPath)) {
|
|
435
|
-
const outCssFile = path.join(outDir, `${resource.type}.${resource.name}.css`);
|
|
436
|
-
// Check if postcss.config.js exists (Tailwind enabled)
|
|
437
|
-
const postcssConfigPath = path.join(process.cwd(), "postcss.config.js");
|
|
438
|
-
if (fs.existsSync(postcssConfigPath)) {
|
|
439
|
-
// Use PostCSS to process CSS (includes Tailwind)
|
|
440
|
-
try {
|
|
441
|
-
execSync(`npx postcss "${cssPath}" -o "${outCssFile}"`, {
|
|
442
|
-
stdio: "pipe",
|
|
443
|
-
cwd: process.cwd(),
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
catch (error) {
|
|
447
|
-
console.warn(chalk.yellow(`Warning: PostCSS processing failed for ${resource.name}: ${error.message}`));
|
|
448
|
-
console.log(chalk.gray("Copying CSS as-is..."));
|
|
449
|
-
fs.copyFileSync(cssPath, outCssFile);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
else {
|
|
453
|
-
// No PostCSS config - just copy CSS
|
|
454
|
-
fs.copyFileSync(cssPath, outCssFile);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
catch (error) {
|
|
459
|
-
console.error(chalk.red(`Build error for ${resource.name}:`), error);
|
|
460
321
|
}
|
|
461
322
|
}
|
|
462
323
|
function setupWatcher(resources, config, sseClients) {
|
|
@@ -524,7 +385,15 @@ function setupWatcher(resources, config, sseClients) {
|
|
|
524
385
|
}
|
|
525
386
|
}
|
|
526
387
|
console.log(chalk.blue(`♻ Rebuilding ${resource.name}...`));
|
|
527
|
-
await buildResource(resource,
|
|
388
|
+
await buildResource(resource, devDir, {
|
|
389
|
+
framework: config.framework,
|
|
390
|
+
minify: false,
|
|
391
|
+
sourcemap: true,
|
|
392
|
+
outputMode: "flat",
|
|
393
|
+
generatePackageJson: false,
|
|
394
|
+
generateTypes: false, // Already generated above
|
|
395
|
+
strict: false,
|
|
396
|
+
});
|
|
528
397
|
console.log(chalk.green(`✓ ${resource.name} rebuilt\n`));
|
|
529
398
|
// Notify SSE clients to reload
|
|
530
399
|
sseClients.forEach((client) => {
|
|
@@ -554,124 +423,6 @@ function setupWatcher(resources, config, sseClients) {
|
|
|
554
423
|
});
|
|
555
424
|
return watcher;
|
|
556
425
|
}
|
|
557
|
-
function generateIndexHTML(resources) {
|
|
558
|
-
const blocks = resources.filter((r) => r.type === "block");
|
|
559
|
-
const templates = resources.filter((r) => r.type === "template");
|
|
560
|
-
return `
|
|
561
|
-
<!DOCTYPE html>
|
|
562
|
-
<html lang="en">
|
|
563
|
-
<head>
|
|
564
|
-
<meta charset="UTF-8">
|
|
565
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
566
|
-
<title>Cmssy Dev Server</title>
|
|
567
|
-
<style>
|
|
568
|
-
/* Only reset specific elements, NOT all */
|
|
569
|
-
body {
|
|
570
|
-
margin: 0;
|
|
571
|
-
padding: 2rem;
|
|
572
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
573
|
-
background: #f5f5f5;
|
|
574
|
-
box-sizing: border-box;
|
|
575
|
-
}
|
|
576
|
-
.container { max-width: 1200px; margin: 0 auto; }
|
|
577
|
-
h1 { font-size: 2.5rem; margin-bottom: 0.5rem; }
|
|
578
|
-
.subtitle { color: #666; margin-bottom: 3rem; }
|
|
579
|
-
.section { margin-bottom: 3rem; }
|
|
580
|
-
.section-title { font-size: 1.5rem; margin-bottom: 1rem; color: #333; }
|
|
581
|
-
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1.5rem; }
|
|
582
|
-
.card {
|
|
583
|
-
background: white;
|
|
584
|
-
border-radius: 8px;
|
|
585
|
-
padding: 1.5rem;
|
|
586
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
587
|
-
transition: transform 0.2s, box-shadow 0.2s;
|
|
588
|
-
}
|
|
589
|
-
.card:hover {
|
|
590
|
-
transform: translateY(-4px);
|
|
591
|
-
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
592
|
-
}
|
|
593
|
-
.card-title { font-size: 1.25rem; margin-bottom: 0.5rem; }
|
|
594
|
-
.card-desc { color: #666; font-size: 0.9rem; margin-bottom: 1rem; }
|
|
595
|
-
.card-category {
|
|
596
|
-
display: inline-block;
|
|
597
|
-
padding: 0.25rem 0.75rem;
|
|
598
|
-
background: #e3f2fd;
|
|
599
|
-
color: #1976d2;
|
|
600
|
-
border-radius: 4px;
|
|
601
|
-
font-size: 0.8rem;
|
|
602
|
-
margin-bottom: 1rem;
|
|
603
|
-
}
|
|
604
|
-
.card-link {
|
|
605
|
-
display: inline-block;
|
|
606
|
-
padding: 0.5rem 1rem;
|
|
607
|
-
background: #667eea;
|
|
608
|
-
color: white;
|
|
609
|
-
text-decoration: none;
|
|
610
|
-
border-radius: 4px;
|
|
611
|
-
font-weight: 500;
|
|
612
|
-
}
|
|
613
|
-
.card-link:hover { background: #5568d3; }
|
|
614
|
-
.empty {
|
|
615
|
-
text-align: center;
|
|
616
|
-
padding: 3rem;
|
|
617
|
-
color: #999;
|
|
618
|
-
}
|
|
619
|
-
</style>
|
|
620
|
-
</head>
|
|
621
|
-
<body>
|
|
622
|
-
<div class="container">
|
|
623
|
-
<h1>🔨 Cmssy</h1>
|
|
624
|
-
<p class="subtitle">Development Server</p>
|
|
625
|
-
|
|
626
|
-
${blocks.length > 0
|
|
627
|
-
? `
|
|
628
|
-
<div class="section">
|
|
629
|
-
<h2 class="section-title">Blocks (${blocks.length})</h2>
|
|
630
|
-
<div class="grid">
|
|
631
|
-
${blocks
|
|
632
|
-
.map((block) => `
|
|
633
|
-
<div class="card">
|
|
634
|
-
<h3 class="card-title">${block.displayName}</h3>
|
|
635
|
-
${block.description
|
|
636
|
-
? `<p class="card-desc">${block.description}</p>`
|
|
637
|
-
: ""}
|
|
638
|
-
${block.category
|
|
639
|
-
? `<div class="card-category">${block.category}</div>`
|
|
640
|
-
: ""}
|
|
641
|
-
<a href="/preview/block/${block.name}" class="card-link">Preview →</a>
|
|
642
|
-
</div>
|
|
643
|
-
`)
|
|
644
|
-
.join("")}
|
|
645
|
-
</div>
|
|
646
|
-
</div>
|
|
647
|
-
`
|
|
648
|
-
: '<div class="empty">No blocks found. Create one with: <code>npx cmssy create block my-block</code></div>'}
|
|
649
|
-
|
|
650
|
-
${templates.length > 0
|
|
651
|
-
? `
|
|
652
|
-
<div class="section">
|
|
653
|
-
<h2 class="section-title">Templates (${templates.length})</h2>
|
|
654
|
-
<div class="grid">
|
|
655
|
-
${templates
|
|
656
|
-
.map((template) => `
|
|
657
|
-
<div class="card">
|
|
658
|
-
<h3 class="card-title">${template.displayName}</h3>
|
|
659
|
-
${template.description
|
|
660
|
-
? `<p class="card-desc">${template.description}</p>`
|
|
661
|
-
: ""}
|
|
662
|
-
<a href="/preview/template/${template.name}" class="card-link">Preview →</a>
|
|
663
|
-
</div>
|
|
664
|
-
`)
|
|
665
|
-
.join("")}
|
|
666
|
-
</div>
|
|
667
|
-
</div>
|
|
668
|
-
`
|
|
669
|
-
: ""}
|
|
670
|
-
</div>
|
|
671
|
-
</body>
|
|
672
|
-
</html>
|
|
673
|
-
`;
|
|
674
|
-
}
|
|
675
426
|
// Execute publish command asynchronously
|
|
676
427
|
async function executePublish(taskId, resource, target, workspaceId, versionBump, publishTasks) {
|
|
677
428
|
const task = publishTasks.get(taskId);
|