@objectstack/cli 3.0.6 → 3.0.8

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.
Files changed (140) hide show
  1. package/.turbo/turbo-build.log +2 -26
  2. package/CHANGELOG.md +27 -0
  3. package/README.md +98 -54
  4. package/bin/run-dev.js +5 -0
  5. package/bin/run.js +5 -0
  6. package/dist/bin.d.ts +11 -0
  7. package/dist/bin.d.ts.map +1 -0
  8. package/dist/bin.js +12 -3767
  9. package/dist/bin.js.map +1 -0
  10. package/dist/commands/codemod/v2-to-v3.d.ts +10 -0
  11. package/dist/commands/codemod/v2-to-v3.d.ts.map +1 -0
  12. package/dist/commands/codemod/v2-to-v3.js +145 -0
  13. package/dist/commands/codemod/v2-to-v3.js.map +1 -0
  14. package/dist/commands/compile.d.ts +13 -0
  15. package/dist/commands/compile.d.ts.map +1 -0
  16. package/dist/commands/compile.js +91 -0
  17. package/dist/commands/compile.js.map +1 -0
  18. package/dist/commands/create.d.ts +91 -0
  19. package/dist/commands/create.d.ts.map +1 -0
  20. package/dist/commands/create.js +259 -0
  21. package/dist/commands/create.js.map +1 -0
  22. package/dist/commands/dev.d.ts +14 -0
  23. package/dist/commands/dev.d.ts.map +1 -0
  24. package/dist/commands/dev.js +67 -0
  25. package/dist/commands/dev.js.map +1 -0
  26. package/dist/commands/diff.d.ts +16 -0
  27. package/dist/commands/diff.d.ts.map +1 -0
  28. package/dist/commands/diff.js +239 -0
  29. package/dist/commands/diff.js.map +1 -0
  30. package/dist/commands/doctor.d.ts +10 -0
  31. package/dist/commands/doctor.d.ts.map +1 -0
  32. package/dist/commands/doctor.js +532 -0
  33. package/dist/commands/doctor.js.map +1 -0
  34. package/dist/commands/explain.d.ts +12 -0
  35. package/dist/commands/explain.d.ts.map +1 -0
  36. package/dist/commands/explain.js +368 -0
  37. package/dist/commands/explain.js.map +1 -0
  38. package/dist/commands/generate.d.ts +17 -0
  39. package/dist/commands/generate.d.ts.map +1 -0
  40. package/dist/commands/generate.js +833 -0
  41. package/dist/commands/generate.js.map +1 -0
  42. package/dist/commands/info.d.ts +12 -0
  43. package/dist/commands/info.d.ts.map +1 -0
  44. package/dist/commands/info.js +100 -0
  45. package/dist/commands/info.js.map +1 -0
  46. package/dist/commands/init.d.ts +22 -0
  47. package/dist/commands/init.d.ts.map +1 -0
  48. package/dist/commands/init.js +295 -0
  49. package/dist/commands/init.js.map +1 -0
  50. package/dist/commands/lint.d.ts +13 -0
  51. package/dist/commands/lint.d.ts.map +1 -0
  52. package/dist/commands/lint.js +255 -0
  53. package/dist/commands/lint.js.map +1 -0
  54. package/dist/commands/plugin/add.d.ts +22 -0
  55. package/dist/commands/plugin/add.d.ts.map +1 -0
  56. package/dist/commands/plugin/add.js +93 -0
  57. package/dist/commands/plugin/add.js.map +1 -0
  58. package/dist/commands/plugin/info.d.ts +10 -0
  59. package/dist/commands/plugin/info.d.ts.map +1 -0
  60. package/dist/commands/plugin/info.js +65 -0
  61. package/dist/commands/plugin/info.js.map +1 -0
  62. package/dist/commands/plugin/list.d.ts +13 -0
  63. package/dist/commands/plugin/list.d.ts.map +1 -0
  64. package/dist/commands/plugin/list.js +78 -0
  65. package/dist/commands/plugin/list.js.map +1 -0
  66. package/dist/commands/plugin/remove.d.ts +20 -0
  67. package/dist/commands/plugin/remove.d.ts.map +1 -0
  68. package/dist/commands/plugin/remove.js +79 -0
  69. package/dist/commands/plugin/remove.js.map +1 -0
  70. package/dist/commands/serve.d.ts +15 -0
  71. package/dist/commands/serve.d.ts.map +1 -0
  72. package/dist/commands/serve.js +286 -0
  73. package/dist/commands/serve.js.map +1 -0
  74. package/dist/commands/studio.d.ts +19 -0
  75. package/dist/commands/studio.d.ts.map +1 -0
  76. package/dist/commands/studio.js +43 -0
  77. package/dist/commands/studio.js.map +1 -0
  78. package/dist/commands/test.d.ts +13 -0
  79. package/dist/commands/test.d.ts.map +1 -0
  80. package/dist/commands/test.js +120 -0
  81. package/dist/commands/test.js.map +1 -0
  82. package/dist/commands/validate.d.ts +13 -0
  83. package/dist/commands/validate.d.ts.map +1 -0
  84. package/dist/commands/validate.js +115 -0
  85. package/dist/commands/validate.js.map +1 -0
  86. package/dist/index.d.ts +15 -114
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +20 -2805
  89. package/dist/index.js.map +1 -0
  90. package/dist/utils/config.d.ts +21 -0
  91. package/dist/utils/config.d.ts.map +1 -0
  92. package/dist/utils/config.js +66 -0
  93. package/dist/utils/config.js.map +1 -0
  94. package/dist/utils/format.d.ts +52 -0
  95. package/dist/utils/format.d.ts.map +1 -0
  96. package/dist/utils/format.js +202 -0
  97. package/dist/utils/format.js.map +1 -0
  98. package/dist/utils/plugin-helpers.d.ts +14 -0
  99. package/dist/utils/plugin-helpers.d.ts.map +1 -0
  100. package/dist/utils/plugin-helpers.js +40 -0
  101. package/dist/utils/plugin-helpers.js.map +1 -0
  102. package/dist/utils/studio.d.ts +58 -0
  103. package/dist/utils/studio.d.ts.map +1 -0
  104. package/dist/utils/studio.js +288 -0
  105. package/dist/utils/studio.js.map +1 -0
  106. package/package.json +33 -15
  107. package/src/bin.ts +11 -104
  108. package/src/commands/{codemod.ts → codemod/v2-to-v3.ts} +21 -28
  109. package/src/commands/compile.ts +31 -22
  110. package/src/commands/create.ts +29 -19
  111. package/src/commands/dev.ts +21 -10
  112. package/src/commands/diff.ts +28 -19
  113. package/src/commands/doctor.ts +17 -10
  114. package/src/commands/explain.ts +20 -10
  115. package/src/commands/generate.ts +81 -90
  116. package/src/commands/info.ts +20 -11
  117. package/src/commands/init.ts +32 -20
  118. package/src/commands/lint.ts +24 -14
  119. package/src/commands/plugin/add.ts +112 -0
  120. package/src/commands/plugin/info.ts +79 -0
  121. package/src/commands/plugin/list.ts +93 -0
  122. package/src/commands/plugin/remove.ts +97 -0
  123. package/src/commands/serve.ts +30 -20
  124. package/src/commands/studio.ts +21 -11
  125. package/src/commands/test.ts +21 -10
  126. package/src/commands/validate.ts +32 -22
  127. package/src/index.ts +20 -12
  128. package/src/utils/plugin-helpers.ts +37 -0
  129. package/src/utils/studio.ts +0 -1
  130. package/test/commands.test.ts +76 -37
  131. package/test/plugin-commands.test.ts +42 -160
  132. package/test/plugin.test.ts +19 -23
  133. package/tsconfig.build.json +18 -0
  134. package/bin/objectstack.js +0 -2
  135. package/dist/chunk-T2YN4AB7.js +0 -249
  136. package/dist/chunk-XNACYTC5.js +0 -251
  137. package/dist/config-FOXDQ5F7.js +0 -10
  138. package/dist/config-GBR54FKL.js +0 -11
  139. package/src/commands/plugin.ts +0 -372
  140. package/src/utils/plugin-commands.ts +0 -163
@@ -0,0 +1,288 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+ /**
3
+ * Studio UI Integration Utilities
4
+ *
5
+ * Handles resolving, spawning, and proxying the @objectstack/studio
6
+ * frontend when the CLI is started with --ui or via the `studio` command.
7
+ */
8
+ import path from 'path';
9
+ import fs from 'fs';
10
+ import net from 'net';
11
+ import { createRequire } from 'module';
12
+ import { pathToFileURL } from 'url';
13
+ import { spawn } from 'child_process';
14
+ // ─── Constants ──────────────────────────────────────────────────────
15
+ /** URL mount path for the Console UI inside the ObjectStack server */
16
+ export const STUDIO_PATH = '/_studio';
17
+ /** Internal port range start for the Vite dev server */
18
+ const VITE_PORT_START = 24678;
19
+ // ─── Path Resolution ────────────────────────────────────────────────
20
+ /**
21
+ * Resolve the filesystem path to the @objectstack/studio package.
22
+ * Searches workspace locations first, then falls back to node_modules.
23
+ */
24
+ export function resolveStudioPath() {
25
+ const cwd = process.cwd();
26
+ // Workspace candidates (monorepo layouts)
27
+ const candidates = [
28
+ path.resolve(cwd, 'apps/studio'),
29
+ path.resolve(cwd, '../../apps/studio'),
30
+ path.resolve(cwd, '../apps/studio'),
31
+ ];
32
+ for (const candidate of candidates) {
33
+ const pkgPath = path.join(candidate, 'package.json');
34
+ if (fs.existsSync(pkgPath)) {
35
+ try {
36
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
37
+ if (pkg.name === '@objectstack/studio')
38
+ return candidate;
39
+ }
40
+ catch {
41
+ // Skip invalid package.json
42
+ }
43
+ }
44
+ }
45
+ // Fallback: resolve from node_modules via createRequire.
46
+ // Try the consumer's cwd first (pnpm strict isolation means the CLI's own
47
+ // import.meta.url cannot see the consumer's dependencies), then the CLI itself.
48
+ const resolutionBases = [
49
+ pathToFileURL(path.join(cwd, 'package.json')).href, // consumer workspace
50
+ import.meta.url, // CLI package itself
51
+ ];
52
+ for (const base of resolutionBases) {
53
+ try {
54
+ const req = createRequire(base);
55
+ const resolved = req.resolve('@objectstack/studio/package.json');
56
+ return path.dirname(resolved);
57
+ }
58
+ catch {
59
+ // Not resolvable from this base — try next
60
+ }
61
+ }
62
+ // Last resort: direct filesystem check in cwd/node_modules
63
+ const directPath = path.join(cwd, 'node_modules', '@objectstack', 'studio');
64
+ if (fs.existsSync(path.join(directPath, 'package.json'))) {
65
+ return directPath;
66
+ }
67
+ return null;
68
+ }
69
+ /**
70
+ * Check whether the Studio has a pre-built `dist/` directory.
71
+ */
72
+ export function hasStudioDist(studioPath) {
73
+ return fs.existsSync(path.join(studioPath, 'dist', 'index.html'));
74
+ }
75
+ // ─── Port Utilities ─────────────────────────────────────────────────
76
+ /**
77
+ * Find the next available TCP port starting from `start`.
78
+ */
79
+ export function findAvailablePort(start = VITE_PORT_START) {
80
+ return new Promise((resolve, reject) => {
81
+ const server = net.createServer();
82
+ server.once('error', () => {
83
+ // Port in use — try next
84
+ findAvailablePort(start + 1).then(resolve, reject);
85
+ });
86
+ server.once('listening', () => {
87
+ server.close(() => resolve(start));
88
+ });
89
+ server.listen(start);
90
+ });
91
+ }
92
+ /**
93
+ * Spawn a Vite dev server for the Console application.
94
+ *
95
+ * Sets environment variables so the Console runs in server mode and
96
+ * connects to the ObjectStack API on the same origin.
97
+ *
98
+ * @param studioPath - Absolute path to the @objectstack/studio package
99
+ * @param options.serverPort - The main ObjectStack server port (for display only)
100
+ */
101
+ export async function spawnViteDevServer(studioPath, options = {}) {
102
+ const vitePort = await findAvailablePort(VITE_PORT_START);
103
+ // Resolve the Vite binary from the Studio's own dependencies
104
+ const viteBinCandidates = [
105
+ path.join(studioPath, 'node_modules', '.bin', 'vite'),
106
+ path.join(studioPath, '..', '..', 'node_modules', '.bin', 'vite'),
107
+ ];
108
+ let viteBin = null;
109
+ for (const candidate of viteBinCandidates) {
110
+ if (fs.existsSync(candidate)) {
111
+ viteBin = candidate;
112
+ break;
113
+ }
114
+ }
115
+ const command = viteBin || 'npx';
116
+ const args = viteBin
117
+ ? ['--port', String(vitePort), '--strictPort']
118
+ : ['vite', '--port', String(vitePort), '--strictPort'];
119
+ const child = spawn(command, args, {
120
+ cwd: studioPath,
121
+ env: {
122
+ ...process.env,
123
+ VITE_BASE: `${STUDIO_PATH}/`,
124
+ VITE_PORT: String(vitePort),
125
+ VITE_HMR_PORT: String(vitePort),
126
+ VITE_RUNTIME_MODE: 'server',
127
+ VITE_SERVER_URL: '', // Same-origin API
128
+ NODE_ENV: 'development',
129
+ },
130
+ stdio: ['ignore', 'pipe', 'pipe'],
131
+ });
132
+ // Accumulate stderr for error reporting
133
+ let stderr = '';
134
+ child.stderr?.on('data', (data) => {
135
+ stderr += data.toString();
136
+ });
137
+ // Wait for Vite to signal readiness
138
+ await new Promise((resolve, reject) => {
139
+ const timeout = setTimeout(() => {
140
+ child.kill();
141
+ reject(new Error(`Vite dev server timed out after 30 s.\n${stderr}`));
142
+ }, 30_000);
143
+ child.stdout?.on('data', (data) => {
144
+ const output = data.toString();
145
+ // Vite prints "ready in Xms" or "Local: http://..." when ready
146
+ if (output.includes('Local:') || output.includes('ready in')) {
147
+ clearTimeout(timeout);
148
+ resolve();
149
+ }
150
+ });
151
+ child.on('error', (err) => {
152
+ clearTimeout(timeout);
153
+ reject(err);
154
+ });
155
+ child.on('exit', (code) => {
156
+ if (code !== 0 && code !== null) {
157
+ clearTimeout(timeout);
158
+ reject(new Error(`Vite exited with code ${code}.\n${stderr}`));
159
+ }
160
+ });
161
+ });
162
+ return { port: vitePort, process: child };
163
+ }
164
+ // ─── Console Plugin Factories ───────────────────────────────────────
165
+ /**
166
+ * Create a lightweight kernel plugin that proxies `/_studio/*` requests
167
+ * to the Vite dev server. Used in development mode.
168
+ */
169
+ export function createStudioProxyPlugin(vitePort) {
170
+ return {
171
+ name: 'com.objectstack.studio-proxy',
172
+ init: async () => { },
173
+ start: async (ctx) => {
174
+ const httpServer = ctx.getService?.('http.server');
175
+ if (!httpServer?.getRawApp) {
176
+ ctx.logger?.warn?.('Studio proxy: http.server service not found — skipping');
177
+ return;
178
+ }
179
+ const app = httpServer.getRawApp();
180
+ // Redirect bare path to trailing-slash (SPA convention)
181
+ app.get(STUDIO_PATH, (c) => c.redirect(`${STUDIO_PATH}/`));
182
+ // Proxy all /_studio/* requests to the Vite dev server
183
+ app.all(`${STUDIO_PATH}/*`, async (c) => {
184
+ const targetUrl = `http://localhost:${vitePort}${c.req.path}`;
185
+ try {
186
+ const headers = new Headers(c.req.raw.headers);
187
+ headers.delete('host');
188
+ const isBodyAllowed = !['GET', 'HEAD'].includes(c.req.method);
189
+ const resp = await fetch(targetUrl, {
190
+ method: c.req.method,
191
+ headers,
192
+ body: isBodyAllowed ? c.req.raw.body : undefined,
193
+ duplex: isBodyAllowed ? 'half' : undefined,
194
+ });
195
+ // Forward the full response (status, headers, body)
196
+ return new Response(resp.body, {
197
+ status: resp.status,
198
+ headers: resp.headers,
199
+ });
200
+ }
201
+ catch {
202
+ return c.text('Console dev server is starting…', 502);
203
+ }
204
+ });
205
+ },
206
+ };
207
+ }
208
+ /**
209
+ * Create a lightweight kernel plugin that serves the pre-built Studio
210
+ * static files at `/_studio/*`. Used in production mode.
211
+ *
212
+ * Uses Node.js built-in fs for static file serving to avoid external
213
+ * bundling dependencies.
214
+ */
215
+ export function createStudioStaticPlugin(distPath, options) {
216
+ return {
217
+ name: 'com.objectstack.studio-static',
218
+ init: async () => { },
219
+ start: async (ctx) => {
220
+ const httpServer = ctx.getService?.('http.server');
221
+ if (!httpServer?.getRawApp) {
222
+ ctx.logger?.warn?.('Studio static: http.server service not found — skipping');
223
+ return;
224
+ }
225
+ const app = httpServer.getRawApp();
226
+ const absoluteDist = path.resolve(distPath);
227
+ const indexPath = path.join(absoluteDist, 'index.html');
228
+ if (!fs.existsSync(indexPath)) {
229
+ ctx.logger?.warn?.(`Studio static: dist not found at ${absoluteDist}`);
230
+ return;
231
+ }
232
+ // Read and rewrite index.html so asset paths respect the mount path.
233
+ // The dist may have been built with base '/' (absolute paths like
234
+ // /assets/...) which won't resolve when mounted under /_studio/.
235
+ const rawHtml = fs.readFileSync(indexPath, 'utf-8');
236
+ const rewrittenHtml = rawHtml.replace(/(\s(?:href|src))="\/(?!\/)/g, `$1="${STUDIO_PATH}/`);
237
+ // In dev mode, redirect root to Studio for convenience
238
+ if (options?.isDev) {
239
+ app.get('/', (c) => c.redirect(`${STUDIO_PATH}/`));
240
+ }
241
+ // Redirect bare path
242
+ app.get(STUDIO_PATH, (c) => c.redirect(`${STUDIO_PATH}/`));
243
+ // Serve static files with SPA fallback
244
+ app.get(`${STUDIO_PATH}/*`, async (c) => {
245
+ const reqPath = c.req.path.substring(STUDIO_PATH.length) || '/';
246
+ const filePath = path.join(absoluteDist, reqPath);
247
+ // Security: prevent path traversal
248
+ if (!filePath.startsWith(absoluteDist)) {
249
+ return c.text('Forbidden', 403);
250
+ }
251
+ // Try serving the exact file
252
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
253
+ const content = fs.readFileSync(filePath);
254
+ return new Response(content, {
255
+ headers: { 'content-type': mimeType(filePath) },
256
+ });
257
+ }
258
+ // SPA fallback: serve rewritten index.html for non-file routes
259
+ return new Response(rewrittenHtml, {
260
+ headers: { 'content-type': 'text/html; charset=utf-8' },
261
+ });
262
+ });
263
+ },
264
+ };
265
+ }
266
+ // ─── Helpers ────────────────────────────────────────────────────────
267
+ const MIME_TYPES = {
268
+ '.html': 'text/html; charset=utf-8',
269
+ '.js': 'application/javascript; charset=utf-8',
270
+ '.mjs': 'application/javascript; charset=utf-8',
271
+ '.css': 'text/css; charset=utf-8',
272
+ '.json': 'application/json; charset=utf-8',
273
+ '.svg': 'image/svg+xml',
274
+ '.png': 'image/png',
275
+ '.jpg': 'image/jpeg',
276
+ '.jpeg': 'image/jpeg',
277
+ '.gif': 'image/gif',
278
+ '.ico': 'image/x-icon',
279
+ '.woff': 'font/woff',
280
+ '.woff2': 'font/woff2',
281
+ '.ttf': 'font/ttf',
282
+ '.map': 'application/json',
283
+ };
284
+ function mimeType(filePath) {
285
+ const ext = path.extname(filePath).toLowerCase();
286
+ return MIME_TYPES[ext] || 'application/octet-stream';
287
+ }
288
+ //# sourceMappingURL=studio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studio.js","sourceRoot":"","sources":["../../src/utils/studio.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,47 +1,65 @@
1
1
  {
2
2
  "name": "@objectstack/cli",
3
- "version": "3.0.6",
3
+ "version": "3.0.8",
4
4
  "description": "Command Line Interface for ObjectStack Protocol",
5
5
  "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
6
7
  "bin": {
7
- "objectstack": "./bin/objectstack.js",
8
- "os": "./bin/objectstack.js"
8
+ "objectstack": "./bin/run.js",
9
+ "os": "./bin/run.js"
9
10
  },
10
11
  "keywords": [
11
12
  "objectstack",
12
13
  "cli",
14
+ "oclif",
13
15
  "compiler",
14
16
  "scaffold"
15
17
  ],
16
18
  "type": "module",
17
19
  "author": "Steedos",
18
20
  "license": "Apache-2.0",
21
+ "oclif": {
22
+ "bin": "os",
23
+ "dirname": "objectstack",
24
+ "commands": {
25
+ "strategy": "pattern",
26
+ "target": "./dist/commands",
27
+ "glob": "**/*.js"
28
+ },
29
+ "plugins": [
30
+ "@oclif/plugin-help",
31
+ "@oclif/plugin-plugins"
32
+ ],
33
+ "topicSeparator": " "
34
+ },
19
35
  "dependencies": {
36
+ "@oclif/core": "^4.8.0",
20
37
  "bundle-require": "^5.1.0",
21
38
  "chalk": "^5.3.0",
22
- "commander": "^14.0.3",
23
39
  "tsx": "^4.7.1",
24
40
  "zod": "^4.3.6",
25
- "@objectstack/core": "3.0.6",
26
- "@objectstack/driver-memory": "^3.0.6",
27
- "@objectstack/objectql": "^3.0.6",
28
- "@objectstack/plugin-hono-server": "3.0.6",
29
- "@objectstack/rest": "3.0.6",
30
- "@objectstack/runtime": "^3.0.6",
31
- "@objectstack/spec": "3.0.6"
41
+ "@objectstack/core": "3.0.8",
42
+ "@objectstack/driver-memory": "^3.0.8",
43
+ "@objectstack/objectql": "^3.0.8",
44
+ "@objectstack/plugin-hono-server": "3.0.8",
45
+ "@objectstack/rest": "3.0.8",
46
+ "@objectstack/runtime": "^3.0.8",
47
+ "@objectstack/spec": "3.0.8"
32
48
  },
33
49
  "peerDependencies": {
34
- "@objectstack/core": "3.0.6"
50
+ "@objectstack/core": "3.0.8"
35
51
  },
36
52
  "devDependencies": {
37
- "@types/node": "^25.2.2",
53
+ "@oclif/plugin-help": "^6.2.37",
54
+ "@oclif/plugin-plugins": "^5.4.56",
55
+ "@types/node": "^25.2.3",
38
56
  "tsup": "^8.0.2",
39
57
  "typescript": "^5.3.3",
40
58
  "vitest": "^4.0.18"
41
59
  },
42
60
  "scripts": {
43
- "build": "tsup",
44
- "dev": "tsup --watch",
61
+ "build": "tsc -p tsconfig.build.json",
62
+ "dev": "tsc -p tsconfig.build.json --watch",
45
63
  "test": "vitest run",
46
64
  "lint": "eslint src"
47
65
  }
package/src/bin.ts CHANGED
@@ -1,106 +1,13 @@
1
1
  // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
2
 
3
- import { createRequire } from 'module';
4
- import { Command } from 'commander';
5
- import chalk from 'chalk';
6
-
7
- // Commands
8
- import { compileCommand } from './commands/compile.js';
9
- import { devCommand } from './commands/dev.js';
10
- import { doctorCommand } from './commands/doctor.js';
11
- import { createCommand } from './commands/create.js';
12
- import { serveCommand } from './commands/serve.js';
13
- import { studioCommand } from './commands/studio.js';
14
- import { testCommand } from './commands/test.js';
15
- import { validateCommand } from './commands/validate.js';
16
- import { initCommand } from './commands/init.js';
17
- import { infoCommand } from './commands/info.js';
18
- import { generateCommand } from './commands/generate.js';
19
- import { pluginCommand } from './commands/plugin.js';
20
- import { diffCommand } from './commands/diff.js';
21
- import { lintCommand } from './commands/lint.js';
22
- import { explainCommand } from './commands/explain.js';
23
- import { codemodCommand } from './commands/codemod.js';
24
- import { loadPluginCommands } from './utils/plugin-commands.js';
25
-
26
- const require = createRequire(import.meta.url);
27
- const pkg = require('../package.json');
28
-
29
- // ─── Global Error Handling ──────────────────────────────────────────
30
- process.on('unhandledRejection', (err: any) => {
31
- console.error(chalk.red(`\n ✗ Unhandled error: ${err?.message || err}`));
32
- if (err?.stack && process.env.DEBUG) {
33
- console.error(chalk.dim(err.stack));
34
- }
35
- process.exit(1);
36
- });
37
-
38
- // ─── Program Definition ─────────────────────────────────────────────
39
- const program = new Command();
40
-
41
- program
42
- .name('objectstack')
43
- .description('ObjectStack CLI — Build metadata-driven apps with the ObjectStack Protocol')
44
- .version(pkg.version, '-v, --version')
45
- .configureHelp({
46
- sortSubcommands: false,
47
- })
48
- .addHelpText('before', `
49
- ${chalk.bold.cyan('◆ ObjectStack CLI')} ${chalk.dim(`v${pkg.version}`)}
50
- `)
51
- .addHelpText('after', `
52
- ${chalk.bold('Workflow:')}
53
- ${chalk.dim('$')} os init ${chalk.dim('# Create a new project')}
54
- ${chalk.dim('$')} os generate object task ${chalk.dim('# Add metadata')}
55
- ${chalk.dim('$')} os plugin add <package> ${chalk.dim('# Add a plugin')}
56
- ${chalk.dim('$')} os validate ${chalk.dim('# Check configuration')}
57
- ${chalk.dim('$')} os dev ${chalk.dim('# Start dev server')}
58
- ${chalk.dim('$')} os studio ${chalk.dim('# Dev server + Studio UI')}
59
- ${chalk.dim('$')} os compile ${chalk.dim('# Build for production')}
60
-
61
- ${chalk.dim('Aliases: objectstack | os')}
62
- ${chalk.dim('Docs: https://objectstack.dev')}
63
- `);
64
-
65
- // ── Development ──
66
- program.addCommand(initCommand);
67
- program.addCommand(devCommand);
68
- program.addCommand(serveCommand);
69
- program.addCommand(studioCommand);
70
-
71
- // ── Build & Validate ──
72
- program.addCommand(compileCommand);
73
- program.addCommand(validateCommand);
74
- program.addCommand(infoCommand);
75
-
76
- // ── Scaffolding ──
77
- program.addCommand(generateCommand);
78
- program.addCommand(createCommand);
79
-
80
- // ── Plugin Management ──
81
- program.addCommand(pluginCommand);
82
-
83
- // ── Quality ──
84
- program.addCommand(testCommand);
85
- program.addCommand(doctorCommand);
86
- program.addCommand(lintCommand);
87
- program.addCommand(diffCommand);
88
-
89
- // ── Reference ──
90
- program.addCommand(explainCommand);
91
-
92
- // ── Code Transforms ──
93
- program.addCommand(codemodCommand);
94
-
95
- // ── Plugin-Contributed Commands ──
96
- // Load commands from installed plugins that declare `contributes.commands` in their manifest.
97
- // This must complete before `program.parse()` so that plugin commands are available.
98
- loadPluginCommands(program).then(() => {
99
- program.parse(process.argv);
100
- }).catch((err) => {
101
- // If plugin command loading fails, still parse with built-in commands
102
- if (process.env.DEBUG) {
103
- console.error(chalk.yellow(`\n ⚠ Plugin command loading failed: ${err?.message || err}`));
104
- }
105
- program.parse(process.argv);
106
- });
3
+ /**
4
+ * ObjectStack CLI oclif-based entry point.
5
+ *
6
+ * All commands are auto-discovered from `src/commands/` by oclif.
7
+ * Plugins extend the CLI via oclif's built-in plugin system
8
+ * (configured in package.json under "oclif.plugins").
9
+ *
10
+ * Run `os --help` for available commands.
11
+ */
12
+
13
+ export { execute } from '@oclif/core';
@@ -1,10 +1,10 @@
1
1
  // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
2
 
3
- import { Command } from 'commander';
3
+ import { Command, Flags } from '@oclif/core';
4
4
  import chalk from 'chalk';
5
5
  import fs from 'fs';
6
6
  import path from 'path';
7
- import { printHeader, printSuccess, printError, printInfo, printStep, createTimer } from '../utils/format.js';
7
+ import { printHeader, printSuccess, printError, printInfo, printStep, createTimer } from '../../utils/format.js';
8
8
 
9
9
  // ─── Transform Definitions ──────────────────────────────────────────
10
10
 
@@ -76,25 +76,31 @@ function walkDir(dir: string, ext: string): string[] {
76
76
  return results;
77
77
  }
78
78
 
79
- // ─── v2-to-v3 Sub-Command ──────────────────────────────────────────
79
+ // ─── Command ────────────────────────────────────────────────────────
80
+
81
+ export default class V2ToV3 extends Command {
82
+ static override description = 'Migrate ObjectStack v2 config to v3 format';
83
+
84
+ static override flags = {
85
+ dir: Flags.string({ description: 'Directory to scan', default: 'src/' }),
86
+ 'dry-run': Flags.boolean({ description: 'Show changes without writing files' }),
87
+ };
88
+
89
+ async run(): Promise<void> {
90
+ const { flags } = await this.parse(V2ToV3);
80
91
 
81
- const v2ToV3Command = new Command('v2-to-v3')
82
- .description('Migrate ObjectStack v2 code patterns to v3')
83
- .option('--dir <directory>', 'Directory to scan', 'src/')
84
- .option('--dry-run', 'Show changes without writing files')
85
- .action(async (options) => {
86
92
  printHeader('Codemod: v2 → v3');
87
93
 
88
94
  const timer = createTimer();
89
- const dir = path.resolve(process.cwd(), options.dir);
95
+ const dir = path.resolve(process.cwd(), flags.dir);
90
96
 
91
97
  if (!fs.existsSync(dir)) {
92
98
  printError(`Directory not found: ${dir}`);
93
99
  process.exit(1);
94
100
  }
95
101
 
96
- console.log(` ${chalk.dim('Directory:')} ${chalk.white(options.dir)}`);
97
- console.log(` ${chalk.dim('Dry run:')} ${chalk.white(options.dryRun ? 'yes' : 'no')}`);
102
+ console.log(` ${chalk.dim('Directory:')} ${chalk.white(flags.dir)}`);
103
+ console.log(` ${chalk.dim('Dry run:')} ${chalk.white(flags['dry-run'] ? 'yes' : 'no')}`);
98
104
  console.log('');
99
105
 
100
106
  printStep('Scanning TypeScript files...');
@@ -132,7 +138,7 @@ const v2ToV3Command = new Command('v2-to-v3')
132
138
  filesModified++;
133
139
  totalTransforms += fileTransforms;
134
140
 
135
- if (options.dryRun) {
141
+ if (flags['dry-run']) {
136
142
  printInfo(`${relPath} — ${fileTransforms} change(s)`);
137
143
  } else {
138
144
  fs.writeFileSync(file, content);
@@ -152,7 +158,7 @@ const v2ToV3Command = new Command('v2-to-v3')
152
158
  }
153
159
  console.log('');
154
160
 
155
- if (options.dryRun) {
161
+ if (flags['dry-run']) {
156
162
  printInfo(`Would modify ${filesModified} file(s) with ${totalTransforms} total change(s)`);
157
163
  console.log(chalk.dim(' Run without --dry-run to apply changes'));
158
164
  } else {
@@ -161,18 +167,5 @@ const v2ToV3Command = new Command('v2-to-v3')
161
167
  }
162
168
 
163
169
  console.log('');
164
- });
165
-
166
- // ─── Main Codemod Command ───────────────────────────────────────────
167
-
168
- export const codemodCommand = new Command('codemod')
169
- .description('Run automated code transformations')
170
- .addCommand(v2ToV3Command)
171
- .action(() => {
172
- printHeader('Codemod');
173
- console.log(chalk.bold(' Available codemods:'));
174
- console.log(` ${chalk.cyan('v2-to-v3'.padEnd(16))} Migrate ObjectStack v2 code patterns to v3`);
175
- console.log('');
176
- console.log(chalk.dim(' Usage: objectstack codemod v2-to-v3 [--dir src/] [--dry-run]'));
177
- console.log('');
178
- });
170
+ }
171
+ }