theokit 0.2.3 → 0.4.0-beta.0
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/LICENSE +201 -0
- package/dist/{actions-virtual-module-E6PU47GV.js → actions-virtual-module-HWNTIEPI.js} +40 -6
- package/dist/actions-virtual-module-HWNTIEPI.js.map +1 -0
- package/dist/{actions-virtual-module-E7IELVHL.js → actions-virtual-module-SEIPACG5.js} +40 -6
- package/dist/actions-virtual-module-SEIPACG5.js.map +1 -0
- package/dist/add-2ZFFGGE4.js +0 -0
- package/dist/{app-typed-client-IMILAGER.js → app-typed-client-62FYBLVJ.js} +4 -4
- package/dist/{app-typed-client-FOWJP534.js → app-typed-client-ITIYTBXO.js} +4 -4
- package/dist/aws-lambda-XYCGZH3I.js +0 -0
- package/dist/broadcast-QOQGUNNK.js +0 -0
- package/dist/{build-KRSHWXMJ.js → build-HIGHJQQV.js} +9 -9
- package/dist/build-request-body-preview-II2235E6.js +0 -0
- package/dist/bun-K73TQEWC.js +0 -0
- package/dist/check-PZR67OY5.js +0 -0
- package/dist/{chunk-ERAZNHHR.js → chunk-2VQKDRVF.js} +3 -3
- package/dist/chunk-5ODOE6EF.js +0 -0
- package/dist/{chunk-MOT42NAH.js → chunk-5OFPQK6N.js} +18 -3
- package/dist/chunk-5OFPQK6N.js.map +1 -0
- package/dist/{chunk-7DHGV77J.js → chunk-7TOMTMHT.js} +18 -3
- package/dist/chunk-7TOMTMHT.js.map +1 -0
- package/dist/{chunk-2BQYEBCK.js → chunk-B6RP57M3.js} +84 -2
- package/dist/chunk-B6RP57M3.js.map +1 -0
- package/dist/{chunk-RIBIAL7A.js → chunk-BIGBFZSU.js} +12 -7
- package/dist/chunk-BIGBFZSU.js.map +1 -0
- package/dist/chunk-F3TG5FJV.js +0 -0
- package/dist/{chunk-F7RLPDXW.js → chunk-JAAHOGKI.js} +12 -7
- package/dist/chunk-JAAHOGKI.js.map +1 -0
- package/dist/chunk-KT3MWNZG.js +0 -0
- package/dist/chunk-O7335ZGH.js +0 -0
- package/dist/{chunk-QLGES2HC.js → chunk-OXIQI2XZ.js} +85 -3
- package/dist/chunk-OXIQI2XZ.js.map +1 -0
- package/dist/chunk-TPCT3MXV.js +0 -0
- package/dist/{chunk-SEVYARIU.js → chunk-TRH2L3FI.js} +3 -3
- package/dist/chunk-WZ7CPVQB.js +0 -0
- package/dist/chunk-X4JAX2U3.js +0 -0
- package/dist/chunk-XMS5VRIK.js +0 -0
- package/dist/chunk-XP7YXRHO.js +0 -0
- package/dist/chunk-ZJW5FFYJ.js +0 -0
- package/dist/chunk-ZOXNJV2O.js +0 -0
- package/dist/cli/index.js +29 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/cloudflare-LCAOTRYZ.js +0 -0
- package/dist/configure-agent-registry-6YGTJYBC.js +0 -0
- package/dist/deno-deploy-ZN4RE5HF.js +0 -0
- package/dist/{dev-UZJVBUF3.js → dev-266MVCVA.js} +7 -7
- package/dist/{dev-emit-I3CKOHML.js → dev-emit-NO6OZJOQ.js} +4 -4
- package/dist/{dev-emit-3CHM73TV.js → dev-emit-RBSFZZNO.js} +4 -4
- package/dist/dispatcher-E6QV32BO.js +0 -0
- package/dist/{dist-E6BL4ZVY.js → dist-5V77Z223.js} +1 -1
- package/dist/docker-EZDA5FT7.js +0 -0
- package/dist/generate-DT4IIAHF.js +0 -0
- package/dist/index.js +3 -3
- package/dist/info-FJ4NXKTB.js +0 -0
- package/dist/lib-NL5JXGEB.js +0 -0
- package/dist/netlify-5VQ22Z2P.js +0 -0
- package/dist/node-3APTLGWB.js +0 -0
- package/dist/{openapi-ILYEJ6OR.js → openapi-FNVSWZOL.js} +4 -4
- package/dist/proper-lockfile-4Y3DP3RP.js +0 -0
- package/dist/{registry-5QFTLOL2.js → registry-4MZ26TZD.js} +1 -1
- package/dist/router-RGZFX75G.js +274 -0
- package/dist/router-RGZFX75G.js.map +1 -0
- package/dist/{routes-IGT42JJO.js → routes-H4SPLFHJ.js} +3 -3
- package/dist/scan-C2BOKLSY.js +0 -0
- package/dist/schema-VR6YNVLQ.js +0 -0
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.js +3 -3
- package/dist/server-routes-hmr-GZJGPWMS.js +44 -0
- package/dist/server-routes-hmr-GZJGPWMS.js.map +1 -0
- package/dist/server-routes-hmr-PBHSKCQJ.js +42 -0
- package/dist/server-routes-hmr-PBHSKCQJ.js.map +1 -0
- package/dist/services-typed-client-ZX5JUHH3.js +0 -0
- package/dist/sqlite-vec-ARPNUBWT.js +0 -0
- package/dist/{start-UX2IPPSH.js → start-HX3QUSOS.js} +6 -6
- package/dist/static-TZBVBDTB.js +0 -0
- package/dist/storage-manager-D5KBXXKB.js +0 -0
- package/dist/theo-cloud-3K4DGB3S.js +0 -0
- package/dist/upgrade-readiness-GUJBCJIS.js +0 -0
- package/dist/vercel-MWW24ABC.js +0 -0
- package/dist/vite-plugin/index.js +3 -3
- package/dist/{vite-plugin-FTYXDKKG.js → vite-plugin-IK3NOWXS.js} +4 -4
- package/package.json +7 -7
- package/dist/actions-virtual-module-E6PU47GV.js.map +0 -1
- package/dist/actions-virtual-module-E7IELVHL.js.map +0 -1
- package/dist/chunk-2BQYEBCK.js.map +0 -1
- package/dist/chunk-7DHGV77J.js.map +0 -1
- package/dist/chunk-F7RLPDXW.js.map +0 -1
- package/dist/chunk-MOT42NAH.js.map +0 -1
- package/dist/chunk-QLGES2HC.js.map +0 -1
- package/dist/chunk-RIBIAL7A.js.map +0 -1
- /package/dist/{app-typed-client-FOWJP534.js.map → app-typed-client-62FYBLVJ.js.map} +0 -0
- /package/dist/{app-typed-client-IMILAGER.js.map → app-typed-client-ITIYTBXO.js.map} +0 -0
- /package/dist/{build-KRSHWXMJ.js.map → build-HIGHJQQV.js.map} +0 -0
- /package/dist/{chunk-ERAZNHHR.js.map → chunk-2VQKDRVF.js.map} +0 -0
- /package/dist/{chunk-SEVYARIU.js.map → chunk-TRH2L3FI.js.map} +0 -0
- /package/dist/{dev-UZJVBUF3.js.map → dev-266MVCVA.js.map} +0 -0
- /package/dist/{dev-emit-I3CKOHML.js.map → dev-emit-NO6OZJOQ.js.map} +0 -0
- /package/dist/{dev-emit-3CHM73TV.js.map → dev-emit-RBSFZZNO.js.map} +0 -0
- /package/dist/{dist-E6BL4ZVY.js.map → dist-5V77Z223.js.map} +0 -0
- /package/dist/{openapi-ILYEJ6OR.js.map → openapi-FNVSWZOL.js.map} +0 -0
- /package/dist/{registry-5QFTLOL2.js.map → registry-4MZ26TZD.js.map} +0 -0
- /package/dist/{routes-IGT42JJO.js.map → routes-H4SPLFHJ.js.map} +0 -0
- /package/dist/{start-UX2IPPSH.js.map → start-HX3QUSOS.js.map} +0 -0
- /package/dist/{vite-plugin-FTYXDKKG.js.map → vite-plugin-IK3NOWXS.js.map} +0 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "tsx/esm";
|
|
3
|
+
import "./chunk-KT3MWNZG.js";
|
|
4
|
+
|
|
5
|
+
// src/cli/commands/migrate/router.ts
|
|
6
|
+
import { execFileSync } from "child_process";
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
|
|
8
|
+
import { createServer } from "net";
|
|
9
|
+
import { dirname, resolve } from "path";
|
|
10
|
+
|
|
11
|
+
// src/cli/commands/migrate/router-codemod.ts
|
|
12
|
+
import { readdirSync, statSync } from "fs";
|
|
13
|
+
import { extname, join, relative, sep } from "path";
|
|
14
|
+
var ROUTE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx"]);
|
|
15
|
+
var TEST_OR_SPEC_RE = /\.(test|spec)\.[jt]sx?$/;
|
|
16
|
+
var RouterMigrationCollisionError = class extends Error {
|
|
17
|
+
name = "RouterMigrationCollisionError";
|
|
18
|
+
from;
|
|
19
|
+
to;
|
|
20
|
+
constructor(from, to) {
|
|
21
|
+
super(
|
|
22
|
+
`Router migration collision: ${from} would rename to ${to}, but that file already exists (case-insensitive match). Resolve manually.`
|
|
23
|
+
);
|
|
24
|
+
this.from = from;
|
|
25
|
+
this.to = to;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
function computeDepthDelta(from, to, routesDir) {
|
|
29
|
+
const depthOf = (p) => {
|
|
30
|
+
const rel = relative(routesDir, p).replace(/\\/g, "/");
|
|
31
|
+
return rel.split("/").length - 1;
|
|
32
|
+
};
|
|
33
|
+
return depthOf(to) - depthOf(from);
|
|
34
|
+
}
|
|
35
|
+
function rewriteRelativeImports(source, delta) {
|
|
36
|
+
if (delta <= 0) return source;
|
|
37
|
+
const prefix = "../".repeat(delta);
|
|
38
|
+
const transformSpecifier = (specifier) => {
|
|
39
|
+
if (specifier.startsWith("./")) return `${prefix}${specifier.slice(2)}`;
|
|
40
|
+
return `${prefix}${specifier}`;
|
|
41
|
+
};
|
|
42
|
+
const fromRe = /\bfrom\s+(['"])(\.{1,2}\/[^'"]+)\1/g;
|
|
43
|
+
const dynRe = /\bimport\s*\(\s*(['"])(\.{1,2}\/[^'"]+)\1\s*\)/g;
|
|
44
|
+
const sideRe = /\bimport\s+(['"])(\.{1,2}\/[^'"]+)\1/g;
|
|
45
|
+
const fromSub = (_m, q, spec) => `from ${q}${transformSpecifier(spec)}${q}`;
|
|
46
|
+
const dynSub = (_m, q, spec) => `import(${q}${transformSpecifier(spec)}${q})`;
|
|
47
|
+
const sideSub = (_m, q, spec) => `import ${q}${transformSpecifier(spec)}${q}`;
|
|
48
|
+
return source.replace(fromRe, fromSub).replace(dynRe, dynSub).replace(sideRe, sideSub);
|
|
49
|
+
}
|
|
50
|
+
function isTestOrSpecFile(filePath) {
|
|
51
|
+
return TEST_OR_SPEC_RE.test(filePath);
|
|
52
|
+
}
|
|
53
|
+
function hasDotOutsideBrackets(segment) {
|
|
54
|
+
let depth = 0;
|
|
55
|
+
for (const ch of segment) {
|
|
56
|
+
if (ch === "[") depth++;
|
|
57
|
+
else if (ch === "]") depth--;
|
|
58
|
+
else if (ch === "." && depth === 0) return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
function splitDottedSegmentOutsideBrackets(segment) {
|
|
63
|
+
const parts = [];
|
|
64
|
+
let current = "";
|
|
65
|
+
let depth = 0;
|
|
66
|
+
for (const ch of segment) {
|
|
67
|
+
if (ch === "[") {
|
|
68
|
+
depth++;
|
|
69
|
+
current += ch;
|
|
70
|
+
} else if (ch === "]") {
|
|
71
|
+
depth--;
|
|
72
|
+
current += ch;
|
|
73
|
+
} else if (ch === "." && depth === 0) {
|
|
74
|
+
if (current) parts.push(current);
|
|
75
|
+
current = "";
|
|
76
|
+
} else {
|
|
77
|
+
current += ch;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (current) parts.push(current);
|
|
81
|
+
return parts;
|
|
82
|
+
}
|
|
83
|
+
function toDirectoryNestedPath(filePath, routesDir) {
|
|
84
|
+
const rel = relative(routesDir, filePath).replace(/\\/g, "/");
|
|
85
|
+
const ext = extname(rel);
|
|
86
|
+
const withoutExt = rel.slice(0, -ext.length);
|
|
87
|
+
const flattened = withoutExt.split("/").flatMap(splitDottedSegmentOutsideBrackets);
|
|
88
|
+
return join(routesDir, `${flattened.join(sep)}${ext}`);
|
|
89
|
+
}
|
|
90
|
+
function walkRoutes(root, onFile) {
|
|
91
|
+
let entries;
|
|
92
|
+
try {
|
|
93
|
+
entries = readdirSync(root, { withFileTypes: true });
|
|
94
|
+
} catch {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
for (const entry of entries) {
|
|
98
|
+
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
99
|
+
const full = join(root, entry.name);
|
|
100
|
+
if (entry.isDirectory()) {
|
|
101
|
+
walkRoutes(full, onFile);
|
|
102
|
+
} else if (entry.isFile() && ROUTE_EXTENSIONS.has(extname(entry.name))) {
|
|
103
|
+
onFile(full);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function isDottedRouteFile(filePath, routesDir) {
|
|
108
|
+
const rel = relative(routesDir, filePath).replace(/\\/g, "/");
|
|
109
|
+
const ext = extname(rel);
|
|
110
|
+
const withoutExt = rel.slice(0, -ext.length);
|
|
111
|
+
return withoutExt.split("/").some(hasDotOutsideBrackets);
|
|
112
|
+
}
|
|
113
|
+
function planRouterMigration(routesDir) {
|
|
114
|
+
const plan = [];
|
|
115
|
+
const existingPathsLowercase = /* @__PURE__ */ new Set();
|
|
116
|
+
walkRoutes(routesDir, (absPath) => {
|
|
117
|
+
existingPathsLowercase.add(absPath.toLowerCase());
|
|
118
|
+
});
|
|
119
|
+
walkRoutes(routesDir, (absPath) => {
|
|
120
|
+
if (isTestOrSpecFile(absPath)) return;
|
|
121
|
+
if (!isDottedRouteFile(absPath, routesDir)) return;
|
|
122
|
+
const to = toDirectoryNestedPath(absPath, routesDir);
|
|
123
|
+
const targetLower = to.toLowerCase();
|
|
124
|
+
if (existingPathsLowercase.has(targetLower) && targetLower !== absPath.toLowerCase()) {
|
|
125
|
+
throw new RouterMigrationCollisionError(absPath, to);
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
if (statSync(to).isFile()) {
|
|
129
|
+
throw new RouterMigrationCollisionError(absPath, to);
|
|
130
|
+
}
|
|
131
|
+
} catch (err) {
|
|
132
|
+
if (err instanceof RouterMigrationCollisionError) throw err;
|
|
133
|
+
}
|
|
134
|
+
plan.push({ from: absPath, to });
|
|
135
|
+
});
|
|
136
|
+
return plan;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/cli/commands/migrate/router.ts
|
|
140
|
+
var RouterMigrationPartialFailure = class extends Error {
|
|
141
|
+
name = "RouterMigrationPartialFailure";
|
|
142
|
+
filesAlreadyMigrated;
|
|
143
|
+
failedFile;
|
|
144
|
+
causeMessage;
|
|
145
|
+
constructor(filesAlreadyMigrated, failedFile, causeMessage) {
|
|
146
|
+
super(
|
|
147
|
+
`Router migration partial failure: ${filesAlreadyMigrated.length} files migrated successfully, then failed on ${failedFile}: ${causeMessage}. Re-run \`theokit migrate router\` to retry \u2014 already-migrated files will be skipped.`
|
|
148
|
+
);
|
|
149
|
+
this.filesAlreadyMigrated = filesAlreadyMigrated;
|
|
150
|
+
this.failedFile = failedFile;
|
|
151
|
+
this.causeMessage = causeMessage;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
async function isPortInUse(port) {
|
|
155
|
+
return await new Promise((resolve2) => {
|
|
156
|
+
const probe = createServer();
|
|
157
|
+
probe.once("error", (err) => {
|
|
158
|
+
probe.close(() => {
|
|
159
|
+
resolve2(err.code === "EADDRINUSE");
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
probe.once("listening", () => {
|
|
163
|
+
probe.close(() => {
|
|
164
|
+
resolve2(false);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
probe.listen(port, "127.0.0.1");
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async function findRunningDevServerPort() {
|
|
171
|
+
for (const port of [3e3, 3100]) {
|
|
172
|
+
if (await isPortInUse(port)) return port;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
function tryGitMv(from, to) {
|
|
177
|
+
try {
|
|
178
|
+
mkdirSync(dirname(to), { recursive: true });
|
|
179
|
+
execFileSync("git", ["mv", from, to], { stdio: "pipe" });
|
|
180
|
+
return true;
|
|
181
|
+
} catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function fallbackRename(from, to) {
|
|
186
|
+
mkdirSync(dirname(to), { recursive: true });
|
|
187
|
+
renameSync(from, to);
|
|
188
|
+
}
|
|
189
|
+
function applyRename(item) {
|
|
190
|
+
if (!existsSync(item.from)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (existsSync(item.to)) {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Refusing to overwrite existing file at ${item.to} during migration of ${item.from}`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
if (!tryGitMv(item.from, item.to)) {
|
|
199
|
+
fallbackRename(item.from, item.to);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function applyImportRewrite(item, routesDir) {
|
|
203
|
+
const delta = computeDepthDelta(item.from, item.to, routesDir);
|
|
204
|
+
if (delta <= 0) return;
|
|
205
|
+
const source = readFileSync(item.to, "utf8");
|
|
206
|
+
const rewritten = rewriteRelativeImports(source, delta);
|
|
207
|
+
if (rewritten !== source) {
|
|
208
|
+
writeFileSync(item.to, rewritten, "utf8");
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function makeLog(silent) {
|
|
212
|
+
if (silent) {
|
|
213
|
+
return (_msg) => {
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return (msg) => {
|
|
217
|
+
console.log(msg);
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
async function assertNoRunningDevServer(opts) {
|
|
221
|
+
if (opts.force) return;
|
|
222
|
+
const runningPort = await findRunningDevServerPort();
|
|
223
|
+
if (runningPort !== null) {
|
|
224
|
+
throw new Error(
|
|
225
|
+
`Detected theokit dev server running on port ${runningPort}. STOP it before running migration to avoid HMR cascade (see EC-2). Re-run with --force to override.`
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function executeRenames(plan, routesDir, log) {
|
|
230
|
+
const migrated = [];
|
|
231
|
+
for (const item of plan) {
|
|
232
|
+
try {
|
|
233
|
+
applyRename(item);
|
|
234
|
+
applyImportRewrite(item, routesDir);
|
|
235
|
+
migrated.push(item);
|
|
236
|
+
log(` \u2713 ${item.from} \u2192 ${item.to}`);
|
|
237
|
+
} catch (err) {
|
|
238
|
+
const causeMessage = err instanceof Error ? err.message : String(err);
|
|
239
|
+
throw new RouterMigrationPartialFailure(
|
|
240
|
+
migrated.map((m) => m.from),
|
|
241
|
+
item.from,
|
|
242
|
+
causeMessage
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return migrated;
|
|
247
|
+
}
|
|
248
|
+
async function routerMigrateCommand(opts = {}) {
|
|
249
|
+
const routesDir = opts.routesDir ?? resolve(process.cwd(), "server", "routes");
|
|
250
|
+
const log = makeLog(opts.silent);
|
|
251
|
+
await assertNoRunningDevServer(opts);
|
|
252
|
+
const plan = planRouterMigration(routesDir);
|
|
253
|
+
if (plan.length === 0) {
|
|
254
|
+
log(" \u2713 Router already uses directory-nested convention. Nothing to do.");
|
|
255
|
+
return { migrated: [], alreadyClean: true };
|
|
256
|
+
}
|
|
257
|
+
log(` \u2192 Migrating ${plan.length} dotted route(s) to directory-nested form...`);
|
|
258
|
+
if (opts.dryRun) {
|
|
259
|
+
for (const item of plan) {
|
|
260
|
+
log(` [dry-run] ${item.from} \u2192 ${item.to}`);
|
|
261
|
+
}
|
|
262
|
+
return { migrated: [], alreadyClean: false };
|
|
263
|
+
}
|
|
264
|
+
const migrated = executeRenames(plan, routesDir, log);
|
|
265
|
+
log(` \u2713 Migrated ${migrated.length} route(s).`);
|
|
266
|
+
return { migrated, alreadyClean: false };
|
|
267
|
+
}
|
|
268
|
+
export {
|
|
269
|
+
RouterMigrationPartialFailure,
|
|
270
|
+
findRunningDevServerPort,
|
|
271
|
+
isPortInUse,
|
|
272
|
+
routerMigrateCommand
|
|
273
|
+
};
|
|
274
|
+
//# sourceMappingURL=router-RGZFX75G.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/migrate/router.ts","../src/cli/commands/migrate/router-codemod.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time codemod: derives all FS paths from the user's `<routesDir>`\n * argument (defaults to `<cwd>/server/routes`). No HTTP input reaches\n * these fs calls. Operator runs this manually via `theokit migrate router`.\n */\n/**\n * G6 T2.1 — `theokit migrate router` CLI subcommand.\n *\n * Plan: .claude/knowledge-base/plans/g6-router-convention-plan.md v1.1\n *\n * Wraps the pure `planRouterMigration` with side effects:\n * - EC-2: pre-flight `isPortInUse(3000|3100)` warning to prevent the\n * dev-server HMR cascade described in the edge-case review.\n * - EC-7: partial failure produces a typed `RouterMigrationPartialFailure`\n * with `filesAlreadyMigrated` so a re-run can continue from where it\n * stopped (idempotent by virtue of `planRouterMigration`).\n * - Prefers `git mv $from $to` so the rename appears as a single\n * history entry; falls back to `mkdir -p $(dirname $to) && fs.rename`\n * when not in a git repo or git mv fails.\n */\nimport { execFileSync } from 'node:child_process'\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { createServer } from 'node:net'\nimport { dirname, resolve } from 'node:path'\n\nimport {\n computeDepthDelta,\n planRouterMigration,\n rewriteRelativeImports,\n type RouterMigrationPlanItem,\n} from './router-codemod.js'\n\nexport interface RouterMigrateOptions {\n /** Absolute path to `<project>/server/routes`. Defaults to `<cwd>/server/routes`. */\n routesDir?: string\n /**\n * Skip the EC-2 dev-server port pre-flight check (CI / non-TTY).\n * Default: false.\n */\n force?: boolean\n /** When true, prints the plan but performs no renames (dry-run). */\n dryRun?: boolean\n /** When true, suppresses stdout (used in tests). */\n silent?: boolean\n}\n\n/**\n * Thrown when the codemod completes with at least one successful rename\n * AND at least one failure — caller can re-run safely (idempotent) and\n * the second pass will skip already-migrated files.\n */\nexport class RouterMigrationPartialFailure extends Error {\n override readonly name = 'RouterMigrationPartialFailure'\n readonly filesAlreadyMigrated: string[]\n readonly failedFile: string\n readonly causeMessage: string\n constructor(filesAlreadyMigrated: string[], failedFile: string, causeMessage: string) {\n super(\n `Router migration partial failure: ${filesAlreadyMigrated.length} files migrated successfully, then failed on ${failedFile}: ${causeMessage}. Re-run \\`theokit migrate router\\` to retry — already-migrated files will be skipped.`,\n )\n this.filesAlreadyMigrated = filesAlreadyMigrated\n this.failedFile = failedFile\n this.causeMessage = causeMessage\n }\n}\n\n/**\n * EC-2: dev-server detection. Returns true if the port is in use (someone\n * is already listening on localhost:<port>). Uses Node's `node:net` —\n * zero new deps.\n */\nexport async function isPortInUse(port: number): Promise<boolean> {\n return await new Promise<boolean>((resolve) => {\n const probe = createServer()\n probe.once('error', (err: NodeJS.ErrnoException) => {\n probe.close(() => {\n resolve(err.code === 'EADDRINUSE')\n })\n })\n probe.once('listening', () => {\n probe.close(() => {\n resolve(false)\n })\n })\n probe.listen(port, '127.0.0.1')\n })\n}\n\n/**\n * EC-2 pre-flight: returns the first port in use among the typical\n * theokit dev ports (3000 + 3100) so the caller can warn the user.\n */\nexport async function findRunningDevServerPort(): Promise<number | null> {\n for (const port of [3000, 3100]) {\n if (await isPortInUse(port)) return port\n }\n return null\n}\n\nfunction tryGitMv(from: string, to: string): boolean {\n try {\n mkdirSync(dirname(to), { recursive: true })\n // Arguments are absolute paths from a recursive walk of <routesDir>.\n // Pass as argv to avoid shell parsing entirely (no `shell: true`).\n // `git` is resolved via the operator's PATH (same security model as\n // every other CLI tool — `theokit dev`, `pnpm install`, etc.).\n // eslint-disable-next-line sonarjs/no-os-command-from-path\n execFileSync('git', ['mv', from, to], { stdio: 'pipe' })\n return true\n } catch {\n return false\n }\n}\n\nfunction fallbackRename(from: string, to: string): void {\n mkdirSync(dirname(to), { recursive: true })\n renameSync(from, to)\n}\n\nfunction applyRename(item: RouterMigrationPlanItem): void {\n if (!existsSync(item.from)) {\n // Idempotency: already migrated — skip silently\n return\n }\n if (existsSync(item.to)) {\n // The plan() phase would have thrown CollisionError if we knew about\n // it at plan time. This branch covers a race condition where the\n // target was created between plan and apply.\n throw new Error(\n `Refusing to overwrite existing file at ${item.to} during migration of ${item.from}`,\n )\n }\n if (!tryGitMv(item.from, item.to)) {\n fallbackRename(item.from, item.to)\n }\n}\n\n/**\n * Adjust relative imports inside the renamed file to compensate for the\n * extra nesting depth. Without this, `import { foo } from './chat'` inside\n * a file moved from `routes/admin.sdk-config.ts` → `routes/admin/sdk-config.ts`\n * would fail to resolve at typecheck/runtime — the import needs `../chat`\n * now that the file lives one level deeper.\n */\nfunction applyImportRewrite(item: RouterMigrationPlanItem, routesDir: string): void {\n const delta = computeDepthDelta(item.from, item.to, routesDir)\n if (delta <= 0) return\n const source = readFileSync(item.to, 'utf8')\n const rewritten = rewriteRelativeImports(source, delta)\n if (rewritten !== source) {\n writeFileSync(item.to, rewritten, 'utf8')\n }\n}\n\nexport interface RouterMigrateResult {\n /** Successfully renamed (from, to) pairs. */\n migrated: RouterMigrationPlanItem[]\n /** Plan was empty — nothing to do (already-nested). */\n alreadyClean: boolean\n}\n\ntype LogFn = (msg: string) => void\n\nfunction makeLog(silent: boolean | undefined): LogFn {\n if (silent) {\n return (_msg: string) => {\n // intentionally silent\n }\n }\n return (msg: string) => {\n console.log(msg)\n }\n}\n\nasync function assertNoRunningDevServer(opts: RouterMigrateOptions): Promise<void> {\n if (opts.force) return\n const runningPort = await findRunningDevServerPort()\n if (runningPort !== null) {\n throw new Error(\n `Detected theokit dev server running on port ${runningPort}. STOP it before running migration to avoid HMR cascade (see EC-2). Re-run with --force to override.`,\n )\n }\n}\n\nfunction executeRenames(\n plan: readonly RouterMigrationPlanItem[],\n routesDir: string,\n log: LogFn,\n): RouterMigrationPlanItem[] {\n const migrated: RouterMigrationPlanItem[] = []\n for (const item of plan) {\n try {\n applyRename(item)\n applyImportRewrite(item, routesDir)\n migrated.push(item)\n log(` ✓ ${item.from} → ${item.to}`)\n } catch (err) {\n // EC-7: partial failure observability — emit structured error with\n // the list of already-migrated files so a re-run can recover.\n const causeMessage = err instanceof Error ? err.message : String(err)\n throw new RouterMigrationPartialFailure(\n migrated.map((m) => m.from),\n item.from,\n causeMessage,\n )\n }\n }\n return migrated\n}\n\nexport async function routerMigrateCommand(\n opts: RouterMigrateOptions = {},\n): Promise<RouterMigrateResult> {\n const routesDir = opts.routesDir ?? resolve(process.cwd(), 'server', 'routes')\n const log = makeLog(opts.silent)\n\n await assertNoRunningDevServer(opts)\n\n const plan = planRouterMigration(routesDir)\n if (plan.length === 0) {\n log(' ✓ Router already uses directory-nested convention. Nothing to do.')\n return { migrated: [], alreadyClean: true }\n }\n\n log(` → Migrating ${plan.length} dotted route(s) to directory-nested form...`)\n\n if (opts.dryRun) {\n for (const item of plan) {\n log(` [dry-run] ${item.from} → ${item.to}`)\n }\n return { migrated: [], alreadyClean: false }\n }\n\n const migrated = executeRenames(plan, routesDir, log)\n log(` ✓ Migrated ${migrated.length} route(s).`)\n return { migrated, alreadyClean: false }\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time codemod: walks `<routesDir>` derived from the operator's\n * cwd via `theokit migrate router`. No HTTP input reaches these fs calls.\n */\n/**\n * G6 T2.1 — Pure codemod core for `theokit migrate router`.\n *\n * Plan: .claude/knowledge-base/plans/g6-router-convention-plan.md v1.1\n *\n * `planRouterMigration` walks `<routesDir>` recursively and returns the\n * set of (from, to) renames required to convert legacy dotted-basename\n * routes (`auth.[provider].login.ts`) into the directory-nested form\n * (`auth/[provider]/login.ts`). The function is PURE — it does NOT\n * touch the filesystem beyond `readdirSync`/`statSync`. The CLI subcommand\n * (`router.ts`) is responsible for executing the renames via `git mv`\n * or `fs.rename` with the appropriate error handling.\n *\n * Edge cases covered:\n * - EC-4: co-located `*.test.[jt]sx?` / `*.spec.[jt]sx?` files are\n * silently skipped (same filter as the scanner).\n * - EC-5: target collision detection is CASE-INSENSITIVE so a\n * macOS/Windows dev doesn't silently overwrite a sibling file that\n * differs only in case.\n * - Idempotent: invoked twice on the same tree, the second pass is empty.\n */\nimport { readdirSync, statSync } from 'node:fs'\nimport { extname, join, relative, sep } from 'node:path'\n\nconst ROUTE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\nconst TEST_OR_SPEC_RE = /\\.(test|spec)\\.[jt]sx?$/\n\n/**\n * One pending rename emitted by `planRouterMigration`.\n */\nexport interface RouterMigrationPlanItem {\n /** Absolute path of the offending dotted-basename file. */\n from: string\n /** Absolute path of the proposed directory-nested replacement. */\n to: string\n}\n\n/**\n * `RouterMigrationCollisionError` is thrown when migrating a dotted file\n * would overwrite an existing file (case-insensitive). The caller MUST\n * resolve the conflict manually before re-running the codemod.\n */\nexport class RouterMigrationCollisionError extends Error {\n override readonly name = 'RouterMigrationCollisionError'\n readonly from: string\n readonly to: string\n constructor(from: string, to: string) {\n super(\n `Router migration collision: ${from} would rename to ${to}, but that file already exists (case-insensitive match). Resolve manually.`,\n )\n this.from = from\n this.to = to\n }\n}\n\n/**\n * Compute the depth delta (number of extra `..` levels needed) between\n * the original (dotted) path and the migrated (nested) path, relative\n * to a common `routesDir` ancestor.\n *\n * - `admin.sdk-config.ts` (depth 0) → `admin/sdk-config.ts` (depth 1): delta = 1\n * - `debug.stability.last.ts` (depth 0) → `debug/stability/last.ts` (depth 2): delta = 2\n * - `canvas/artifacts.[id].ts` (depth 1) → `canvas/artifacts/[id].ts` (depth 2): delta = 1\n */\nexport function computeDepthDelta(from: string, to: string, routesDir: string): number {\n const depthOf = (p: string): number => {\n const rel = relative(routesDir, p).replace(/\\\\/g, '/')\n // depth = number of `/` separators in the relative path\n return rel.split('/').length - 1\n }\n return depthOf(to) - depthOf(from)\n}\n\n/**\n * Rewrite all relative imports in `source` by prepending `../` × `delta`\n * to every `./X` or `../X` specifier. Absolute / package specifiers\n * (`theokit/server`, `zod`, `node:fs`) are untouched.\n *\n * Handles three import shapes:\n * - `import ... from './foo'`\n * - `import('./foo')` (dynamic)\n * - `import './foo'` (side-effect only)\n * - `export ... from './foo'` (re-exports)\n *\n * Pure: returns the new source; does NOT touch disk.\n */\nexport function rewriteRelativeImports(source: string, delta: number): string {\n if (delta <= 0) return source\n\n const prefix = '../'.repeat(delta)\n\n // Rewrites a captured relative specifier: `./foo` → `<prefix>foo`,\n // `../foo` → `<prefix>../foo`. Single source of truth for the algorithm\n // shared by all three import-shape regexes below.\n const transformSpecifier = (specifier: string): string => {\n if (specifier.startsWith('./')) return `${prefix}${specifier.slice(2)}`\n return `${prefix}${specifier}`\n }\n\n // Three narrow regexes keep us out of catastrophic-backtracking territory.\n // Each is anchored on a keyword (`from`, `import`) and uses a possessive\n // character class (`[^'\"]+`) for the specifier, so backtracking is bounded.\n const fromRe = /\\bfrom\\s+(['\"])(\\.{1,2}\\/[^'\"]+)\\1/g\n const dynRe = /\\bimport\\s*\\(\\s*(['\"])(\\.{1,2}\\/[^'\"]+)\\1\\s*\\)/g\n const sideRe = /\\bimport\\s+(['\"])(\\.{1,2}\\/[^'\"]+)\\1/g\n\n const fromSub = (_m: string, q: string, spec: string): string =>\n `from ${q}${transformSpecifier(spec)}${q}`\n const dynSub = (_m: string, q: string, spec: string): string =>\n `import(${q}${transformSpecifier(spec)}${q})`\n const sideSub = (_m: string, q: string, spec: string): string =>\n `import ${q}${transformSpecifier(spec)}${q}`\n\n // `from` covers both `import ... from '...'` and `export ... from '...'`\n // (the `\\bfrom\\s+` anchor matches the keyword position in both shapes).\n // `dynRe` handles `import('...')`. `sideRe` handles bare `import '...'`.\n // No overlap — `sideRe` requires `import` followed by whitespace then\n // a quote (vs. `import(` for dynRe and `import ... from` for fromRe).\n return source.replace(fromRe, fromSub).replace(dynRe, dynSub).replace(sideRe, sideSub)\n}\n\nfunction isTestOrSpecFile(filePath: string): boolean {\n return TEST_OR_SPEC_RE.test(filePath)\n}\n\nfunction hasDotOutsideBrackets(segment: string): boolean {\n let depth = 0\n for (const ch of segment) {\n if (ch === '[') depth++\n else if (ch === ']') depth--\n else if (ch === '.' && depth === 0) return true\n }\n return false\n}\n\nfunction splitDottedSegmentOutsideBrackets(segment: string): string[] {\n const parts: string[] = []\n let current = ''\n let depth = 0\n for (const ch of segment) {\n if (ch === '[') {\n depth++\n current += ch\n } else if (ch === ']') {\n depth--\n current += ch\n } else if (ch === '.' && depth === 0) {\n if (current) parts.push(current)\n current = ''\n } else {\n current += ch\n }\n }\n if (current) parts.push(current)\n return parts\n}\n\nfunction toDirectoryNestedPath(filePath: string, routesDir: string): string {\n const rel = relative(routesDir, filePath).replace(/\\\\/g, '/')\n const ext = extname(rel)\n const withoutExt = rel.slice(0, -ext.length)\n const flattened = withoutExt.split('/').flatMap(splitDottedSegmentOutsideBrackets)\n return join(routesDir, `${flattened.join(sep)}${ext}`)\n}\n\nfunction walkRoutes(root: string, onFile: (absPath: string) => void): void {\n let entries\n try {\n entries = readdirSync(root, { withFileTypes: true })\n } catch {\n return\n }\n for (const entry of entries) {\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue\n const full = join(root, entry.name)\n if (entry.isDirectory()) {\n walkRoutes(full, onFile)\n } else if (entry.isFile() && ROUTE_EXTENSIONS.has(extname(entry.name))) {\n onFile(full)\n }\n }\n}\n\nfunction isDottedRouteFile(filePath: string, routesDir: string): boolean {\n const rel = relative(routesDir, filePath).replace(/\\\\/g, '/')\n const ext = extname(rel)\n const withoutExt = rel.slice(0, -ext.length)\n return withoutExt.split('/').some(hasDotOutsideBrackets)\n}\n\n/**\n * Compute the migration plan for a `<server>/routes` tree.\n *\n * Pure: does NOT mutate the filesystem.\n *\n * @throws RouterMigrationCollisionError when a target collides with an\n * existing file (case-insensitive).\n */\nexport function planRouterMigration(routesDir: string): RouterMigrationPlanItem[] {\n const plan: RouterMigrationPlanItem[] = []\n const existingPathsLowercase = new Set<string>()\n\n walkRoutes(routesDir, (absPath) => {\n existingPathsLowercase.add(absPath.toLowerCase())\n })\n\n walkRoutes(routesDir, (absPath) => {\n if (isTestOrSpecFile(absPath)) return\n if (!isDottedRouteFile(absPath, routesDir)) return\n\n const to = toDirectoryNestedPath(absPath, routesDir)\n\n // EC-5: case-insensitive collision check — macOS HFS+/APFS default\n // and Windows NTFS treat case-only differences as the same path. If\n // any pre-existing file at a case-insensitive match exists, the codemod\n // would silently overwrite on those platforms; we bail explicitly.\n const targetLower = to.toLowerCase()\n if (existingPathsLowercase.has(targetLower) && targetLower !== absPath.toLowerCase()) {\n throw new RouterMigrationCollisionError(absPath, to)\n }\n // Also guard against statSync race using an explicit existence check.\n try {\n if (statSync(to).isFile()) {\n throw new RouterMigrationCollisionError(absPath, to)\n }\n } catch (err) {\n if (err instanceof RouterMigrationCollisionError) throw err\n // ENOENT — fine, target does not exist\n }\n\n plan.push({ from: absPath, to })\n })\n\n return plan\n}\n"],"mappings":";;;;;AAoBA,SAAS,oBAAoB;AAC7B,SAAS,YAAY,WAAW,cAAc,YAAY,qBAAqB;AAC/E,SAAS,oBAAoB;AAC7B,SAAS,SAAS,eAAe;;;ACEjC,SAAS,aAAa,gBAAgB;AACtC,SAAS,SAAS,MAAM,UAAU,WAAW;AAE7C,IAAM,mBAAmB,oBAAI,IAAI,CAAC,OAAO,QAAQ,OAAO,MAAM,CAAC;AAC/D,IAAM,kBAAkB;AAiBjB,IAAM,gCAAN,cAA4C,MAAM;AAAA,EACrC,OAAO;AAAA,EAChB;AAAA,EACA;AAAA,EACT,YAAY,MAAc,IAAY;AACpC;AAAA,MACE,+BAA+B,IAAI,oBAAoB,EAAE;AAAA,IAC3D;AACA,SAAK,OAAO;AACZ,SAAK,KAAK;AAAA,EACZ;AACF;AAWO,SAAS,kBAAkB,MAAc,IAAY,WAA2B;AACrF,QAAM,UAAU,CAAC,MAAsB;AACrC,UAAM,MAAM,SAAS,WAAW,CAAC,EAAE,QAAQ,OAAO,GAAG;AAErD,WAAO,IAAI,MAAM,GAAG,EAAE,SAAS;AAAA,EACjC;AACA,SAAO,QAAQ,EAAE,IAAI,QAAQ,IAAI;AACnC;AAeO,SAAS,uBAAuB,QAAgB,OAAuB;AAC5E,MAAI,SAAS,EAAG,QAAO;AAEvB,QAAM,SAAS,MAAM,OAAO,KAAK;AAKjC,QAAM,qBAAqB,CAAC,cAA8B;AACxD,QAAI,UAAU,WAAW,IAAI,EAAG,QAAO,GAAG,MAAM,GAAG,UAAU,MAAM,CAAC,CAAC;AACrE,WAAO,GAAG,MAAM,GAAG,SAAS;AAAA,EAC9B;AAKA,QAAM,SAAS;AACf,QAAM,QAAQ;AACd,QAAM,SAAS;AAEf,QAAM,UAAU,CAAC,IAAY,GAAW,SACtC,QAAQ,CAAC,GAAG,mBAAmB,IAAI,CAAC,GAAG,CAAC;AAC1C,QAAM,SAAS,CAAC,IAAY,GAAW,SACrC,UAAU,CAAC,GAAG,mBAAmB,IAAI,CAAC,GAAG,CAAC;AAC5C,QAAM,UAAU,CAAC,IAAY,GAAW,SACtC,UAAU,CAAC,GAAG,mBAAmB,IAAI,CAAC,GAAG,CAAC;AAO5C,SAAO,OAAO,QAAQ,QAAQ,OAAO,EAAE,QAAQ,OAAO,MAAM,EAAE,QAAQ,QAAQ,OAAO;AACvF;AAEA,SAAS,iBAAiB,UAA2B;AACnD,SAAO,gBAAgB,KAAK,QAAQ;AACtC;AAEA,SAAS,sBAAsB,SAA0B;AACvD,MAAI,QAAQ;AACZ,aAAW,MAAM,SAAS;AACxB,QAAI,OAAO,IAAK;AAAA,aACP,OAAO,IAAK;AAAA,aACZ,OAAO,OAAO,UAAU,EAAG,QAAO;AAAA,EAC7C;AACA,SAAO;AACT;AAEA,SAAS,kCAAkC,SAA2B;AACpE,QAAM,QAAkB,CAAC;AACzB,MAAI,UAAU;AACd,MAAI,QAAQ;AACZ,aAAW,MAAM,SAAS;AACxB,QAAI,OAAO,KAAK;AACd;AACA,iBAAW;AAAA,IACb,WAAW,OAAO,KAAK;AACrB;AACA,iBAAW;AAAA,IACb,WAAW,OAAO,OAAO,UAAU,GAAG;AACpC,UAAI,QAAS,OAAM,KAAK,OAAO;AAC/B,gBAAU;AAAA,IACZ,OAAO;AACL,iBAAW;AAAA,IACb;AAAA,EACF;AACA,MAAI,QAAS,OAAM,KAAK,OAAO;AAC/B,SAAO;AACT;AAEA,SAAS,sBAAsB,UAAkB,WAA2B;AAC1E,QAAM,MAAM,SAAS,WAAW,QAAQ,EAAE,QAAQ,OAAO,GAAG;AAC5D,QAAM,MAAM,QAAQ,GAAG;AACvB,QAAM,aAAa,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM;AAC3C,QAAM,YAAY,WAAW,MAAM,GAAG,EAAE,QAAQ,iCAAiC;AACjF,SAAO,KAAK,WAAW,GAAG,UAAU,KAAK,GAAG,CAAC,GAAG,GAAG,EAAE;AACvD;AAEA,SAAS,WAAW,MAAc,QAAyC;AACzE,MAAI;AACJ,MAAI;AACF,cAAU,YAAY,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EACrD,QAAQ;AACN;AAAA,EACF;AACA,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,KAAK,WAAW,GAAG,KAAK,MAAM,KAAK,WAAW,GAAG,EAAG;AAC9D,UAAM,OAAO,KAAK,MAAM,MAAM,IAAI;AAClC,QAAI,MAAM,YAAY,GAAG;AACvB,iBAAW,MAAM,MAAM;AAAA,IACzB,WAAW,MAAM,OAAO,KAAK,iBAAiB,IAAI,QAAQ,MAAM,IAAI,CAAC,GAAG;AACtE,aAAO,IAAI;AAAA,IACb;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,UAAkB,WAA4B;AACvE,QAAM,MAAM,SAAS,WAAW,QAAQ,EAAE,QAAQ,OAAO,GAAG;AAC5D,QAAM,MAAM,QAAQ,GAAG;AACvB,QAAM,aAAa,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM;AAC3C,SAAO,WAAW,MAAM,GAAG,EAAE,KAAK,qBAAqB;AACzD;AAUO,SAAS,oBAAoB,WAA8C;AAChF,QAAM,OAAkC,CAAC;AACzC,QAAM,yBAAyB,oBAAI,IAAY;AAE/C,aAAW,WAAW,CAAC,YAAY;AACjC,2BAAuB,IAAI,QAAQ,YAAY,CAAC;AAAA,EAClD,CAAC;AAED,aAAW,WAAW,CAAC,YAAY;AACjC,QAAI,iBAAiB,OAAO,EAAG;AAC/B,QAAI,CAAC,kBAAkB,SAAS,SAAS,EAAG;AAE5C,UAAM,KAAK,sBAAsB,SAAS,SAAS;AAMnD,UAAM,cAAc,GAAG,YAAY;AACnC,QAAI,uBAAuB,IAAI,WAAW,KAAK,gBAAgB,QAAQ,YAAY,GAAG;AACpF,YAAM,IAAI,8BAA8B,SAAS,EAAE;AAAA,IACrD;AAEA,QAAI;AACF,UAAI,SAAS,EAAE,EAAE,OAAO,GAAG;AACzB,cAAM,IAAI,8BAA8B,SAAS,EAAE;AAAA,MACrD;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,8BAA+B,OAAM;AAAA,IAE1D;AAEA,SAAK,KAAK,EAAE,MAAM,SAAS,GAAG,CAAC;AAAA,EACjC,CAAC;AAED,SAAO;AACT;;;AD3LO,IAAM,gCAAN,cAA4C,MAAM;AAAA,EACrC,OAAO;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACT,YAAY,sBAAgC,YAAoB,cAAsB;AACpF;AAAA,MACE,qCAAqC,qBAAqB,MAAM,gDAAgD,UAAU,KAAK,YAAY;AAAA,IAC7I;AACA,SAAK,uBAAuB;AAC5B,SAAK,aAAa;AAClB,SAAK,eAAe;AAAA,EACtB;AACF;AAOA,eAAsB,YAAY,MAAgC;AAChE,SAAO,MAAM,IAAI,QAAiB,CAACA,aAAY;AAC7C,UAAM,QAAQ,aAAa;AAC3B,UAAM,KAAK,SAAS,CAAC,QAA+B;AAClD,YAAM,MAAM,MAAM;AAChB,QAAAA,SAAQ,IAAI,SAAS,YAAY;AAAA,MACnC,CAAC;AAAA,IACH,CAAC;AACD,UAAM,KAAK,aAAa,MAAM;AAC5B,YAAM,MAAM,MAAM;AAChB,QAAAA,SAAQ,KAAK;AAAA,MACf,CAAC;AAAA,IACH,CAAC;AACD,UAAM,OAAO,MAAM,WAAW;AAAA,EAChC,CAAC;AACH;AAMA,eAAsB,2BAAmD;AACvE,aAAW,QAAQ,CAAC,KAAM,IAAI,GAAG;AAC/B,QAAI,MAAM,YAAY,IAAI,EAAG,QAAO;AAAA,EACtC;AACA,SAAO;AACT;AAEA,SAAS,SAAS,MAAc,IAAqB;AACnD,MAAI;AACF,cAAU,QAAQ,EAAE,GAAG,EAAE,WAAW,KAAK,CAAC;AAM1C,iBAAa,OAAO,CAAC,MAAM,MAAM,EAAE,GAAG,EAAE,OAAO,OAAO,CAAC;AACvD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,eAAe,MAAc,IAAkB;AACtD,YAAU,QAAQ,EAAE,GAAG,EAAE,WAAW,KAAK,CAAC;AAC1C,aAAW,MAAM,EAAE;AACrB;AAEA,SAAS,YAAY,MAAqC;AACxD,MAAI,CAAC,WAAW,KAAK,IAAI,GAAG;AAE1B;AAAA,EACF;AACA,MAAI,WAAW,KAAK,EAAE,GAAG;AAIvB,UAAM,IAAI;AAAA,MACR,0CAA0C,KAAK,EAAE,wBAAwB,KAAK,IAAI;AAAA,IACpF;AAAA,EACF;AACA,MAAI,CAAC,SAAS,KAAK,MAAM,KAAK,EAAE,GAAG;AACjC,mBAAe,KAAK,MAAM,KAAK,EAAE;AAAA,EACnC;AACF;AASA,SAAS,mBAAmB,MAA+B,WAAyB;AAClF,QAAM,QAAQ,kBAAkB,KAAK,MAAM,KAAK,IAAI,SAAS;AAC7D,MAAI,SAAS,EAAG;AAChB,QAAM,SAAS,aAAa,KAAK,IAAI,MAAM;AAC3C,QAAM,YAAY,uBAAuB,QAAQ,KAAK;AACtD,MAAI,cAAc,QAAQ;AACxB,kBAAc,KAAK,IAAI,WAAW,MAAM;AAAA,EAC1C;AACF;AAWA,SAAS,QAAQ,QAAoC;AACnD,MAAI,QAAQ;AACV,WAAO,CAAC,SAAiB;AAAA,IAEzB;AAAA,EACF;AACA,SAAO,CAAC,QAAgB;AACtB,YAAQ,IAAI,GAAG;AAAA,EACjB;AACF;AAEA,eAAe,yBAAyB,MAA2C;AACjF,MAAI,KAAK,MAAO;AAChB,QAAM,cAAc,MAAM,yBAAyB;AACnD,MAAI,gBAAgB,MAAM;AACxB,UAAM,IAAI;AAAA,MACR,+CAA+C,WAAW;AAAA,IAC5D;AAAA,EACF;AACF;AAEA,SAAS,eACP,MACA,WACA,KAC2B;AAC3B,QAAM,WAAsC,CAAC;AAC7C,aAAW,QAAQ,MAAM;AACvB,QAAI;AACF,kBAAY,IAAI;AAChB,yBAAmB,MAAM,SAAS;AAClC,eAAS,KAAK,IAAI;AAClB,UAAI,eAAU,KAAK,IAAI,WAAM,KAAK,EAAE,EAAE;AAAA,IACxC,SAAS,KAAK;AAGZ,YAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACpE,YAAM,IAAI;AAAA,QACR,SAAS,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,QAC1B,KAAK;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,qBACpB,OAA6B,CAAC,GACA;AAC9B,QAAM,YAAY,KAAK,aAAa,QAAQ,QAAQ,IAAI,GAAG,UAAU,QAAQ;AAC7E,QAAM,MAAM,QAAQ,KAAK,MAAM;AAE/B,QAAM,yBAAyB,IAAI;AAEnC,QAAM,OAAO,oBAAoB,SAAS;AAC1C,MAAI,KAAK,WAAW,GAAG;AACrB,QAAI,0EAAqE;AACzE,WAAO,EAAE,UAAU,CAAC,GAAG,cAAc,KAAK;AAAA,EAC5C;AAEA,MAAI,sBAAiB,KAAK,MAAM,8CAA8C;AAE9E,MAAI,KAAK,QAAQ;AACf,eAAW,QAAQ,MAAM;AACvB,UAAI,kBAAkB,KAAK,IAAI,WAAM,KAAK,EAAE,EAAE;AAAA,IAChD;AACA,WAAO,EAAE,UAAU,CAAC,GAAG,cAAc,MAAM;AAAA,EAC7C;AAEA,QAAM,WAAW,eAAe,MAAM,WAAW,GAAG;AACpD,MAAI,qBAAgB,SAAS,MAAM,YAAY;AAC/C,SAAO,EAAE,UAAU,cAAc,MAAM;AACzC;","names":["resolve"]}
|
|
@@ -11,10 +11,10 @@ import "./chunk-WZ7CPVQB.js";
|
|
|
11
11
|
import {
|
|
12
12
|
scanServerRoutes,
|
|
13
13
|
scanWebSocketRoutes
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-OXIQI2XZ.js";
|
|
15
15
|
import {
|
|
16
16
|
scanServerActions
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-5OFPQK6N.js";
|
|
18
18
|
import "./chunk-KT3MWNZG.js";
|
|
19
19
|
|
|
20
20
|
// src/cli/commands/routes.ts
|
|
@@ -63,4 +63,4 @@ async function routesCommand() {
|
|
|
63
63
|
export {
|
|
64
64
|
routesCommand
|
|
65
65
|
};
|
|
66
|
-
//# sourceMappingURL=routes-
|
|
66
|
+
//# sourceMappingURL=routes-H4SPLFHJ.js.map
|
package/dist/scan-C2BOKLSY.js
CHANGED
|
File without changes
|
package/dist/schema-VR6YNVLQ.js
CHANGED
|
File without changes
|
package/dist/server/index.d.ts
CHANGED
|
@@ -881,6 +881,16 @@ interface ActionManifestEntry$1 {
|
|
|
881
881
|
urlPath: string;
|
|
882
882
|
accept: 'form' | 'json';
|
|
883
883
|
hasInput: boolean;
|
|
884
|
+
/**
|
|
885
|
+
* P#4 plugin-forms shared-schema convention (per plan p4-plugin-forms v1.1 T1.1).
|
|
886
|
+
* When present, points to an isomorphic schema file at
|
|
887
|
+
* `<serverDir>/actions/schemas/<basename>.ts` exporting `export const schema = z.object(...)`.
|
|
888
|
+
* Virtual module emits `import {schema} from '<schemaFilePath>'` + attaches as
|
|
889
|
+
* `actions.X.__zodSchema` so client-side <TheoForm> can drive zodResolver.
|
|
890
|
+
* Undefined when convention not followed (graceful degrade — TheoForm still
|
|
891
|
+
* works via explicit `schema={...}` prop escape hatch).
|
|
892
|
+
*/
|
|
893
|
+
schemaFilePath?: string;
|
|
884
894
|
}
|
|
885
895
|
/**
|
|
886
896
|
* EC-2: structured error for scan-time defects (name collision, reserved
|
package/dist/server/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
generateManifest,
|
|
3
3
|
loadManifest,
|
|
4
4
|
writeManifest
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-2VQKDRVF.js";
|
|
6
6
|
import {
|
|
7
7
|
_resetKeyCacheForTests,
|
|
8
8
|
assertProductionSecret,
|
|
@@ -137,12 +137,12 @@ import {
|
|
|
137
137
|
matchRoute,
|
|
138
138
|
scanServerRoutes,
|
|
139
139
|
scanWebSocketRoutes
|
|
140
|
-
} from "../chunk-
|
|
140
|
+
} from "../chunk-B6RP57M3.js";
|
|
141
141
|
import {
|
|
142
142
|
ActionScanError,
|
|
143
143
|
scanServerActions,
|
|
144
144
|
scanServerActionsEnriched
|
|
145
|
-
} from "../chunk-
|
|
145
|
+
} from "../chunk-7TOMTMHT.js";
|
|
146
146
|
import {
|
|
147
147
|
AuthRequiredError,
|
|
148
148
|
generateNonce,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "tsx/esm";
|
|
3
|
+
import "./chunk-KT3MWNZG.js";
|
|
4
|
+
|
|
5
|
+
// src/vite-plugin/server-routes-hmr.ts
|
|
6
|
+
import { sep } from "path";
|
|
7
|
+
function serverRoutesHmrPlugin(opts) {
|
|
8
|
+
const routesDir = `${opts.serverDir}${sep}routes${sep}`;
|
|
9
|
+
const routesDirPosix = routesDir.replace(/\\/g, "/");
|
|
10
|
+
const debounceMs = opts.debounceMs ?? 50;
|
|
11
|
+
const isUnderRoutes = (filePath) => {
|
|
12
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
13
|
+
return normalized.startsWith(routesDirPosix);
|
|
14
|
+
};
|
|
15
|
+
return {
|
|
16
|
+
name: "theokit:server-routes-hmr",
|
|
17
|
+
configureServer(server) {
|
|
18
|
+
const srv = server;
|
|
19
|
+
let timer = null;
|
|
20
|
+
const fireInvalidation = () => {
|
|
21
|
+
timer = null;
|
|
22
|
+
for (const mod of srv.moduleGraph.idToModuleMap.values()) {
|
|
23
|
+
const normalizedId = mod.id.replace(/\\/g, "/");
|
|
24
|
+
if (normalizedId.startsWith(routesDirPosix)) {
|
|
25
|
+
srv.moduleGraph.invalidateModule(mod);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
srv.ws.send({ type: "full-reload" });
|
|
29
|
+
};
|
|
30
|
+
const scheduleInvalidation = (filePath) => {
|
|
31
|
+
if (!isUnderRoutes(filePath)) return;
|
|
32
|
+
if (timer !== null) clearTimeout(timer);
|
|
33
|
+
timer = setTimeout(fireInvalidation, debounceMs);
|
|
34
|
+
};
|
|
35
|
+
srv.watcher.on("add", scheduleInvalidation);
|
|
36
|
+
srv.watcher.on("change", scheduleInvalidation);
|
|
37
|
+
srv.watcher.on("unlink", scheduleInvalidation);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
serverRoutesHmrPlugin
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=server-routes-hmr-GZJGPWMS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vite-plugin/server-routes-hmr.ts"],"sourcesContent":["/**\n * G6 T1.2 — Vite plugin: watch `server/routes/**` and invalidate SSR module\n * cache on add/change/unlink with a 50 ms debounce window.\n *\n * Plan: .claude/knowledge-base/plans/g6-router-convention-plan.md v1.1\n *\n * Pattern reference: SvelteKit `exports/vite/dev/index.js:335-398`.\n *\n * Why this exists: in dev, `scanServerRoutes` runs per-request (fresh disk\n * read), so adding/removing routes already takes effect on next request.\n * But the SSR dynamic-import cache holds stale code for EDITED routes — Vite\n * needs an explicit `invalidateModule` call to bust it. We also send a\n * `full-reload` so any browser code that imported a route module\n * (rare, but the typed client G1 does this for ts-only type resolution)\n * picks up the change.\n *\n * EC-6: 50 ms debounce collapses bursty file events (e.g., codemod-driven\n * 21-rename storm in T2.1) into a single invalidation cycle — without it,\n * 21 invalidations + 21 full-reloads in 5 s would hang the dev server.\n */\nimport { sep } from 'node:path'\n\nimport type { Plugin, ViteDevServer } from 'vite'\n\nexport interface ServerRoutesHmrPluginOptions {\n /** Absolute path of the consumer's `server/` directory. */\n serverDir: string\n /** Debounce window in milliseconds (default 50 ms per EC-6). */\n debounceMs?: number\n}\n\ninterface ModuleGraphLike {\n getModuleById: (id: string) => unknown\n invalidateModule: (mod: unknown) => void\n idToModuleMap: Map<string, { id: string }>\n}\n\ninterface ViteDevServerLike {\n watcher: { on: (event: string, listener: (path: string) => void) => void }\n moduleGraph: ModuleGraphLike\n ws: { send: (payload: { type: string }) => void }\n}\n\nexport function serverRoutesHmrPlugin(opts: ServerRoutesHmrPluginOptions): Plugin {\n const routesDir = `${opts.serverDir}${sep}routes${sep}`\n // Cross-platform: on Windows the watcher MAY emit forward slashes even on NTFS.\n const routesDirPosix = routesDir.replace(/\\\\/g, '/')\n const debounceMs = opts.debounceMs ?? 50\n\n const isUnderRoutes = (filePath: string): boolean => {\n const normalized = filePath.replace(/\\\\/g, '/')\n return normalized.startsWith(routesDirPosix)\n }\n\n return {\n name: 'theokit:server-routes-hmr',\n\n configureServer(server: ViteDevServer) {\n const srv = server as unknown as ViteDevServerLike\n let timer: ReturnType<typeof setTimeout> | null = null\n\n const fireInvalidation = (): void => {\n timer = null\n for (const mod of srv.moduleGraph.idToModuleMap.values()) {\n const normalizedId = mod.id.replace(/\\\\/g, '/')\n if (normalizedId.startsWith(routesDirPosix)) {\n srv.moduleGraph.invalidateModule(mod)\n }\n }\n srv.ws.send({ type: 'full-reload' })\n }\n\n const scheduleInvalidation = (filePath: string): void => {\n if (!isUnderRoutes(filePath)) return\n if (timer !== null) clearTimeout(timer)\n timer = setTimeout(fireInvalidation, debounceMs)\n }\n\n srv.watcher.on('add', scheduleInvalidation)\n srv.watcher.on('change', scheduleInvalidation)\n srv.watcher.on('unlink', scheduleInvalidation)\n },\n }\n}\n"],"mappings":";;;;;AAoBA,SAAS,WAAW;AAuBb,SAAS,sBAAsB,MAA4C;AAChF,QAAM,YAAY,GAAG,KAAK,SAAS,GAAG,GAAG,SAAS,GAAG;AAErD,QAAM,iBAAiB,UAAU,QAAQ,OAAO,GAAG;AACnD,QAAM,aAAa,KAAK,cAAc;AAEtC,QAAM,gBAAgB,CAAC,aAA8B;AACnD,UAAM,aAAa,SAAS,QAAQ,OAAO,GAAG;AAC9C,WAAO,WAAW,WAAW,cAAc;AAAA,EAC7C;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,gBAAgB,QAAuB;AACrC,YAAM,MAAM;AACZ,UAAI,QAA8C;AAElD,YAAM,mBAAmB,MAAY;AACnC,gBAAQ;AACR,mBAAW,OAAO,IAAI,YAAY,cAAc,OAAO,GAAG;AACxD,gBAAM,eAAe,IAAI,GAAG,QAAQ,OAAO,GAAG;AAC9C,cAAI,aAAa,WAAW,cAAc,GAAG;AAC3C,gBAAI,YAAY,iBAAiB,GAAG;AAAA,UACtC;AAAA,QACF;AACA,YAAI,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC;AAAA,MACrC;AAEA,YAAM,uBAAuB,CAAC,aAA2B;AACvD,YAAI,CAAC,cAAc,QAAQ,EAAG;AAC9B,YAAI,UAAU,KAAM,cAAa,KAAK;AACtC,gBAAQ,WAAW,kBAAkB,UAAU;AAAA,MACjD;AAEA,UAAI,QAAQ,GAAG,OAAO,oBAAoB;AAC1C,UAAI,QAAQ,GAAG,UAAU,oBAAoB;AAC7C,UAAI,QAAQ,GAAG,UAAU,oBAAoB;AAAA,IAC/C;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import "./chunk-DGUM43GV.js";
|
|
2
|
+
|
|
3
|
+
// src/vite-plugin/server-routes-hmr.ts
|
|
4
|
+
import { sep } from "path";
|
|
5
|
+
function serverRoutesHmrPlugin(opts) {
|
|
6
|
+
const routesDir = `${opts.serverDir}${sep}routes${sep}`;
|
|
7
|
+
const routesDirPosix = routesDir.replace(/\\/g, "/");
|
|
8
|
+
const debounceMs = opts.debounceMs ?? 50;
|
|
9
|
+
const isUnderRoutes = (filePath) => {
|
|
10
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
11
|
+
return normalized.startsWith(routesDirPosix);
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
name: "theokit:server-routes-hmr",
|
|
15
|
+
configureServer(server) {
|
|
16
|
+
const srv = server;
|
|
17
|
+
let timer = null;
|
|
18
|
+
const fireInvalidation = () => {
|
|
19
|
+
timer = null;
|
|
20
|
+
for (const mod of srv.moduleGraph.idToModuleMap.values()) {
|
|
21
|
+
const normalizedId = mod.id.replace(/\\/g, "/");
|
|
22
|
+
if (normalizedId.startsWith(routesDirPosix)) {
|
|
23
|
+
srv.moduleGraph.invalidateModule(mod);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
srv.ws.send({ type: "full-reload" });
|
|
27
|
+
};
|
|
28
|
+
const scheduleInvalidation = (filePath) => {
|
|
29
|
+
if (!isUnderRoutes(filePath)) return;
|
|
30
|
+
if (timer !== null) clearTimeout(timer);
|
|
31
|
+
timer = setTimeout(fireInvalidation, debounceMs);
|
|
32
|
+
};
|
|
33
|
+
srv.watcher.on("add", scheduleInvalidation);
|
|
34
|
+
srv.watcher.on("change", scheduleInvalidation);
|
|
35
|
+
srv.watcher.on("unlink", scheduleInvalidation);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
serverRoutesHmrPlugin
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=server-routes-hmr-PBHSKCQJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vite-plugin/server-routes-hmr.ts"],"sourcesContent":["/**\n * G6 T1.2 — Vite plugin: watch `server/routes/**` and invalidate SSR module\n * cache on add/change/unlink with a 50 ms debounce window.\n *\n * Plan: .claude/knowledge-base/plans/g6-router-convention-plan.md v1.1\n *\n * Pattern reference: SvelteKit `exports/vite/dev/index.js:335-398`.\n *\n * Why this exists: in dev, `scanServerRoutes` runs per-request (fresh disk\n * read), so adding/removing routes already takes effect on next request.\n * But the SSR dynamic-import cache holds stale code for EDITED routes — Vite\n * needs an explicit `invalidateModule` call to bust it. We also send a\n * `full-reload` so any browser code that imported a route module\n * (rare, but the typed client G1 does this for ts-only type resolution)\n * picks up the change.\n *\n * EC-6: 50 ms debounce collapses bursty file events (e.g., codemod-driven\n * 21-rename storm in T2.1) into a single invalidation cycle — without it,\n * 21 invalidations + 21 full-reloads in 5 s would hang the dev server.\n */\nimport { sep } from 'node:path'\n\nimport type { Plugin, ViteDevServer } from 'vite'\n\nexport interface ServerRoutesHmrPluginOptions {\n /** Absolute path of the consumer's `server/` directory. */\n serverDir: string\n /** Debounce window in milliseconds (default 50 ms per EC-6). */\n debounceMs?: number\n}\n\ninterface ModuleGraphLike {\n getModuleById: (id: string) => unknown\n invalidateModule: (mod: unknown) => void\n idToModuleMap: Map<string, { id: string }>\n}\n\ninterface ViteDevServerLike {\n watcher: { on: (event: string, listener: (path: string) => void) => void }\n moduleGraph: ModuleGraphLike\n ws: { send: (payload: { type: string }) => void }\n}\n\nexport function serverRoutesHmrPlugin(opts: ServerRoutesHmrPluginOptions): Plugin {\n const routesDir = `${opts.serverDir}${sep}routes${sep}`\n // Cross-platform: on Windows the watcher MAY emit forward slashes even on NTFS.\n const routesDirPosix = routesDir.replace(/\\\\/g, '/')\n const debounceMs = opts.debounceMs ?? 50\n\n const isUnderRoutes = (filePath: string): boolean => {\n const normalized = filePath.replace(/\\\\/g, '/')\n return normalized.startsWith(routesDirPosix)\n }\n\n return {\n name: 'theokit:server-routes-hmr',\n\n configureServer(server: ViteDevServer) {\n const srv = server as unknown as ViteDevServerLike\n let timer: ReturnType<typeof setTimeout> | null = null\n\n const fireInvalidation = (): void => {\n timer = null\n for (const mod of srv.moduleGraph.idToModuleMap.values()) {\n const normalizedId = mod.id.replace(/\\\\/g, '/')\n if (normalizedId.startsWith(routesDirPosix)) {\n srv.moduleGraph.invalidateModule(mod)\n }\n }\n srv.ws.send({ type: 'full-reload' })\n }\n\n const scheduleInvalidation = (filePath: string): void => {\n if (!isUnderRoutes(filePath)) return\n if (timer !== null) clearTimeout(timer)\n timer = setTimeout(fireInvalidation, debounceMs)\n }\n\n srv.watcher.on('add', scheduleInvalidation)\n srv.watcher.on('change', scheduleInvalidation)\n srv.watcher.on('unlink', scheduleInvalidation)\n },\n }\n}\n"],"mappings":";;;AAoBA,SAAS,WAAW;AAuBb,SAAS,sBAAsB,MAA4C;AAChF,QAAM,YAAY,GAAG,KAAK,SAAS,GAAG,GAAG,SAAS,GAAG;AAErD,QAAM,iBAAiB,UAAU,QAAQ,OAAO,GAAG;AACnD,QAAM,aAAa,KAAK,cAAc;AAEtC,QAAM,gBAAgB,CAAC,aAA8B;AACnD,UAAM,aAAa,SAAS,QAAQ,OAAO,GAAG;AAC9C,WAAO,WAAW,WAAW,cAAc;AAAA,EAC7C;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,gBAAgB,QAAuB;AACrC,YAAM,MAAM;AACZ,UAAI,QAA8C;AAElD,YAAM,mBAAmB,MAAY;AACnC,gBAAQ;AACR,mBAAW,OAAO,IAAI,YAAY,cAAc,OAAO,GAAG;AACxD,gBAAM,eAAe,IAAI,GAAG,QAAQ,OAAO,GAAG;AAC9C,cAAI,aAAa,WAAW,cAAc,GAAG;AAC3C,gBAAI,YAAY,iBAAiB,GAAG;AAAA,UACtC;AAAA,QACF;AACA,YAAI,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC;AAAA,MACrC;AAEA,YAAM,uBAAuB,CAAC,aAA2B;AACvD,YAAI,CAAC,cAAc,QAAQ,EAAG;AAC9B,YAAI,UAAU,KAAM,cAAa,KAAK;AACtC,gBAAQ,WAAW,kBAAkB,UAAU;AAAA,MACjD;AAEA,UAAI,QAAQ,GAAG,OAAO,oBAAoB;AAC1C,UAAI,QAAQ,GAAG,UAAU,oBAAoB;AAC7C,UAAI,QAAQ,GAAG,UAAU,oBAAoB;AAAA,IAC/C;AAAA,EACF;AACF;","names":[]}
|
|
File without changes
|
|
File without changes
|
|
@@ -25,15 +25,15 @@ import "./chunk-X4JAX2U3.js";
|
|
|
25
25
|
import "./chunk-WZ7CPVQB.js";
|
|
26
26
|
import {
|
|
27
27
|
loadManifest
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-TRH2L3FI.js";
|
|
29
29
|
import {
|
|
30
30
|
matchRoute,
|
|
31
31
|
scanServerRoutes,
|
|
32
32
|
scanWebSocketRoutes
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-OXIQI2XZ.js";
|
|
34
34
|
import {
|
|
35
35
|
scanServerActions
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-5OFPQK6N.js";
|
|
37
37
|
import "./chunk-KT3MWNZG.js";
|
|
38
38
|
|
|
39
39
|
// src/cli/commands/start.ts
|
|
@@ -47,7 +47,7 @@ import { resolve } from "path";
|
|
|
47
47
|
async function configureAgentRegistryFromConfig(registryConfig) {
|
|
48
48
|
if (registryConfig === void 0) return;
|
|
49
49
|
try {
|
|
50
|
-
const sdk = await import("./dist-
|
|
50
|
+
const sdk = await import("./dist-5V77Z223.js").catch(() => null);
|
|
51
51
|
const sdkConfigure = sdk?.Agent?.registry?.configure;
|
|
52
52
|
if (sdkConfigure === void 0) return;
|
|
53
53
|
const { configureAgentRegistryOnce } = await import("./configure-agent-registry-6YGTJYBC.js");
|
|
@@ -101,7 +101,7 @@ function installGracefulShutdown(server) {
|
|
|
101
101
|
[theokit] ${signal} received \u2014 evicting agents`);
|
|
102
102
|
void (async () => {
|
|
103
103
|
try {
|
|
104
|
-
const sdk = await import("./dist-
|
|
104
|
+
const sdk = await import("./dist-5V77Z223.js").catch(() => null);
|
|
105
105
|
if (sdk?.Agent?.registry?.evictAll !== void 0) {
|
|
106
106
|
await sdk.Agent.registry.evictAll();
|
|
107
107
|
}
|
|
@@ -612,4 +612,4 @@ export {
|
|
|
612
612
|
resolveSsrEntry,
|
|
613
613
|
startCommand
|
|
614
614
|
};
|
|
615
|
-
//# sourceMappingURL=start-
|
|
615
|
+
//# sourceMappingURL=start-HX3QUSOS.js.map
|
package/dist/static-TZBVBDTB.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/vercel-MWW24ABC.js
CHANGED
|
File without changes
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
defineTheoIntegration,
|
|
6
6
|
theoPlugin,
|
|
7
7
|
theoPluginAsync
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-BIGBFZSU.js";
|
|
9
9
|
import "../chunk-7BIM27LV.js";
|
|
10
10
|
import "../chunk-O4BLVPML.js";
|
|
11
11
|
import "../chunk-CZM6WWWS.js";
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-B6RP57M3.js";
|
|
13
|
+
import "../chunk-7TOMTMHT.js";
|
|
14
14
|
import "../chunk-PB4GR7EP.js";
|
|
15
15
|
import "../chunk-GY5Q27BJ.js";
|
|
16
16
|
import "../chunk-X2VVCJ4V.js";
|
|
@@ -7,15 +7,15 @@ import {
|
|
|
7
7
|
defineTheoIntegration,
|
|
8
8
|
theoPlugin,
|
|
9
9
|
theoPluginAsync
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JAAHOGKI.js";
|
|
11
11
|
import "./chunk-TPCT3MXV.js";
|
|
12
12
|
import "./chunk-XP7YXRHO.js";
|
|
13
13
|
import "./chunk-X4JAX2U3.js";
|
|
14
14
|
import "./chunk-5ODOE6EF.js";
|
|
15
15
|
import "./chunk-O7335ZGH.js";
|
|
16
16
|
import "./chunk-WZ7CPVQB.js";
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-OXIQI2XZ.js";
|
|
18
|
+
import "./chunk-5OFPQK6N.js";
|
|
19
19
|
import "./chunk-KT3MWNZG.js";
|
|
20
20
|
export {
|
|
21
21
|
IntegrationRouteCollisionError,
|
|
@@ -25,4 +25,4 @@ export {
|
|
|
25
25
|
theoPlugin,
|
|
26
26
|
theoPluginAsync
|
|
27
27
|
};
|
|
28
|
-
//# sourceMappingURL=vite-plugin-
|
|
28
|
+
//# sourceMappingURL=vite-plugin-IK3NOWXS.js.map
|
package/package.json
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theokit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-beta.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"build": "tsup"
|
|
8
|
-
},
|
|
9
6
|
"bin": {
|
|
10
7
|
"theokit": "./dist/cli/index.js"
|
|
11
8
|
},
|
|
@@ -102,11 +99,14 @@
|
|
|
102
99
|
"@types/busboy": "^1.5.4",
|
|
103
100
|
"@types/pg": "^8.20.0",
|
|
104
101
|
"@types/picomatch": "^4.0.0",
|
|
105
|
-
"@theokit/sdk": "workspace:*",
|
|
106
102
|
"better-sqlite3": "^12.10.0",
|
|
107
103
|
"db0": "^0.3.0",
|
|
108
104
|
"pg": "^8.21.0",
|
|
109
105
|
"pg-mem": "^3.0.14",
|
|
110
|
-
"unstorage": "^1.10.0"
|
|
106
|
+
"unstorage": "^1.10.0",
|
|
107
|
+
"@theokit/sdk": "1.6.2"
|
|
108
|
+
},
|
|
109
|
+
"scripts": {
|
|
110
|
+
"build": "tsup"
|
|
111
111
|
}
|
|
112
|
-
}
|
|
112
|
+
}
|