forgeos 0.1.0-alpha.0 → 0.1.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +9 -1
- package/AGENTS.md +6 -1
- package/CHANGELOG.md +30 -0
- package/CONTRIBUTING.md +22 -1
- package/README.md +30 -3
- package/bin/forge.mjs +4 -3
- package/package.json +3 -1
- package/packages/eslint-plugin-forge/index.ts +15 -15
- package/packages/eslint-plugin-forge/package.json +10 -10
- package/packages/eslint-plugin-forge/src/check-source.ts +95 -95
- package/packages/eslint-plugin-forge/src/load-artifacts.ts +24 -24
- package/packages/eslint-plugin-forge/src/rule-no-forge-guard-violation.ts +93 -93
- package/src/forge/_generated/actionSubscriptions.json +2 -2
- package/src/forge/_generated/actionSubscriptions.ts +3 -3
- package/src/forge/_generated/agentAdapterManifest.json +2 -2
- package/src/forge/_generated/agentAdapterManifest.ts +3 -3
- package/src/forge/_generated/agentContract.json +2 -2
- package/src/forge/_generated/agentContract.ts +6786 -2
- package/src/forge/_generated/agentQuickstart.md +1 -1
- package/src/forge/_generated/aiContext.ts +1 -1
- package/src/forge/_generated/aiModels.json +1 -1
- package/src/forge/_generated/aiModels.ts +1 -1
- package/src/forge/_generated/aiProviders.json +1 -1
- package/src/forge/_generated/aiProviders.ts +1 -1
- package/src/forge/_generated/aiRegistry.json +2 -2
- package/src/forge/_generated/aiRegistry.ts +3 -3
- package/src/forge/_generated/api.json +2 -2
- package/src/forge/_generated/api.ts +1 -1
- package/src/forge/_generated/appGraph.json +2 -2
- package/src/forge/_generated/appGraph.ts +1297 -1141
- package/src/forge/_generated/appMap.md +1 -1
- package/src/forge/_generated/artifactManifest.json +2 -2
- package/src/forge/_generated/artifactManifest.ts +2 -2
- package/src/forge/_generated/authClaims.json +1 -1
- package/src/forge/_generated/authClaims.ts +1 -1
- package/src/forge/_generated/authConfig.json +1 -1
- package/src/forge/_generated/authConfig.ts +1 -1
- package/src/forge/_generated/authContext.ts +1 -1
- package/src/forge/_generated/authRegistry.json +1 -1
- package/src/forge/_generated/authRegistry.ts +1 -1
- package/src/forge/_generated/buildInfo.json +2 -2
- package/src/forge/_generated/buildInfo.ts +4 -4
- package/src/forge/_generated/capabilityMap.json +2 -2
- package/src/forge/_generated/capabilityMap.md +1 -1
- package/src/forge/_generated/capabilityMap.ts +2 -2
- package/src/forge/_generated/client.ts +1 -1
- package/src/forge/_generated/clientApi.ts +1 -1
- package/src/forge/_generated/clientManifest.json +2 -2
- package/src/forge/_generated/clientManifest.ts +3 -3
- package/src/forge/_generated/clientTypes.ts +1 -1
- package/src/forge/_generated/configRegistry.json +1 -1
- package/src/forge/_generated/configRegistry.ts +1 -1
- package/src/forge/_generated/dataGraph.json +2 -2
- package/src/forge/_generated/dataGraph.ts +3 -3
- package/src/forge/_generated/db.json +1 -1
- package/src/forge/_generated/db.ts +1 -1
- package/src/forge/_generated/dbSecurityManifest.json +1 -1
- package/src/forge/_generated/dbSecurityManifest.ts +1 -1
- package/src/forge/_generated/dbSessionContext.json +1 -1
- package/src/forge/_generated/dbSessionContext.ts +1 -1
- package/src/forge/_generated/deployManifest.json +2 -2
- package/src/forge/_generated/deployManifest.ts +7 -7
- package/src/forge/_generated/devManifest.json +2 -2
- package/src/forge/_generated/devManifest.ts +3 -3
- package/src/forge/_generated/envSchema.json +1 -1
- package/src/forge/_generated/envSchema.ts +1 -1
- package/src/forge/_generated/frontendGraph.json +1 -1
- package/src/forge/_generated/frontendGraph.ts +1 -1
- package/src/forge/_generated/importGuards.json +2 -2
- package/src/forge/_generated/importGuards.ts +35 -1
- package/src/forge/_generated/index.ts +1 -1
- package/src/forge/_generated/liveProductionManifest.json +1 -1
- package/src/forge/_generated/liveProductionManifest.ts +1 -1
- package/src/forge/_generated/liveProtocol.json +1 -1
- package/src/forge/_generated/liveProtocol.ts +1 -1
- package/src/forge/_generated/liveQueryRegistry.json +2 -2
- package/src/forge/_generated/liveQueryRegistry.ts +3 -3
- package/src/forge/_generated/liveTransportConfig.json +1 -1
- package/src/forge/_generated/liveTransportConfig.ts +1 -1
- package/src/forge/_generated/makeRegistry.json +2 -2
- package/src/forge/_generated/makeRegistry.ts +2 -2
- package/src/forge/_generated/makeTemplates.json +1 -1
- package/src/forge/_generated/makeTemplates.ts +1 -1
- package/src/forge/_generated/mockMap.json +1 -1
- package/src/forge/_generated/mockMap.ts +1 -1
- package/src/forge/_generated/operationPlaybooks.md +7 -5
- package/src/forge/_generated/packageGraph.json +2 -2
- package/src/forge/_generated/packageGraph.ts +90964 -14284
- package/src/forge/_generated/packageUpgradeRegistry.json +2 -2
- package/src/forge/_generated/packageUpgradeRegistry.ts +2 -2
- package/src/forge/_generated/permissionMatrix.json +2 -2
- package/src/forge/_generated/permissionMatrix.ts +3 -3
- package/src/forge/_generated/policyRegistry.json +2 -2
- package/src/forge/_generated/policyRegistry.ts +3 -3
- package/src/forge/_generated/queryRegistry.json +2 -2
- package/src/forge/_generated/queryRegistry.ts +3 -3
- package/src/forge/_generated/react.d.ts +1 -1
- package/src/forge/_generated/react.ts +1 -1
- package/src/forge/_generated/reactManifest.json +2 -2
- package/src/forge/_generated/reactManifest.ts +3 -3
- package/src/forge/_generated/releaseManifest.json +2 -2
- package/src/forge/_generated/releaseManifest.ts +3 -3
- package/src/forge/_generated/rlsPolicies.json +1 -1
- package/src/forge/_generated/rlsPolicies.sql +1 -1
- package/src/forge/_generated/rlsPolicies.ts +1 -1
- package/src/forge/_generated/runtimeGraph.json +2 -2
- package/src/forge/_generated/runtimeGraph.ts +3 -3
- package/src/forge/_generated/runtimeMatrix.json +2 -2
- package/src/forge/_generated/runtimeMatrix.ts +106177 -7917
- package/src/forge/_generated/runtimeRegistry.ts +1 -1
- package/src/forge/_generated/runtimeRules.md +1 -1
- package/src/forge/_generated/secretRegistry.json +1 -1
- package/src/forge/_generated/secretRegistry.ts +1 -1
- package/src/forge/_generated/secretsContext.ts +1 -1
- package/src/forge/_generated/serverApi.ts +1 -1
- package/src/forge/_generated/sourceMapManifest.json +2 -2
- package/src/forge/_generated/sourceMapManifest.ts +2 -2
- package/src/forge/_generated/sqlPlan.json +1 -1
- package/src/forge/_generated/sqlPlan.ts +1 -1
- package/src/forge/_generated/subscriptionManifest.json +2 -2
- package/src/forge/_generated/subscriptionManifest.ts +3 -3
- package/src/forge/_generated/symbolicationManifest.json +2 -2
- package/src/forge/_generated/symbolicationManifest.ts +2 -2
- package/src/forge/_generated/telemetryRegistry.json +2 -2
- package/src/forge/_generated/telemetryRegistry.ts +3 -3
- package/src/forge/_generated/telemetrySinks.json +2 -2
- package/src/forge/_generated/telemetrySinks.ts +2 -2
- package/src/forge/_generated/tenantScope.json +2 -2
- package/src/forge/_generated/tenantScope.ts +3 -3
- package/src/forge/_generated/testGraph.json +2 -2
- package/src/forge/_generated/testGraph.ts +129 -75
- package/src/forge/_generated/testPlanRegistry.json +2 -2
- package/src/forge/_generated/testPlanRegistry.ts +2 -2
- package/src/forge/_generated/uiRoutes.json +1 -1
- package/src/forge/_generated/uiRoutes.ts +1 -1
- package/src/forge/_generated/uiScenarios.json +1 -1
- package/src/forge/_generated/uiScenarios.ts +1 -1
- package/src/forge/_generated/uiTestManifest.json +2 -2
- package/src/forge/_generated/uiTestManifest.ts +2 -2
- package/src/forge/_generated/workflowRegistry.json +2 -2
- package/src/forge/_generated/workflowRegistry.ts +3 -3
- package/src/forge/_generated/workflowSubscriptions.json +2 -2
- package/src/forge/_generated/workflowSubscriptions.ts +3 -3
- package/src/forge/cli/commands.ts +861 -861
- package/src/forge/cli/deps.ts +178 -11
- package/src/forge/cli/dev.ts +32 -5
- package/src/forge/cli/index.ts +7 -7
- package/src/forge/cli/main.ts +54 -54
- package/src/forge/cli/new.ts +29 -1
- package/src/forge/cli/output.ts +97 -97
- package/src/forge/cli/parse.ts +679 -673
- package/src/forge/cli/version.ts +1 -1
- package/src/forge/compiler/agent-contract/build.ts +28 -0
- package/src/forge/compiler/agent-contract/types.ts +16 -0
- package/src/forge/compiler/app-graph/build.ts +112 -112
- package/src/forge/compiler/app-graph/classify.ts +10 -10
- package/src/forge/compiler/app-graph/dup-symbol.ts +29 -29
- package/src/forge/compiler/app-graph/extract.ts +123 -123
- package/src/forge/compiler/app-graph/forge-apis.ts +29 -29
- package/src/forge/compiler/app-graph/index.ts +11 -11
- package/src/forge/compiler/app-graph/module-graph.ts +316 -316
- package/src/forge/compiler/app-graph/parser.ts +119 -119
- package/src/forge/compiler/app-graph/symbols.ts +48 -48
- package/src/forge/compiler/app-graph/tsconfig-hash.ts +62 -62
- package/src/forge/compiler/app-graph/types.ts +43 -43
- package/src/forge/compiler/app-graph/versions.ts +14 -14
- package/src/forge/compiler/cache/index.ts +17 -17
- package/src/forge/compiler/cache/key.ts +46 -46
- package/src/forge/compiler/cache/scheduler.ts +72 -72
- package/src/forge/compiler/cache/store.ts +78 -78
- package/src/forge/compiler/classifier/capabilities.ts +78 -78
- package/src/forge/compiler/classifier/classify.ts +113 -113
- package/src/forge/compiler/classifier/contexts.ts +188 -188
- package/src/forge/compiler/classifier/index.ts +18 -18
- package/src/forge/compiler/classifier/runtime-matrix.ts +45 -45
- package/src/forge/compiler/classifier/secrets.ts +41 -41
- package/src/forge/compiler/classifier/signals.ts +129 -129
- package/src/forge/compiler/diagnostics/codes.ts +125 -120
- package/src/forge/compiler/diagnostics/create.ts +87 -87
- package/src/forge/compiler/diagnostics/index.ts +41 -41
- package/src/forge/compiler/emitter/artifact-kind.ts +14 -14
- package/src/forge/compiler/emitter/barrel.ts +38 -38
- package/src/forge/compiler/emitter/constants.ts +7 -7
- package/src/forge/compiler/emitter/emit.ts +234 -237
- package/src/forge/compiler/emitter/index.ts +24 -24
- package/src/forge/compiler/emitter/lock.ts +61 -61
- package/src/forge/compiler/emitter/render.ts +73 -73
- package/src/forge/compiler/guards/artifacts.ts +96 -96
- package/src/forge/compiler/guards/check-import-guards.ts +106 -106
- package/src/forge/compiler/guards/index.ts +11 -11
- package/src/forge/compiler/guards/propagate-contexts.ts +57 -57
- package/src/forge/compiler/index.ts +17 -17
- package/src/forge/compiler/integration/add.ts +493 -493
- package/src/forge/compiler/integration/index.ts +17 -17
- package/src/forge/compiler/integration/plan.ts +279 -279
- package/src/forge/compiler/integration/render.ts +189 -189
- package/src/forge/compiler/integration/snapshot.ts +52 -52
- package/src/forge/compiler/orchestrator/discover.ts +214 -214
- package/src/forge/compiler/orchestrator/guards.ts +5 -5
- package/src/forge/compiler/orchestrator/index.ts +27 -27
- package/src/forge/compiler/orchestrator/manifest.ts +69 -69
- package/src/forge/compiler/orchestrator/orphans.ts +51 -51
- package/src/forge/compiler/orchestrator/plan.ts +804 -804
- package/src/forge/compiler/orchestrator/run.ts +178 -178
- package/src/forge/compiler/orchestrator/serialize.ts +859 -859
- package/src/forge/compiler/orchestrator/types.ts +23 -23
- package/src/forge/compiler/orchestrator/verify.ts +35 -35
- package/src/forge/compiler/package-graph/capabilities-stub.ts +33 -33
- package/src/forge/compiler/package-graph/checksum.ts +107 -97
- package/src/forge/compiler/package-graph/compiler.ts +444 -363
- package/src/forge/compiler/package-graph/constants.ts +4 -4
- package/src/forge/compiler/package-graph/exports-discovery.ts +91 -84
- package/src/forge/compiler/package-graph/extract-dts.ts +32 -32
- package/src/forge/compiler/package-graph/index.ts +24 -24
- package/src/forge/compiler/package-graph/jsdoc.ts +50 -50
- package/src/forge/compiler/package-graph/oracle.ts +326 -0
- package/src/forge/compiler/package-graph/read-file.ts +21 -21
- package/src/forge/compiler/package-graph/resolve.ts +131 -127
- package/src/forge/compiler/package-manager/adapter.ts +232 -232
- package/src/forge/compiler/package-manager/commands.ts +47 -47
- package/src/forge/compiler/package-manager/detect.ts +65 -65
- package/src/forge/compiler/package-manager/executor.ts +29 -29
- package/src/forge/compiler/package-manager/index.ts +22 -22
- package/src/forge/compiler/package-manager/parse-spec.ts +16 -16
- package/src/forge/compiler/package-manager/version.ts +20 -20
- package/src/forge/compiler/primitives/compare.ts +26 -26
- package/src/forge/compiler/primitives/hash.ts +42 -33
- package/src/forge/compiler/primitives/header.ts +43 -43
- package/src/forge/compiler/primitives/index.ts +45 -45
- package/src/forge/compiler/primitives/paths.ts +24 -24
- package/src/forge/compiler/primitives/serialize.ts +66 -66
- package/src/forge/compiler/primitives/sort.ts +87 -87
- package/src/forge/compiler/recipes/definitions.ts +269 -269
- package/src/forge/compiler/recipes/helpers.ts +37 -37
- package/src/forge/compiler/recipes/index.ts +21 -21
- package/src/forge/compiler/recipes/registry.ts +87 -87
- package/src/forge/compiler/sandbox/artifact-sanitize.ts +26 -26
- package/src/forge/compiler/sandbox/backends/child.ts +123 -123
- package/src/forge/compiler/sandbox/backends/docker.ts +173 -173
- package/src/forge/compiler/sandbox/index.ts +51 -51
- package/src/forge/compiler/sandbox/inspect.ts +143 -143
- package/src/forge/compiler/sandbox/inspector-entry.ts +115 -115
- package/src/forge/compiler/sandbox/limits.ts +31 -31
- package/src/forge/compiler/sandbox/scrub-env.ts +60 -60
- package/src/forge/compiler/sandbox/secret-scan.ts +54 -54
- package/src/forge/compiler/sandbox/serialize.ts +106 -106
- package/src/forge/compiler/sandbox/types.ts +7 -7
- package/src/forge/compiler/types/app-graph.ts +71 -71
- package/src/forge/compiler/types/capability.ts +29 -29
- package/src/forge/compiler/types/classification.ts +9 -9
- package/src/forge/compiler/types/cli.ts +85 -85
- package/src/forge/compiler/types/diagnostic.ts +2 -2
- package/src/forge/compiler/types/emit.ts +25 -25
- package/src/forge/compiler/types/import-guards.ts +19 -19
- package/src/forge/compiler/types/index.ts +98 -98
- package/src/forge/compiler/types/integration.ts +25 -25
- package/src/forge/compiler/types/json.ts +3 -3
- package/src/forge/compiler/types/lock.ts +37 -37
- package/src/forge/compiler/types/package-graph.ts +122 -77
- package/src/forge/compiler/types/runtime-matrix.ts +16 -16
- package/src/forge/compiler/types/runtime.ts +30 -30
- package/src/forge/compiler/types/sandbox.ts +24 -24
- package/src/forge/dev/server.ts +16 -2
- package/src/forge/refactor/index.ts +10 -2
- package/src/forge/refactor/runtime-rename.ts +598 -0
- package/src/forge/runtime/executor.ts +3 -2
- package/src/forge/runtime/live/live-query-runner.ts +2 -1
- package/src/forge/runtime/outbox/process.ts +2 -1
- package/src/forge/runtime/query/run-query.ts +2 -1
- package/src/forge/runtime/runner/run-entry.ts +2 -1
- package/src/forge/runtime/telemetry/sinks/posthog.ts +4 -5
- package/src/forge/runtime/telemetry/sinks/sentry.ts +4 -5
- package/src/forge/runtime/workflows/resolve-step.ts +2 -1
- package/src/forge/version.ts +3 -0
- package/templates/b2b-support-web/src/actions/captureTicketCreated.ts +7 -2
- package/templates/b2b-support-web/src/commands/closeTicket.ts +6 -1
- package/templates/b2b-support-web/src/commands/createTicket.ts +8 -2
- package/templates/b2b-support-web/src/queries/getTicket.ts +8 -1
- package/templates/b2b-support-web/web/components/CreateTicketForm.tsx +1 -2
- package/templates/b2b-support-web/web/components/PolicyDeniedDemo.tsx +1 -2
- package/templates/b2b-support-web/web/components/TicketList.tsx +1 -2
- package/templates/b2b-support-web/web/components/TraceDetails.tsx +1 -1
- package/templates/b2b-support-web/web/lib/forge.ts +1 -0
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { createDiagnostic } from "../compiler/diagnostics/create.ts";
|
|
3
|
+
import type { Diagnostic } from "../compiler/types/diagnostic.ts";
|
|
4
|
+
import type { PlannedFile, PlannedPatch } from "../make/types.ts";
|
|
5
|
+
import type { RefactorIntent } from "./types.ts";
|
|
6
|
+
import { isGenerated, makeFile, makePatchFromContent, patchFile, readText, walkFiles } from "./workspace-fs.ts";
|
|
7
|
+
|
|
8
|
+
export type RenameRuntimeEntryIntent = Extract<RefactorIntent, { kind: "renameRuntimeEntry" }>;
|
|
9
|
+
|
|
10
|
+
function diagnostic(
|
|
11
|
+
severity: Diagnostic["severity"],
|
|
12
|
+
code: string,
|
|
13
|
+
message: string,
|
|
14
|
+
file?: string,
|
|
15
|
+
): Diagnostic {
|
|
16
|
+
return createDiagnostic({
|
|
17
|
+
severity,
|
|
18
|
+
code,
|
|
19
|
+
message,
|
|
20
|
+
...(file ? { file } : {}),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function runtimeCollectionProperty(entryKind: RenameRuntimeEntryIntent["entryKind"]): string {
|
|
25
|
+
return {
|
|
26
|
+
command: "commands",
|
|
27
|
+
query: "queries",
|
|
28
|
+
liveQuery: "liveQueries",
|
|
29
|
+
action: "actions",
|
|
30
|
+
workflow: "workflows",
|
|
31
|
+
}[entryKind];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function runtimeEntryDirectories(entryKind: RenameRuntimeEntryIntent["entryKind"]): string[] {
|
|
35
|
+
return {
|
|
36
|
+
command: ["src/commands"],
|
|
37
|
+
query: ["src/queries"],
|
|
38
|
+
liveQuery: ["src/queries"],
|
|
39
|
+
action: ["src/actions"],
|
|
40
|
+
workflow: ["src/workflows"],
|
|
41
|
+
}[entryKind];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function runtimeEntryCallName(entryKind: RenameRuntimeEntryIntent["entryKind"]): string {
|
|
45
|
+
return {
|
|
46
|
+
command: "command",
|
|
47
|
+
query: "query",
|
|
48
|
+
liveQuery: "liveQuery",
|
|
49
|
+
action: "action",
|
|
50
|
+
workflow: "workflow",
|
|
51
|
+
}[entryKind];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function runtimeHttpSegment(entryKind: RenameRuntimeEntryIntent["entryKind"]): string | null {
|
|
55
|
+
return {
|
|
56
|
+
command: "commands",
|
|
57
|
+
query: "queries",
|
|
58
|
+
liveQuery: "live",
|
|
59
|
+
action: null,
|
|
60
|
+
workflow: null,
|
|
61
|
+
}[entryKind];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isTypeScriptLike(file: string): boolean {
|
|
65
|
+
return file.endsWith(".ts") || file.endsWith(".tsx") || file.endsWith(".js") || file.endsWith(".jsx");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function scriptKindForFile(file: string): ts.ScriptKind {
|
|
69
|
+
if (file.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
70
|
+
if (file.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
71
|
+
if (file.endsWith(".js")) return ts.ScriptKind.JS;
|
|
72
|
+
return ts.ScriptKind.TS;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function renameIdentifierNode(to: string): ts.Identifier {
|
|
76
|
+
return ts.factory.createIdentifier(to);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function isRuntimeEntryCall(node: ts.Expression | undefined, entryKind: RenameRuntimeEntryIntent["entryKind"]): boolean {
|
|
80
|
+
if (!node || !ts.isCallExpression(node)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const expected = runtimeEntryCallName(entryKind);
|
|
84
|
+
return (
|
|
85
|
+
(ts.isIdentifier(node.expression) && node.expression.text === expected) ||
|
|
86
|
+
(ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === expected)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function isCapabilityMapRuntimeAccess(
|
|
91
|
+
node: ts.PropertyAccessExpression,
|
|
92
|
+
from: string,
|
|
93
|
+
entryKind: RenameRuntimeEntryIntent["entryKind"],
|
|
94
|
+
sourceFile: ts.SourceFile,
|
|
95
|
+
): boolean {
|
|
96
|
+
if (node.name.text !== from) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const collection = runtimeCollectionProperty(entryKind);
|
|
100
|
+
const parent = node.expression;
|
|
101
|
+
if (ts.isIdentifier(parent)) {
|
|
102
|
+
return parent.text === collection && hasForgeBridgeImport(sourceFile, collection);
|
|
103
|
+
}
|
|
104
|
+
if (!ts.isPropertyAccessExpression(parent)) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
if (parent.name.text !== collection) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
const root = parent.expression;
|
|
111
|
+
return (
|
|
112
|
+
ts.isIdentifier(root) &&
|
|
113
|
+
hasForgeBridgeImport(sourceFile, root.text) &&
|
|
114
|
+
(root.text === "api" ||
|
|
115
|
+
root.text === "client" ||
|
|
116
|
+
root.text === "commands" ||
|
|
117
|
+
root.text === "queries" ||
|
|
118
|
+
root.text === "liveQueries")
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function importLooksLikeForgeBridge(specifier: string): boolean {
|
|
123
|
+
const normalized = specifier.replace(/\\/g, "/");
|
|
124
|
+
return (
|
|
125
|
+
normalized.includes("/_generated/") ||
|
|
126
|
+
normalized.endsWith("/_generated/api") ||
|
|
127
|
+
normalized.endsWith("/_generated/api.js") ||
|
|
128
|
+
normalized.endsWith("/_generated/api.ts") ||
|
|
129
|
+
normalized.endsWith("/lib/forge") ||
|
|
130
|
+
normalized.endsWith("/lib/forge.js") ||
|
|
131
|
+
normalized.endsWith("/lib/forge.ts") ||
|
|
132
|
+
normalized.endsWith("/lib/forge.tsx") ||
|
|
133
|
+
normalized === "forge/client" ||
|
|
134
|
+
normalized === "forge/react"
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function hasForgeBridgeImport(sourceFile: ts.SourceFile, name: string): boolean {
|
|
139
|
+
for (const statement of sourceFile.statements) {
|
|
140
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (!importLooksLikeForgeBridge(statement.moduleSpecifier.text)) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const importClause = statement.importClause;
|
|
147
|
+
if (!importClause) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (importClause.name?.text === name) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
const namedBindings = importClause.namedBindings;
|
|
154
|
+
if (!namedBindings || !ts.isNamedImports(namedBindings)) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (namedBindings.elements.some((element) => element.name.text === name)) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function hookKindForCall(node: ts.CallExpression): RenameRuntimeEntryIntent["entryKind"] | null {
|
|
165
|
+
if (!ts.isIdentifier(node.expression)) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const map: Record<string, RenameRuntimeEntryIntent["entryKind"]> = {
|
|
169
|
+
useCommand: "command",
|
|
170
|
+
useQuery: "query",
|
|
171
|
+
useLiveQuery: "liveQuery",
|
|
172
|
+
};
|
|
173
|
+
return map[node.expression.text] ?? null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function clientMethodForEntry(entryKind: RenameRuntimeEntryIntent["entryKind"]): string | null {
|
|
177
|
+
return {
|
|
178
|
+
command: "command",
|
|
179
|
+
query: "query",
|
|
180
|
+
liveQuery: "liveQuery",
|
|
181
|
+
action: null,
|
|
182
|
+
workflow: null,
|
|
183
|
+
}[entryKind];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function isRuntimeStringLiteralContext(
|
|
187
|
+
node: ts.StringLiteral | ts.NoSubstitutionTemplateLiteral,
|
|
188
|
+
intent: RenameRuntimeEntryIntent,
|
|
189
|
+
): boolean {
|
|
190
|
+
const parent = node.parent;
|
|
191
|
+
if (ts.isCallExpression(parent)) {
|
|
192
|
+
const hookKind = hookKindForCall(parent);
|
|
193
|
+
if (hookKind === intent.entryKind && parent.arguments[0] === node) {
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
const clientMethod = clientMethodForEntry(intent.entryKind);
|
|
197
|
+
if (
|
|
198
|
+
clientMethod &&
|
|
199
|
+
ts.isPropertyAccessExpression(parent.expression) &&
|
|
200
|
+
parent.expression.name.text === clientMethod &&
|
|
201
|
+
parent.arguments[0] === node
|
|
202
|
+
) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const segment = runtimeHttpSegment(intent.entryKind);
|
|
207
|
+
if (segment && runtimeHttpPathReferences(node.text, segment, intent.from)) {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function renameImportSpecifierPath(specifier: string, from: string, to: string): string {
|
|
214
|
+
const slashIndex = specifier.lastIndexOf("/");
|
|
215
|
+
if (slashIndex === -1) {
|
|
216
|
+
return specifier;
|
|
217
|
+
}
|
|
218
|
+
const prefix = specifier.slice(0, slashIndex + 1);
|
|
219
|
+
const leaf = specifier.slice(slashIndex + 1);
|
|
220
|
+
for (const ext of ["", ".js", ".jsx", ".ts", ".tsx"]) {
|
|
221
|
+
if (leaf === `${from}${ext}`) {
|
|
222
|
+
return `${prefix}${to}${ext}`;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return specifier;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function importSpecifierReferencesRuntimeEntry(specifier: string, from: string, to = from): boolean {
|
|
229
|
+
return renameImportSpecifierPath(specifier, from, to) !== specifier;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function runtimeHttpPathReferences(value: string, segment: string, name: string): boolean {
|
|
233
|
+
const marker = `/${segment}/${name}`;
|
|
234
|
+
const index = value.indexOf(marker);
|
|
235
|
+
if (index === -1) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
const next = value[index + marker.length];
|
|
239
|
+
return next === undefined || next === "/" || next === "?" || next === "#" || next === "&";
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function renameRuntimeHttpPath(value: string, segment: string, from: string, to: string): string {
|
|
243
|
+
const marker = `/${segment}/${from}`;
|
|
244
|
+
if (!runtimeHttpPathReferences(value, segment, from)) {
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
let output = "";
|
|
248
|
+
let cursor = 0;
|
|
249
|
+
while (cursor < value.length) {
|
|
250
|
+
const index = value.indexOf(marker, cursor);
|
|
251
|
+
if (index === -1) {
|
|
252
|
+
output += value.slice(cursor);
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
const next = value[index + marker.length];
|
|
256
|
+
if (next === undefined || next === "/" || next === "?" || next === "#" || next === "&") {
|
|
257
|
+
output += value.slice(cursor, index) + `/${segment}/${to}`;
|
|
258
|
+
cursor = index + marker.length;
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
output += value.slice(cursor, index + marker.length);
|
|
262
|
+
cursor = index + marker.length;
|
|
263
|
+
}
|
|
264
|
+
return output;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function findRuntimeEntryFile(
|
|
268
|
+
workspaceRoot: string,
|
|
269
|
+
entryKind: RenameRuntimeEntryIntent["entryKind"],
|
|
270
|
+
name: string,
|
|
271
|
+
): string | null {
|
|
272
|
+
for (const dir of runtimeEntryDirectories(entryKind)) {
|
|
273
|
+
for (const ext of [".ts", ".tsx"]) {
|
|
274
|
+
const candidate = `${dir}/${name}${ext}`;
|
|
275
|
+
if (readText(workspaceRoot, candidate)) {
|
|
276
|
+
return candidate;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
for (const file of walkFiles(workspaceRoot)) {
|
|
281
|
+
if (!runtimeEntryDirectories(entryKind).some((dir) => file.startsWith(`${dir}/`))) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
const content = readText(workspaceRoot, file) ?? "";
|
|
285
|
+
if (content.includes(`export const ${name}`)) {
|
|
286
|
+
return file;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export function sourceReferencesRuntimeEntry(source: string, file: string, intent: RenameRuntimeEntryIntent): boolean {
|
|
293
|
+
if (file.endsWith(`/${intent.from}.ts`) || file.endsWith(`/${intent.from}.tsx`)) {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
if (!source.includes(intent.from)) {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
if (isTypeScriptLike(file)) {
|
|
300
|
+
const sourceFile = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, scriptKindForFile(file));
|
|
301
|
+
let found = false;
|
|
302
|
+
const visit = (node: ts.Node): void => {
|
|
303
|
+
if (found) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (
|
|
307
|
+
ts.isVariableDeclaration(node) &&
|
|
308
|
+
ts.isIdentifier(node.name) &&
|
|
309
|
+
node.name.text === intent.from &&
|
|
310
|
+
isRuntimeEntryCall(node.initializer, intent.entryKind)
|
|
311
|
+
) {
|
|
312
|
+
found = true;
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (ts.isPropertyAccessExpression(node) && isCapabilityMapRuntimeAccess(node, intent.from, intent.entryKind, sourceFile)) {
|
|
316
|
+
found = true;
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (
|
|
320
|
+
(ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) &&
|
|
321
|
+
node.text === intent.from &&
|
|
322
|
+
isRuntimeStringLiteralContext(node, intent)
|
|
323
|
+
) {
|
|
324
|
+
found = true;
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
328
|
+
if (importSpecifierReferencesRuntimeEntry(node.moduleSpecifier.text, intent.from)) {
|
|
329
|
+
found = true;
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const segment = runtimeHttpSegment(intent.entryKind);
|
|
334
|
+
if (
|
|
335
|
+
segment &&
|
|
336
|
+
(ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) &&
|
|
337
|
+
runtimeHttpPathReferences(node.text, segment, intent.from)
|
|
338
|
+
) {
|
|
339
|
+
found = true;
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
ts.forEachChild(node, visit);
|
|
343
|
+
};
|
|
344
|
+
visit(sourceFile);
|
|
345
|
+
return found;
|
|
346
|
+
}
|
|
347
|
+
if (file.endsWith(".json")) {
|
|
348
|
+
try {
|
|
349
|
+
return jsonReferencesRuntimeEntry(JSON.parse(source) as unknown, intent.from, intent.entryKind);
|
|
350
|
+
} catch {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function jsonReferencesRuntimeEntry(value: unknown, name: string, entryKind: RenameRuntimeEntryIntent["entryKind"]): boolean {
|
|
358
|
+
return jsonReferencesRuntimeEntryAtKey(value, name, entryKind, undefined);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function runtimeJsonKeys(entryKind: RenameRuntimeEntryIntent["entryKind"]): Set<string> {
|
|
362
|
+
return new Set([
|
|
363
|
+
runtimeEntryCallName(entryKind),
|
|
364
|
+
runtimeCollectionProperty(entryKind),
|
|
365
|
+
entryKind,
|
|
366
|
+
]);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function jsonReferencesRuntimeEntryAtKey(
|
|
370
|
+
value: unknown,
|
|
371
|
+
name: string,
|
|
372
|
+
entryKind: RenameRuntimeEntryIntent["entryKind"],
|
|
373
|
+
key: string | undefined,
|
|
374
|
+
): boolean {
|
|
375
|
+
const allowedKeys = runtimeJsonKeys(entryKind);
|
|
376
|
+
if (typeof value === "string") {
|
|
377
|
+
return value === name && !!key && allowedKeys.has(key);
|
|
378
|
+
}
|
|
379
|
+
if (Array.isArray(value)) {
|
|
380
|
+
return value.some((entry) => jsonReferencesRuntimeEntryAtKey(entry, name, entryKind, key));
|
|
381
|
+
}
|
|
382
|
+
if (value && typeof value === "object") {
|
|
383
|
+
const record = value as Record<string, unknown>;
|
|
384
|
+
if (record.kind === entryKind && record.name === name) {
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
return Object.entries(record).some(([childKey, entry]) =>
|
|
388
|
+
jsonReferencesRuntimeEntryAtKey(entry, name, entryKind, childKey),
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function renameRuntimeEntryInJson(source: string, intent: RenameRuntimeEntryIntent): string {
|
|
395
|
+
const parsed = JSON.parse(source) as unknown;
|
|
396
|
+
return `${JSON.stringify(renameRuntimeEntryJsonValue(parsed, intent), null, 2)}\n`;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function renameRuntimeEntryJsonValue(value: unknown, intent: RenameRuntimeEntryIntent): unknown {
|
|
400
|
+
return renameRuntimeEntryJsonValueAtKey(value, intent, undefined);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function renameRuntimeEntryJsonValueAtKey(
|
|
404
|
+
value: unknown,
|
|
405
|
+
intent: RenameRuntimeEntryIntent,
|
|
406
|
+
key: string | undefined,
|
|
407
|
+
): unknown {
|
|
408
|
+
const allowedKeys = runtimeJsonKeys(intent.entryKind);
|
|
409
|
+
if (typeof value === "string") {
|
|
410
|
+
return value === intent.from && !!key && allowedKeys.has(key) ? intent.to : value;
|
|
411
|
+
}
|
|
412
|
+
if (Array.isArray(value)) {
|
|
413
|
+
return value.map((entry) => renameRuntimeEntryJsonValueAtKey(entry, intent, key));
|
|
414
|
+
}
|
|
415
|
+
if (value && typeof value === "object") {
|
|
416
|
+
const record = value as Record<string, unknown>;
|
|
417
|
+
const output: Record<string, unknown> = {};
|
|
418
|
+
for (const [childKey, entry] of Object.entries(record)) {
|
|
419
|
+
output[childKey] =
|
|
420
|
+
childKey === "name" && record.kind === intent.entryKind && entry === intent.from
|
|
421
|
+
? intent.to
|
|
422
|
+
: renameRuntimeEntryJsonValueAtKey(entry, intent, childKey);
|
|
423
|
+
}
|
|
424
|
+
return output;
|
|
425
|
+
}
|
|
426
|
+
return value;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
export function renameRuntimeEntryContent(source: string, file: string, intent: RenameRuntimeEntryIntent): string {
|
|
430
|
+
if (isTypeScriptLike(file)) {
|
|
431
|
+
return renameRuntimeEntryInSource(source, file, intent);
|
|
432
|
+
}
|
|
433
|
+
if (file.endsWith(".json")) {
|
|
434
|
+
return renameRuntimeEntryInJson(source, intent);
|
|
435
|
+
}
|
|
436
|
+
return source;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function renameRuntimeEntryInSource(source: string, file: string, intent: RenameRuntimeEntryIntent): string {
|
|
440
|
+
const sourceFile = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, scriptKindForFile(file));
|
|
441
|
+
const transform: ts.TransformerFactory<ts.SourceFile> = (context) => {
|
|
442
|
+
const visit: ts.Visitor = (node) => {
|
|
443
|
+
if (
|
|
444
|
+
ts.isVariableDeclaration(node) &&
|
|
445
|
+
ts.isIdentifier(node.name) &&
|
|
446
|
+
node.name.text === intent.from &&
|
|
447
|
+
isRuntimeEntryCall(node.initializer, intent.entryKind)
|
|
448
|
+
) {
|
|
449
|
+
return ts.factory.updateVariableDeclaration(
|
|
450
|
+
node,
|
|
451
|
+
renameIdentifierNode(intent.to),
|
|
452
|
+
node.exclamationToken,
|
|
453
|
+
node.type,
|
|
454
|
+
ts.visitNode(node.initializer, visit, ts.isExpression) ?? node.initializer,
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
if (ts.isPropertyAccessExpression(node) && isCapabilityMapRuntimeAccess(node, intent.from, intent.entryKind, sourceFile)) {
|
|
458
|
+
return ts.factory.updatePropertyAccessExpression(node, node.expression, renameIdentifierNode(intent.to));
|
|
459
|
+
}
|
|
460
|
+
if (
|
|
461
|
+
(ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) &&
|
|
462
|
+
node.text === intent.from &&
|
|
463
|
+
isRuntimeStringLiteralContext(node, intent)
|
|
464
|
+
) {
|
|
465
|
+
return ts.isNoSubstitutionTemplateLiteral(node)
|
|
466
|
+
? ts.factory.createNoSubstitutionTemplateLiteral(intent.to)
|
|
467
|
+
: ts.factory.createStringLiteral(intent.to);
|
|
468
|
+
}
|
|
469
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
470
|
+
const segment = runtimeHttpSegment(intent.entryKind);
|
|
471
|
+
if (segment) {
|
|
472
|
+
const nextPath = renameRuntimeHttpPath(node.text, segment, intent.from, intent.to);
|
|
473
|
+
if (nextPath !== node.text) {
|
|
474
|
+
return ts.isNoSubstitutionTemplateLiteral(node)
|
|
475
|
+
? ts.factory.createNoSubstitutionTemplateLiteral(nextPath)
|
|
476
|
+
: ts.factory.createStringLiteral(nextPath);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
481
|
+
const nextSpecifier = renameImportSpecifierPath(node.moduleSpecifier.text, intent.from, intent.to);
|
|
482
|
+
if (nextSpecifier !== node.moduleSpecifier.text) {
|
|
483
|
+
return ts.factory.updateImportDeclaration(
|
|
484
|
+
node,
|
|
485
|
+
node.modifiers,
|
|
486
|
+
node.importClause,
|
|
487
|
+
ts.factory.createStringLiteral(nextSpecifier),
|
|
488
|
+
node.attributes,
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return ts.visitEachChild(node, visit, context);
|
|
493
|
+
};
|
|
494
|
+
return (node) => ts.visitNode(node, visit) as ts.SourceFile;
|
|
495
|
+
};
|
|
496
|
+
const result = ts.transform(sourceFile, [transform]);
|
|
497
|
+
try {
|
|
498
|
+
const transformed = result.transformed[0];
|
|
499
|
+
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
500
|
+
return printer.printFile(transformed);
|
|
501
|
+
} finally {
|
|
502
|
+
result.dispose();
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
export function buildRenameRuntimeEntryPlan(
|
|
507
|
+
workspaceRoot: string,
|
|
508
|
+
intent: RenameRuntimeEntryIntent,
|
|
509
|
+
): {
|
|
510
|
+
patches: PlannedPatch[];
|
|
511
|
+
filesToCreate: PlannedFile[];
|
|
512
|
+
filesToDelete: Array<{ file: string; description: string }>;
|
|
513
|
+
diagnostics: Diagnostic[];
|
|
514
|
+
} {
|
|
515
|
+
const patches: PlannedPatch[] = [];
|
|
516
|
+
const filesToCreate: PlannedFile[] = [];
|
|
517
|
+
const filesToDelete: Array<{ file: string; description: string }> = [];
|
|
518
|
+
const diagnostics: Diagnostic[] = [];
|
|
519
|
+
const definitionFile = findRuntimeEntryFile(workspaceRoot, intent.entryKind, intent.from);
|
|
520
|
+
if (!definitionFile) {
|
|
521
|
+
return {
|
|
522
|
+
patches,
|
|
523
|
+
filesToCreate,
|
|
524
|
+
filesToDelete,
|
|
525
|
+
diagnostics: [
|
|
526
|
+
diagnostic(
|
|
527
|
+
"error",
|
|
528
|
+
"FORGE_REFACTOR_TARGET_NOT_FOUND",
|
|
529
|
+
`${intent.entryKind} '${intent.from}' was not found`,
|
|
530
|
+
),
|
|
531
|
+
],
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
let found = false;
|
|
536
|
+
for (const file of walkFiles(workspaceRoot)) {
|
|
537
|
+
if (isGenerated(file)) {
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
const content = readText(workspaceRoot, file) ?? "";
|
|
541
|
+
if (!sourceReferencesRuntimeEntry(content, file, intent)) {
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
if (file === definitionFile) {
|
|
545
|
+
const shouldRenameFile = file.endsWith(`/${intent.from}.ts`) || file.endsWith(`/${intent.from}.tsx`);
|
|
546
|
+
const renamedContent = renameRuntimeEntryContent(content, file, intent);
|
|
547
|
+
if (shouldRenameFile) {
|
|
548
|
+
const renamedPath = file.replace(`/${intent.from}.`, `/${intent.to}.`);
|
|
549
|
+
filesToCreate.push(
|
|
550
|
+
makeFile(
|
|
551
|
+
workspaceRoot,
|
|
552
|
+
renamedPath,
|
|
553
|
+
`Rename ${intent.entryKind} file ${intent.from} to ${intent.to}`,
|
|
554
|
+
renamedContent,
|
|
555
|
+
),
|
|
556
|
+
);
|
|
557
|
+
filesToDelete.push({
|
|
558
|
+
file,
|
|
559
|
+
description: `Remove old ${intent.entryKind} file ${intent.from}`,
|
|
560
|
+
});
|
|
561
|
+
} else {
|
|
562
|
+
const patch = makePatchFromContent(
|
|
563
|
+
file,
|
|
564
|
+
`Rename ${intent.entryKind} ${intent.from} to ${intent.to}`,
|
|
565
|
+
content,
|
|
566
|
+
renamedContent,
|
|
567
|
+
);
|
|
568
|
+
if (patch) {
|
|
569
|
+
patches.push(patch);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
found = true;
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
const patch = patchFile(
|
|
576
|
+
workspaceRoot,
|
|
577
|
+
file,
|
|
578
|
+
`Rename ${intent.entryKind} ${intent.from} to ${intent.to}`,
|
|
579
|
+
(source) => renameRuntimeEntryContent(source, file, intent),
|
|
580
|
+
);
|
|
581
|
+
if (patch) {
|
|
582
|
+
found = true;
|
|
583
|
+
patches.push(patch);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (!found) {
|
|
588
|
+
diagnostics.push(
|
|
589
|
+
diagnostic(
|
|
590
|
+
"error",
|
|
591
|
+
"FORGE_REFACTOR_TARGET_NOT_FOUND",
|
|
592
|
+
`${intent.entryKind} '${intent.from}' was not found in editable sources`,
|
|
593
|
+
),
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
return { patches, filesToCreate, filesToDelete, diagnostics };
|
|
598
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { nodeFileSystem } from "../compiler/fs/index.ts";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
3
4
|
import { buildAppGraph } from "../compiler/app-graph/build.ts";
|
|
4
5
|
import { buildRuntimeMatrix } from "../compiler/classifier/runtime-matrix.ts";
|
|
5
6
|
import { classify } from "../compiler/classifier/classify.ts";
|
|
@@ -218,7 +219,7 @@ async function applyMocks(workspaceRoot: string, lock: ForgeLock | null): Promis
|
|
|
218
219
|
continue;
|
|
219
220
|
}
|
|
220
221
|
|
|
221
|
-
const mod = (await import(absolute)) as Record<string, unknown>;
|
|
222
|
+
const mod = (await import(pathToFileURL(absolute).href)) as Record<string, unknown>;
|
|
222
223
|
const factoryName = `create${capitalizeSegment(packageName)}Mock`;
|
|
223
224
|
const factory = mod[factoryName];
|
|
224
225
|
|
|
@@ -387,7 +388,7 @@ export async function runEntry(
|
|
|
387
388
|
});
|
|
388
389
|
|
|
389
390
|
const absolutePath = join(workspaceRoot, entry.file);
|
|
390
|
-
const mod = (await import(absolutePath)) as Record<string, unknown>;
|
|
391
|
+
const mod = (await import(pathToFileURL(absolutePath).href)) as Record<string, unknown>;
|
|
391
392
|
const resolved = resolveHandlerFromModule(mod, entry.name);
|
|
392
393
|
|
|
393
394
|
if (!resolved) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
2
3
|
import { createDiagnostic } from "../../compiler/diagnostics/create.ts";
|
|
3
4
|
import {
|
|
4
5
|
FORGE_LIVEQUERY_AI_FORBIDDEN,
|
|
@@ -185,7 +186,7 @@ export async function runLiveQuery(
|
|
|
185
186
|
|
|
186
187
|
try {
|
|
187
188
|
const absolutePath = join(workspaceRoot, liveQuery.file);
|
|
188
|
-
const mod = (await import(absolutePath)) as Record<string, unknown>;
|
|
189
|
+
const mod = (await import(pathToFileURL(absolutePath).href)) as Record<string, unknown>;
|
|
189
190
|
const exported = mod[liveQuery.exportName];
|
|
190
191
|
|
|
191
192
|
if (
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
2
3
|
import { createDiagnostic } from "../../compiler/diagnostics/create.ts";
|
|
3
4
|
import {
|
|
4
5
|
FORGE_OUTBOX_PROCESS_FAILED,
|
|
@@ -66,7 +67,7 @@ async function runDeliveryAction(
|
|
|
66
67
|
await prepareRuntimeEnvironment(workspaceRoot, { mock, db: adapter });
|
|
67
68
|
|
|
68
69
|
const absolutePath = join(workspaceRoot, entry.file);
|
|
69
|
-
const mod = (await import(absolutePath)) as Record<string, unknown>;
|
|
70
|
+
const mod = (await import(pathToFileURL(absolutePath).href)) as Record<string, unknown>;
|
|
70
71
|
const exported = mod[entry.name];
|
|
71
72
|
|
|
72
73
|
if (
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
2
3
|
import { createDiagnostic } from "../../compiler/diagnostics/create.ts";
|
|
3
4
|
import {
|
|
4
5
|
FORGE_POLICY_DENIED,
|
|
@@ -249,7 +250,7 @@ export async function runQuery(
|
|
|
249
250
|
await setDbSessionContext(tx, auth);
|
|
250
251
|
|
|
251
252
|
const absolutePath = join(workspaceRoot, query.file);
|
|
252
|
-
const mod = (await import(absolutePath)) as Record<string, unknown>;
|
|
253
|
+
const mod = (await import(pathToFileURL(absolutePath).href)) as Record<string, unknown>;
|
|
253
254
|
const exported = mod[query.name];
|
|
254
255
|
|
|
255
256
|
if (
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
2
3
|
import { createDiagnostic } from "../../compiler/diagnostics/create.ts";
|
|
3
4
|
import {
|
|
4
5
|
FORGE_DB_ADAPTER_UNAVAILABLE,
|
|
@@ -162,7 +163,7 @@ export async function executeResolvedEntry(
|
|
|
162
163
|
runtime.tableMap
|
|
163
164
|
) {
|
|
164
165
|
const absolutePath = join(workspaceRoot, entry.file);
|
|
165
|
-
const mod = (await import(absolutePath)) as Record<string, unknown>;
|
|
166
|
+
const mod = (await import(pathToFileURL(absolutePath).href)) as Record<string, unknown>;
|
|
166
167
|
const exported = mod[entry.name];
|
|
167
168
|
const handler = (exported as { handler: (ctx: unknown, args: unknown) => unknown })
|
|
168
169
|
.handler;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
1
3
|
import type { ForgeTelemetryEnvelope } from "../types.ts";
|
|
2
4
|
|
|
3
5
|
export interface PosthogCaptureFn {
|
|
@@ -33,11 +35,8 @@ export async function sendToPosthog(
|
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
try {
|
|
36
|
-
const adapterPath =
|
|
37
|
-
|
|
38
|
-
"/",
|
|
39
|
-
);
|
|
40
|
-
const mod = (await import(adapterPath)) as {
|
|
38
|
+
const adapterPath = join(workspaceRoot, "src/forge/_generated/packages/posthog.server.ts");
|
|
39
|
+
const mod = (await import(pathToFileURL(adapterPath).href)) as {
|
|
41
40
|
createPosthogServer?: () => { capture: (args: unknown) => void; shutdown: () => Promise<void> };
|
|
42
41
|
};
|
|
43
42
|
|