@agentuity/cli 1.0.59 → 2.0.0-beta.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/bin/cli.ts +2 -3
- package/dist/cmd/build/app-config-extractor.d.ts +27 -0
- package/dist/cmd/build/app-config-extractor.d.ts.map +1 -0
- package/dist/cmd/build/app-config-extractor.js +152 -0
- package/dist/cmd/build/app-config-extractor.js.map +1 -0
- package/dist/cmd/build/app-router-detector.d.ts +2 -5
- package/dist/cmd/build/app-router-detector.d.ts.map +1 -1
- package/dist/cmd/build/app-router-detector.js +130 -154
- package/dist/cmd/build/app-router-detector.js.map +1 -1
- package/dist/cmd/build/ci.d.ts.map +1 -1
- package/dist/cmd/build/ci.js +5 -21
- package/dist/cmd/build/ci.js.map +1 -1
- package/dist/cmd/build/ids.d.ts +11 -0
- package/dist/cmd/build/ids.d.ts.map +1 -0
- package/dist/cmd/build/ids.js +18 -0
- package/dist/cmd/build/ids.js.map +1 -0
- package/dist/cmd/build/index.d.ts.map +1 -1
- package/dist/cmd/build/index.js +8 -0
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.d.ts +8 -4
- package/dist/cmd/build/vite/agent-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.js +166 -487
- package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts +43 -14
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +290 -129
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/build/vite/config-loader.d.ts +15 -20
- package/dist/cmd/build/vite/config-loader.d.ts.map +1 -1
- package/dist/cmd/build/vite/config-loader.js +41 -74
- package/dist/cmd/build/vite/config-loader.js.map +1 -1
- package/dist/cmd/build/vite/docs-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/docs-generator.js +0 -2
- package/dist/cmd/build/vite/docs-generator.js.map +1 -1
- package/dist/cmd/build/vite/index.d.ts.map +1 -1
- package/dist/cmd/build/vite/index.js +0 -36
- package/dist/cmd/build/vite/index.js.map +1 -1
- package/dist/cmd/build/vite/lifecycle-generator.d.ts +10 -2
- package/dist/cmd/build/vite/lifecycle-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/lifecycle-generator.js +302 -23
- package/dist/cmd/build/vite/lifecycle-generator.js.map +1 -1
- package/dist/cmd/build/vite/route-discovery.d.ts +11 -38
- package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/route-discovery.js +97 -177
- package/dist/cmd/build/vite/route-discovery.js.map +1 -1
- package/dist/cmd/build/vite/server-bundler.js +1 -1
- package/dist/cmd/build/vite/server-bundler.js.map +1 -1
- package/dist/cmd/build/vite/static-renderer.d.ts +0 -2
- package/dist/cmd/build/vite/static-renderer.d.ts.map +1 -1
- package/dist/cmd/build/vite/static-renderer.js +19 -13
- package/dist/cmd/build/vite/static-renderer.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.d.ts +6 -3
- package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.js +175 -69
- package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.d.ts +8 -3
- package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.js +14 -13
- package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +42 -190
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/build/vite/ws-proxy.d.ts +53 -0
- package/dist/cmd/build/vite/ws-proxy.d.ts.map +1 -0
- package/dist/cmd/build/vite/ws-proxy.js +95 -0
- package/dist/cmd/build/vite/ws-proxy.js.map +1 -0
- package/dist/cmd/build/vite-bundler.d.ts.map +1 -1
- package/dist/cmd/build/vite-bundler.js +0 -3
- package/dist/cmd/build/vite-bundler.js.map +1 -1
- package/dist/cmd/cloud/deploy-fork.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy-fork.js +15 -36
- package/dist/cmd/cloud/deploy-fork.js.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +28 -86
- package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
- package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/run.js +2 -9
- package/dist/cmd/cloud/sandbox/run.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.js +2 -2
- package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
- package/dist/cmd/coder/hub-url.d.ts.map +1 -1
- package/dist/cmd/coder/hub-url.js +1 -3
- package/dist/cmd/coder/hub-url.js.map +1 -1
- package/dist/cmd/coder/start.js +6 -6
- package/dist/cmd/coder/start.js.map +1 -1
- package/dist/cmd/coder/tui-init.d.ts +2 -2
- package/dist/cmd/coder/tui-init.js +2 -2
- package/dist/cmd/coder/tui-init.js.map +1 -1
- package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
- package/dist/cmd/dev/file-watcher.js +2 -8
- package/dist/cmd/dev/file-watcher.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +432 -752
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/process-manager.d.ts +104 -0
- package/dist/cmd/dev/process-manager.d.ts.map +1 -0
- package/dist/cmd/dev/process-manager.js +204 -0
- package/dist/cmd/dev/process-manager.js.map +1 -0
- package/dist/errors.d.ts +10 -24
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +12 -42
- package/dist/errors.js.map +1 -1
- package/dist/schema-generator.d.ts.map +1 -1
- package/dist/schema-generator.js +12 -2
- package/dist/schema-generator.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +5 -19
- package/dist/tui.js.map +1 -1
- package/dist/utils/version-mismatch.d.ts +39 -0
- package/dist/utils/version-mismatch.d.ts.map +1 -0
- package/dist/utils/version-mismatch.js +161 -0
- package/dist/utils/version-mismatch.js.map +1 -0
- package/package.json +6 -6
- package/src/cmd/ai/prompt/agent.md +0 -1
- package/src/cmd/ai/prompt/api.md +0 -7
- package/src/cmd/ai/prompt/web.md +51 -213
- package/src/cmd/build/app-config-extractor.ts +186 -0
- package/src/cmd/build/app-router-detector.ts +152 -182
- package/src/cmd/build/ci.ts +5 -21
- package/src/cmd/build/ids.ts +19 -0
- package/src/cmd/build/index.ts +10 -0
- package/src/cmd/build/vite/agent-discovery.ts +208 -679
- package/src/cmd/build/vite/bun-dev-server.ts +383 -146
- package/src/cmd/build/vite/config-loader.ts +45 -77
- package/src/cmd/build/vite/docs-generator.ts +0 -2
- package/src/cmd/build/vite/index.ts +1 -42
- package/src/cmd/build/vite/lifecycle-generator.ts +345 -21
- package/src/cmd/build/vite/route-discovery.ts +116 -274
- package/src/cmd/build/vite/server-bundler.ts +1 -1
- package/src/cmd/build/vite/static-renderer.ts +23 -15
- package/src/cmd/build/vite/vite-asset-server-config.ts +200 -70
- package/src/cmd/build/vite/vite-asset-server.ts +25 -15
- package/src/cmd/build/vite/vite-builder.ts +49 -220
- package/src/cmd/build/vite/ws-proxy.ts +126 -0
- package/src/cmd/build/vite-bundler.ts +0 -4
- package/src/cmd/cloud/deploy-fork.ts +16 -39
- package/src/cmd/cloud/sandbox/exec.ts +23 -130
- package/src/cmd/cloud/sandbox/run.ts +2 -9
- package/src/cmd/cloud/sandbox/snapshot/build.ts +2 -2
- package/src/cmd/coder/hub-url.ts +1 -3
- package/src/cmd/coder/start.ts +6 -6
- package/src/cmd/coder/tui-init.ts +4 -4
- package/src/cmd/dev/file-watcher.ts +2 -9
- package/src/cmd/dev/index.ts +476 -859
- package/src/cmd/dev/process-manager.ts +261 -0
- package/src/errors.ts +12 -44
- package/src/schema-generator.ts +12 -2
- package/src/tui.ts +5 -18
- package/src/utils/version-mismatch.ts +204 -0
- package/dist/cmd/build/ast.d.ts +0 -78
- package/dist/cmd/build/ast.d.ts.map +0 -1
- package/dist/cmd/build/ast.js +0 -2703
- package/dist/cmd/build/ast.js.map +0 -1
- package/dist/cmd/build/entry-generator.d.ts +0 -25
- package/dist/cmd/build/entry-generator.d.ts.map +0 -1
- package/dist/cmd/build/entry-generator.js +0 -695
- package/dist/cmd/build/entry-generator.js.map +0 -1
- package/dist/cmd/build/vite/api-mount-path.d.ts +0 -61
- package/dist/cmd/build/vite/api-mount-path.d.ts.map +0 -1
- package/dist/cmd/build/vite/api-mount-path.js +0 -83
- package/dist/cmd/build/vite/api-mount-path.js.map +0 -1
- package/dist/cmd/build/vite/registry-generator.d.ts +0 -19
- package/dist/cmd/build/vite/registry-generator.d.ts.map +0 -1
- package/dist/cmd/build/vite/registry-generator.js +0 -1108
- package/dist/cmd/build/vite/registry-generator.js.map +0 -1
- package/dist/cmd/build/webanalytics-generator.d.ts +0 -16
- package/dist/cmd/build/webanalytics-generator.d.ts.map +0 -1
- package/dist/cmd/build/webanalytics-generator.js +0 -178
- package/dist/cmd/build/webanalytics-generator.js.map +0 -1
- package/dist/cmd/build/workbench.d.ts +0 -7
- package/dist/cmd/build/workbench.d.ts.map +0 -1
- package/dist/cmd/build/workbench.js +0 -55
- package/dist/cmd/build/workbench.js.map +0 -1
- package/dist/utils/route-migration.d.ts +0 -62
- package/dist/utils/route-migration.d.ts.map +0 -1
- package/dist/utils/route-migration.js +0 -630
- package/dist/utils/route-migration.js.map +0 -1
- package/dist/utils/stream-capture.d.ts +0 -9
- package/dist/utils/stream-capture.d.ts.map +0 -1
- package/dist/utils/stream-capture.js +0 -34
- package/dist/utils/stream-capture.js.map +0 -1
- package/src/cmd/build/ast.ts +0 -3529
- package/src/cmd/build/entry-generator.ts +0 -760
- package/src/cmd/build/vite/api-mount-path.ts +0 -87
- package/src/cmd/build/vite/registry-generator.ts +0 -1267
- package/src/cmd/build/webanalytics-generator.ts +0 -197
- package/src/cmd/build/workbench.ts +0 -58
- package/src/utils/route-migration.ts +0 -757
- package/src/utils/stream-capture.ts +0 -39
package/bin/cli.ts
CHANGED
|
@@ -153,6 +153,7 @@ if (!hasHelp) {
|
|
|
153
153
|
parsedOperands = parsed.operands;
|
|
154
154
|
}
|
|
155
155
|
const earlyOpts = program.opts();
|
|
156
|
+
|
|
156
157
|
// Normalize --org alias → orgId (agents prefer --org over --org-id)
|
|
157
158
|
if (earlyOpts.org !== undefined && earlyOpts.orgId === undefined) {
|
|
158
159
|
earlyOpts.orgId = earlyOpts.org;
|
|
@@ -325,9 +326,7 @@ async function main() {
|
|
|
325
326
|
closeDatabase();
|
|
326
327
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
327
328
|
const exit = (globalThis as any).AGENTUITY_PROCESS_EXIT || process.exit;
|
|
328
|
-
|
|
329
|
-
// propagate the sandbox process's exit code). Default to 0 for success.
|
|
330
|
-
exit(process.exitCode ?? 0);
|
|
329
|
+
exit(0);
|
|
331
330
|
}
|
|
332
331
|
|
|
333
332
|
try {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Config Extractor
|
|
3
|
+
*
|
|
4
|
+
* Extracts analytics and workbench config from the user's createApp() call
|
|
5
|
+
* in app.ts. This is the v2 approach where createApp() is the single source
|
|
6
|
+
* of truth for runtime configuration (replacing agentuity.config.ts).
|
|
7
|
+
*
|
|
8
|
+
* Uses TypeScript's compiler API to reliably detect and extract values.
|
|
9
|
+
*/
|
|
10
|
+
import type { Logger } from '../../types';
|
|
11
|
+
/**
|
|
12
|
+
* Extracted runtime config from createApp() call.
|
|
13
|
+
*/
|
|
14
|
+
export interface ExtractedAppConfig {
|
|
15
|
+
/** analytics option value: boolean, object, or undefined if not set */
|
|
16
|
+
analytics?: boolean | Record<string, unknown>;
|
|
17
|
+
/** workbench option value: boolean, string, object, or undefined if not set */
|
|
18
|
+
workbench?: boolean | string | Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Detect and extract analytics/workbench config from app.ts.
|
|
22
|
+
*
|
|
23
|
+
* This is the v2 approach: runtime config lives in createApp() only.
|
|
24
|
+
* The CLI reads these values at build time via AST parsing.
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractAppConfig(rootDir: string, logger: Logger): Promise<ExtractedAppConfig>;
|
|
27
|
+
//# sourceMappingURL=app-config-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-config-extractor.d.ts","sourceRoot":"","sources":["../../../src/cmd/build/app-config-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvD;AA+GD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,kBAAkB,CAAC,CA2C7B"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Config Extractor
|
|
3
|
+
*
|
|
4
|
+
* Extracts analytics and workbench config from the user's createApp() call
|
|
5
|
+
* in app.ts. This is the v2 approach where createApp() is the single source
|
|
6
|
+
* of truth for runtime configuration (replacing agentuity.config.ts).
|
|
7
|
+
*
|
|
8
|
+
* Uses TypeScript's compiler API to reliably detect and extract values.
|
|
9
|
+
*/
|
|
10
|
+
import ts from 'typescript';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
/**
|
|
13
|
+
* Extract analytics and workbench config from a createApp() call.
|
|
14
|
+
*
|
|
15
|
+
* Uses TypeScript AST to find `createApp({ ... })` and extract the values
|
|
16
|
+
* of the `analytics` and `workbench` properties.
|
|
17
|
+
*/
|
|
18
|
+
function extractCreateAppConfig(sourceFile) {
|
|
19
|
+
const result = {};
|
|
20
|
+
// Walk the AST looking for createApp({ ... }) calls
|
|
21
|
+
function visit(node) {
|
|
22
|
+
// Check for createApp(...) call
|
|
23
|
+
if (ts.isCallExpression(node) &&
|
|
24
|
+
ts.isIdentifier(node.expression) &&
|
|
25
|
+
node.expression.text === 'createApp' &&
|
|
26
|
+
node.arguments.length > 0) {
|
|
27
|
+
const firstArg = node.arguments[0];
|
|
28
|
+
if (!firstArg)
|
|
29
|
+
return;
|
|
30
|
+
if (ts.isObjectLiteralExpression(firstArg)) {
|
|
31
|
+
// Found createApp({ ... }) — extract properties
|
|
32
|
+
for (const prop of firstArg.properties) {
|
|
33
|
+
if (!ts.isPropertyAssignment(prop))
|
|
34
|
+
continue;
|
|
35
|
+
const name = ts.isIdentifier(prop.name) ? prop.name.text : undefined;
|
|
36
|
+
if (!name)
|
|
37
|
+
continue;
|
|
38
|
+
// prop.initializer should always exist for PropertyAssignment, but check to satisfy TS
|
|
39
|
+
if (!('initializer' in prop))
|
|
40
|
+
continue;
|
|
41
|
+
const initializer = prop.initializer;
|
|
42
|
+
if (name === 'analytics') {
|
|
43
|
+
const value = extractValue(initializer);
|
|
44
|
+
if (value !== undefined) {
|
|
45
|
+
if (typeof value === 'boolean') {
|
|
46
|
+
result.analytics = value;
|
|
47
|
+
}
|
|
48
|
+
else if (typeof value === 'object') {
|
|
49
|
+
result.analytics = value;
|
|
50
|
+
}
|
|
51
|
+
// Ignore string/number for analytics
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else if (name === 'workbench') {
|
|
55
|
+
const value = extractValue(initializer);
|
|
56
|
+
if (value !== undefined) {
|
|
57
|
+
if (typeof value === 'boolean' || typeof value === 'string') {
|
|
58
|
+
result.workbench = value;
|
|
59
|
+
}
|
|
60
|
+
else if (typeof value === 'object') {
|
|
61
|
+
result.workbench = value;
|
|
62
|
+
}
|
|
63
|
+
// Ignore number for workbench
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
ts.forEachChild(node, visit);
|
|
70
|
+
}
|
|
71
|
+
visit(sourceFile);
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Extract a JavaScript value from a TypeScript AST expression node.
|
|
76
|
+
* Handles: boolean literals, string literals, numeric literals,
|
|
77
|
+
* object literals (as Record), and identifier references (by name).
|
|
78
|
+
*/
|
|
79
|
+
function extractValue(node) {
|
|
80
|
+
if (ts.isLiteralExpression(node)) {
|
|
81
|
+
// String literal or numeric literal
|
|
82
|
+
if (ts.isStringLiteral(node)) {
|
|
83
|
+
return node.text;
|
|
84
|
+
}
|
|
85
|
+
if (ts.isNumericLiteral(node)) {
|
|
86
|
+
return Number(node.text);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
if (ts.isIdentifier(node)) {
|
|
96
|
+
// Return the identifier name (e.g., a variable reference)
|
|
97
|
+
return node.text;
|
|
98
|
+
}
|
|
99
|
+
if (ts.isObjectLiteralExpression(node)) {
|
|
100
|
+
const obj = {};
|
|
101
|
+
for (const prop of node.properties) {
|
|
102
|
+
if (!ts.isPropertyAssignment(prop))
|
|
103
|
+
continue;
|
|
104
|
+
if (!ts.isIdentifier(prop.name))
|
|
105
|
+
continue;
|
|
106
|
+
const key = prop.name.text;
|
|
107
|
+
obj[key] = extractValue(prop.initializer);
|
|
108
|
+
}
|
|
109
|
+
return obj;
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Detect and extract analytics/workbench config from app.ts.
|
|
115
|
+
*
|
|
116
|
+
* This is the v2 approach: runtime config lives in createApp() only.
|
|
117
|
+
* The CLI reads these values at build time via AST parsing.
|
|
118
|
+
*/
|
|
119
|
+
export async function extractAppConfig(rootDir, logger) {
|
|
120
|
+
// Look for app.ts in root first, then src/
|
|
121
|
+
let appFile = join(rootDir, 'app.ts');
|
|
122
|
+
if (!(await Bun.file(appFile).exists())) {
|
|
123
|
+
appFile = join(rootDir, 'src', 'app.ts');
|
|
124
|
+
if (!(await Bun.file(appFile).exists())) {
|
|
125
|
+
logger.trace('[config-extract] No app.ts found');
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const source = await Bun.file(appFile).text();
|
|
131
|
+
// Quick bail-out before parsing
|
|
132
|
+
if (!source.includes('createApp')) {
|
|
133
|
+
logger.trace('[config-extract] No createApp call in %s', appFile);
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
// Parse with TypeScript
|
|
137
|
+
const sourceFile = ts.createSourceFile(appFile, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
138
|
+
const config = extractCreateAppConfig(sourceFile);
|
|
139
|
+
if (config.analytics !== undefined) {
|
|
140
|
+
logger.debug('[config-extract] Found analytics in createApp(): %o', config.analytics);
|
|
141
|
+
}
|
|
142
|
+
if (config.workbench !== undefined) {
|
|
143
|
+
logger.debug('[config-extract] Found workbench in createApp(): %o', config.workbench);
|
|
144
|
+
}
|
|
145
|
+
return config;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
logger.warn('[config-extract] Failed to parse app.ts:', error);
|
|
149
|
+
return {};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=app-config-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-config-extractor.js","sourceRoot":"","sources":["../../../src/cmd/build/app-config-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* to `createApp()`. If detected, resolves the router variable(s) to their import
|
|
6
6
|
* sources and mount paths.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Uses TypeScript's compiler API to reliably detect the pattern, consistent with
|
|
9
|
+
* the lifecycle generator approach.
|
|
10
10
|
*/
|
|
11
11
|
import type { Logger } from '../../types';
|
|
12
12
|
/**
|
|
@@ -30,9 +30,6 @@ export interface AppRouterDetection {
|
|
|
30
30
|
/**
|
|
31
31
|
* Detect whether `src/app.ts` uses `createApp({ router })`.
|
|
32
32
|
*
|
|
33
|
-
* Parses the file with acorn-loose, finds `createApp()` calls,
|
|
34
|
-
* and resolves router variables to their import source files.
|
|
35
|
-
*
|
|
36
33
|
* Returns `{ detected: false, mounts: [] }` when:
|
|
37
34
|
* - `src/app.ts` doesn't exist
|
|
38
35
|
* - `createApp()` is called without a `router` property
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-router-detector.d.ts","sourceRoot":"","sources":["../../../src/cmd/build/app-router-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"app-router-detector.d.ts","sourceRoot":"","sources":["../../../src/cmd/build/app-router-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,gDAAgD;IAChD,QAAQ,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,MAAM,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAuLD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,kBAAkB,CAAC,CA2F7B"}
|
|
@@ -5,23 +5,24 @@
|
|
|
5
5
|
* to `createApp()`. If detected, resolves the router variable(s) to their import
|
|
6
6
|
* sources and mount paths.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Uses TypeScript's compiler API to reliably detect the pattern, consistent with
|
|
9
|
+
* the lifecycle generator approach.
|
|
10
10
|
*/
|
|
11
|
-
import
|
|
11
|
+
import ts from 'typescript';
|
|
12
12
|
import { join, dirname, resolve } from 'node:path';
|
|
13
|
-
import {
|
|
13
|
+
import { statSync } from 'node:fs';
|
|
14
14
|
/**
|
|
15
15
|
* Resolve an import path to an actual file on disk.
|
|
16
16
|
* Tries the path as-is, then with common extensions.
|
|
17
17
|
*/
|
|
18
|
-
function resolveImportFile(fromDir, importPath) {
|
|
18
|
+
async function resolveImportFile(fromDir, importPath) {
|
|
19
19
|
if (!importPath.startsWith('.') && !importPath.startsWith('/')) {
|
|
20
20
|
return null; // Package import — can't resolve
|
|
21
21
|
}
|
|
22
22
|
const basePath = resolve(fromDir, importPath);
|
|
23
23
|
const extensions = ['.ts', '.tsx', '/index.ts', '/index.tsx'];
|
|
24
|
-
|
|
24
|
+
const baseFile = Bun.file(basePath);
|
|
25
|
+
if (await baseFile.exists()) {
|
|
25
26
|
try {
|
|
26
27
|
if (statSync(basePath).isFile())
|
|
27
28
|
return basePath;
|
|
@@ -32,82 +33,138 @@ function resolveImportFile(fromDir, importPath) {
|
|
|
32
33
|
}
|
|
33
34
|
for (const ext of extensions) {
|
|
34
35
|
const candidate = basePath + ext;
|
|
35
|
-
if (
|
|
36
|
+
if (await Bun.file(candidate).exists()) {
|
|
36
37
|
return candidate;
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
return null;
|
|
40
41
|
}
|
|
41
42
|
/**
|
|
42
|
-
* Extract
|
|
43
|
-
*
|
|
44
|
-
* Handles three forms:
|
|
45
|
-
* - `createApp({ router: myVar })` → plain Hono, default /api mount
|
|
46
|
-
* - `createApp({ router: { path: '/v1', router: myVar } })` → single RouteMount
|
|
47
|
-
* - `createApp({ router: [{ path: '/v1', router: v1 }, ...] })` → array of RouteMounts
|
|
43
|
+
* Extract router mounts from a createApp() call using TypeScript's AST.
|
|
44
|
+
* Returns null if no router property found.
|
|
48
45
|
*/
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (configArg.type !== 'ObjectExpression') {
|
|
46
|
+
function extractRouterMounts(sourceFile) {
|
|
47
|
+
let result = null;
|
|
48
|
+
function getStringLiteral(node) {
|
|
49
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
50
|
+
return node.text;
|
|
51
|
+
}
|
|
56
52
|
return null;
|
|
57
53
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
function extractMountFromObject(obj) {
|
|
55
|
+
let path;
|
|
56
|
+
let varName;
|
|
57
|
+
for (const prop of obj.properties) {
|
|
58
|
+
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name))
|
|
59
|
+
continue;
|
|
60
|
+
if (prop.name.text === 'path') {
|
|
61
|
+
path = getStringLiteral(prop.initializer) ?? undefined;
|
|
62
|
+
}
|
|
63
|
+
if (prop.name.text === 'router') {
|
|
64
|
+
if (ts.isIdentifier(prop.initializer)) {
|
|
65
|
+
varName = prop.initializer.text;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Also handle shorthand: { path: '/v1', router } where router is shorthand
|
|
70
|
+
for (const prop of obj.properties) {
|
|
71
|
+
if (ts.isShorthandPropertyAssignment(prop) && prop.name.text === 'router') {
|
|
72
|
+
varName = prop.name.text;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return path && varName ? { path, varName } : null;
|
|
67
76
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
function processRouterValue(value) {
|
|
78
|
+
// Form 1: Identifier → createApp({ router: myRouter })
|
|
79
|
+
if (ts.isIdentifier(value)) {
|
|
80
|
+
return [{ path: '/api', varName: value.text }];
|
|
81
|
+
}
|
|
82
|
+
// Form 2: Object → createApp({ router: { path: '/v1', router: myRouter } })
|
|
83
|
+
if (ts.isObjectLiteralExpression(value)) {
|
|
84
|
+
const mount = extractMountFromObject(value);
|
|
85
|
+
return mount ? [mount] : null;
|
|
86
|
+
}
|
|
87
|
+
// Form 3: Array → createApp({ router: [...] })
|
|
88
|
+
if (ts.isArrayLiteralExpression(value)) {
|
|
89
|
+
const mounts = [];
|
|
90
|
+
for (const element of value.elements) {
|
|
91
|
+
if (ts.isObjectLiteralExpression(element)) {
|
|
92
|
+
const mount = extractMountFromObject(element);
|
|
93
|
+
if (mount)
|
|
94
|
+
mounts.push(mount);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return mounts.length > 0 ? mounts : null;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
72
100
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
101
|
+
function visit(node) {
|
|
102
|
+
if (result)
|
|
103
|
+
return;
|
|
104
|
+
// Find createApp(...) — with or without await
|
|
105
|
+
let callExpr;
|
|
106
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
|
107
|
+
if (node.expression.text === 'createApp')
|
|
108
|
+
callExpr = node;
|
|
109
|
+
}
|
|
110
|
+
else if (ts.isAwaitExpression(node) && ts.isCallExpression(node.expression)) {
|
|
111
|
+
const call = node.expression;
|
|
112
|
+
if (ts.isIdentifier(call.expression) && call.expression.text === 'createApp') {
|
|
113
|
+
callExpr = call;
|
|
81
114
|
}
|
|
82
115
|
}
|
|
83
|
-
|
|
116
|
+
if (callExpr && callExpr.arguments.length > 0) {
|
|
117
|
+
const configArg = callExpr.arguments[0];
|
|
118
|
+
if (configArg && ts.isObjectLiteralExpression(configArg)) {
|
|
119
|
+
for (const prop of configArg.properties) {
|
|
120
|
+
// Handle: router: value
|
|
121
|
+
if (ts.isPropertyAssignment(prop) &&
|
|
122
|
+
ts.isIdentifier(prop.name) &&
|
|
123
|
+
prop.name.text === 'router') {
|
|
124
|
+
result = processRouterValue(prop.initializer);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Handle shorthand: createApp({ router })
|
|
128
|
+
if (ts.isShorthandPropertyAssignment(prop) && prop.name.text === 'router') {
|
|
129
|
+
result = [{ path: '/api', varName: 'router' }];
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
ts.forEachChild(node, visit);
|
|
84
136
|
}
|
|
85
|
-
|
|
137
|
+
visit(sourceFile);
|
|
138
|
+
return result;
|
|
86
139
|
}
|
|
87
140
|
/**
|
|
88
|
-
*
|
|
141
|
+
* Build import map from the source file: variable name → import path
|
|
89
142
|
*/
|
|
90
|
-
function
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
143
|
+
function buildImportMap(sourceFile) {
|
|
144
|
+
const importMap = new Map();
|
|
145
|
+
for (const stmt of sourceFile.statements) {
|
|
146
|
+
if (!ts.isImportDeclaration(stmt) || !ts.isStringLiteral(stmt.moduleSpecifier))
|
|
147
|
+
continue;
|
|
148
|
+
const importPath = stmt.moduleSpecifier.text;
|
|
149
|
+
const clause = stmt.importClause;
|
|
150
|
+
if (!clause)
|
|
95
151
|
continue;
|
|
96
|
-
|
|
97
|
-
|
|
152
|
+
// Default import: import router from './api'
|
|
153
|
+
if (clause.name) {
|
|
154
|
+
importMap.set(clause.name.text, importPath);
|
|
98
155
|
}
|
|
99
|
-
|
|
100
|
-
|
|
156
|
+
// Named imports: import { v1, v2 } from './routers'
|
|
157
|
+
if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {
|
|
158
|
+
for (const spec of clause.namedBindings.elements) {
|
|
159
|
+
importMap.set(spec.name.text, importPath);
|
|
160
|
+
}
|
|
101
161
|
}
|
|
102
162
|
}
|
|
103
|
-
return
|
|
163
|
+
return importMap;
|
|
104
164
|
}
|
|
105
165
|
/**
|
|
106
166
|
* Detect whether `src/app.ts` uses `createApp({ router })`.
|
|
107
167
|
*
|
|
108
|
-
* Parses the file with acorn-loose, finds `createApp()` calls,
|
|
109
|
-
* and resolves router variables to their import source files.
|
|
110
|
-
*
|
|
111
168
|
* Returns `{ detected: false, mounts: [] }` when:
|
|
112
169
|
* - `src/app.ts` doesn't exist
|
|
113
170
|
* - `createApp()` is called without a `router` property
|
|
@@ -115,63 +172,41 @@ function extractRouteMountFromObject(objNode) {
|
|
|
115
172
|
*/
|
|
116
173
|
export async function detectExplicitRouter(rootDir, logger) {
|
|
117
174
|
const noDetection = { detected: false, mounts: [] };
|
|
118
|
-
// Look for app.ts in src/ (standard location)
|
|
119
|
-
|
|
120
|
-
if (!
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (!existsSync(rootAppFile)) {
|
|
175
|
+
// Look for app.ts in src/ (standard location), then root
|
|
176
|
+
let appFile = join(rootDir, 'src', 'app.ts');
|
|
177
|
+
if (!(await Bun.file(appFile).exists())) {
|
|
178
|
+
appFile = join(rootDir, 'app.ts');
|
|
179
|
+
if (!(await Bun.file(appFile).exists())) {
|
|
124
180
|
logger.trace('[router-detect] No app.ts found');
|
|
125
181
|
return noDetection;
|
|
126
182
|
}
|
|
127
|
-
return detectInFile(rootAppFile, logger);
|
|
128
183
|
}
|
|
129
|
-
return detectInFile(appFile, logger);
|
|
130
|
-
}
|
|
131
|
-
async function detectInFile(appFile, logger) {
|
|
132
|
-
const noDetection = { detected: false, mounts: [] };
|
|
133
|
-
const appDir = dirname(appFile);
|
|
134
184
|
try {
|
|
135
185
|
const source = await Bun.file(appFile).text();
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (!contents.includes('createApp') || !contents.includes('router')) {
|
|
186
|
+
const appDir = dirname(appFile);
|
|
187
|
+
// Quick bail-out before parsing
|
|
188
|
+
if (!source.includes('createApp') || !source.includes('router')) {
|
|
140
189
|
logger.trace('[router-detect] No createApp + router pattern found in %s', appFile);
|
|
141
190
|
return noDetection;
|
|
142
191
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
});
|
|
148
|
-
// Build import map: variable name → import path
|
|
149
|
-
const importMap = new Map();
|
|
150
|
-
for (const node of ast.body || []) {
|
|
151
|
-
if (node.type === 'ImportDeclaration' && node.source?.value) {
|
|
152
|
-
for (const spec of node.specifiers || []) {
|
|
153
|
-
if (spec.local?.name) {
|
|
154
|
-
importMap.set(spec.local.name, String(node.source.value));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
// Walk all statements looking for createApp() calls
|
|
160
|
-
const routerMounts = findCreateAppRouterCalls(ast, importMap);
|
|
161
|
-
if (!routerMounts || routerMounts.length === 0) {
|
|
192
|
+
// Parse with TypeScript
|
|
193
|
+
const sourceFile = ts.createSourceFile(appFile, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
194
|
+
const rawMounts = extractRouterMounts(sourceFile);
|
|
195
|
+
if (!rawMounts || rawMounts.length === 0) {
|
|
162
196
|
logger.trace('[router-detect] createApp() found but no router property');
|
|
163
197
|
return noDetection;
|
|
164
198
|
}
|
|
199
|
+
// Build import map to resolve variable names to file paths
|
|
200
|
+
const importMap = buildImportMap(sourceFile);
|
|
165
201
|
// Resolve each router variable to its file
|
|
166
202
|
const mounts = [];
|
|
167
|
-
for (const { path, varName } of
|
|
203
|
+
for (const { path, varName } of rawMounts) {
|
|
168
204
|
const importPath = importMap.get(varName);
|
|
169
205
|
if (!importPath) {
|
|
170
206
|
logger.debug('[router-detect] Router variable %s is not imported — may be defined locally', varName);
|
|
171
|
-
// Could be defined in the same file — skip for now
|
|
172
207
|
continue;
|
|
173
208
|
}
|
|
174
|
-
const resolvedFile = resolveImportFile(appDir, importPath);
|
|
209
|
+
const resolvedFile = await resolveImportFile(appDir, importPath);
|
|
175
210
|
if (!resolvedFile) {
|
|
176
211
|
logger.warn('[router-detect] Could not resolve import %s for router variable %s', importPath, varName);
|
|
177
212
|
continue;
|
|
@@ -191,63 +226,4 @@ async function detectInFile(appFile, logger) {
|
|
|
191
226
|
return noDetection;
|
|
192
227
|
}
|
|
193
228
|
}
|
|
194
|
-
/**
|
|
195
|
-
* Walk the AST looking for `createApp({ router: ... })` calls.
|
|
196
|
-
* Handles:
|
|
197
|
-
* - `createApp({ router })` (top-level expression)
|
|
198
|
-
* - `const app = await createApp({ router })` (variable declaration)
|
|
199
|
-
* - `export const app = await createApp({ router })` (exported)
|
|
200
|
-
*/
|
|
201
|
-
function findCreateAppRouterCalls(ast, importMap) {
|
|
202
|
-
for (const node of ast.body || []) {
|
|
203
|
-
// Check expression statements: createApp({ router })
|
|
204
|
-
if (node.type === 'ExpressionStatement') {
|
|
205
|
-
const result = checkForCreateAppCall(node.expression, importMap);
|
|
206
|
-
if (result)
|
|
207
|
-
return result;
|
|
208
|
-
}
|
|
209
|
-
// Check variable declarations: const app = await createApp({ router })
|
|
210
|
-
if (node.type === 'VariableDeclaration') {
|
|
211
|
-
for (const decl of node.declarations || []) {
|
|
212
|
-
if (decl.init) {
|
|
213
|
-
const result = checkForCreateAppCall(decl.init, importMap);
|
|
214
|
-
if (result)
|
|
215
|
-
return result;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
// Check exports: export const app = await createApp({ router })
|
|
220
|
-
if (node.type === 'ExportNamedDeclaration' && node.declaration) {
|
|
221
|
-
if (node.declaration.type === 'VariableDeclaration') {
|
|
222
|
-
for (const decl of node.declaration.declarations || []) {
|
|
223
|
-
if (decl.init) {
|
|
224
|
-
const result = checkForCreateAppCall(decl.init, importMap);
|
|
225
|
-
if (result)
|
|
226
|
-
return result;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Check if an expression node is a `createApp({ router })` call.
|
|
236
|
-
* Unwraps `await` expressions.
|
|
237
|
-
*/
|
|
238
|
-
function checkForCreateAppCall(expr, importMap) {
|
|
239
|
-
if (!expr)
|
|
240
|
-
return null;
|
|
241
|
-
// Unwrap AwaitExpression: await createApp(...)
|
|
242
|
-
if (expr.type === 'AwaitExpression' && expr.argument) {
|
|
243
|
-
return checkForCreateAppCall(expr.argument, importMap);
|
|
244
|
-
}
|
|
245
|
-
// Check for createApp({ router })
|
|
246
|
-
if (expr.type === 'CallExpression' &&
|
|
247
|
-
expr.callee?.type === 'Identifier' &&
|
|
248
|
-
expr.callee?.name === 'createApp') {
|
|
249
|
-
return extractRouterFromCreateApp(expr);
|
|
250
|
-
}
|
|
251
|
-
return null;
|
|
252
|
-
}
|
|
253
229
|
//# sourceMappingURL=app-router-detector.js.map
|