@simplysm/sd-cli 13.0.69 → 13.0.71
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/README.md +10 -957
- package/dist/builders/BaseBuilder.d.ts +23 -23
- package/dist/builders/BaseBuilder.d.ts.map +1 -1
- package/dist/builders/BaseBuilder.js +15 -15
- package/dist/builders/DtsBuilder.d.ts +4 -4
- package/dist/builders/DtsBuilder.js +1 -1
- package/dist/builders/LibraryBuilder.d.ts +3 -3
- package/dist/builders/types.d.ts +10 -10
- package/dist/capacitor/capacitor.d.ts +36 -36
- package/dist/capacitor/capacitor.js +63 -63
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/add-client.d.ts +8 -8
- package/dist/commands/add-client.js +15 -15
- package/dist/commands/add-client.js.map +1 -1
- package/dist/commands/add-server.d.ts +9 -9
- package/dist/commands/add-server.js +13 -13
- package/dist/commands/add-server.js.map +1 -1
- package/dist/commands/build.d.ts +9 -9
- package/dist/commands/check.js +3 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/dev.d.ts +9 -9
- package/dist/commands/device.d.ts +9 -9
- package/dist/commands/device.d.ts.map +1 -1
- package/dist/commands/device.js +17 -17
- package/dist/commands/device.js.map +1 -1
- package/dist/commands/init.d.ts +6 -6
- package/dist/commands/init.js +12 -12
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/lint.d.ts +23 -23
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +25 -25
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/publish.d.ts +13 -13
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +61 -61
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/replace-deps.d.ts +3 -3
- package/dist/commands/replace-deps.d.ts.map +1 -1
- package/dist/commands/replace-deps.js +1 -1
- package/dist/commands/replace-deps.js.map +1 -1
- package/dist/commands/typecheck.d.ts +20 -20
- package/dist/commands/typecheck.d.ts.map +1 -1
- package/dist/commands/typecheck.js +20 -20
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/commands/watch.d.ts +7 -7
- package/dist/electron/electron.d.ts +27 -27
- package/dist/electron/electron.js +32 -32
- package/dist/electron/electron.js.map +1 -1
- package/dist/infra/ResultCollector.d.ts +9 -9
- package/dist/infra/ResultCollector.js +5 -5
- package/dist/infra/SignalHandler.d.ts +7 -7
- package/dist/infra/SignalHandler.js +4 -4
- package/dist/infra/WorkerManager.d.ts +14 -14
- package/dist/infra/WorkerManager.js +11 -11
- package/dist/orchestrators/BuildOrchestrator.d.ts +19 -19
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +26 -26
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevOrchestrator.d.ts +25 -25
- package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevOrchestrator.js +30 -30
- package/dist/orchestrators/DevOrchestrator.js.map +1 -1
- package/dist/orchestrators/WatchOrchestrator.d.ts +13 -13
- package/dist/orchestrators/WatchOrchestrator.js +17 -17
- package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
- package/dist/sd-cli-entry.d.ts +2 -2
- package/dist/sd-cli-entry.js +38 -38
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.d.ts +2 -2
- package/dist/sd-cli.js +1 -1
- package/dist/sd-cli.js.map +1 -1
- package/dist/sd-config.types.d.ts +84 -84
- package/dist/sd-config.types.d.ts.map +1 -1
- package/dist/utils/build-env.d.ts +1 -1
- package/dist/utils/config-editor.d.ts +5 -5
- package/dist/utils/config-editor.js +2 -2
- package/dist/utils/config-editor.js.map +1 -1
- package/dist/utils/copy-public.d.ts +9 -9
- package/dist/utils/copy-src.d.ts +9 -9
- package/dist/utils/esbuild-config.d.ts +30 -30
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/output-utils.d.ts +6 -6
- package/dist/utils/package-utils.d.ts +6 -6
- package/dist/utils/package-utils.js +1 -1
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/rebuild-manager.js +3 -3
- package/dist/utils/rebuild-manager.js.map +1 -1
- package/dist/utils/replace-deps.d.ts +25 -25
- package/dist/utils/replace-deps.js +3 -3
- package/dist/utils/replace-deps.js.map +1 -1
- package/dist/utils/sd-config.d.ts +3 -3
- package/dist/utils/sd-config.js +3 -3
- package/dist/utils/sd-config.js.map +1 -1
- package/dist/utils/tailwind-config-deps.d.ts +3 -3
- package/dist/utils/template.d.ts +8 -8
- package/dist/utils/tsconfig.d.ts +16 -16
- package/dist/utils/tsconfig.js +2 -2
- package/dist/utils/tsconfig.js.map +1 -1
- package/dist/utils/typecheck-serialization.d.ts +8 -8
- package/dist/utils/vite-config.d.ts +8 -8
- package/dist/utils/vite-config.d.ts.map +1 -1
- package/dist/utils/vite-config.js +3 -3
- package/dist/utils/worker-events.d.ts +12 -12
- package/dist/utils/worker-events.d.ts.map +1 -1
- package/dist/utils/worker-utils.d.ts +3 -3
- package/dist/utils/worker-utils.js +2 -2
- package/dist/utils/worker-utils.js.map +1 -1
- package/dist/workers/client.worker.d.ts +14 -14
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +1 -1
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/dts.worker.d.ts +13 -13
- package/dist/workers/dts.worker.d.ts.map +1 -1
- package/dist/workers/dts.worker.js +3 -3
- package/dist/workers/dts.worker.js.map +1 -1
- package/dist/workers/library.worker.d.ts +12 -12
- package/dist/workers/library.worker.js +1 -1
- package/dist/workers/library.worker.js.map +1 -1
- package/dist/workers/lint.worker.d.ts +1 -1
- package/dist/workers/server-runtime.worker.d.ts +6 -6
- package/dist/workers/server-runtime.worker.js +6 -6
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/dist/workers/server.worker.d.ts +20 -20
- package/dist/workers/server.worker.d.ts.map +1 -1
- package/dist/workers/server.worker.js +6 -6
- package/dist/workers/server.worker.js.map +1 -1
- package/package.json +8 -7
- package/src/builders/BaseBuilder.ts +33 -33
- package/src/builders/DtsBuilder.ts +5 -5
- package/src/builders/LibraryBuilder.ts +9 -9
- package/src/builders/types.ts +10 -10
- package/src/capacitor/capacitor.ts +119 -119
- package/src/commands/add-client.ts +31 -31
- package/src/commands/add-server.ts +34 -34
- package/src/commands/build.ts +9 -9
- package/src/commands/check.ts +5 -5
- package/src/commands/dev.ts +9 -9
- package/src/commands/device.ts +30 -30
- package/src/commands/init.ts +25 -25
- package/src/commands/lint.ts +64 -64
- package/src/commands/publish.ts +139 -139
- package/src/commands/replace-deps.ts +4 -4
- package/src/commands/typecheck.ts +74 -74
- package/src/commands/watch.ts +7 -7
- package/src/electron/electron.ts +51 -51
- package/src/infra/ResultCollector.ts +9 -9
- package/src/infra/SignalHandler.ts +7 -7
- package/src/infra/WorkerManager.ts +14 -14
- package/src/orchestrators/BuildOrchestrator.ts +76 -76
- package/src/orchestrators/DevOrchestrator.ts +88 -88
- package/src/orchestrators/WatchOrchestrator.ts +39 -39
- package/src/sd-cli-entry.ts +43 -43
- package/src/sd-cli.ts +15 -15
- package/src/sd-config.types.ts +85 -85
- package/src/utils/build-env.ts +1 -1
- package/src/utils/config-editor.ts +19 -19
- package/src/utils/copy-public.ts +17 -17
- package/src/utils/copy-src.ts +11 -11
- package/src/utils/esbuild-config.ts +33 -33
- package/src/utils/output-utils.ts +11 -11
- package/src/utils/package-utils.ts +12 -12
- package/src/utils/rebuild-manager.ts +3 -3
- package/src/utils/replace-deps.ts +361 -361
- package/src/utils/sd-config.ts +44 -44
- package/src/utils/tailwind-config-deps.ts +98 -98
- package/src/utils/template.ts +56 -56
- package/src/utils/tsconfig.ts +127 -127
- package/src/utils/typecheck-serialization.ts +86 -86
- package/src/utils/vite-config.ts +341 -341
- package/src/utils/worker-events.ts +16 -16
- package/src/utils/worker-utils.ts +45 -45
- package/src/workers/client.worker.ts +34 -34
- package/src/workers/dts.worker.ts +467 -467
- package/src/workers/library.worker.ts +314 -314
- package/src/workers/lint.worker.ts +16 -16
- package/src/workers/server-runtime.worker.ts +157 -157
- package/src/workers/server.worker.ts +572 -572
- package/templates/add-client/__CLIENT__/package.json.hbs +1 -1
- package/templates/add-server/__SERVER__/package.json.hbs +2 -2
- package/templates/init/package.json.hbs +3 -3
- package/tests/config-editor.spec.ts +160 -0
- package/tests/copy-src.spec.ts +50 -0
- package/tests/get-compiler-options-for-package.spec.ts +139 -0
- package/tests/get-package-source-files.spec.ts +181 -0
- package/tests/get-types-from-package-json.spec.ts +107 -0
- package/tests/infra/ResultCollector.spec.ts +39 -0
- package/tests/infra/SignalHandler.spec.ts +38 -0
- package/tests/infra/WorkerManager.spec.ts +97 -0
- package/tests/load-ignore-patterns.spec.ts +188 -0
- package/tests/load-sd-config.spec.ts +137 -0
- package/tests/package-utils.spec.ts +188 -0
- package/tests/parse-root-tsconfig.spec.ts +89 -0
- package/tests/replace-deps.spec.ts +308 -0
- package/tests/run-lint.spec.ts +415 -0
- package/tests/run-typecheck.spec.ts +653 -0
- package/tests/run-watch.spec.ts +75 -0
- package/tests/sd-cli.spec.ts +330 -0
- package/tests/tailwind-config-deps.spec.ts +30 -0
- package/tests/template.spec.ts +70 -0
- package/tests/utils/rebuild-manager.spec.ts +43 -0
- package/tests/write-changed-output-files.spec.ts +97 -0
|
@@ -10,7 +10,7 @@ import { findPackageRoot } from "../utils/package-utils";
|
|
|
10
10
|
//#region Types
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Add-client
|
|
13
|
+
* Add-client command options
|
|
14
14
|
*/
|
|
15
15
|
export interface AddClientOptions {}
|
|
16
16
|
|
|
@@ -22,56 +22,56 @@ export interface AddClientOptions {}
|
|
|
22
22
|
//#region Main
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* Add client package to the project.
|
|
26
26
|
*
|
|
27
|
-
* 1.
|
|
28
|
-
* 2.
|
|
29
|
-
* 3.
|
|
30
|
-
* 4. Handlebars
|
|
31
|
-
* 5. sd.config.ts
|
|
32
|
-
* 6. eslint.config.ts
|
|
27
|
+
* 1. Verify project root (sd.config.ts exists)
|
|
28
|
+
* 2. Interactive prompt (name suffix, router usage)
|
|
29
|
+
* 3. Check for duplicate package directory
|
|
30
|
+
* 4. Render Handlebars template
|
|
31
|
+
* 5. Add package entry to sd.config.ts (ts-morph)
|
|
32
|
+
* 6. Add tailwind configuration to eslint.config.ts (if first client)
|
|
33
33
|
* 7. pnpm install
|
|
34
34
|
*/
|
|
35
35
|
export async function runAddClient(_options: AddClientOptions): Promise<void> {
|
|
36
36
|
const cwd = process.cwd();
|
|
37
37
|
const logger = consola.withTag("sd:cli:add-client");
|
|
38
38
|
|
|
39
|
-
// 1.
|
|
39
|
+
// 1. Verify project root
|
|
40
40
|
if (!fs.existsSync(path.join(cwd, "sd.config.ts"))) {
|
|
41
|
-
consola.error("sd.config.ts
|
|
41
|
+
consola.error("Cannot find sd.config.ts. Please run from the project root.");
|
|
42
42
|
process.exitCode = 1;
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
//
|
|
46
|
+
// Project name
|
|
47
47
|
const projectName = path.basename(cwd);
|
|
48
48
|
|
|
49
|
-
// 2.
|
|
49
|
+
// 2. Interactive prompt
|
|
50
50
|
const clientSuffix = await input({
|
|
51
|
-
message: "
|
|
51
|
+
message: "Enter client name suffix (client-___):",
|
|
52
52
|
validate: (value) => {
|
|
53
|
-
if (!value.trim()) return "
|
|
54
|
-
if (!/^[a-z][a-z0-9-]*$/.test(value)) return "
|
|
53
|
+
if (!value.trim()) return "Please enter a name.";
|
|
54
|
+
if (!/^[a-z][a-z0-9-]*$/.test(value)) return "Only lowercase letters, numbers, and hyphens are allowed.";
|
|
55
55
|
return true;
|
|
56
56
|
},
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
const useRouter = await confirm({
|
|
60
|
-
message: "
|
|
60
|
+
message: "Do you want to use router?",
|
|
61
61
|
default: true,
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
const clientName = `client-${clientSuffix}`;
|
|
65
65
|
|
|
66
|
-
// 3.
|
|
66
|
+
// 3. Check for duplicate package directory
|
|
67
67
|
const packageDir = path.join(cwd, "packages", clientName);
|
|
68
68
|
if (fs.existsSync(packageDir)) {
|
|
69
|
-
consola.error(`packages/${clientName}
|
|
69
|
+
consola.error(`packages/${clientName} directory already exists.`);
|
|
70
70
|
process.exitCode = 1;
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
// 4.
|
|
74
|
+
// 4. Render template
|
|
75
75
|
const pkgRoot = findPackageRoot(import.meta.dirname);
|
|
76
76
|
const templateDir = path.join(pkgRoot, "templates", "add-client");
|
|
77
77
|
|
|
@@ -86,39 +86,39 @@ export async function runAddClient(_options: AddClientOptions): Promise<void> {
|
|
|
86
86
|
__CLIENT__: clientName,
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
logger.info(
|
|
89
|
+
logger.info(`Creating ${clientName} package...`);
|
|
90
90
|
await renderTemplateDir(templateDir, path.join(cwd, "packages"), context, dirReplacements);
|
|
91
|
-
logger.success(`packages/${clientName}
|
|
91
|
+
logger.success(`packages/${clientName} created successfully`);
|
|
92
92
|
|
|
93
|
-
// 5. sd.config.ts
|
|
93
|
+
// 5. Update sd.config.ts
|
|
94
94
|
const sdConfigPath = path.join(cwd, "sd.config.ts");
|
|
95
95
|
const added = addPackageToSdConfig(sdConfigPath, clientName, { target: "client" });
|
|
96
96
|
if (added) {
|
|
97
|
-
logger.success("sd.config.ts
|
|
97
|
+
logger.success("sd.config.ts updated successfully");
|
|
98
98
|
} else {
|
|
99
|
-
consola.warn(`"${clientName}"
|
|
99
|
+
consola.warn(`"${clientName}" already exists in sd.config.ts.`);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
// 6. eslint.config.ts
|
|
102
|
+
// 6. Add tailwind configuration to eslint.config.ts (if first client)
|
|
103
103
|
const eslintConfigPath = path.join(cwd, "eslint.config.ts");
|
|
104
104
|
if (fs.existsSync(eslintConfigPath)) {
|
|
105
105
|
const tailwindAdded = addTailwindToEslintConfig(eslintConfigPath, clientName);
|
|
106
106
|
if (tailwindAdded) {
|
|
107
|
-
logger.success("eslint.config.ts
|
|
107
|
+
logger.success("Added tailwind configuration to eslint.config.ts");
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// 7. pnpm install
|
|
112
|
-
logger.info("pnpm install
|
|
112
|
+
logger.info("Running pnpm install...");
|
|
113
113
|
await execa("pnpm", ["install"], { cwd });
|
|
114
|
-
logger.success("pnpm install
|
|
114
|
+
logger.success("pnpm install completed");
|
|
115
115
|
|
|
116
|
-
//
|
|
116
|
+
// Done
|
|
117
117
|
consola.box(
|
|
118
118
|
[
|
|
119
|
-
|
|
119
|
+
`Client "${clientName}" has been added!`,
|
|
120
120
|
"",
|
|
121
|
-
` pnpm dev ${clientName}
|
|
121
|
+
` pnpm dev ${clientName} Run development server`,
|
|
122
122
|
].join("\n"),
|
|
123
123
|
);
|
|
124
124
|
}
|
|
@@ -10,7 +10,7 @@ import { findPackageRoot } from "../utils/package-utils";
|
|
|
10
10
|
//#region Types
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Add-server
|
|
13
|
+
* Add-server command options
|
|
14
14
|
*/
|
|
15
15
|
export interface AddServerOptions {}
|
|
16
16
|
|
|
@@ -19,13 +19,13 @@ export interface AddServerOptions {}
|
|
|
19
19
|
//#region Utilities
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* sd.config.ts
|
|
22
|
+
* Reads sd.config.ts and returns a list of package names with target "client".
|
|
23
23
|
*/
|
|
24
24
|
function findClientPackages(sdConfigPath: string): string[] {
|
|
25
25
|
const content = fs.readFileSync(sdConfigPath, "utf-8");
|
|
26
26
|
const clients: string[] = [];
|
|
27
27
|
|
|
28
|
-
//
|
|
28
|
+
// Find client packages using simple pattern matching
|
|
29
29
|
const regex = /"([^"]+)":\s*\{[^}]*target:\s*"client"/g;
|
|
30
30
|
let match: RegExpExecArray | null;
|
|
31
31
|
while ((match = regex.exec(content)) != null) {
|
|
@@ -39,62 +39,62 @@ function findClientPackages(sdConfigPath: string): string[] {
|
|
|
39
39
|
//#region Main
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
42
|
+
* Adds a server package to the project.
|
|
43
43
|
*
|
|
44
|
-
* 1.
|
|
45
|
-
* 2.
|
|
46
|
-
* 3.
|
|
47
|
-
* 4. Handlebars
|
|
48
|
-
* 5. sd.config.ts
|
|
49
|
-
* 6.
|
|
50
|
-
* 7. pnpm install
|
|
44
|
+
* 1. Verify project root
|
|
45
|
+
* 2. Interactive prompts (name suffix, client selection)
|
|
46
|
+
* 3. Check for duplicate package directory
|
|
47
|
+
* 4. Render Handlebars template
|
|
48
|
+
* 5. Add server package entry to sd.config.ts
|
|
49
|
+
* 6. Update server field in selected clients
|
|
50
|
+
* 7. Run pnpm install
|
|
51
51
|
*/
|
|
52
52
|
export async function runAddServer(_options: AddServerOptions): Promise<void> {
|
|
53
53
|
const cwd = process.cwd();
|
|
54
54
|
const logger = consola.withTag("sd:cli:add-server");
|
|
55
55
|
|
|
56
|
-
// 1.
|
|
56
|
+
// 1. Verify project root
|
|
57
57
|
const sdConfigPath = path.join(cwd, "sd.config.ts");
|
|
58
58
|
if (!fs.existsSync(sdConfigPath)) {
|
|
59
|
-
consola.error("sd.config.ts
|
|
59
|
+
consola.error("Cannot find sd.config.ts. Please run this from the project root.");
|
|
60
60
|
process.exitCode = 1;
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
const projectName = path.basename(cwd);
|
|
65
65
|
|
|
66
|
-
// 2.
|
|
66
|
+
// 2. Interactive prompts
|
|
67
67
|
const serverSuffix = await input({
|
|
68
|
-
message: '
|
|
68
|
+
message: 'Server name suffix (leave empty for "server"):',
|
|
69
69
|
validate: (value) => {
|
|
70
|
-
if (value.trim() === "") return true; //
|
|
71
|
-
if (!/^[a-z][a-z0-9-]*$/.test(value)) return "
|
|
70
|
+
if (value.trim() === "") return true; // Allow empty value
|
|
71
|
+
if (!/^[a-z][a-z0-9-]*$/.test(value)) return "Only lowercase letters, numbers, and hyphens are allowed.";
|
|
72
72
|
return true;
|
|
73
73
|
},
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
const serverName = serverSuffix.trim() === "" ? "server" : `server-${serverSuffix}`;
|
|
77
77
|
|
|
78
|
-
//
|
|
78
|
+
// Client selection (if existing clients are present)
|
|
79
79
|
const clientPackages = findClientPackages(sdConfigPath);
|
|
80
80
|
let selectedClients: string[] = [];
|
|
81
81
|
|
|
82
82
|
if (clientPackages.length > 0) {
|
|
83
83
|
selectedClients = await checkbox({
|
|
84
|
-
message: "
|
|
84
|
+
message: "Select the clients this server will serve:",
|
|
85
85
|
choices: clientPackages.map((name) => ({ name, value: name })),
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
// 3.
|
|
89
|
+
// 3. Check for duplicate package directory
|
|
90
90
|
const packageDir = path.join(cwd, "packages", serverName);
|
|
91
91
|
if (fs.existsSync(packageDir)) {
|
|
92
|
-
consola.error(`packages/${serverName}
|
|
92
|
+
consola.error(`packages/${serverName} directory already exists.`);
|
|
93
93
|
process.exitCode = 1;
|
|
94
94
|
return;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
// 4.
|
|
97
|
+
// 4. Render template
|
|
98
98
|
const pkgRoot = findPackageRoot(import.meta.dirname);
|
|
99
99
|
const templateDir = path.join(pkgRoot, "templates", "add-server");
|
|
100
100
|
|
|
@@ -108,31 +108,31 @@ export async function runAddServer(_options: AddServerOptions): Promise<void> {
|
|
|
108
108
|
__SERVER__: serverName,
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
logger.info(
|
|
111
|
+
logger.info(`Creating ${serverName} package...`);
|
|
112
112
|
await renderTemplateDir(templateDir, path.join(cwd, "packages"), context, dirReplacements);
|
|
113
|
-
logger.success(`packages/${serverName}
|
|
113
|
+
logger.success(`packages/${serverName} created successfully`);
|
|
114
114
|
|
|
115
|
-
// 5. sd.config.ts
|
|
115
|
+
// 5. Add server package to sd.config.ts
|
|
116
116
|
const added = addPackageToSdConfig(sdConfigPath, serverName, { target: "server" });
|
|
117
117
|
if (added) {
|
|
118
|
-
logger.success("sd.config.ts
|
|
118
|
+
logger.success("Server package added to sd.config.ts");
|
|
119
119
|
} else {
|
|
120
|
-
consola.warn(`"${serverName}"
|
|
120
|
+
consola.warn(`"${serverName}" already exists in sd.config.ts.`);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
// 6.
|
|
123
|
+
// 6. Update server field in selected clients
|
|
124
124
|
for (const clientName of selectedClients) {
|
|
125
125
|
setClientServerInSdConfig(sdConfigPath, clientName, serverName);
|
|
126
|
-
logger.info(
|
|
126
|
+
logger.info(`Set ${clientName} server to "${serverName}"`);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
// 7. pnpm install
|
|
130
|
-
logger.info("pnpm install
|
|
129
|
+
// 7. Run pnpm install
|
|
130
|
+
logger.info("Running pnpm install...");
|
|
131
131
|
await execa("pnpm", ["install"], { cwd });
|
|
132
|
-
logger.success("pnpm install
|
|
132
|
+
logger.success("pnpm install completed");
|
|
133
133
|
|
|
134
|
-
//
|
|
135
|
-
consola.box(
|
|
134
|
+
// Done
|
|
135
|
+
consola.box(`Server "${serverName}" has been added!`);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
//#endregion
|
package/src/commands/build.ts
CHANGED
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
} from "../orchestrators/BuildOrchestrator";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Run production build.
|
|
8
8
|
*
|
|
9
|
-
* - `sd.config.ts
|
|
10
|
-
* - lint
|
|
11
|
-
* - dist
|
|
12
|
-
* - `node`/`browser`/`neutral`
|
|
13
|
-
* - `client`
|
|
14
|
-
* -
|
|
9
|
+
* - Load `sd.config.ts` to check build target info per package (required)
|
|
10
|
+
* - Run lint
|
|
11
|
+
* - Clean dist folder (clean build)
|
|
12
|
+
* - `node`/`browser`/`neutral` target: esbuild JS build + dts generation (with type check)
|
|
13
|
+
* - `client` target: Vite production build + typecheck (dts not needed)
|
|
14
|
+
* - Set `process.exitCode = 1` if any step fails
|
|
15
15
|
*
|
|
16
|
-
* @param options - build
|
|
17
|
-
* @returns
|
|
16
|
+
* @param options - build execution options
|
|
17
|
+
* @returns resolves on completion
|
|
18
18
|
*/
|
|
19
19
|
export async function runBuild(options: BuildOrchestratorOptions): Promise<void> {
|
|
20
20
|
const orchestrator = new BuildOrchestrator(options);
|
package/src/commands/check.ts
CHANGED
|
@@ -83,7 +83,7 @@ export async function runCheck(options: CheckOptions): Promise<void> {
|
|
|
83
83
|
const { targets, types } = options;
|
|
84
84
|
const logger = consola.withTag("sd:cli:check");
|
|
85
85
|
|
|
86
|
-
logger.debug("check
|
|
86
|
+
logger.debug("start check", { targets, types });
|
|
87
87
|
|
|
88
88
|
const tasks: Promise<CheckResult>[] = [];
|
|
89
89
|
|
|
@@ -129,11 +129,11 @@ export async function runCheck(options: CheckOptions): Promise<void> {
|
|
|
129
129
|
tasks.push(spawnVitest(targets));
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
logger.start(`check
|
|
132
|
+
logger.start(`running check... (${types.join(", ")})`);
|
|
133
133
|
const results = await Promise.allSettled(tasks);
|
|
134
|
-
logger.success("check
|
|
134
|
+
logger.success("check completed");
|
|
135
135
|
|
|
136
|
-
//
|
|
136
|
+
// Collect results
|
|
137
137
|
const checkResults: CheckResult[] = results.map((r) => {
|
|
138
138
|
if (r.status === "fulfilled") return r.value;
|
|
139
139
|
return {
|
|
@@ -145,7 +145,7 @@ export async function runCheck(options: CheckOptions): Promise<void> {
|
|
|
145
145
|
};
|
|
146
146
|
});
|
|
147
147
|
|
|
148
|
-
//
|
|
148
|
+
// Output by section (guarantee order: typecheck → lint → test)
|
|
149
149
|
const order = ["TYPECHECK", "LINT", "TEST"];
|
|
150
150
|
checkResults.sort((a, b) => order.indexOf(a.name) - order.indexOf(b.name));
|
|
151
151
|
|
package/src/commands/dev.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { DevOrchestrator, type DevOrchestratorOptions } from "../orchestrators/DevOrchestrator";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Client
|
|
4
|
+
* Run Client and Server packages in development mode.
|
|
5
5
|
*
|
|
6
|
-
* - `sd.config.ts
|
|
7
|
-
* - `client`
|
|
8
|
-
* - `server`
|
|
9
|
-
* - Server-Client
|
|
10
|
-
* - Capacitor
|
|
11
|
-
* - SIGINT/SIGTERM
|
|
6
|
+
* - Load `sd.config.ts` to check build target info per package (required)
|
|
7
|
+
* - `client` target: Start Vite dev server
|
|
8
|
+
* - `server` target: Server Build Worker + Server Runtime Worker
|
|
9
|
+
* - Support Server-Client proxy connections
|
|
10
|
+
* - Support Capacitor initialization
|
|
11
|
+
* - Terminate with SIGINT/SIGTERM signals
|
|
12
12
|
*
|
|
13
|
-
* @param options - dev
|
|
14
|
-
* @returns
|
|
13
|
+
* @param options - dev execution options
|
|
14
|
+
* @returns resolves on termination signal
|
|
15
15
|
*/
|
|
16
16
|
export async function runDev(options: DevOrchestratorOptions): Promise<void> {
|
|
17
17
|
const orchestrator = new DevOrchestrator(options);
|
package/src/commands/device.ts
CHANGED
|
@@ -9,14 +9,14 @@ import { Electron } from "../electron/electron";
|
|
|
9
9
|
//#region Types
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Device
|
|
12
|
+
* Device command options
|
|
13
13
|
*/
|
|
14
14
|
export interface DeviceOptions {
|
|
15
|
-
/**
|
|
15
|
+
/** Package name (required) */
|
|
16
16
|
package: string;
|
|
17
|
-
/**
|
|
17
|
+
/** Development server URL (optional, uses server config from sd.config.ts if not specified) */
|
|
18
18
|
url?: string;
|
|
19
|
-
/** sd.config.ts
|
|
19
|
+
/** Additional options to pass to sd.config.ts */
|
|
20
20
|
options: string[];
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -25,42 +25,42 @@ export interface DeviceOptions {
|
|
|
25
25
|
//#region Main
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Runs an app on an Android device.
|
|
29
29
|
*
|
|
30
|
-
* -
|
|
31
|
-
* -
|
|
30
|
+
* - Runs app on connected Android device
|
|
31
|
+
* - Connects development server URL to WebView to support Hot Reload
|
|
32
32
|
*
|
|
33
|
-
* @param options - device
|
|
34
|
-
* @returns
|
|
33
|
+
* @param options - device execution options
|
|
34
|
+
* @returns resolves when complete
|
|
35
35
|
*/
|
|
36
36
|
export async function runDevice(options: DeviceOptions): Promise<void> {
|
|
37
37
|
const { package: packageName, url } = options;
|
|
38
38
|
const cwd = process.cwd();
|
|
39
39
|
const logger = consola.withTag("sd:cli:device");
|
|
40
40
|
|
|
41
|
-
logger.debug("device
|
|
41
|
+
logger.debug("device start", { package: packageName, url });
|
|
42
42
|
|
|
43
|
-
// sd.config.ts
|
|
43
|
+
// Load sd.config.ts
|
|
44
44
|
let sdConfig: SdConfig;
|
|
45
45
|
try {
|
|
46
46
|
sdConfig = await loadSdConfig({ cwd, dev: true, opt: options.options });
|
|
47
|
-
logger.debug("sd.config.ts
|
|
47
|
+
logger.debug("sd.config.ts loaded");
|
|
48
48
|
} catch (err) {
|
|
49
|
-
logger.error(`sd.config.ts
|
|
49
|
+
logger.error(`Failed to load sd.config.ts: ${err instanceof Error ? err.message : err}`);
|
|
50
50
|
process.exitCode = 1;
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
//
|
|
54
|
+
// Verify package config
|
|
55
55
|
const pkgConfig = sdConfig.packages[packageName];
|
|
56
56
|
if (pkgConfig == null) {
|
|
57
|
-
logger.error(
|
|
57
|
+
logger.error(`Package not found: ${packageName}`);
|
|
58
58
|
process.exitCode = 1;
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
if (pkgConfig.target !== "client") {
|
|
63
|
-
logger.error(`client
|
|
63
|
+
logger.error(`Only client target packages are supported: ${packageName} (current: ${pkgConfig.target})`);
|
|
64
64
|
process.exitCode = 1;
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
@@ -69,40 +69,40 @@ export async function runDevice(options: DeviceOptions): Promise<void> {
|
|
|
69
69
|
const pkgDir = path.join(cwd, "packages", packageName);
|
|
70
70
|
|
|
71
71
|
if (clientConfig.electron != null) {
|
|
72
|
-
// Electron
|
|
72
|
+
// Run Electron development
|
|
73
73
|
let serverUrl = url;
|
|
74
74
|
if (serverUrl == null) {
|
|
75
75
|
if (typeof clientConfig.server === "number") {
|
|
76
76
|
serverUrl = `http://localhost:${clientConfig.server}/${packageName}/`;
|
|
77
77
|
} else {
|
|
78
78
|
logger.error(
|
|
79
|
-
`--url
|
|
79
|
+
`--url option is required. server is set to package name: ${clientConfig.server}`,
|
|
80
80
|
);
|
|
81
81
|
process.exitCode = 1;
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
logger.debug("
|
|
86
|
+
logger.debug("development server URL", { serverUrl });
|
|
87
87
|
|
|
88
|
-
logger.start(
|
|
88
|
+
logger.start(`Running ${packageName} (electron)...`);
|
|
89
89
|
try {
|
|
90
90
|
const electron = await Electron.create(pkgDir, clientConfig.electron);
|
|
91
91
|
await electron.run(serverUrl);
|
|
92
|
-
logger.success("Electron
|
|
92
|
+
logger.success("Electron execution completed");
|
|
93
93
|
} catch (err) {
|
|
94
|
-
logger.error(`
|
|
94
|
+
logger.error(`Failed to run Electron: ${err instanceof Error ? err.message : err}`);
|
|
95
95
|
process.exitCode = 1;
|
|
96
96
|
}
|
|
97
97
|
} else if (clientConfig.capacitor != null) {
|
|
98
|
-
// Capacitor
|
|
98
|
+
// Run Capacitor device (existing logic)
|
|
99
99
|
let serverUrl = url;
|
|
100
100
|
if (serverUrl == null) {
|
|
101
101
|
if (typeof clientConfig.server === "number") {
|
|
102
102
|
serverUrl = `http://localhost:${clientConfig.server}/${packageName}/capacitor/`;
|
|
103
103
|
} else {
|
|
104
104
|
logger.error(
|
|
105
|
-
`--url
|
|
105
|
+
`--url option is required. server is set to package name: ${clientConfig.server}`,
|
|
106
106
|
);
|
|
107
107
|
process.exitCode = 1;
|
|
108
108
|
return;
|
|
@@ -111,28 +111,28 @@ export async function runDevice(options: DeviceOptions): Promise<void> {
|
|
|
111
111
|
serverUrl = `${serverUrl}/${packageName}/capacitor/`;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
logger.debug("
|
|
114
|
+
logger.debug("development server URL", { serverUrl });
|
|
115
115
|
|
|
116
116
|
const capPath = path.join(pkgDir, ".capacitor");
|
|
117
117
|
if (!(await fsExists(capPath))) {
|
|
118
118
|
logger.error(
|
|
119
|
-
`Capacitor
|
|
119
|
+
`Capacitor project is not initialized. First run 'pnpm watch ${packageName}'.`,
|
|
120
120
|
);
|
|
121
121
|
process.exitCode = 1;
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
logger.start(
|
|
125
|
+
logger.start(`Running ${packageName} (device)...`);
|
|
126
126
|
try {
|
|
127
127
|
const cap = await Capacitor.create(pkgDir, clientConfig.capacitor);
|
|
128
128
|
await cap.runOnDevice(serverUrl);
|
|
129
|
-
logger.success("
|
|
129
|
+
logger.success("Device execution completed");
|
|
130
130
|
} catch (err) {
|
|
131
|
-
logger.error(
|
|
131
|
+
logger.error(`Failed to run device: ${err instanceof Error ? err.message : err}`);
|
|
132
132
|
process.exitCode = 1;
|
|
133
133
|
}
|
|
134
134
|
} else {
|
|
135
|
-
logger.error(`electron
|
|
135
|
+
logger.error(`No electron or capacitor config found: ${packageName}`);
|
|
136
136
|
process.exitCode = 1;
|
|
137
137
|
}
|
|
138
138
|
}
|
package/src/commands/init.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { findPackageRoot } from "../utils/package-utils";
|
|
|
8
8
|
//#region Types
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Init
|
|
11
|
+
* Init command options
|
|
12
12
|
*/
|
|
13
13
|
export interface InitOptions {}
|
|
14
14
|
|
|
@@ -17,7 +17,7 @@ export interface InitOptions {}
|
|
|
17
17
|
//#region Utilities
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* npm
|
|
20
|
+
* Validates npm scope name validity
|
|
21
21
|
*/
|
|
22
22
|
function isValidScopeName(name: string): boolean {
|
|
23
23
|
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
@@ -28,65 +28,65 @@ function isValidScopeName(name: string): boolean {
|
|
|
28
28
|
//#region Main
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
31
|
+
* Initializes a new Simplysm project in the current directory.
|
|
32
32
|
*
|
|
33
|
-
* 1.
|
|
34
|
-
* 2.
|
|
35
|
-
* 3. Handlebars
|
|
36
|
-
* 4. pnpm install
|
|
33
|
+
* 1. Check if directory is empty
|
|
34
|
+
* 2. Validate project name (folder name)
|
|
35
|
+
* 3. Render Handlebars template
|
|
36
|
+
* 4. Run pnpm install
|
|
37
37
|
*/
|
|
38
38
|
export async function runInit(_options: InitOptions): Promise<void> {
|
|
39
39
|
const cwd = process.cwd();
|
|
40
40
|
const logger = consola.withTag("sd:cli:init");
|
|
41
41
|
|
|
42
|
-
// 1.
|
|
42
|
+
// 1. Check if directory is empty (exclude dotfiles/dotfolders)
|
|
43
43
|
const entries = fs.readdirSync(cwd).filter((e) => !e.startsWith("."));
|
|
44
44
|
if (entries.length > 0) {
|
|
45
|
-
consola.error("
|
|
45
|
+
consola.error("Directory is not empty. Please run this from an empty directory.");
|
|
46
46
|
process.exitCode = 1;
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
// 2.
|
|
50
|
+
// 2. Validate project name
|
|
51
51
|
const projectName = path.basename(cwd);
|
|
52
52
|
if (!isValidScopeName(projectName)) {
|
|
53
53
|
consola.error(
|
|
54
|
-
|
|
54
|
+
`Project name "${projectName}" is not valid. Only lowercase letters, numbers, and hyphens are allowed.`,
|
|
55
55
|
);
|
|
56
56
|
process.exitCode = 1;
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
// 3.
|
|
60
|
+
// 3. Render template
|
|
61
61
|
const pkgRoot = findPackageRoot(import.meta.dirname);
|
|
62
62
|
const templateDir = path.join(pkgRoot, "templates", "init");
|
|
63
63
|
|
|
64
64
|
const context = { projectName };
|
|
65
65
|
|
|
66
|
-
logger.info("
|
|
66
|
+
logger.info("Creating project files...");
|
|
67
67
|
await renderTemplateDir(templateDir, cwd, context);
|
|
68
|
-
logger.success("
|
|
68
|
+
logger.success("Project files created successfully");
|
|
69
69
|
|
|
70
|
-
// 4. pnpm install
|
|
71
|
-
logger.info("pnpm install
|
|
70
|
+
// 4. Run pnpm install
|
|
71
|
+
logger.info("Running pnpm install...");
|
|
72
72
|
await execa("pnpm", ["install"], { cwd });
|
|
73
|
-
logger.success("pnpm install
|
|
73
|
+
logger.success("pnpm install completed");
|
|
74
74
|
|
|
75
|
-
// 5. git
|
|
76
|
-
logger.info("git
|
|
75
|
+
// 5. Initialize git repository
|
|
76
|
+
logger.info("Initializing git repository...");
|
|
77
77
|
await execa("git", ["init"], { cwd });
|
|
78
78
|
await execa("git", ["add", "."], { cwd });
|
|
79
79
|
await execa("git", ["commit", "-m", "init"], { cwd });
|
|
80
|
-
logger.success("git
|
|
80
|
+
logger.success("git repository initialized");
|
|
81
81
|
|
|
82
|
-
// 6.
|
|
82
|
+
// 6. Completion message
|
|
83
83
|
consola.box(
|
|
84
84
|
[
|
|
85
|
-
"
|
|
85
|
+
"Project created!",
|
|
86
86
|
"",
|
|
87
|
-
"
|
|
88
|
-
" sd-cli add client
|
|
89
|
-
" sd-cli add server
|
|
87
|
+
"Next steps:",
|
|
88
|
+
" sd-cli add client Add a client package",
|
|
89
|
+
" sd-cli add server Add a server package",
|
|
90
90
|
].join("\n"),
|
|
91
91
|
);
|
|
92
92
|
}
|