@akanjs/cli 3.1.0-rc.2 → 3.1.0-rc.20
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/.build-stamp +1 -1
- package/{CodeAgent-q50k4s45.js → CodeAgent-n3tzjm91.js} +2 -2
- package/{CodeAgentRpcHost-p7h6n2hp.js → CodeAgentRpcHost-9g27hmer.js} +1 -1
- package/{CodeTui-62g35ztk.js → CodeTui-fnm9ft4d.js} +47 -4
- package/TunnelShare-661cxz5e.js +14 -0
- package/{agent.command-adfd5299.js → agent.command-3qxf4xcj.js} +5 -5
- package/akanCode.js +7 -5
- package/{application.command-hj3gv1rx.js → application.command-zfja7x4r.js} +12 -11
- package/{applicationBuildRunner-by10r9gf.js → applicationBuildRunner-vh4j6vdv.js} +16 -9
- package/buildBatch.proc.js +7 -7
- package/{cloud.command-k2fhaape.js → cloud.command-fcc8e8tp.js} +17 -16
- package/cloud.script-1xt3tnts.js +24 -0
- package/{code.command-kt5zgcc2.js → code.command-130bdmhe.js} +25 -12
- package/{context.command-8fgn42jw.js → context.command-0qx447mb.js} +17 -16
- package/context.runner-1vsjztjg.js +25 -0
- package/{dependencyScanner-06z2dmrr.js → dependencyScanner-3afj2vt1.js} +1 -1
- package/{guideline.command-3yxxr2mm.js → guideline.command-cv5bmrx2.js} +2 -2
- package/guidelines/agentRule/agentRule.instruction.md +25 -10
- package/guidelines/conventions/conventions.instruction.md +463 -1084
- package/guidelines/cssRule/cssRule.instruction.md +16 -1
- package/guidelines/fieldRule/fieldRule.instruction.md +74 -0
- package/guidelines/framework/framework.instruction.md +4 -7
- package/guidelines/mcpRule/mcpRule.instruction.md +16 -9
- package/guidelines/modelConstant/modelConstant.instruction.md +2 -1
- package/guidelines/modelStore/modelStore.instruction.md +16 -0
- package/guidelines/pageRule/pageRule.instruction.md +80 -0
- package/guidelines/queryRule/queryRule.instruction.md +47 -12
- package/guidelines/runtimeRule/runtimeRule.instruction.md +89 -2
- package/guidelines/ssrRule/ssrRule.instruction.md +13 -0
- package/guidelines/transportRule/transportRule.instruction.md +107 -8
- package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +4 -4
- package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +70 -7
- package/incrementalBuilder.proc.js +4 -4
- package/{index-nq045px5.js → index-192ha4xh.js} +356 -307
- package/{index-t7nws9mx.js → index-1djcjcre.js} +661 -448
- package/{index-h85cxfkg.js → index-1p98exm2.js} +2 -2
- package/{index-hnby7p9n.js → index-1xj2t7cb.js} +7 -7
- package/{index-wa5jbxj1.js → index-2mrn1mrg.js} +1 -0
- package/{index-58vvz603.js → index-35hc95h5.js} +1 -1
- package/{index-tv8fjaba.js → index-4mhy6qme.js} +4 -4
- package/{index-rk9sdys3.js → index-5edzv8fn.js} +5 -5
- package/{index-k9rrten6.js → index-5nd1wtkv.js} +92 -94
- package/index-62md4dwy.js +260 -0
- package/{index-kc8z134d.js → index-665zp9rs.js} +38 -15
- package/{index-jwqtchha.js → index-86jt2a0e.js} +1 -1
- package/{index-d2242ksy.js → index-at7bz0xq.js} +3 -0
- package/{index-sqfdmb5b.js → index-awbdfcf2.js} +4 -4
- package/{index-azh29dc8.js → index-axs61rna.js} +19 -14
- package/{index-3hx1z96c.js → index-bqbf654f.js} +1 -1
- package/{index-6726qr1m.js → index-cpb3nvma.js} +57 -58
- package/{index-pyxn1b53.js → index-d72hfmdm.js} +13 -13
- package/{index-8zdwpxef.js → index-dye8pnxx.js} +119 -81
- package/{index-z507nzhg.js → index-fmzcs8v6.js} +4 -4
- package/{index-3reaaa1h.js → index-fyq1z6kt.js} +29 -27
- package/{index-0909wckt.js → index-g1mbppa9.js} +238 -236
- package/{index-fjsv10hd.js → index-hsadfb6c.js} +7 -7
- package/{index-tz5evhdr.js → index-j237xtew.js} +6 -6
- package/{index-nq2ja5e0.js → index-j4mkhz93.js} +3 -3
- package/{index-31ce9vhg.js → index-jw1zm273.js} +28 -30
- package/{index-q958tqqg.js → index-m9jj544v.js} +1 -1
- package/{index-8935h3n1.js → index-mdjc93e1.js} +1 -1
- package/{index-bea2gwc6.js → index-pydbnfez.js} +2 -2
- package/{index-20cebtth.js → index-qtfmtcrw.js} +17 -15
- package/{index-sby8fe1p.js → index-qwa5k1j8.js} +1 -1
- package/{index-e9prnmyt.js → index-tamvyvj3.js} +3 -3
- package/{index-rhbabmja.js → index-trpasv9q.js} +260 -259
- package/{index-2ahj896a.js → index-tvehn2sp.js} +1 -1
- package/{index-2etqq75t.js → index-va06nr10.js} +1090 -1078
- package/{index-g0vwzy9m.js → index-vk0pa0mn.js} +20 -21
- package/{index-xpdgxsj5.js → index-w44cy4vs.js} +2216 -2216
- package/index.js +22 -22
- package/{library.command-8tw59xzj.js → library.command-erp2f56n.js} +3 -3
- package/{localRegistry.command-tf3dmznd.js → localRegistry.command-hj3p16p5.js} +15 -14
- package/{module.command-9vm8hffy.js → module.command-gs2r615e.js} +5 -5
- package/{package.command-erbxe2tz.js → package.command-j10r76ax.js} +4 -4
- package/package.json +21 -21
- package/{page.command-jpavcj0p.js → page.command-4h4a8pnh.js} +3 -3
- package/{pipeline.command-b8rzvjvv.js → pipeline.command-a2nrk26m.js} +3 -3
- package/{primitive.command-sm32chzk.js → primitive.command-w6t0asqz.js} +6 -6
- package/{projectTypecheck-jamtx95x.js → projectTypecheck-f534enqj.js} +1 -1
- package/{quality.command-pkd17n6y.js → quality.command-77x7vbbx.js} +4 -4
- package/{repair.command-8y4mq6hs.js → repair.command-y6sstev7.js} +5 -5
- package/{scalar.command-q8khmyx5.js → scalar.command-20b8cy0k.js} +4 -4
- package/skills/akan-code/SKILL.md +4 -0
- package/skills/akan-store/SKILL.md +2 -1
- package/{subspace.command-51n0ykbx.js → subspace.command-baz73jpk.js} +11 -10
- package/templates/appSample/lib/task/Task.Util.tsx +7 -7
- package/templates/appSample/lib/task/Task.Zone.tsx +1 -1
- package/templates/appSample/ui/QuantityControl.tsx +2 -2
- package/templates/crudSinglePage/page.tsx +1 -1
- package/templates/lib/cnst.ts +0 -1
- package/templates/workspaceRoot/.gitignore.template +23 -52
- package/templates/workspaceRoot/biome.json.template +1 -1
- package/{tunnel.command-7820vtxq.js → tunnel.command-2kw8vt9g.js} +8 -7
- package/{workflow.command-n5sv4wqz.js → workflow.command-2djwmpqf.js} +10 -10
- package/{workspace.command-zdy60jh8.js → workspace.command-jqs7vjhe.js} +29 -28
- package/TunnelShare-f1egrktx.js +0 -13
- package/cloud.script-z8p5dz7e.js +0 -23
- package/context.runner-hnh0rg7m.js +0 -24
- package/index-n68jx79w.js +0 -120
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import {
|
|
3
|
-
FileSys2
|
|
4
|
-
} from "./index-52w0fvh8.js";
|
|
5
2
|
import {
|
|
6
3
|
AsyncDefaultExportDetector,
|
|
7
4
|
resolveSsrPageEntriesForApp
|
|
8
|
-
} from "./index-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import path3 from "path";
|
|
5
|
+
} from "./index-va06nr10.js";
|
|
6
|
+
import {
|
|
7
|
+
FileSys2
|
|
8
|
+
} from "./index-52w0fvh8.js";
|
|
13
9
|
|
|
14
|
-
// pkgs/@akanjs/devkit/transforms/
|
|
10
|
+
// pkgs/@akanjs/devkit/transforms/barrelAnalyzer.ts
|
|
15
11
|
import path from "path";
|
|
16
|
-
import
|
|
12
|
+
import { Logger } from "akanjs/common";
|
|
17
13
|
|
|
18
14
|
// pkgs/@akanjs/devkit/transforms/moduleSyntax.ts
|
|
19
15
|
var loaderFor = (absPath) => {
|
|
@@ -47,237 +43,7 @@ var parseNamedList = (listBody) => {
|
|
|
47
43
|
return out;
|
|
48
44
|
};
|
|
49
45
|
|
|
50
|
-
// pkgs/@akanjs/devkit/transforms/rscUseClientTransform.ts
|
|
51
|
-
var USE_CLIENT_RE = /^\s*(?:\/\*[\s\S]*?\*\/\s*|\/\/[^\n]*\n\s*)*["']use client["']/;
|
|
52
|
-
var IMPLICIT_ROOT_LAYOUT_RE = /[/\\]\.akan[/\\]generated[/\\](?:implicit-root-layout|root-layouts[/\\].*__root_layout)\.(tsx|ts|jsx|js)$/;
|
|
53
|
-
var STAR_REEXPORT_HINT_RE = /\bexport\s*\*\s*from\b/;
|
|
54
|
-
var hasUseClientDirective = (source) => USE_CLIENT_RE.test(source);
|
|
55
|
-
function toClientReferencePath(absPath, workspaceRoot) {
|
|
56
|
-
return path.relative(path.resolve(workspaceRoot), path.resolve(absPath)).split(path.sep).join("/");
|
|
57
|
-
}
|
|
58
|
-
var starReexportSpecifiers = (source, filePath) => ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest).statements.filter((statement) => ts.isExportDeclaration(statement) && !statement.exportClause && !statement.isTypeOnly && !!statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier)).map((statement) => statement.moduleSpecifier.text);
|
|
59
|
-
var scanUseClientExports = (source, filePath, workspaceRoot) => {
|
|
60
|
-
const stars = USE_CLIENT_RE.test(source) && STAR_REEXPORT_HINT_RE.test(source) ? starReexportSpecifiers(source, filePath) : [];
|
|
61
|
-
if (stars.length) {
|
|
62
|
-
const file = workspaceRoot ? toClientReferencePath(filePath, workspaceRoot) : filePath;
|
|
63
|
-
const listed = stars.slice(0, 3).map((specifier) => `\`export * from ${JSON.stringify(specifier)}\``);
|
|
64
|
-
const written = stars.length > 3 ? `${listed.join(", ")} (and ${stars.length - 3} more)` : listed.join(", ");
|
|
65
|
-
throw new Error(`${file} is a "use client" module, so it cannot ${written}: the server sees only the names a client module ` + `declares, and a star re-export declares none. Re-export them by name \u2014 \`export { \u2026 } from ${JSON.stringify(stars[0])}\`.`);
|
|
66
|
-
}
|
|
67
|
-
return new Bun.Transpiler({ loader: loaderFor(filePath) }).scan(source).exports;
|
|
68
|
-
};
|
|
69
|
-
function transformUseClient(source, args) {
|
|
70
|
-
if (!USE_CLIENT_RE.test(source))
|
|
71
|
-
return null;
|
|
72
|
-
if (IMPLICIT_ROOT_LAYOUT_RE.test(args.path))
|
|
73
|
-
return null;
|
|
74
|
-
const exports = scanUseClientExports(source, args.path, args.workspaceRoot);
|
|
75
|
-
if (exports.length === 0)
|
|
76
|
-
return null;
|
|
77
|
-
args.onClientModule?.(args.path, exports);
|
|
78
|
-
const referencePath = args.workspaceRoot ? toClientReferencePath(args.path, args.workspaceRoot) : args.path;
|
|
79
|
-
const filePathLit = JSON.stringify(referencePath);
|
|
80
|
-
const lines = [`import { registerClientReference } from "react-server-dom-webpack/server.node";`];
|
|
81
|
-
for (const name of exports) {
|
|
82
|
-
const nameLit = JSON.stringify(name);
|
|
83
|
-
const errMsg = JSON.stringify(`Attempted to call '${name}' from '${referencePath}' on the server, but it is a client-only export.`);
|
|
84
|
-
const proxy = `() => { throw new Error(${errMsg}); }`;
|
|
85
|
-
const binding = name === "default" ? `export default registerClientReference(${proxy}, ${filePathLit}, ${nameLit});` : `export const ${name} = registerClientReference(${proxy}, ${filePathLit}, ${nameLit});`;
|
|
86
|
-
lines.push(binding);
|
|
87
|
-
}
|
|
88
|
-
return lines.join(`
|
|
89
|
-
`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// pkgs/@akanjs/devkit/frontendBuild/csrDevPaths.ts
|
|
93
|
-
import fs from "fs";
|
|
94
|
-
import path2 from "path";
|
|
95
|
-
|
|
96
|
-
class CsrDevPaths {
|
|
97
|
-
static modulePrefix = "akan-module:";
|
|
98
|
-
static stubPrefix = "stub:";
|
|
99
|
-
static emptyStubPrefix = "stub:empty:";
|
|
100
|
-
static vendorPrefix = "vendor:";
|
|
101
|
-
root;
|
|
102
|
-
constructor(workspaceRoot) {
|
|
103
|
-
this.root = CsrDevPaths.realpath(workspaceRoot);
|
|
104
|
-
}
|
|
105
|
-
idOf(file) {
|
|
106
|
-
const real = CsrDevPaths.realpath(file);
|
|
107
|
-
const relative = path2.relative(this.root, real);
|
|
108
|
-
const id = relative.startsWith("..") || path2.isAbsolute(relative) ? real : relative;
|
|
109
|
-
return id.split(path2.sep).join("/");
|
|
110
|
-
}
|
|
111
|
-
fileOf(id) {
|
|
112
|
-
return path2.isAbsolute(id) ? id : path2.join(this.root, id);
|
|
113
|
-
}
|
|
114
|
-
static isStub(target) {
|
|
115
|
-
return target.startsWith(CsrDevPaths.stubPrefix);
|
|
116
|
-
}
|
|
117
|
-
static isVendorFile(file) {
|
|
118
|
-
return file.includes(`${path2.sep}node_modules${path2.sep}`);
|
|
119
|
-
}
|
|
120
|
-
static isScript(file) {
|
|
121
|
-
return /\.[cm]?[jt]sx?$/.test(file);
|
|
122
|
-
}
|
|
123
|
-
static mtimeOf(file) {
|
|
124
|
-
return fs.statSync(file, { throwIfNoEntry: false })?.mtimeMs ?? -1;
|
|
125
|
-
}
|
|
126
|
-
static async hashOf(file) {
|
|
127
|
-
const source = Bun.file(file);
|
|
128
|
-
return await source.exists() ? Bun.hash(await source.arrayBuffer()).toString(36) : "";
|
|
129
|
-
}
|
|
130
|
-
static realpath(file) {
|
|
131
|
-
return fs.existsSync(file) ? fs.realpathSync.native(file) : path2.resolve(file);
|
|
132
|
-
}
|
|
133
|
-
static isNamed(file) {
|
|
134
|
-
try {
|
|
135
|
-
return fs.realpathSync.native(file) === file;
|
|
136
|
-
} catch {
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
static #extensions = {
|
|
141
|
-
import: [".tsx", ".jsx", ".mts", ".ts", ".mjs", ".js", ".cts", ".cjs"],
|
|
142
|
-
require: [".tsx", ".ts", ".jsx", ".cts", ".cjs", ".js", ".mjs", ".mts"]
|
|
143
|
-
};
|
|
144
|
-
static resolveOnDisk(base, kind = "import") {
|
|
145
|
-
return CsrDevPaths.#asFile(base, kind) ?? CsrDevPaths.#asFolder(base, kind);
|
|
146
|
-
}
|
|
147
|
-
static resolveRelative(dir, specifier, kind = "import") {
|
|
148
|
-
const base = path2.resolve(dir, specifier);
|
|
149
|
-
const folder = /(^|[\\/])\.\.?$|[\\/]$/.test(specifier);
|
|
150
|
-
return folder ? CsrDevPaths.#asFolder(base, kind) : CsrDevPaths.resolveOnDisk(base, kind);
|
|
151
|
-
}
|
|
152
|
-
static #asFile(base, kind) {
|
|
153
|
-
const isFile = (candidate) => fs.statSync(candidate, { throwIfNoEntry: false })?.isFile() ?? false;
|
|
154
|
-
return [base, ...CsrDevPaths.#extensions[kind].map((extension) => `${base}${extension}`)].find(isFile) ?? null;
|
|
155
|
-
}
|
|
156
|
-
static #asFolder(dir, kind) {
|
|
157
|
-
const entry = CsrDevPaths.#packageEntryOf(dir, kind);
|
|
158
|
-
const named = entry ? CsrDevPaths.#asFile(path2.join(dir, entry), kind) ?? CsrDevPaths.#indexOf(path2.join(dir, entry), kind) : null;
|
|
159
|
-
return named ?? CsrDevPaths.#indexOf(dir, kind);
|
|
160
|
-
}
|
|
161
|
-
static #indexOf(dir, kind) {
|
|
162
|
-
return CsrDevPaths.#asFile(path2.join(dir, "index"), kind);
|
|
163
|
-
}
|
|
164
|
-
static #packageEntryOf(dir, kind) {
|
|
165
|
-
try {
|
|
166
|
-
const pkg = JSON.parse(fs.readFileSync(path2.join(dir, "package.json"), "utf8"));
|
|
167
|
-
const fields = kind === "require" ? [pkg.browser, pkg.main] : [pkg.browser, pkg.module, pkg.main];
|
|
168
|
-
const entry = fields.find((field) => typeof field === "string");
|
|
169
|
-
return typeof entry === "string" ? entry : null;
|
|
170
|
-
} catch {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
static installedSince(specifier, from, since) {
|
|
175
|
-
const [first = "", second = ""] = specifier.split("/");
|
|
176
|
-
const name = first.startsWith("@") ? `${first}/${second}` : first;
|
|
177
|
-
if (!name || name.startsWith("."))
|
|
178
|
-
return false;
|
|
179
|
-
for (let dir = path2.resolve(from);; dir = path2.dirname(dir)) {
|
|
180
|
-
const pkgDir = path2.join(dir, "node_modules", name);
|
|
181
|
-
if (fs.existsSync(path2.join(pkgDir, "package.json")))
|
|
182
|
-
return (fs.statSync(pkgDir, { throwIfNoEntry: false })?.ctimeMs ?? 0) > since;
|
|
183
|
-
if (path2.dirname(dir) === dir)
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
static tryResolve(specifier, from) {
|
|
188
|
-
try {
|
|
189
|
-
return Bun.resolveSync(specifier, from);
|
|
190
|
-
} catch {
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
static lineCount(text) {
|
|
195
|
-
let count = 0;
|
|
196
|
-
for (let index = text.indexOf(`
|
|
197
|
-
`);index !== -1; index = text.indexOf(`
|
|
198
|
-
`, index + 1))
|
|
199
|
-
count += 1;
|
|
200
|
-
return count;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// pkgs/@akanjs/devkit/frontendBuild/serverGraphFile.ts
|
|
205
|
-
class ServerGraphFile {
|
|
206
|
-
static fileName = "server-graph.json";
|
|
207
|
-
static #cache = null;
|
|
208
|
-
static async read(artifactDir) {
|
|
209
|
-
const file = path3.join(artifactDir, ServerGraphFile.fileName);
|
|
210
|
-
const stat = fs2.statSync(file, { throwIfNoEntry: false });
|
|
211
|
-
if (!stat)
|
|
212
|
-
return null;
|
|
213
|
-
const stamp = `${stat.ino}:${stat.size}:${stat.mtimeMs}`;
|
|
214
|
-
const cached = ServerGraphFile.#cache;
|
|
215
|
-
if (cached?.file === file && cached.stamp === stamp)
|
|
216
|
-
return cached.graph;
|
|
217
|
-
const graph = await Bun.file(file).json().catch(() => null);
|
|
218
|
-
if (graph)
|
|
219
|
-
ServerGraphFile.#cache = { file, stamp, graph };
|
|
220
|
-
return graph;
|
|
221
|
-
}
|
|
222
|
-
static async write(artifactDir, graph) {
|
|
223
|
-
const file = path3.join(artifactDir, ServerGraphFile.fileName);
|
|
224
|
-
const temp = `${file}.${process.pid}.tmp`;
|
|
225
|
-
await Bun.write(temp, JSON.stringify(graph));
|
|
226
|
-
await FileSys2.replace(temp, file);
|
|
227
|
-
}
|
|
228
|
-
static async carry(artifactDir, files) {
|
|
229
|
-
const graph = await ServerGraphFile.read(artifactDir);
|
|
230
|
-
if (!graph || files.length === 0)
|
|
231
|
-
return;
|
|
232
|
-
const carried = [...new Set([...graph.carried ?? [], ...files.map((file) => CsrDevPaths.realpath(file))])];
|
|
233
|
-
await ServerGraphFile.write(artifactDir, { ...graph, carried });
|
|
234
|
-
}
|
|
235
|
-
static async touches(graph, files, exportsNow, next) {
|
|
236
|
-
if (!graph)
|
|
237
|
-
return true;
|
|
238
|
-
const inputs = new Set(graph.inputs);
|
|
239
|
-
const joined = new Set((next?.inputs ?? []).filter((input) => !inputs.has(input)));
|
|
240
|
-
for (const rawFile of files) {
|
|
241
|
-
const file = CsrDevPaths.realpath(rawFile);
|
|
242
|
-
if (joined.has(file))
|
|
243
|
-
return true;
|
|
244
|
-
if (!inputs.has(file))
|
|
245
|
-
continue;
|
|
246
|
-
const before = graph.clientExports[file];
|
|
247
|
-
if (!before)
|
|
248
|
-
return true;
|
|
249
|
-
const now = await exportsNow(file);
|
|
250
|
-
if (!now || ServerGraphFile.#names(now) !== ServerGraphFile.#names(before))
|
|
251
|
-
return true;
|
|
252
|
-
}
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
static async clientExportsOf(file) {
|
|
256
|
-
const source = await Bun.file(file).text().catch(() => null);
|
|
257
|
-
if (source === null || !hasUseClientDirective(source))
|
|
258
|
-
return null;
|
|
259
|
-
try {
|
|
260
|
-
return scanUseClientExports(source, file);
|
|
261
|
-
} catch {
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
static #names(exports) {
|
|
266
|
-
return [...exports].sort().join(",");
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// pkgs/@akanjs/devkit/frontendBuild/pagesBundleBuilder.ts
|
|
271
|
-
import fs3 from "fs";
|
|
272
|
-
import path8 from "path";
|
|
273
|
-
|
|
274
|
-
// pkgs/@akanjs/devkit/transforms/barrelImportsPlugin.ts
|
|
275
|
-
import path5 from "path";
|
|
276
|
-
import ts2 from "typescript";
|
|
277
|
-
|
|
278
46
|
// pkgs/@akanjs/devkit/transforms/barrelAnalyzer.ts
|
|
279
|
-
import path4 from "path";
|
|
280
|
-
import { Logger } from "akanjs/common";
|
|
281
47
|
var REEXPORT_RE = /(?:^|\n)\s*export\s+(?:type\s+)?(?:(\*)(?:\s+as\s+(\w+))?|\{\s*([^}]*?)\s*\})\s+from\s+(["'])([^"']+)\4;?/g;
|
|
282
48
|
var LOCAL_NAMED_RE = /(?:^|\n)\s*export\s+\{\s*([^}]*?)\s*\}(?!\s*from)/g;
|
|
283
49
|
var CANDIDATE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
@@ -381,7 +147,7 @@ class BarrelAnalyzer {
|
|
|
381
147
|
}
|
|
382
148
|
#scanExports(source, absFile) {
|
|
383
149
|
try {
|
|
384
|
-
const transpiler = [".tsx", ".jsx"].includes(
|
|
150
|
+
const transpiler = [".tsx", ".jsx"].includes(path.extname(absFile)) ? this.#tsxTranspiler : this.#tsTranspiler;
|
|
385
151
|
const { exports } = transpiler.scan(source);
|
|
386
152
|
return new Set(exports);
|
|
387
153
|
} catch (err) {
|
|
@@ -390,13 +156,13 @@ class BarrelAnalyzer {
|
|
|
390
156
|
}
|
|
391
157
|
}
|
|
392
158
|
#subpathFor(pkg, absFile) {
|
|
393
|
-
const rel =
|
|
394
|
-
if (!rel || rel.startsWith("..") ||
|
|
159
|
+
const rel = path.relative(pkg.pkgDir, absFile);
|
|
160
|
+
if (!rel || rel.startsWith("..") || path.isAbsolute(rel))
|
|
395
161
|
return null;
|
|
396
162
|
if (pkg.preserveFilePath)
|
|
397
|
-
return `${pkg.pkgName}/${rel.split(
|
|
163
|
+
return `${pkg.pkgName}/${rel.split(path.sep).join("/")}`;
|
|
398
164
|
const ext = CANDIDATE_EXTS.find((candidate) => rel.endsWith(candidate));
|
|
399
|
-
const parts = (ext ? rel.slice(0, -ext.length) : rel).split(
|
|
165
|
+
const parts = (ext ? rel.slice(0, -ext.length) : rel).split(path.sep);
|
|
400
166
|
if (parts[parts.length - 1] === "index")
|
|
401
167
|
parts.pop();
|
|
402
168
|
const tail = parts.join("/");
|
|
@@ -412,9 +178,9 @@ var isRelative = (spec) => {
|
|
|
412
178
|
return spec.startsWith("./") || spec.startsWith("../") || spec === "." || spec === "..";
|
|
413
179
|
};
|
|
414
180
|
var defaultResolveRelative = async (fromFile, relSpec) => {
|
|
415
|
-
const baseDir =
|
|
416
|
-
const joined =
|
|
417
|
-
if (
|
|
181
|
+
const baseDir = path.dirname(fromFile);
|
|
182
|
+
const joined = path.resolve(baseDir, relSpec);
|
|
183
|
+
if (path.extname(joined)) {
|
|
418
184
|
if (await Bun.file(joined).exists())
|
|
419
185
|
return joined;
|
|
420
186
|
return null;
|
|
@@ -425,7 +191,7 @@ var defaultResolveRelative = async (fromFile, relSpec) => {
|
|
|
425
191
|
return cand;
|
|
426
192
|
}
|
|
427
193
|
for (const ext of CANDIDATE_EXTS) {
|
|
428
|
-
const cand =
|
|
194
|
+
const cand = path.join(joined, `index${ext}`);
|
|
429
195
|
if (await Bun.file(cand).exists())
|
|
430
196
|
return cand;
|
|
431
197
|
}
|
|
@@ -433,6 +199,8 @@ var defaultResolveRelative = async (fromFile, relSpec) => {
|
|
|
433
199
|
};
|
|
434
200
|
|
|
435
201
|
// pkgs/@akanjs/devkit/transforms/barrelImportsPlugin.ts
|
|
202
|
+
import path2 from "path";
|
|
203
|
+
import ts from "typescript";
|
|
436
204
|
var createBarrelImportsPlugin = async (app, { skipPath = defaultSkipPath, pipeAfter } = {}) => {
|
|
437
205
|
const akanConfig = await app.getConfig();
|
|
438
206
|
const barrels = [...new Set(akanConfig.barrelImports)].filter(Boolean);
|
|
@@ -475,14 +243,14 @@ var createTsconfigPackageResolver = async (app) => {
|
|
|
475
243
|
const raw = exact[0];
|
|
476
244
|
if (!raw)
|
|
477
245
|
return null;
|
|
478
|
-
const entryFile =
|
|
246
|
+
const entryFile = path2.resolve(app.workspace.workspaceRoot, raw);
|
|
479
247
|
if (!await Bun.file(entryFile).exists())
|
|
480
248
|
return null;
|
|
481
|
-
const parsed =
|
|
249
|
+
const parsed = path2.parse(entryFile);
|
|
482
250
|
const lastSlash = pkgName.lastIndexOf("/");
|
|
483
251
|
if (parsed.name !== "index" && lastSlash > 0 && pkgName.slice(lastSlash + 1) === parsed.name)
|
|
484
252
|
return { pkgName: pkgName.slice(0, lastSlash), entryFile, pkgDir: parsed.dir };
|
|
485
|
-
return { pkgName, entryFile, pkgDir:
|
|
253
|
+
return { pkgName, entryFile, pkgDir: path2.dirname(entryFile) };
|
|
486
254
|
}
|
|
487
255
|
for (const { prefix, replacements } of wildcardEntries) {
|
|
488
256
|
if (!pkgName.startsWith(prefix))
|
|
@@ -492,17 +260,17 @@ var createTsconfigPackageResolver = async (app) => {
|
|
|
492
260
|
if (!repl)
|
|
493
261
|
continue;
|
|
494
262
|
const replPath = repl.endsWith("/*") ? repl.slice(0, -1) : repl;
|
|
495
|
-
const candidate =
|
|
263
|
+
const candidate = path2.resolve(app.workspace.workspaceRoot, replPath + suffix);
|
|
496
264
|
for (const ext of CANDIDATE_EXTS2) {
|
|
497
265
|
const file = `${candidate}${ext}`;
|
|
498
266
|
if (await Bun.file(file).exists()) {
|
|
499
267
|
const lastSlash = pkgName.lastIndexOf("/");
|
|
500
268
|
const parentSpec = lastSlash > 0 ? pkgName.slice(0, lastSlash) : pkgName;
|
|
501
|
-
return { pkgName: parentSpec, entryFile: file, pkgDir:
|
|
269
|
+
return { pkgName: parentSpec, entryFile: file, pkgDir: path2.dirname(file) };
|
|
502
270
|
}
|
|
503
271
|
}
|
|
504
272
|
for (const ext of CANDIDATE_EXTS2) {
|
|
505
|
-
const file =
|
|
273
|
+
const file = path2.join(candidate, `index${ext}`);
|
|
506
274
|
if (await Bun.file(file).exists())
|
|
507
275
|
return { pkgName, entryFile: file, pkgDir: candidate };
|
|
508
276
|
}
|
|
@@ -512,16 +280,16 @@ var createTsconfigPackageResolver = async (app) => {
|
|
|
512
280
|
const exported = await resolveNodePackageExport(app.workspace.workspaceRoot, pkgName);
|
|
513
281
|
if (exported)
|
|
514
282
|
return exported;
|
|
515
|
-
const pkgJsonPath =
|
|
283
|
+
const pkgJsonPath = path2.join(app.workspace.workspaceRoot, "node_modules", pkgName, "package.json");
|
|
516
284
|
if (!await Bun.file(pkgJsonPath).exists())
|
|
517
285
|
return null;
|
|
518
286
|
try {
|
|
519
287
|
const pkgJson = JSON.parse(await Bun.file(pkgJsonPath).text());
|
|
520
288
|
const rel = pkgJson.module ?? pkgJson.main ?? "index.js";
|
|
521
|
-
const entryFile =
|
|
289
|
+
const entryFile = path2.resolve(path2.dirname(pkgJsonPath), rel);
|
|
522
290
|
if (!await Bun.file(entryFile).exists())
|
|
523
291
|
return null;
|
|
524
|
-
return { pkgName, entryFile, pkgDir:
|
|
292
|
+
return { pkgName, entryFile, pkgDir: path2.dirname(pkgJsonPath) };
|
|
525
293
|
} catch {
|
|
526
294
|
return null;
|
|
527
295
|
}
|
|
@@ -535,21 +303,21 @@ var resolveNodePackageExport = async (workspaceRoot, specifier) => {
|
|
|
535
303
|
const packageName = getPackageName(specifier);
|
|
536
304
|
if (!packageName)
|
|
537
305
|
return null;
|
|
538
|
-
const pkgJsonPath =
|
|
306
|
+
const pkgJsonPath = path2.join(workspaceRoot, "node_modules", packageName, "package.json");
|
|
539
307
|
if (!await Bun.file(pkgJsonPath).exists())
|
|
540
308
|
return null;
|
|
541
309
|
try {
|
|
542
|
-
const pkgDir =
|
|
310
|
+
const pkgDir = path2.dirname(pkgJsonPath);
|
|
543
311
|
const pkgJson = JSON.parse(await Bun.file(pkgJsonPath).text());
|
|
544
312
|
const subpath = specifier === packageName ? "." : `.${specifier.slice(packageName.length)}`;
|
|
545
313
|
const exported = resolvePackageExport(pkgJson.exports, subpath);
|
|
546
314
|
const rel = exported ?? (subpath === "." ? pkgJson.module ?? pkgJson.main ?? "index.js" : null);
|
|
547
315
|
if (!rel?.startsWith("."))
|
|
548
316
|
return null;
|
|
549
|
-
const entryFile = await resolveFileCandidate(
|
|
317
|
+
const entryFile = await resolveFileCandidate(path2.resolve(pkgDir, rel));
|
|
550
318
|
if (!entryFile)
|
|
551
319
|
return null;
|
|
552
|
-
return { pkgName: specifier, entryFile, pkgDir:
|
|
320
|
+
return { pkgName: specifier, entryFile, pkgDir: path2.dirname(entryFile), preserveFilePath: true };
|
|
553
321
|
} catch {
|
|
554
322
|
return null;
|
|
555
323
|
}
|
|
@@ -591,7 +359,7 @@ var resolvePackageExport = (exportsMap, subpath) => {
|
|
|
591
359
|
const wildcard = subpath.slice(prefix.length, subpath.length - suffix.length);
|
|
592
360
|
const resolved = resolveExportValue(value);
|
|
593
361
|
if (resolved)
|
|
594
|
-
return resolved.
|
|
362
|
+
return resolved.split("*").join(wildcard);
|
|
595
363
|
}
|
|
596
364
|
return null;
|
|
597
365
|
};
|
|
@@ -606,7 +374,7 @@ var getPackageName = (specifier) => {
|
|
|
606
374
|
var resolveFileCandidate = async (candidate) => {
|
|
607
375
|
if (await Bun.file(candidate).exists())
|
|
608
376
|
return candidate;
|
|
609
|
-
if (
|
|
377
|
+
if (path2.extname(candidate))
|
|
610
378
|
return null;
|
|
611
379
|
for (const ext of CANDIDATE_EXTS2) {
|
|
612
380
|
const file = `${candidate}${ext}`;
|
|
@@ -614,7 +382,7 @@ var resolveFileCandidate = async (candidate) => {
|
|
|
614
382
|
return file;
|
|
615
383
|
}
|
|
616
384
|
for (const ext of CANDIDATE_EXTS2) {
|
|
617
|
-
const file =
|
|
385
|
+
const file = path2.join(candidate, `index${ext}`);
|
|
618
386
|
if (await Bun.file(file).exists())
|
|
619
387
|
return file;
|
|
620
388
|
}
|
|
@@ -648,11 +416,11 @@ var rewriteBarrelImports = async (source, barrels, analyzer) => {
|
|
|
648
416
|
};
|
|
649
417
|
var findImportStatements = (source) => {
|
|
650
418
|
const statements = [];
|
|
651
|
-
const sourceFile =
|
|
419
|
+
const sourceFile = ts.createSourceFile("barrel-imports.tsx", source, ts.ScriptTarget.Latest, false, ts.ScriptKind.TSX);
|
|
652
420
|
for (const statement of sourceFile.statements) {
|
|
653
|
-
if (!
|
|
421
|
+
if (!ts.isImportDeclaration(statement))
|
|
654
422
|
continue;
|
|
655
|
-
if (!
|
|
423
|
+
if (!ts.isStringLiteral(statement.moduleSpecifier))
|
|
656
424
|
continue;
|
|
657
425
|
const importClause = statement.importClause;
|
|
658
426
|
if (!importClause)
|
|
@@ -750,8 +518,156 @@ var serializeNamedItem = (item) => {
|
|
|
750
518
|
return `${prefix}${item.imported} as ${item.local}`;
|
|
751
519
|
};
|
|
752
520
|
|
|
521
|
+
// pkgs/@akanjs/devkit/frontendBuild/bundleDefine.ts
|
|
522
|
+
var bundleDefine = (app, command, renderEnv) => {
|
|
523
|
+
const nodeEnv = command === "build" ? "production" : "development";
|
|
524
|
+
return {
|
|
525
|
+
"process.env.NODE_ENV": JSON.stringify(nodeEnv),
|
|
526
|
+
"process.env.AKAN_PUBLIC_RENDER_ENV": JSON.stringify(renderEnv),
|
|
527
|
+
...Object.fromEntries(Object.entries(app.getPublicEnv()).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, value]) => [`process.env.${key}`, JSON.stringify(value)]))
|
|
528
|
+
};
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
// pkgs/@akanjs/devkit/frontendBuild/csrDevPaths.ts
|
|
532
|
+
import fs from "fs";
|
|
533
|
+
import path3 from "path";
|
|
534
|
+
|
|
535
|
+
class CsrDevPaths {
|
|
536
|
+
static modulePrefix = "akan-module:";
|
|
537
|
+
static stubPrefix = "stub:";
|
|
538
|
+
static emptyStubPrefix = "stub:empty:";
|
|
539
|
+
static vendorPrefix = "vendor:";
|
|
540
|
+
root;
|
|
541
|
+
constructor(workspaceRoot) {
|
|
542
|
+
this.root = CsrDevPaths.realpath(workspaceRoot);
|
|
543
|
+
}
|
|
544
|
+
idOf(file) {
|
|
545
|
+
const real = CsrDevPaths.realpath(file);
|
|
546
|
+
const relative = path3.relative(this.root, real);
|
|
547
|
+
const id = relative.startsWith("..") || path3.isAbsolute(relative) ? real : relative;
|
|
548
|
+
return id.split(path3.sep).join("/");
|
|
549
|
+
}
|
|
550
|
+
fileOf(id) {
|
|
551
|
+
return path3.isAbsolute(id) ? id : path3.join(this.root, id);
|
|
552
|
+
}
|
|
553
|
+
static isStub(target) {
|
|
554
|
+
return target.startsWith(CsrDevPaths.stubPrefix);
|
|
555
|
+
}
|
|
556
|
+
static isVendorFile(file) {
|
|
557
|
+
return file.includes(`${path3.sep}node_modules${path3.sep}`);
|
|
558
|
+
}
|
|
559
|
+
static isScript(file) {
|
|
560
|
+
return /\.[cm]?[jt]sx?$/.test(file);
|
|
561
|
+
}
|
|
562
|
+
static mtimeOf(file) {
|
|
563
|
+
return fs.statSync(file, { throwIfNoEntry: false })?.mtimeMs ?? -1;
|
|
564
|
+
}
|
|
565
|
+
static async hashOf(file) {
|
|
566
|
+
const source = Bun.file(file);
|
|
567
|
+
return await source.exists() ? Bun.hash(await source.arrayBuffer()).toString(36) : "";
|
|
568
|
+
}
|
|
569
|
+
static realpath(file) {
|
|
570
|
+
return fs.existsSync(file) ? fs.realpathSync.native(file) : path3.resolve(file);
|
|
571
|
+
}
|
|
572
|
+
static isNamed(file) {
|
|
573
|
+
try {
|
|
574
|
+
return fs.realpathSync.native(file) === file;
|
|
575
|
+
} catch {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
static #extensions = {
|
|
580
|
+
import: [".tsx", ".jsx", ".mts", ".ts", ".mjs", ".js", ".cts", ".cjs"],
|
|
581
|
+
require: [".tsx", ".ts", ".jsx", ".cts", ".cjs", ".js", ".mjs", ".mts"]
|
|
582
|
+
};
|
|
583
|
+
static resolveOnDisk(base, kind = "import") {
|
|
584
|
+
return CsrDevPaths.#asFile(base, kind) ?? CsrDevPaths.#asFolder(base, kind);
|
|
585
|
+
}
|
|
586
|
+
static resolveRelative(dir, specifier, kind = "import") {
|
|
587
|
+
const base = path3.resolve(dir, specifier);
|
|
588
|
+
const folder = /(^|[\\/])\.\.?$|[\\/]$/.test(specifier);
|
|
589
|
+
return folder ? CsrDevPaths.#asFolder(base, kind) : CsrDevPaths.resolveOnDisk(base, kind);
|
|
590
|
+
}
|
|
591
|
+
static #asFile(base, kind) {
|
|
592
|
+
const isFile = (candidate) => fs.statSync(candidate, { throwIfNoEntry: false })?.isFile() ?? false;
|
|
593
|
+
return [base, ...CsrDevPaths.#extensions[kind].map((extension) => `${base}${extension}`)].find(isFile) ?? null;
|
|
594
|
+
}
|
|
595
|
+
static #asFolder(dir, kind) {
|
|
596
|
+
const entry = CsrDevPaths.#packageEntryOf(dir, kind);
|
|
597
|
+
const named = entry ? CsrDevPaths.#asFile(path3.join(dir, entry), kind) ?? CsrDevPaths.#indexOf(path3.join(dir, entry), kind) : null;
|
|
598
|
+
return named ?? CsrDevPaths.#indexOf(dir, kind);
|
|
599
|
+
}
|
|
600
|
+
static #indexOf(dir, kind) {
|
|
601
|
+
return CsrDevPaths.#asFile(path3.join(dir, "index"), kind);
|
|
602
|
+
}
|
|
603
|
+
static #packageEntryOf(dir, kind) {
|
|
604
|
+
try {
|
|
605
|
+
const pkg = JSON.parse(fs.readFileSync(path3.join(dir, "package.json"), "utf8"));
|
|
606
|
+
const fields = kind === "require" ? [pkg.browser, pkg.main] : [pkg.browser, pkg.module, pkg.main];
|
|
607
|
+
const entry = fields.find((field) => typeof field === "string");
|
|
608
|
+
return typeof entry === "string" ? entry : null;
|
|
609
|
+
} catch {
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
static installedSince(specifier, from, since) {
|
|
614
|
+
const [first = "", second = ""] = specifier.split("/");
|
|
615
|
+
const name = first.startsWith("@") ? `${first}/${second}` : first;
|
|
616
|
+
if (!name || name.startsWith("."))
|
|
617
|
+
return false;
|
|
618
|
+
for (let dir = path3.resolve(from);; dir = path3.dirname(dir)) {
|
|
619
|
+
const pkgDir = path3.join(dir, "node_modules", name);
|
|
620
|
+
if (fs.existsSync(path3.join(pkgDir, "package.json")))
|
|
621
|
+
return (fs.statSync(pkgDir, { throwIfNoEntry: false })?.ctimeMs ?? 0) > since;
|
|
622
|
+
if (path3.dirname(dir) === dir)
|
|
623
|
+
return false;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
static tryResolve(specifier, from) {
|
|
627
|
+
try {
|
|
628
|
+
return Bun.resolveSync(specifier, from);
|
|
629
|
+
} catch {
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
static lineCount(text) {
|
|
634
|
+
let count = 0;
|
|
635
|
+
for (let index = text.indexOf(`
|
|
636
|
+
`);index !== -1; index = text.indexOf(`
|
|
637
|
+
`, index + 1))
|
|
638
|
+
count += 1;
|
|
639
|
+
return count;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// pkgs/@akanjs/devkit/frontendBuild/csrEntryFiles.ts
|
|
644
|
+
import path4 from "path";
|
|
645
|
+
|
|
646
|
+
class CsrEntryFiles {
|
|
647
|
+
static entryFilename(basePath) {
|
|
648
|
+
return `${basePath || "index"}.csr.tsx`;
|
|
649
|
+
}
|
|
650
|
+
static pageEntriesForBasePath(pageEntries, basePath, basePaths) {
|
|
651
|
+
return pageEntries.filter((entry) => {
|
|
652
|
+
const entryBasePath = CsrEntryFiles.basePathOfPageKey(entry.key, basePaths);
|
|
653
|
+
return entryBasePath === null || entryBasePath === basePath;
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
static basePathOfPageKey(pageKey, basePaths) {
|
|
657
|
+
const normalized = pageKey.split(path4.sep).join("/").replace(/^\.\//, "");
|
|
658
|
+
const segments = normalized.split("/");
|
|
659
|
+
const firstPublicSegment = segments.find((segment) => segment !== "[lang]" && !/^\(.+\)$/.test(segment));
|
|
660
|
+
return firstPublicSegment && basePaths.includes(firstPublicSegment) ? firstPublicSegment : null;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// pkgs/@akanjs/devkit/frontendBuild/pagesBundleBuilder.ts
|
|
665
|
+
import fs3 from "fs";
|
|
666
|
+
import path9 from "path";
|
|
667
|
+
import ts3 from "typescript";
|
|
668
|
+
|
|
753
669
|
// pkgs/@akanjs/devkit/transforms/externalizeFrameworkPlugin.ts
|
|
754
|
-
import
|
|
670
|
+
import path5 from "path";
|
|
755
671
|
var DEFAULT_INCLUDE = ["akanjs/", "@apps/", "@libs/"];
|
|
756
672
|
var DEFAULT_EXCLUDE_EXACT = new Set(["akanjs/webkit", "@akanjs/cli", "@akanjs/devkit"]);
|
|
757
673
|
var DEFAULT_EXCLUDE_PREFIX = ["@akanjs/cli/", "@akanjs/devkit/"];
|
|
@@ -787,7 +703,7 @@ async function createExternalizeFrameworkPlugin(options) {
|
|
|
787
703
|
const replPath = repl?.endsWith("/*") ? repl.slice(0, -1) : repl ?? "";
|
|
788
704
|
if (!replPath)
|
|
789
705
|
continue;
|
|
790
|
-
const candidate =
|
|
706
|
+
const candidate = path5.resolve(workspaceRoot, replPath + suffix);
|
|
791
707
|
const hit = await firstExisting(candidate);
|
|
792
708
|
if (hit)
|
|
793
709
|
return hit;
|
|
@@ -797,8 +713,8 @@ async function createExternalizeFrameworkPlugin(options) {
|
|
|
797
713
|
if (!spec.startsWith(`${pkg}/`))
|
|
798
714
|
continue;
|
|
799
715
|
const suffix = spec.slice(pkg.length + 1);
|
|
800
|
-
const pkgDir =
|
|
801
|
-
const candidate =
|
|
716
|
+
const pkgDir = path5.dirname(path5.resolve(workspaceRoot, entryFile));
|
|
717
|
+
const candidate = path5.join(pkgDir, suffix);
|
|
802
718
|
const hit = await firstExisting(candidate);
|
|
803
719
|
if (hit)
|
|
804
720
|
return hit;
|
|
@@ -843,13 +759,57 @@ async function firstExisting(basePath) {
|
|
|
843
759
|
return candidate;
|
|
844
760
|
}
|
|
845
761
|
for (const ext of CANDIDATE_EXTS3) {
|
|
846
|
-
const candidate =
|
|
762
|
+
const candidate = path5.join(basePath, `index${ext}`);
|
|
847
763
|
if (await Bun.file(candidate).exists())
|
|
848
764
|
return candidate;
|
|
849
765
|
}
|
|
850
766
|
return null;
|
|
851
767
|
}
|
|
852
768
|
|
|
769
|
+
// pkgs/@akanjs/devkit/transforms/rscUseClientTransform.ts
|
|
770
|
+
import path6 from "path";
|
|
771
|
+
import ts2 from "typescript";
|
|
772
|
+
var USE_CLIENT_RE = /^\s*(?:\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*|\/\/[^\n]*\n\s*)*["']use client["']/;
|
|
773
|
+
var IMPLICIT_ROOT_LAYOUT_RE = /[/\\]\.akan[/\\]generated[/\\](?:implicit-root-layout|root-layouts[/\\][^/\\]*__root_layout)\.(tsx|ts|jsx|js)$/;
|
|
774
|
+
var STAR_REEXPORT_HINT_RE = /\bexport\s*\*\s*from\b/;
|
|
775
|
+
var hasUseClientDirective = (source) => USE_CLIENT_RE.test(source);
|
|
776
|
+
function toClientReferencePath(absPath, workspaceRoot) {
|
|
777
|
+
return path6.relative(path6.resolve(workspaceRoot), path6.resolve(absPath)).split(path6.sep).join("/");
|
|
778
|
+
}
|
|
779
|
+
var starReexportSpecifiers = (source, filePath) => ts2.createSourceFile(filePath, source, ts2.ScriptTarget.Latest).statements.filter((statement) => ts2.isExportDeclaration(statement) && !statement.exportClause && !statement.isTypeOnly && !!statement.moduleSpecifier && ts2.isStringLiteral(statement.moduleSpecifier)).map((statement) => statement.moduleSpecifier.text);
|
|
780
|
+
var scanUseClientExports = (source, filePath, workspaceRoot) => {
|
|
781
|
+
const stars = USE_CLIENT_RE.test(source) && STAR_REEXPORT_HINT_RE.test(source) ? starReexportSpecifiers(source, filePath) : [];
|
|
782
|
+
if (stars.length) {
|
|
783
|
+
const file = workspaceRoot ? toClientReferencePath(filePath, workspaceRoot) : filePath;
|
|
784
|
+
const listed = stars.slice(0, 3).map((specifier) => `\`export * from ${JSON.stringify(specifier)}\``);
|
|
785
|
+
const written = stars.length > 3 ? `${listed.join(", ")} (and ${stars.length - 3} more)` : listed.join(", ");
|
|
786
|
+
throw new Error(`${file} is a "use client" module, so it cannot ${written}: the server sees only the names a client module ` + `declares, and a star re-export declares none. Re-export them by name \u2014 \`export { \u2026 } from ${JSON.stringify(stars[0])}\`.`);
|
|
787
|
+
}
|
|
788
|
+
return new Bun.Transpiler({ loader: loaderFor(filePath) }).scan(source).exports;
|
|
789
|
+
};
|
|
790
|
+
function transformUseClient(source, args) {
|
|
791
|
+
if (!USE_CLIENT_RE.test(source))
|
|
792
|
+
return null;
|
|
793
|
+
if (IMPLICIT_ROOT_LAYOUT_RE.test(args.path))
|
|
794
|
+
return null;
|
|
795
|
+
const exports = scanUseClientExports(source, args.path, args.workspaceRoot);
|
|
796
|
+
if (exports.length === 0)
|
|
797
|
+
return null;
|
|
798
|
+
args.onClientModule?.(args.path, exports);
|
|
799
|
+
const referencePath = args.workspaceRoot ? toClientReferencePath(args.path, args.workspaceRoot) : args.path;
|
|
800
|
+
const filePathLit = JSON.stringify(referencePath);
|
|
801
|
+
const lines = [`import { registerClientReference } from "react-server-dom-webpack/server.node";`];
|
|
802
|
+
for (const name of exports) {
|
|
803
|
+
const nameLit = JSON.stringify(name);
|
|
804
|
+
const errMsg = JSON.stringify(`Attempted to call '${name}' from '${referencePath}' on the server, but it is a client-only export.`);
|
|
805
|
+
const proxy = `() => { throw new Error(${errMsg}); }`;
|
|
806
|
+
const binding = name === "default" ? `export default registerClientReference(${proxy}, ${filePathLit}, ${nameLit});` : `export const ${name} = registerClientReference(${proxy}, ${filePathLit}, ${nameLit});`;
|
|
807
|
+
lines.push(binding);
|
|
808
|
+
}
|
|
809
|
+
return lines.join(`
|
|
810
|
+
`);
|
|
811
|
+
}
|
|
812
|
+
|
|
853
813
|
// pkgs/@akanjs/devkit/transforms/useClientBundlePlugin.ts
|
|
854
814
|
function createUseClientBundlePlugin(options = {}) {
|
|
855
815
|
return {
|
|
@@ -877,16 +837,6 @@ function createUseClientBundlePlugin(options = {}) {
|
|
|
877
837
|
};
|
|
878
838
|
}
|
|
879
839
|
|
|
880
|
-
// pkgs/@akanjs/devkit/frontendBuild/bundleDefine.ts
|
|
881
|
-
var bundleDefine = (app, command, renderEnv) => {
|
|
882
|
-
const nodeEnv = command === "build" ? "production" : "development";
|
|
883
|
-
return {
|
|
884
|
-
"process.env.NODE_ENV": JSON.stringify(nodeEnv),
|
|
885
|
-
"process.env.AKAN_PUBLIC_RENDER_ENV": JSON.stringify(renderEnv),
|
|
886
|
-
...Object.fromEntries(Object.entries(app.getPublicEnv()).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, value]) => [`process.env.${key}`, JSON.stringify(value)]))
|
|
887
|
-
};
|
|
888
|
-
};
|
|
889
|
-
|
|
890
840
|
// pkgs/@akanjs/devkit/frontendBuild/pagesEntrySourceGenerator.ts
|
|
891
841
|
import path7 from "path";
|
|
892
842
|
class PagesEntrySourceGenerator {
|
|
@@ -967,6 +917,74 @@ ${entries.join(`
|
|
|
967
917
|
}
|
|
968
918
|
}
|
|
969
919
|
|
|
920
|
+
// pkgs/@akanjs/devkit/frontendBuild/serverGraphFile.ts
|
|
921
|
+
import fs2 from "fs";
|
|
922
|
+
import path8 from "path";
|
|
923
|
+
class ServerGraphFile {
|
|
924
|
+
static fileName = "server-graph.json";
|
|
925
|
+
static #cache = null;
|
|
926
|
+
static async read(artifactDir) {
|
|
927
|
+
const file = path8.join(artifactDir, ServerGraphFile.fileName);
|
|
928
|
+
const stat = fs2.statSync(file, { throwIfNoEntry: false });
|
|
929
|
+
if (!stat)
|
|
930
|
+
return null;
|
|
931
|
+
const stamp = `${stat.ino}:${stat.size}:${stat.mtimeMs}`;
|
|
932
|
+
const cached = ServerGraphFile.#cache;
|
|
933
|
+
if (cached?.file === file && cached.stamp === stamp)
|
|
934
|
+
return cached.graph;
|
|
935
|
+
const graph = await Bun.file(file).json().catch(() => null);
|
|
936
|
+
if (graph)
|
|
937
|
+
ServerGraphFile.#cache = { file, stamp, graph };
|
|
938
|
+
return graph;
|
|
939
|
+
}
|
|
940
|
+
static async write(artifactDir, graph) {
|
|
941
|
+
const file = path8.join(artifactDir, ServerGraphFile.fileName);
|
|
942
|
+
const temp = `${file}.${process.pid}.tmp`;
|
|
943
|
+
await Bun.write(temp, JSON.stringify(graph));
|
|
944
|
+
await FileSys2.replace(temp, file);
|
|
945
|
+
}
|
|
946
|
+
static async carry(artifactDir, files) {
|
|
947
|
+
const graph = await ServerGraphFile.read(artifactDir);
|
|
948
|
+
if (!graph || files.length === 0)
|
|
949
|
+
return;
|
|
950
|
+
const carried = [...new Set([...graph.carried ?? [], ...files.map((file) => CsrDevPaths.realpath(file))])];
|
|
951
|
+
await ServerGraphFile.write(artifactDir, { ...graph, carried });
|
|
952
|
+
}
|
|
953
|
+
static async touches(graph, files, exportsNow, next) {
|
|
954
|
+
if (!graph)
|
|
955
|
+
return true;
|
|
956
|
+
const inputs = new Set(graph.inputs);
|
|
957
|
+
const joined = new Set((next?.inputs ?? []).filter((input) => !inputs.has(input)));
|
|
958
|
+
for (const rawFile of files) {
|
|
959
|
+
const file = CsrDevPaths.realpath(rawFile);
|
|
960
|
+
if (joined.has(file))
|
|
961
|
+
return true;
|
|
962
|
+
if (!inputs.has(file))
|
|
963
|
+
continue;
|
|
964
|
+
const before = graph.clientExports[file];
|
|
965
|
+
if (!before)
|
|
966
|
+
return true;
|
|
967
|
+
const now = await exportsNow(file);
|
|
968
|
+
if (!now || ServerGraphFile.#names(now) !== ServerGraphFile.#names(before))
|
|
969
|
+
return true;
|
|
970
|
+
}
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
static async clientExportsOf(file) {
|
|
974
|
+
const source = await Bun.file(file).text().catch(() => null);
|
|
975
|
+
if (source === null || !hasUseClientDirective(source))
|
|
976
|
+
return null;
|
|
977
|
+
try {
|
|
978
|
+
return scanUseClientExports(source, file);
|
|
979
|
+
} catch {
|
|
980
|
+
return null;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
static #names(exports) {
|
|
984
|
+
return [...exports].sort().join(",");
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
970
988
|
// pkgs/@akanjs/devkit/frontendBuild/pagesBundleBuilder.ts
|
|
971
989
|
var VIRTUAL_PAGES_ENTRY = "akan-pages-entry";
|
|
972
990
|
|
|
@@ -1026,13 +1044,13 @@ class PagesBundleBuilder {
|
|
|
1026
1044
|
const entryArtifact = result.outputs.find((a) => a.kind === "entry-point");
|
|
1027
1045
|
if (!entryArtifact)
|
|
1028
1046
|
throw new Error("[PagesBundleBuilder] Bun.build emitted no entry-point artifact");
|
|
1029
|
-
const bundlePath =
|
|
1047
|
+
const bundlePath = path9.resolve(entryArtifact.path);
|
|
1030
1048
|
const buildId = Date.now();
|
|
1031
1049
|
if (dev && result.metafile)
|
|
1032
1050
|
await ServerGraphFile.write(this.#artifactDir, this.#serverGraph(result.metafile, clientExports));
|
|
1033
1051
|
const outputBytes = result.outputs.reduce((sum, output) => sum + output.size, 0);
|
|
1034
1052
|
const chunkCount = result.outputs.filter((output) => output.kind === "chunk").length;
|
|
1035
|
-
this.#app.verbose(`[PagesBundleBuilder] ${
|
|
1053
|
+
this.#app.verbose(`[PagesBundleBuilder] ${path9.basename(bundlePath)} emitted in ${Date.now() - this.#started}ms splitting=${this.#splitting} entry=${entryArtifact.size} bytes outputs=${result.outputs.length} chunks=${chunkCount} total=${outputBytes} bytes`);
|
|
1036
1054
|
return {
|
|
1037
1055
|
bundlePath,
|
|
1038
1056
|
buildId,
|
|
@@ -1044,7 +1062,7 @@ class PagesBundleBuilder {
|
|
|
1044
1062
|
};
|
|
1045
1063
|
}
|
|
1046
1064
|
#serverGraph(metafile, clientExports) {
|
|
1047
|
-
const inputs = Object.keys(metafile.inputs).filter((input) => !input.includes("node_modules")).map((input) =>
|
|
1065
|
+
const inputs = Object.keys(metafile.inputs).filter((input) => !input.includes("node_modules")).map((input) => path9.resolve(input)).filter((input) => fs3.existsSync(input)).map((input) => CsrDevPaths.realpath(input));
|
|
1048
1066
|
return { inputs, clientExports };
|
|
1049
1067
|
}
|
|
1050
1068
|
get #artifactDir() {
|
|
@@ -1096,28 +1114,59 @@ class PagesBundleBuilder {
|
|
|
1096
1114
|
static transformServerUseClientFetchSource(source) {
|
|
1097
1115
|
if (!source.includes(`with { type: "macro" }`) || !source.includes("FetchClient.build"))
|
|
1098
1116
|
return source;
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1117
|
+
const tokens = PagesBundleBuilder.#tokenize(source);
|
|
1118
|
+
const edits = [];
|
|
1119
|
+
const importAt = PagesBundleBuilder.#indexOfTokens(tokens, PagesBundleBuilder.#macroImportTokens);
|
|
1120
|
+
if (importAt !== -1)
|
|
1121
|
+
edits.push({
|
|
1122
|
+
start: tokens[importAt].start,
|
|
1123
|
+
end: tokens[importAt + PagesBundleBuilder.#macroImportTokens.length - 1].end,
|
|
1124
|
+
text: `import { fetch as serverFetch } from "./sig";`
|
|
1125
|
+
});
|
|
1126
|
+
const fetchProtoAt = PagesBundleBuilder.#indexOfTokens(tokens, PagesBundleBuilder.#fetchProtoTokens);
|
|
1127
|
+
const fetchProtoEnd = fetchProtoAt === -1 ? undefined : tokens.slice(fetchProtoAt).find(({ text }) => text === ";");
|
|
1128
|
+
if (fetchProtoEnd)
|
|
1129
|
+
edits.push({
|
|
1130
|
+
start: tokens[fetchProtoAt].start,
|
|
1131
|
+
end: fetchProtoEnd.end,
|
|
1132
|
+
text: "const fetchProto = FetchClient.build<typeof signal>(cnst, serverFetch.serializedSignal, { Err: pageProto.Err, base: serverFetch });"
|
|
1133
|
+
});
|
|
1134
|
+
let transformed = source;
|
|
1135
|
+
for (const { start, end, text } of edits.sort((a, b) => b.start - a.start))
|
|
1136
|
+
transformed = transformed.slice(0, start) + text + transformed.slice(end);
|
|
1137
|
+
return transformed;
|
|
1138
|
+
}
|
|
1139
|
+
static #macroImportTokens = [
|
|
1140
|
+
"import",
|
|
1141
|
+
"{",
|
|
1142
|
+
"getSerializedSignal",
|
|
1143
|
+
"}",
|
|
1144
|
+
"from",
|
|
1145
|
+
'"./sig"',
|
|
1146
|
+
"with",
|
|
1147
|
+
"{",
|
|
1148
|
+
"type",
|
|
1149
|
+
":",
|
|
1150
|
+
'"macro"',
|
|
1151
|
+
"}",
|
|
1152
|
+
";"
|
|
1153
|
+
];
|
|
1154
|
+
static #fetchProtoTokens = ["const", "fetchProto", "=", "FetchClient", ".", "build", "<"];
|
|
1155
|
+
static #tokenize(source) {
|
|
1156
|
+
const scanner = ts3.createScanner(ts3.ScriptTarget.Latest, true, ts3.LanguageVariant.Standard, source);
|
|
1157
|
+
const tokens = [];
|
|
1158
|
+
for (let kind = scanner.scan();kind !== ts3.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
|
|
1159
|
+
const text = kind === ts3.SyntaxKind.StringLiteral ? JSON.stringify(scanner.getTokenValue()) : scanner.getTokenText();
|
|
1160
|
+
tokens.push({ text, start: scanner.getTokenStart(), end: scanner.getTokenEnd() });
|
|
1161
|
+
}
|
|
1162
|
+
return tokens;
|
|
1115
1163
|
}
|
|
1116
|
-
static
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1164
|
+
static #indexOfTokens(tokens, pattern) {
|
|
1165
|
+
for (let idx = 0;idx + pattern.length <= tokens.length; idx += 1) {
|
|
1166
|
+
if (pattern.every((text, offset) => tokens[idx + offset].text === text))
|
|
1167
|
+
return idx;
|
|
1168
|
+
}
|
|
1169
|
+
return -1;
|
|
1121
1170
|
}
|
|
1122
1171
|
}
|
|
1123
1172
|
|