@akanjs/cli 2.4.2-rc.3 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.build-stamp +1 -1
- package/{abstractCompactor-ghh1q9an.js → abstractCompactor-bjd2h5pq.js} +1 -1
- package/{agent.command-de4r6vk8.js → agent.command-dwxr73jr.js} +8 -7
- package/{application.command-nfsfm96y.js → application.command-8k6xs7q0.js} +6 -5
- package/{applicationBuildRunner-554a2vnk.js → applicationBuildRunner-hn86q106.js} +5 -4
- package/{applicationReleasePackager-pjbxc793.js → applicationReleasePackager-b1zh40kd.js} +1 -1
- package/buildBatch.proc.js +4 -3
- package/{capacitorApp-yg9b4ajz.js → capacitorApp-sqr41tck.js} +27 -26
- package/{cloud.command-1qf95x67.js → cloud.command-5wh9krwx.js} +9 -8
- package/{context.command-hhjyjtp7.js → context.command-rydtf2vy.js} +15 -14
- package/{dependencyScanner-f6grrep3.js → dependencyScanner-rbs2407b.js} +1 -1
- package/{guideline.command-vj956kfr.js → guideline.command-dtkrftpc.js} +5 -4
- package/incrementalBuilder.proc.js +3 -2
- package/{index-pfnh87f9.js → index-0476y8pz.js} +1 -1
- package/{index-zn9rh7sh.js → index-2f6mjanp.js} +3 -3
- package/{index-xftstr5s.js → index-3f3bjcwc.js} +1 -1
- package/{index-xwfg9bam.js → index-3g17wsqr.js} +10 -5
- package/{index-7ppn9v4n.js → index-3hyw3026.js} +3 -3
- package/{index-s9s0n5fz.js → index-4fh6v6qr.js} +2 -2
- package/{index-y1e79mz3.js → index-4j0qw1hz.js} +11 -11
- package/{index-z36qzgzp.js → index-6a9008sh.js} +2 -2
- package/{index-h971erkm.js → index-90a0z8xq.js} +3 -3
- package/{index-04as43rp.js → index-dscrzdk0.js} +7 -6
- package/{index-7k9sj7j5.js → index-f2s5z0p7.js} +91 -341
- package/index-f39512t6.js +255 -0
- package/{index-d0h48d2f.js → index-g10wmymm.js} +2 -2
- package/{index-fbv96xaw.js → index-hr3n31n0.js} +8 -8
- package/{index-dgeaqwmw.js → index-jf5k3bt8.js} +1 -1
- package/{index-h6eav7zx.js → index-med3vqnc.js} +5 -5
- package/{index-zfp1gz9f.js → index-ms3vpys1.js} +1 -1
- package/{index-v9jqrdd1.js → index-n3drhjgc.js} +2 -2
- package/{index-z5v766nx.js → index-pw9qhve8.js} +3 -3
- package/{index-acwxfncv.js → index-r8drwwr8.js} +4 -4
- package/{index-h5cvg9z9.js → index-z1eqzrj9.js} +3 -3
- package/index.js +20 -19
- package/{library.command-68ah07a3.js → library.command-w11wnq7q.js} +5 -4
- package/{localRegistry.command-84dz000g.js → localRegistry.command-fkq49j84.js} +8 -7
- package/{module.command-t68xhamx.js → module.command-wyjgbg0d.js} +8 -7
- package/{package.command-00ncttab.js → package.command-5ann132q.js} +5 -4
- package/package.json +2 -2
- package/{page.command-1096s18n.js → page.command-e75nxwrw.js} +5 -4
- package/{primitive.command-02eqpx6t.js → primitive.command-gy7nwn5w.js} +9 -8
- package/{quality.command-r9cageqb.js → quality.command-41tw1g5g.js} +4 -3
- package/{repair.command-7dynpnf1.js → repair.command-xr4664h4.js} +7 -6
- package/{routeSourceValidator-cncd92fv.js → routeSourceValidator-rk64s1g4.js} +2 -1
- package/{scalar.command-3kxy3fkh.js → scalar.command-agc839az.js} +7 -6
- package/templates/module/__Model__.Template.tsx +2 -1
- package/templates/module/__Model__.Unit.tsx +2 -1
- package/templates/module/__Model__.Util.tsx +2 -1
- package/templates/module/__Model__.View.tsx +2 -1
- package/templates/module/__Model__.Zone.tsx +2 -1
- package/{typeChecker-kravn7ns.js → typeChecker-g6bh0xfv.js} +1 -1
- package/typecheck.proc.js +1 -1
- package/{workflow.command-yy0d9gk3.js → workflow.command-jf09cq6k.js} +12 -11
- package/{workspace.command-stv9g4a0.js → workspace.command-a57b7ybw.js} +21 -20
- /package/{index-r24hmh0q.js → index-yb2wsc7f.js} +0 -0
|
@@ -10,275 +10,25 @@ import {
|
|
|
10
10
|
rewriteBarrelImports,
|
|
11
11
|
transformUseClient
|
|
12
12
|
} from "./index-rh16j3c7.js";
|
|
13
|
+
import {
|
|
14
|
+
resolveSsrPageEntriesForApp
|
|
15
|
+
} from "./index-f39512t6.js";
|
|
13
16
|
import {
|
|
14
17
|
__require
|
|
15
|
-
} from "./index-
|
|
18
|
+
} from "./index-yb2wsc7f.js";
|
|
16
19
|
|
|
17
20
|
// pkgs/@akanjs/devkit/frontendBuild/allRoutesBuilder.ts
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
// pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
|
|
21
|
-
import { mkdir } from "fs/promises";
|
|
22
|
-
import path from "path";
|
|
23
|
-
var LAYOUT_KEY_RE = /^\.\/(.+\/)?_layout\.(tsx|ts|jsx|js)$/;
|
|
24
|
-
async function appHasStModule(appCwdPath) {
|
|
25
|
-
return Bun.file(path.join(appCwdPath, "lib", "st.ts")).exists();
|
|
26
|
-
}
|
|
27
|
-
var IMPLICIT_LAYOUT_DIR = path.join(".akan", "generated", "root-layouts");
|
|
28
|
-
var IMPLICIT_DICT_DIR = path.join(".akan", "generated", "dict");
|
|
29
|
-
var IMPLICIT_OVERRIDES_DIR = path.join(".akan", "generated", "overrides");
|
|
30
|
-
var OVERRIDES_KEY_RE = /^\.\/(.+\/)?_overrides\.(tsx|ts|jsx|js)$/;
|
|
31
|
-
async function writeGeneratedOverridesLayoutFile(opts) {
|
|
32
|
-
const filename = `${opts.key.replace(/^\.\//, "").replace(/[^a-zA-Z0-9]+/g, "_")}.tsx`;
|
|
33
|
-
const absPath = path.join(path.resolve(opts.appCwdPath), IMPLICIT_OVERRIDES_DIR, filename);
|
|
34
|
-
const userRel = path.relative(path.dirname(absPath), opts.userAbsPath).split(path.sep).join("/");
|
|
35
|
-
const userSpecifier = userRel.startsWith(".") ? userRel : `./${userRel}`;
|
|
36
|
-
const source = `"use client";
|
|
37
|
-
import { UiOverrideProvider } from "akanjs/ui";
|
|
38
|
-
import { createElement, type ReactNode } from "react";
|
|
39
|
-
import value from ${JSON.stringify(userSpecifier)};
|
|
40
|
-
|
|
41
|
-
export default function AkanUiOverridesLayout({ children }: { children?: ReactNode }) {
|
|
42
|
-
return createElement(UiOverrideProvider, { value }, children);
|
|
43
|
-
}
|
|
44
|
-
`;
|
|
45
|
-
await Bun.write(absPath, source);
|
|
46
|
-
return absPath;
|
|
47
|
-
}
|
|
48
|
-
function getRootBoundarySegments(key) {
|
|
49
|
-
const match = LAYOUT_KEY_RE.exec(key);
|
|
50
|
-
if (!match)
|
|
51
|
-
return null;
|
|
52
|
-
const prefix = match[1]?.replace(/\/$/, "");
|
|
53
|
-
if (!prefix)
|
|
54
|
-
return [];
|
|
55
|
-
return prefix.split("/").filter(Boolean);
|
|
56
|
-
}
|
|
57
|
-
function implicitRootLayoutKey(segments) {
|
|
58
|
-
return `./${[...segments, "__root_layout"].join("/")}.tsx`;
|
|
59
|
-
}
|
|
60
|
-
function implicitRootLayoutAbsPath(appCwdPath, segments) {
|
|
61
|
-
const filename = segments.length ? `${segments.join("__")}__root_layout.tsx` : "__root_layout.tsx";
|
|
62
|
-
return path.join(path.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
|
|
63
|
-
}
|
|
64
|
-
function implicitDictionaryMacroAbsPath(appCwdPath) {
|
|
65
|
-
return path.join(path.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
|
|
66
|
-
}
|
|
67
|
-
function isRootBoundarySegments(segments, basePaths) {
|
|
68
|
-
const firstVisibleIndex = segments.findIndex((segment) => !/^\(.+\)$/.test(segment));
|
|
69
|
-
if (firstVisibleIndex === -1)
|
|
70
|
-
return segments.length <= 1;
|
|
71
|
-
if (segments.slice(firstVisibleIndex + 1).some((segment) => /^\(.+\)$/.test(segment)))
|
|
72
|
-
return false;
|
|
73
|
-
const visible = segments.slice(firstVisibleIndex);
|
|
74
|
-
const allowedBasePaths = new Set([...basePaths].map((basePath) => basePath.trim()).filter(Boolean));
|
|
75
|
-
return visible.length === 1 && (firstVisibleIndex > 0 || allowedBasePaths.has(visible[0] ?? ""));
|
|
76
|
-
}
|
|
77
|
-
function findRootBoundaries(pageKeys, appCwdPath, basePaths) {
|
|
78
|
-
const boundaries = new Map;
|
|
79
|
-
for (const key of pageKeys) {
|
|
80
|
-
const segments = getRootBoundarySegments(key);
|
|
81
|
-
if (!segments)
|
|
82
|
-
continue;
|
|
83
|
-
if (!isRootBoundarySegments(segments, basePaths))
|
|
84
|
-
continue;
|
|
85
|
-
const id = segments.join("/");
|
|
86
|
-
boundaries.set(id, {
|
|
87
|
-
sourceKey: key,
|
|
88
|
-
sourceAbsPath: path.resolve(appCwdPath, "page", key.replace(/^\.\//, "")),
|
|
89
|
-
segments
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
const hasExplicitRootBoundary = [...boundaries.values()].some((boundary) => boundary.segments.length === 0);
|
|
93
|
-
if (!hasExplicitRootBoundary && boundaries.size === 0) {
|
|
94
|
-
boundaries.set("", { sourceKey: null, sourceAbsPath: null, segments: [] });
|
|
95
|
-
}
|
|
96
|
-
return [...boundaries.values()].sort((a, b) => a.segments.join("/").localeCompare(b.segments.join("/")));
|
|
97
|
-
}
|
|
98
|
-
function hasAncestorRootBoundary(boundary, boundaries) {
|
|
99
|
-
return boundaries.some((candidate) => candidate !== boundary && candidate.segments.length < boundary.segments.length && candidate.segments.every((segment, index) => boundary.segments[index] === segment));
|
|
100
|
-
}
|
|
101
|
-
function findExplicitRootLayoutAbsPath(pageKeys, appCwdPath) {
|
|
102
|
-
const rootLayoutKey = pageKeys.find((key) => {
|
|
103
|
-
const segments = getRootBoundarySegments(key);
|
|
104
|
-
return segments !== null && segments.length === 0;
|
|
105
|
-
});
|
|
106
|
-
return rootLayoutKey ? path.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
|
|
107
|
-
}
|
|
108
|
-
function routePrefixForSegments(segments) {
|
|
109
|
-
const visible = segments.filter((segment) => !/^\(.+\)$/.test(segment));
|
|
110
|
-
return visible[0] ?? null;
|
|
111
|
-
}
|
|
112
|
-
async function assertEnvClientConvention(appCwdPath, appName) {
|
|
113
|
-
const envPath = path.join(appCwdPath, "env", "env.client.ts");
|
|
114
|
-
if (!await Bun.file(envPath).exists()) {
|
|
115
|
-
throw new Error(`[route-convention] app "${appName}" must provide env/env.client.ts exporting "env" for generated System.Provider`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
async function writeGeneratedDictionaryMacroFile(appCwdPath, appName) {
|
|
119
|
-
const absPath = implicitDictionaryMacroAbsPath(appCwdPath);
|
|
120
|
-
await mkdir(path.dirname(absPath), { recursive: true });
|
|
121
|
-
await Bun.write(absPath, `import { getAllDictionary } from "@apps/${appName}/lib/dict" with { type: "macro" };
|
|
122
|
-
|
|
123
|
-
export const allDictionary = getAllDictionary();
|
|
124
|
-
`);
|
|
125
|
-
return absPath;
|
|
126
|
-
}
|
|
127
|
-
async function writeGeneratedRootLayoutFile(opts) {
|
|
128
|
-
await assertEnvClientConvention(opts.appCwdPath, opts.appName);
|
|
129
|
-
const dictMacroAbsPath = opts.includeSystemProvider ? await writeGeneratedDictionaryMacroFile(opts.appCwdPath, opts.appName) : null;
|
|
130
|
-
const absPath = implicitRootLayoutAbsPath(opts.appCwdPath, opts.boundary.segments);
|
|
131
|
-
await mkdir(path.dirname(absPath), { recursive: true });
|
|
132
|
-
const dictMacroRel = dictMacroAbsPath ? path.relative(path.dirname(absPath), dictMacroAbsPath).split(path.sep).join("/") : null;
|
|
133
|
-
const dictMacroSpecifier = dictMacroRel ? dictMacroRel.startsWith(".") ? dictMacroRel : `./${dictMacroRel}` : null;
|
|
134
|
-
const sourceRel = opts.boundary.sourceAbsPath ? path.relative(path.dirname(absPath), opts.boundary.sourceAbsPath).split(path.sep).join("/") : null;
|
|
135
|
-
const sourceSpecifier = sourceRel ? sourceRel.startsWith(".") ? sourceRel : `./${sourceRel}` : null;
|
|
136
|
-
const inheritedSourceAbsPath = opts.rootSourceAbsPath && opts.rootSourceAbsPath !== opts.boundary.sourceAbsPath ? opts.rootSourceAbsPath : null;
|
|
137
|
-
const inheritedSourceRel = inheritedSourceAbsPath ? path.relative(path.dirname(absPath), inheritedSourceAbsPath).split(path.sep).join("/") : null;
|
|
138
|
-
const inheritedSourceSpecifier = inheritedSourceRel ? inheritedSourceRel.startsWith(".") ? inheritedSourceRel : `./${inheritedSourceRel}` : null;
|
|
139
|
-
const clientImport = opts.includeStInit ? `import { st } from "@apps/${opts.appName}/client";
|
|
140
|
-
void st;
|
|
141
|
-
` : `import "@apps/${opts.appName}/client";
|
|
142
|
-
`;
|
|
143
|
-
const inheritedImport = inheritedSourceSpecifier ? `import * as inheritedLayout from ${JSON.stringify(inheritedSourceSpecifier)};
|
|
144
|
-
` : `const inheritedLayout = {};
|
|
145
|
-
`;
|
|
146
|
-
const prefix = routePrefixForSegments(opts.boundary.segments);
|
|
147
|
-
const userImport = sourceSpecifier ? `import UserLayout, * as userLayout from ${JSON.stringify(sourceSpecifier)};
|
|
148
|
-
` : `const UserLayout = ({ children }) => children;
|
|
149
|
-
const userLayout = {};
|
|
150
|
-
`;
|
|
151
|
-
const source = opts.includeSystemProvider ? `import type { LayoutProps, PageProps } from "akanjs/client";
|
|
152
|
-
import { loadFonts } from "akanjs/client";
|
|
153
|
-
import { System } from "akanjs/ui";
|
|
154
|
-
import { env } from "@apps/${opts.appName}/env/env.client";
|
|
155
|
-
import { allDictionary } from ${JSON.stringify(dictMacroSpecifier)};
|
|
156
|
-
${clientImport}${inheritedImport}${userImport}
|
|
157
|
-
const userFonts = userLayout.fonts ?? inheritedLayout.fonts ?? [];
|
|
158
|
-
const defaultFonts = userFonts.filter((font) => font.default);
|
|
159
|
-
if (defaultFonts.length > 1) throw new Error("[route-convention] only one default font is allowed per root layout");
|
|
160
|
-
const defaultFont = defaultFonts[0];
|
|
161
|
-
const defaultFontClassName = defaultFont ? (defaultFont.className ?? \`font-\${defaultFont.name}\`) : undefined;
|
|
162
|
-
|
|
163
|
-
export async function generateHead(props: PageProps) {
|
|
164
|
-
if (userLayout.generateHead) return userLayout.generateHead(props);
|
|
165
|
-
if (userLayout.head !== undefined) return userLayout.head;
|
|
166
|
-
if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
|
|
167
|
-
return inheritedLayout.head;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export async function generateMetadata(props: PageProps) {
|
|
171
|
-
if (userLayout.generateMetadata) return userLayout.generateMetadata(props);
|
|
172
|
-
if (userLayout.metadata !== undefined) return userLayout.metadata;
|
|
173
|
-
if (inheritedLayout.generateMetadata) return inheritedLayout.generateMetadata(props);
|
|
174
|
-
return inheritedLayout.metadata;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
|
|
178
|
-
export const Error = userLayout.Error ?? inheritedLayout.Error;
|
|
179
|
-
export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
|
|
180
|
-
|
|
181
|
-
export default function GeneratedLayout({ children, params, searchParams }: LayoutProps) {
|
|
182
|
-
return (
|
|
183
|
-
<System.Provider
|
|
184
|
-
of={GeneratedLayout as never}
|
|
185
|
-
appName=${JSON.stringify(opts.appName)}
|
|
186
|
-
${prefix ? `prefix=${JSON.stringify(prefix)}
|
|
187
|
-
` : ""}params={params}
|
|
188
|
-
manifest={userLayout.manifest ?? inheritedLayout.manifest}
|
|
189
|
-
env={env}
|
|
190
|
-
theme={userLayout.theme ?? inheritedLayout.theme}
|
|
191
|
-
fonts={loadFonts(userFonts)}
|
|
192
|
-
className={defaultFontClassName}
|
|
193
|
-
gaTrackingId={userLayout.gaTrackingId ?? inheritedLayout.gaTrackingId}
|
|
194
|
-
layoutStyle={userLayout.layoutStyle ?? inheritedLayout.layoutStyle}
|
|
195
|
-
reconnect={userLayout.reconnect ?? inheritedLayout.reconnect ?? false}
|
|
196
|
-
wsConnect={userLayout.wsConnect ?? inheritedLayout.wsConnect ?? true}
|
|
197
|
-
allDictionary={process.env.AKAN_PUBLIC_RENDER_ENV === "ssr" ? allDictionary : undefined}
|
|
198
|
-
>
|
|
199
|
-
<UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>
|
|
200
|
-
</System.Provider>
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
` : `import type { LayoutProps, PageProps } from "akanjs/client";
|
|
204
|
-
${inheritedImport}${userImport}
|
|
205
|
-
export async function generateHead(props: PageProps) {
|
|
206
|
-
if (userLayout.generateHead) return userLayout.generateHead(props);
|
|
207
|
-
if (userLayout.head !== undefined) return userLayout.head;
|
|
208
|
-
if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
|
|
209
|
-
return inheritedLayout.head;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export async function generateMetadata(props: PageProps) {
|
|
213
|
-
if (userLayout.generateMetadata) return userLayout.generateMetadata(props);
|
|
214
|
-
if (userLayout.metadata !== undefined) return userLayout.metadata;
|
|
215
|
-
if (inheritedLayout.generateMetadata) return inheritedLayout.generateMetadata(props);
|
|
216
|
-
return inheritedLayout.metadata;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
|
|
220
|
-
export const Error = userLayout.Error ?? inheritedLayout.Error;
|
|
221
|
-
export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
|
|
222
|
-
|
|
223
|
-
export default function GeneratedLayout({ children, params, searchParams }: LayoutProps) {
|
|
224
|
-
return <UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>;
|
|
225
|
-
}
|
|
226
|
-
`;
|
|
227
|
-
await Bun.write(absPath, source);
|
|
228
|
-
return absPath;
|
|
229
|
-
}
|
|
230
|
-
async function resolveSsrPageEntries(opts) {
|
|
231
|
-
const absPageDir = path.resolve(opts.appCwdPath, "page");
|
|
232
|
-
const hasSt = await appHasStModule(opts.appCwdPath);
|
|
233
|
-
const basePaths = opts.basePaths ?? [];
|
|
234
|
-
const rootSourceAbsPath = findExplicitRootLayoutAbsPath(opts.pageKeys, opts.appCwdPath);
|
|
235
|
-
const rootBoundaries = findRootBoundaries(opts.pageKeys, opts.appCwdPath, basePaths);
|
|
236
|
-
const rootLayoutKeys = new Set(opts.pageKeys.filter((key) => {
|
|
237
|
-
const segments = getRootBoundarySegments(key);
|
|
238
|
-
return segments !== null && isRootBoundarySegments(segments, basePaths);
|
|
239
|
-
}));
|
|
240
|
-
const base = await Promise.all(opts.pageKeys.filter((key) => !rootLayoutKeys.has(key)).map(async (key) => {
|
|
241
|
-
const userAbsPath = path.resolve(absPageDir, key);
|
|
242
|
-
if (OVERRIDES_KEY_RE.test(key)) {
|
|
243
|
-
const moduleAbsPath = await writeGeneratedOverridesLayoutFile({
|
|
244
|
-
appCwdPath: opts.appCwdPath,
|
|
245
|
-
key,
|
|
246
|
-
userAbsPath
|
|
247
|
-
});
|
|
248
|
-
return { key, moduleAbsPath, seedAbsPaths: [userAbsPath] };
|
|
249
|
-
}
|
|
250
|
-
return { key, moduleAbsPath: userAbsPath };
|
|
251
|
-
}));
|
|
252
|
-
const generated = await Promise.all(rootBoundaries.map(async (boundary) => ({
|
|
253
|
-
key: implicitRootLayoutKey(boundary.segments),
|
|
254
|
-
moduleAbsPath: await writeGeneratedRootLayoutFile({
|
|
255
|
-
appCwdPath: opts.appCwdPath,
|
|
256
|
-
appName: opts.appName,
|
|
257
|
-
boundary,
|
|
258
|
-
rootSourceAbsPath,
|
|
259
|
-
includeStInit: hasSt && boundary.segments.length === 0,
|
|
260
|
-
includeSystemProvider: !hasAncestorRootBoundary(boundary, rootBoundaries)
|
|
261
|
-
}),
|
|
262
|
-
seedAbsPaths: [...new Set([boundary.sourceAbsPath, rootSourceAbsPath].filter((absPath) => absPath !== null))]
|
|
263
|
-
})));
|
|
264
|
-
const entries = [...base, ...generated];
|
|
265
|
-
entries.sort((a, b) => a.key.localeCompare(b.key));
|
|
266
|
-
return entries;
|
|
267
|
-
}
|
|
268
|
-
async function resolveSsrPageEntriesForApp(app, pageKeys) {
|
|
269
|
-
const config = await app.getConfig();
|
|
270
|
-
return resolveSsrPageEntries({ appCwdPath: app.cwdPath, appName: app.name, pageKeys, basePaths: config.basePaths });
|
|
271
|
-
}
|
|
21
|
+
import path3 from "path";
|
|
272
22
|
|
|
273
23
|
// pkgs/@akanjs/devkit/artifact/routeSeedIndex.ts
|
|
274
|
-
import
|
|
24
|
+
import path from "path";
|
|
275
25
|
import { assertUniqueRoutePatterns, compareRouteSpecificity, parseRouteModuleKey } from "akanjs/common";
|
|
276
26
|
function computeRouteSeedIndex(pageEntries) {
|
|
277
27
|
const layoutsByPrefix = new Map;
|
|
278
28
|
const pagesBySegments = [];
|
|
279
29
|
for (const { key, moduleAbsPath, seedAbsPaths } of pageEntries) {
|
|
280
30
|
const parsed = parseRouteModuleKey(key);
|
|
281
|
-
const files = [
|
|
31
|
+
const files = [path.resolve(moduleAbsPath), ...(seedAbsPaths ?? []).map((seed) => path.resolve(seed))];
|
|
282
32
|
if (parsed.kind === "layout" || parsed.kind === "overrides") {
|
|
283
33
|
const prefix = parsed.routeSegments.join("/");
|
|
284
34
|
const prev = layoutsByPrefix.get(prefix) ?? [];
|
|
@@ -315,7 +65,7 @@ function computeRouteSeedIndex(pageEntries) {
|
|
|
315
65
|
}
|
|
316
66
|
var ROUTE_SEED_INDEX_JSON = "route-seed-index.json";
|
|
317
67
|
function serializeRouteSeedIndexForArtifact(index, artifactDir, options = {}) {
|
|
318
|
-
const normalizedArtifactDir =
|
|
68
|
+
const normalizedArtifactDir = path.resolve(artifactDir);
|
|
319
69
|
if (options.production) {
|
|
320
70
|
return {
|
|
321
71
|
entries: index.entries.map((entry) => ({ routeId: entry.routeId }))
|
|
@@ -330,19 +80,19 @@ function serializeRouteSeedIndexForArtifact(index, artifactDir, options = {}) {
|
|
|
330
80
|
};
|
|
331
81
|
}
|
|
332
82
|
async function saveRouteSeedIndex(artifactDir, index, options = {}) {
|
|
333
|
-
const absPath =
|
|
83
|
+
const absPath = path.join(path.resolve(artifactDir), ROUTE_SEED_INDEX_JSON);
|
|
334
84
|
await Bun.write(absPath, `${JSON.stringify(serializeRouteSeedIndexForArtifact(index, artifactDir, options), null, 2)}
|
|
335
85
|
`);
|
|
336
86
|
return absPath;
|
|
337
87
|
}
|
|
338
88
|
function serializeArtifactPath(artifactPath, artifactDir) {
|
|
339
|
-
if (!
|
|
89
|
+
if (!path.isAbsolute(artifactPath))
|
|
340
90
|
return artifactPath;
|
|
341
|
-
return
|
|
91
|
+
return path.relative(artifactDir, artifactPath).split(path.sep).join("/");
|
|
342
92
|
}
|
|
343
93
|
|
|
344
94
|
// pkgs/@akanjs/devkit/frontendBuild/routesManifestArtifactSerializer.ts
|
|
345
|
-
import
|
|
95
|
+
import path2 from "path";
|
|
346
96
|
|
|
347
97
|
class RoutesManifestArtifactSerializer {
|
|
348
98
|
#manifest;
|
|
@@ -350,7 +100,7 @@ class RoutesManifestArtifactSerializer {
|
|
|
350
100
|
#production;
|
|
351
101
|
constructor(manifest, artifactDir, options = {}) {
|
|
352
102
|
this.#manifest = manifest;
|
|
353
|
-
this.#artifactDir =
|
|
103
|
+
this.#artifactDir = path2.resolve(artifactDir);
|
|
354
104
|
this.#production = options.production ?? false;
|
|
355
105
|
}
|
|
356
106
|
static serialize(manifest, artifactDir, options = {}) {
|
|
@@ -383,9 +133,9 @@ class RoutesManifestArtifactSerializer {
|
|
|
383
133
|
};
|
|
384
134
|
}
|
|
385
135
|
#serializeArtifactPath(artifactPath) {
|
|
386
|
-
if (!
|
|
136
|
+
if (!path2.isAbsolute(artifactPath))
|
|
387
137
|
return artifactPath;
|
|
388
|
-
return
|
|
138
|
+
return path2.relative(this.#artifactDir, artifactPath).split(path2.sep).join("/");
|
|
389
139
|
}
|
|
390
140
|
}
|
|
391
141
|
|
|
@@ -425,7 +175,7 @@ class AllRoutesBuilder {
|
|
|
425
175
|
routeIds: this.#routeIds,
|
|
426
176
|
...this.#merged
|
|
427
177
|
};
|
|
428
|
-
const manifestPath =
|
|
178
|
+
const manifestPath = path3.join(path3.resolve(this.#artifactDir), "routes-manifest.json");
|
|
429
179
|
await Bun.write(manifestPath, `${JSON.stringify(RoutesManifestArtifactSerializer.serialize(manifest, this.#artifactDir, {
|
|
430
180
|
production: this.#command === "build"
|
|
431
181
|
}), null, 2)}
|
|
@@ -462,12 +212,12 @@ class AllRoutesBuilder {
|
|
|
462
212
|
}
|
|
463
213
|
|
|
464
214
|
// pkgs/@akanjs/devkit/frontendBuild/csrArtifactBuilder.ts
|
|
465
|
-
import { mkdir
|
|
466
|
-
import
|
|
215
|
+
import { mkdir, rm, unlink } from "fs/promises";
|
|
216
|
+
import path5 from "path";
|
|
467
217
|
|
|
468
218
|
// pkgs/@akanjs/devkit/frontendBuild/pagesEntrySourceGenerator.ts
|
|
469
219
|
import fs from "fs";
|
|
470
|
-
import
|
|
220
|
+
import path4 from "path";
|
|
471
221
|
import ts from "typescript";
|
|
472
222
|
|
|
473
223
|
class PagesEntrySourceGenerator {
|
|
@@ -510,11 +260,11 @@ ${entries.join(`
|
|
|
510
260
|
`;
|
|
511
261
|
}
|
|
512
262
|
static #toImportSpecifier(moduleAbsPath) {
|
|
513
|
-
return
|
|
263
|
+
return path4.resolve(moduleAbsPath).split(path4.sep).join("/");
|
|
514
264
|
}
|
|
515
265
|
static #hasAsyncDefaultExport(moduleAbsPath) {
|
|
516
266
|
try {
|
|
517
|
-
const source = fs.readFileSync(
|
|
267
|
+
const source = fs.readFileSync(path4.resolve(moduleAbsPath), "utf8");
|
|
518
268
|
const sourceFile = ts.createSourceFile(moduleAbsPath, source, ts.ScriptTarget.Latest, true, PagesEntrySourceGenerator.#scriptKind(moduleAbsPath));
|
|
519
269
|
return PagesEntrySourceGenerator.#sourceFileHasAsyncDefaultExport(sourceFile);
|
|
520
270
|
} catch {
|
|
@@ -593,7 +343,7 @@ class CsrArtifactBuilder {
|
|
|
593
343
|
const csrBasePaths = [...akanConfig.basePaths];
|
|
594
344
|
const htmlEntries = csrBasePaths.length > 0 ? csrBasePaths : ["index"];
|
|
595
345
|
await rm(this.#outputDir, { recursive: true, force: true });
|
|
596
|
-
await
|
|
346
|
+
await mkdir(path5.join(this.#app.cwdPath, ".akan/generated/csr"), { recursive: true });
|
|
597
347
|
const generatedHtmlFiles = Object.fromEntries(htmlEntries.map((basePath) => this.#createHtmlFile(basePath)));
|
|
598
348
|
const result = await Bun.build({
|
|
599
349
|
target: "browser",
|
|
@@ -625,7 +375,7 @@ ${logs}` : ""}`);
|
|
|
625
375
|
return { outputDir: this.#outputDir };
|
|
626
376
|
}
|
|
627
377
|
get #outputDir() {
|
|
628
|
-
return
|
|
378
|
+
return path5.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, this.#command === "build" ? "csr" : ".akan/artifact/csr");
|
|
629
379
|
}
|
|
630
380
|
#define() {
|
|
631
381
|
const nodeEnv = this.#command === "build" ? "production" : "development";
|
|
@@ -656,8 +406,8 @@ ${logs}` : ""}`);
|
|
|
656
406
|
];
|
|
657
407
|
}
|
|
658
408
|
async#loadCsrArtifact() {
|
|
659
|
-
const artifactDir =
|
|
660
|
-
const artifactFile = Bun.file(
|
|
409
|
+
const artifactDir = path5.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact");
|
|
410
|
+
const artifactFile = Bun.file(path5.join(artifactDir, "base-artifact.json"));
|
|
661
411
|
if (!await artifactFile.exists())
|
|
662
412
|
return { cssAssets: {} };
|
|
663
413
|
const artifact = await artifactFile.json();
|
|
@@ -670,7 +420,7 @@ ${logs}` : ""}`);
|
|
|
670
420
|
const htmlFile = Bun.file(htmlPath);
|
|
671
421
|
if (!await htmlFile.exists())
|
|
672
422
|
continue;
|
|
673
|
-
const basePath =
|
|
423
|
+
const basePath = path5.basename(htmlPath, ".html") === "index" ? "" : path5.basename(htmlPath, ".html");
|
|
674
424
|
const inlined = await this.#inlineHtmlAssets(await htmlFile.text(), htmlPath, cssAssets[basePath]);
|
|
675
425
|
for (const filePath of inlined.jsFiles)
|
|
676
426
|
jsFiles.add(filePath);
|
|
@@ -712,7 +462,7 @@ ${remainingAssets.join(`
|
|
|
712
462
|
next = CsrArtifactBuilder.injectBeforeHeadEnd(next, style);
|
|
713
463
|
}
|
|
714
464
|
if (cssAsset) {
|
|
715
|
-
const cssPath =
|
|
465
|
+
const cssPath = path5.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact", cssAsset.cssRelPath);
|
|
716
466
|
const css = await Bun.file(cssPath).text();
|
|
717
467
|
const style = CsrArtifactBuilder.createInlineStyle(css);
|
|
718
468
|
if (!next.includes(style))
|
|
@@ -783,12 +533,12 @@ ${CsrArtifactBuilder.escapeInlineScript(await loadScript(src))}
|
|
|
783
533
|
throw new Error(`[csr-build] cannot inline external script: ${src}`);
|
|
784
534
|
}
|
|
785
535
|
const normalized = src.startsWith("/") ? src.slice(1) : src;
|
|
786
|
-
return
|
|
536
|
+
return path5.resolve(path5.dirname(htmlPath), normalized);
|
|
787
537
|
}
|
|
788
538
|
}
|
|
789
539
|
|
|
790
540
|
// pkgs/@akanjs/devkit/frontendBuild/cssCompiler.ts
|
|
791
|
-
import
|
|
541
|
+
import path7 from "path";
|
|
792
542
|
import { Logger } from "akanjs/common";
|
|
793
543
|
import { compile } from "tailwindcss";
|
|
794
544
|
|
|
@@ -859,7 +609,7 @@ class CssCandidateCache {
|
|
|
859
609
|
}
|
|
860
610
|
|
|
861
611
|
// pkgs/@akanjs/devkit/frontendBuild/cssImportResolver.ts
|
|
862
|
-
import
|
|
612
|
+
import path6 from "path";
|
|
863
613
|
var CSS_IMPORT_EXTS = ["", ".css", "/styles.css", "/index.css"];
|
|
864
614
|
|
|
865
615
|
class CssImportResolver {
|
|
@@ -912,7 +662,7 @@ class CssImportResolver {
|
|
|
912
662
|
const exact = this.#paths[id];
|
|
913
663
|
if (exact) {
|
|
914
664
|
for (const repl of exact) {
|
|
915
|
-
const resolved = await this.#firstExisting(
|
|
665
|
+
const resolved = await this.#firstExisting(path6.resolve(this.#workspaceRoot, repl));
|
|
916
666
|
if (resolved)
|
|
917
667
|
return resolved;
|
|
918
668
|
}
|
|
@@ -923,7 +673,7 @@ class CssImportResolver {
|
|
|
923
673
|
const suffix = id.slice(prefix.length);
|
|
924
674
|
for (const repl of replacements) {
|
|
925
675
|
const replPath = repl.endsWith("/*") ? repl.slice(0, -1) : repl;
|
|
926
|
-
const resolved = await this.#firstExisting(
|
|
676
|
+
const resolved = await this.#firstExisting(path6.resolve(this.#workspaceRoot, replPath + suffix));
|
|
927
677
|
if (resolved)
|
|
928
678
|
return resolved;
|
|
929
679
|
}
|
|
@@ -953,25 +703,25 @@ class CssImportResolver {
|
|
|
953
703
|
try {
|
|
954
704
|
if (!await Bun.file(pkgPath).exists())
|
|
955
705
|
return null;
|
|
956
|
-
const pkgDir =
|
|
706
|
+
const pkgDir = path6.dirname(pkgPath);
|
|
957
707
|
const pkg = await Bun.file(pkgPath).json();
|
|
958
708
|
const subpath = id === pkgName ? "." : `.${id.slice(pkgName.length)}`;
|
|
959
709
|
const exportValue = pkg.exports?.[subpath];
|
|
960
710
|
const styleEntry = (typeof exportValue === "string" ? exportValue : exportValue?.style || exportValue?.import || exportValue?.default) || pkg.exports?.["."]?.style || pkg.style || "index.css";
|
|
961
|
-
return await this.#firstExisting(
|
|
711
|
+
return await this.#firstExisting(path6.resolve(pkgDir, styleEntry));
|
|
962
712
|
} catch {
|
|
963
713
|
return null;
|
|
964
714
|
}
|
|
965
715
|
}
|
|
966
716
|
#resolutionBases(fromBase) {
|
|
967
|
-
return [fromBase, this.#workspaceRoot,
|
|
717
|
+
return [fromBase, this.#workspaceRoot, path6.dirname(Bun.main), path6.resolve(path6.dirname(Bun.main), "../..")];
|
|
968
718
|
}
|
|
969
719
|
#packageJsonCandidates(pkgName) {
|
|
970
720
|
return [
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
721
|
+
path6.join(this.#workspaceRoot, "pkgs", pkgName, "package.json"),
|
|
722
|
+
path6.join(this.#workspaceRoot, "node_modules", pkgName, "package.json"),
|
|
723
|
+
path6.join(path6.dirname(Bun.main), "node_modules", pkgName, "package.json"),
|
|
724
|
+
path6.join(path6.dirname(Bun.main), "../../", pkgName, "package.json")
|
|
975
725
|
];
|
|
976
726
|
}
|
|
977
727
|
async#firstExisting(basePath) {
|
|
@@ -989,7 +739,7 @@ class CssImportResolver {
|
|
|
989
739
|
return parts[0] ?? null;
|
|
990
740
|
}
|
|
991
741
|
static isCssFile(filePath) {
|
|
992
|
-
return
|
|
742
|
+
return path6.extname(filePath) === ".css";
|
|
993
743
|
}
|
|
994
744
|
}
|
|
995
745
|
|
|
@@ -1008,7 +758,7 @@ class CssCompiler {
|
|
|
1008
758
|
this.#app = app;
|
|
1009
759
|
}
|
|
1010
760
|
get #candidateCachePath() {
|
|
1011
|
-
return
|
|
761
|
+
return path7.join(this.#app.cwdPath, ".akan/cache/cssCandidates.json");
|
|
1012
762
|
}
|
|
1013
763
|
#cssText = null;
|
|
1014
764
|
#cssTextByBasePath = null;
|
|
@@ -1036,7 +786,7 @@ class CssCompiler {
|
|
|
1036
786
|
return filePath;
|
|
1037
787
|
}
|
|
1038
788
|
for (const ext of SOURCE_EXTS) {
|
|
1039
|
-
const filePath =
|
|
789
|
+
const filePath = path7.join(absPathNoExt, `index${ext}`);
|
|
1040
790
|
if (await this.#fileExists(filePath))
|
|
1041
791
|
return filePath;
|
|
1042
792
|
}
|
|
@@ -1092,7 +842,7 @@ class CssCompiler {
|
|
|
1092
842
|
pageKeys
|
|
1093
843
|
} = {}) {
|
|
1094
844
|
pageKeys ??= await this.#app.getPageKeys({ refresh });
|
|
1095
|
-
const seeds = pageKeys.map((key) =>
|
|
845
|
+
const seeds = pageKeys.map((key) => path7.resolve(this.#app.cwdPath, "page", key));
|
|
1096
846
|
const cssFiles = new Set;
|
|
1097
847
|
const sourceFiles = new Set;
|
|
1098
848
|
const queue = [...seeds];
|
|
@@ -1124,7 +874,7 @@ class CssCompiler {
|
|
|
1124
874
|
} catch {
|
|
1125
875
|
continue;
|
|
1126
876
|
}
|
|
1127
|
-
const importerDir =
|
|
877
|
+
const importerDir = path7.dirname(filePath);
|
|
1128
878
|
for (const imp of imports) {
|
|
1129
879
|
const spec = imp.path;
|
|
1130
880
|
if (!spec)
|
|
@@ -1150,7 +900,7 @@ class CssCompiler {
|
|
|
1150
900
|
const compileStarted = Date.now();
|
|
1151
901
|
const compilers = await Promise.all(cssPaths.map(async (cssPath) => {
|
|
1152
902
|
const css = await Bun.file(cssPath).text();
|
|
1153
|
-
const base =
|
|
903
|
+
const base = path7.dirname(cssPath);
|
|
1154
904
|
const compiler = await compile(css, {
|
|
1155
905
|
base,
|
|
1156
906
|
loadStylesheet: (id, fromBase) => this.#loadStylesheet(id, fromBase),
|
|
@@ -1181,11 +931,11 @@ class CssCompiler {
|
|
|
1181
931
|
async#loadStylesheet(id, fromBase) {
|
|
1182
932
|
const p = await this.#resolveCssImport(id, fromBase);
|
|
1183
933
|
const content = await Bun.file(p).text();
|
|
1184
|
-
return { path: p, base:
|
|
934
|
+
return { path: p, base: path7.dirname(p), content };
|
|
1185
935
|
}
|
|
1186
936
|
async#resolveCssImport(id, fromBase) {
|
|
1187
937
|
if (id.startsWith(".") || id.startsWith("/"))
|
|
1188
|
-
return
|
|
938
|
+
return path7.resolve(fromBase, id);
|
|
1189
939
|
const resolver = await this.#getCssImportResolver();
|
|
1190
940
|
const resolved = await resolver.resolve(id, fromBase);
|
|
1191
941
|
if (resolved)
|
|
@@ -1201,7 +951,7 @@ class CssCompiler {
|
|
|
1201
951
|
async#loadModule(id, fromBase) {
|
|
1202
952
|
const p = __require.resolve(id, { paths: [fromBase] });
|
|
1203
953
|
const mod = await import(p);
|
|
1204
|
-
return { path: p, base:
|
|
954
|
+
return { path: p, base: path7.dirname(p), module: mod.default ?? mod };
|
|
1205
955
|
}
|
|
1206
956
|
#resolveSourceImport(id, fromBase, resolvePackage) {
|
|
1207
957
|
const cacheKey = `${fromBase}\x00${id}`;
|
|
@@ -1214,7 +964,7 @@ class CssCompiler {
|
|
|
1214
964
|
}
|
|
1215
965
|
async#resolveSourceImportUncached(id, fromBase, resolvePackage) {
|
|
1216
966
|
if (id.startsWith(".") || id.startsWith("/")) {
|
|
1217
|
-
const abs = id.startsWith("/") ? id :
|
|
967
|
+
const abs = id.startsWith("/") ? id : path7.resolve(fromBase, id);
|
|
1218
968
|
return this.#resolveSourceFileCandidate(abs);
|
|
1219
969
|
}
|
|
1220
970
|
const pkg = await resolvePackage(id);
|
|
@@ -1265,21 +1015,21 @@ function resolveSourceWithRequire(id, fromBase) {
|
|
|
1265
1015
|
}
|
|
1266
1016
|
}
|
|
1267
1017
|
function isSourceFile(filePath) {
|
|
1268
|
-
return SOURCE_EXTS.includes(
|
|
1018
|
+
return SOURCE_EXTS.includes(path7.extname(filePath));
|
|
1269
1019
|
}
|
|
1270
1020
|
function isIgnoredNodeModuleSource(filePath) {
|
|
1271
1021
|
return NODE_MODULES_RE.test(filePath) && !AKANJS_NODE_MODULE_RE.test(filePath);
|
|
1272
1022
|
}
|
|
1273
1023
|
function getPageKeyBasePath(pageKey, basePaths) {
|
|
1274
|
-
const normalized = pageKey.split(
|
|
1024
|
+
const normalized = pageKey.split(path7.sep).join("/").replace(/^\.\//, "");
|
|
1275
1025
|
const segments = normalized.split("/");
|
|
1276
1026
|
const firstPublicSegment = segments.find((segment) => segment !== "[lang]" && !/^\(.+\)$/.test(segment));
|
|
1277
1027
|
return firstPublicSegment && basePaths.includes(firstPublicSegment) ? firstPublicSegment : null;
|
|
1278
1028
|
}
|
|
1279
1029
|
|
|
1280
1030
|
// pkgs/@akanjs/devkit/frontendBuild/fontOptimizer.ts
|
|
1281
|
-
import { mkdir as
|
|
1282
|
-
import
|
|
1031
|
+
import { mkdir as mkdir2, stat as stat2 } from "fs/promises";
|
|
1032
|
+
import path8 from "path";
|
|
1283
1033
|
import ts2 from "typescript";
|
|
1284
1034
|
var FONT_URL_PREFIX = "/_akan/fonts";
|
|
1285
1035
|
var DEFAULT_FONT_SUBSETS = ["latin"];
|
|
@@ -1296,7 +1046,7 @@ class FontOptimizer {
|
|
|
1296
1046
|
constructor(app, command = "start") {
|
|
1297
1047
|
this.#app = app;
|
|
1298
1048
|
this.#command = command;
|
|
1299
|
-
this.#artifactRoot =
|
|
1049
|
+
this.#artifactRoot = path8.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
|
|
1300
1050
|
}
|
|
1301
1051
|
async optimize() {
|
|
1302
1052
|
const fonts = await this.discoverFonts();
|
|
@@ -1321,7 +1071,7 @@ class FontOptimizer {
|
|
|
1321
1071
|
return result;
|
|
1322
1072
|
}
|
|
1323
1073
|
get #cachePath() {
|
|
1324
|
-
return
|
|
1074
|
+
return path8.join(this.#artifactRoot, "fontCache.json");
|
|
1325
1075
|
}
|
|
1326
1076
|
async#buildCacheKey(fonts) {
|
|
1327
1077
|
const sources = [];
|
|
@@ -1336,7 +1086,7 @@ class FontOptimizer {
|
|
|
1336
1086
|
sources.push({ optimizedSrc: face.optimizedSrc, ...stamp });
|
|
1337
1087
|
}
|
|
1338
1088
|
for (const filePath of font.subsetFiles ?? []) {
|
|
1339
|
-
const abs =
|
|
1089
|
+
const abs = path8.isAbsolute(filePath) ? filePath : path8.join(this.#app.cwdPath, filePath);
|
|
1340
1090
|
const stamp = await this.#fileStamp(abs);
|
|
1341
1091
|
if (!stamp)
|
|
1342
1092
|
return null;
|
|
@@ -1359,7 +1109,7 @@ class FontOptimizer {
|
|
|
1359
1109
|
const cache = await Bun.file(this.#cachePath).json().catch(() => null);
|
|
1360
1110
|
if (cache?.version !== FontOptimizer.#cacheVersion || cache.key !== key)
|
|
1361
1111
|
return null;
|
|
1362
|
-
const files = cache.files.map((relativePath) =>
|
|
1112
|
+
const files = cache.files.map((relativePath) => path8.join(this.#artifactRoot, relativePath));
|
|
1363
1113
|
for (const filePath of files) {
|
|
1364
1114
|
if (!await Bun.file(filePath).exists())
|
|
1365
1115
|
return null;
|
|
@@ -1371,7 +1121,7 @@ class FontOptimizer {
|
|
|
1371
1121
|
version: FontOptimizer.#cacheVersion,
|
|
1372
1122
|
key,
|
|
1373
1123
|
css: result.css,
|
|
1374
|
-
files: result.files.map((filePath) =>
|
|
1124
|
+
files: result.files.map((filePath) => path8.relative(this.#artifactRoot, filePath))
|
|
1375
1125
|
};
|
|
1376
1126
|
await Bun.write(this.#cachePath, JSON.stringify(cache));
|
|
1377
1127
|
}
|
|
@@ -1379,7 +1129,7 @@ class FontOptimizer {
|
|
|
1379
1129
|
const pageKeys = await this.#app.getPageKeys();
|
|
1380
1130
|
const fonts = [];
|
|
1381
1131
|
await Promise.all(pageKeys.map(async (key) => {
|
|
1382
|
-
const filePath =
|
|
1132
|
+
const filePath = path8.resolve(this.#app.cwdPath, "page", key);
|
|
1383
1133
|
const file = Bun.file(filePath);
|
|
1384
1134
|
if (!await file.exists())
|
|
1385
1135
|
return;
|
|
@@ -1398,8 +1148,8 @@ class FontOptimizer {
|
|
|
1398
1148
|
this.#app.logger.warn(`[font] source not found: ${face.src}`);
|
|
1399
1149
|
continue;
|
|
1400
1150
|
}
|
|
1401
|
-
const outputPath =
|
|
1402
|
-
await
|
|
1151
|
+
const outputPath = path8.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
|
|
1152
|
+
await mkdir2(path8.dirname(outputPath), { recursive: true });
|
|
1403
1153
|
const sourceBuffer = Buffer.from(await Bun.file(sourcePath).arrayBuffer());
|
|
1404
1154
|
const outputBuffer = await this.#buildFontBuffer(font, sourceBuffer, sourcePath);
|
|
1405
1155
|
await Bun.write(outputPath, outputBuffer);
|
|
@@ -1546,8 +1296,8 @@ class FontOptimizer {
|
|
|
1546
1296
|
return null;
|
|
1547
1297
|
const rel = src.replace(/^\//, "");
|
|
1548
1298
|
const candidates = [
|
|
1549
|
-
this.#command === "build" ?
|
|
1550
|
-
|
|
1299
|
+
this.#command === "build" ? path8.join(this.#app.dist.cwdPath, "public", rel) : null,
|
|
1300
|
+
path8.join(this.#app.cwdPath, "public", rel),
|
|
1551
1301
|
this.#resolveWorkspacePublicPath(rel)
|
|
1552
1302
|
].filter(Boolean);
|
|
1553
1303
|
for (const candidate of candidates) {
|
|
@@ -1582,7 +1332,7 @@ class FontOptimizer {
|
|
|
1582
1332
|
return "woff2";
|
|
1583
1333
|
if (signature === "OTTO")
|
|
1584
1334
|
return "otf";
|
|
1585
|
-
const ext =
|
|
1335
|
+
const ext = path8.extname(sourcePath).slice(1).toLowerCase();
|
|
1586
1336
|
if (ext === "otf" || ext === "woff" || ext === "woff2")
|
|
1587
1337
|
return ext;
|
|
1588
1338
|
return "ttf";
|
|
@@ -1591,7 +1341,7 @@ class FontOptimizer {
|
|
|
1591
1341
|
const [root, dep, ...rest] = rel.split("/");
|
|
1592
1342
|
if (root !== "libs" || !dep || rest.length === 0)
|
|
1593
1343
|
return null;
|
|
1594
|
-
return
|
|
1344
|
+
return path8.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
|
|
1595
1345
|
}
|
|
1596
1346
|
async#getSubsetText(font) {
|
|
1597
1347
|
const parts = new Set;
|
|
@@ -1601,7 +1351,7 @@ class FontOptimizer {
|
|
|
1601
1351
|
if (font.subsetText)
|
|
1602
1352
|
parts.add(font.subsetText);
|
|
1603
1353
|
for (const filePath of font.subsetFiles ?? []) {
|
|
1604
|
-
const abs =
|
|
1354
|
+
const abs = path8.isAbsolute(filePath) ? filePath : path8.join(this.#app.cwdPath, filePath);
|
|
1605
1355
|
const file = Bun.file(abs);
|
|
1606
1356
|
if (await file.exists())
|
|
1607
1357
|
parts.add(await file.text());
|
|
@@ -1621,7 +1371,7 @@ class FontOptimizer {
|
|
|
1621
1371
|
}
|
|
1622
1372
|
async#collectAutoSubsetText() {
|
|
1623
1373
|
const libPageRoots = (await this.#app.getPageRoots()).filter((root) => root.keyPrefix).map((root) => root.dir);
|
|
1624
|
-
const roots = [...["page", "ui"].map((dir) =>
|
|
1374
|
+
const roots = [...["page", "ui"].map((dir) => path8.join(this.#app.cwdPath, dir)), ...libPageRoots];
|
|
1625
1375
|
const glob = new Bun.Glob("**/*.{ts,tsx,js,jsx,html,md}");
|
|
1626
1376
|
const parts = [];
|
|
1627
1377
|
await Promise.all(roots.map(async (root) => {
|
|
@@ -1737,10 +1487,10 @@ ${declarations.map(([prop, value]) => ` ${prop}: ${value};`).join(`
|
|
|
1737
1487
|
}
|
|
1738
1488
|
|
|
1739
1489
|
// pkgs/@akanjs/devkit/frontendBuild/pagesBundleBuilder.ts
|
|
1740
|
-
import
|
|
1490
|
+
import path10 from "path";
|
|
1741
1491
|
|
|
1742
1492
|
// pkgs/@akanjs/devkit/transforms/externalizeFrameworkPlugin.ts
|
|
1743
|
-
import
|
|
1493
|
+
import path9 from "path";
|
|
1744
1494
|
var DEFAULT_INCLUDE = ["akanjs/", "@apps/", "@libs/"];
|
|
1745
1495
|
var DEFAULT_EXCLUDE_EXACT = new Set(["akanjs/webkit", "@akanjs/cli", "@akanjs/devkit"]);
|
|
1746
1496
|
var DEFAULT_EXCLUDE_PREFIX = ["@akanjs/cli/", "@akanjs/devkit/"];
|
|
@@ -1783,7 +1533,7 @@ async function createExternalizeFrameworkPlugin(options) {
|
|
|
1783
1533
|
const replPath = repl?.endsWith("/*") ? repl.slice(0, -1) : repl ?? "";
|
|
1784
1534
|
if (!replPath)
|
|
1785
1535
|
continue;
|
|
1786
|
-
const candidate =
|
|
1536
|
+
const candidate = path9.resolve(workspaceRoot, replPath + suffix);
|
|
1787
1537
|
const hit = await firstExisting(candidate);
|
|
1788
1538
|
if (hit)
|
|
1789
1539
|
return hit;
|
|
@@ -1795,8 +1545,8 @@ async function createExternalizeFrameworkPlugin(options) {
|
|
|
1795
1545
|
if (spec === pkg)
|
|
1796
1546
|
continue;
|
|
1797
1547
|
const suffix = spec.slice(pkg.length + 1);
|
|
1798
|
-
const pkgDir =
|
|
1799
|
-
const candidate =
|
|
1548
|
+
const pkgDir = path9.dirname(path9.resolve(workspaceRoot, entryFile));
|
|
1549
|
+
const candidate = path9.join(pkgDir, suffix);
|
|
1800
1550
|
const hit = await firstExisting(candidate);
|
|
1801
1551
|
if (hit)
|
|
1802
1552
|
return hit;
|
|
@@ -1846,7 +1596,7 @@ async function firstExisting(basePath) {
|
|
|
1846
1596
|
return candidate;
|
|
1847
1597
|
}
|
|
1848
1598
|
for (const ext of CANDIDATE_EXTS) {
|
|
1849
|
-
const candidate =
|
|
1599
|
+
const candidate = path9.join(basePath, `index${ext}`);
|
|
1850
1600
|
if (await Bun.file(candidate).exists())
|
|
1851
1601
|
return candidate;
|
|
1852
1602
|
}
|
|
@@ -1937,11 +1687,11 @@ class PagesBundleBuilder {
|
|
|
1937
1687
|
const entryArtifact = result.outputs.find((a) => a.kind === "entry-point");
|
|
1938
1688
|
if (!entryArtifact)
|
|
1939
1689
|
throw new Error("[PagesBundleBuilder] Bun.build emitted no entry-point artifact");
|
|
1940
|
-
const bundlePath =
|
|
1690
|
+
const bundlePath = path10.resolve(entryArtifact.path);
|
|
1941
1691
|
const buildId = Date.now();
|
|
1942
1692
|
const outputBytes = result.outputs.reduce((sum, output) => sum + output.size, 0);
|
|
1943
1693
|
const chunkCount = result.outputs.filter((output) => output.kind === "chunk").length;
|
|
1944
|
-
this.#app.verbose(`[PagesBundleBuilder] ${
|
|
1694
|
+
this.#app.verbose(`[PagesBundleBuilder] ${path10.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`);
|
|
1945
1695
|
return {
|
|
1946
1696
|
bundlePath,
|
|
1947
1697
|
buildId,
|
|
@@ -2024,11 +1774,11 @@ function loaderFor2(absPath) {
|
|
|
2024
1774
|
|
|
2025
1775
|
// pkgs/@akanjs/devkit/frontendBuild/precompressArtifacts.ts
|
|
2026
1776
|
import fs2 from "fs";
|
|
2027
|
-
import
|
|
1777
|
+
import path11 from "path";
|
|
2028
1778
|
var COMPRESSIBLE_EXTS = new Set([".css", ".html", ".js", ".json", ".svg"]);
|
|
2029
1779
|
var MIN_COMPRESS_BYTES = 1024;
|
|
2030
1780
|
async function precompressArtifacts(app) {
|
|
2031
|
-
const roots = [
|
|
1781
|
+
const roots = [path11.join(app.dist.cwdPath, ".akan/artifact/client")];
|
|
2032
1782
|
const result = { files: 0, inputBytes: 0, outputBytes: 0 };
|
|
2033
1783
|
await Promise.all(roots.map((root) => precompressRoot(root, result)));
|
|
2034
1784
|
if (result.files > 0) {
|
|
@@ -2054,7 +1804,7 @@ async function precompressRoot(root, result) {
|
|
|
2054
1804
|
async function shouldPrecompress(filePath) {
|
|
2055
1805
|
if (filePath.endsWith(".gz"))
|
|
2056
1806
|
return false;
|
|
2057
|
-
if (!COMPRESSIBLE_EXTS.has(
|
|
1807
|
+
if (!COMPRESSIBLE_EXTS.has(path11.extname(filePath).toLowerCase()))
|
|
2058
1808
|
return false;
|
|
2059
1809
|
const file = Bun.file(filePath);
|
|
2060
1810
|
if (!await file.exists())
|
|
@@ -2073,7 +1823,7 @@ function formatBytes(bytes) {
|
|
|
2073
1823
|
}
|
|
2074
1824
|
|
|
2075
1825
|
// pkgs/@akanjs/devkit/frontendBuild/ssrBaseArtifactBuilder.ts
|
|
2076
|
-
import
|
|
1826
|
+
import path12 from "path";
|
|
2077
1827
|
import { optimize } from "@tailwindcss/node";
|
|
2078
1828
|
function prepareCssAsset(command, basePath, cssText) {
|
|
2079
1829
|
return optimize(cssText, { file: `${basePath || "root"}.css`, minify: command === "build" }).code;
|
|
@@ -2089,7 +1839,7 @@ class SsrBaseArtifactBuilder {
|
|
|
2089
1839
|
this.#app = app;
|
|
2090
1840
|
this.#command = command;
|
|
2091
1841
|
this.#artifactDir = `${command === "build" ? app.dist.cwdPath : app.cwdPath}/.akan/artifact`;
|
|
2092
|
-
this.#absArtifactDir =
|
|
1842
|
+
this.#absArtifactDir = path12.resolve(this.#artifactDir);
|
|
2093
1843
|
}
|
|
2094
1844
|
async build() {
|
|
2095
1845
|
const akanConfig = await this.#app.getConfig();
|
|
@@ -2111,7 +1861,7 @@ class SsrBaseArtifactBuilder {
|
|
|
2111
1861
|
rscRuntimeSsrManifest,
|
|
2112
1862
|
vendorMap,
|
|
2113
1863
|
cssAssets,
|
|
2114
|
-
pagesBundlePath: this.#command === "build" ?
|
|
1864
|
+
pagesBundlePath: this.#command === "build" ? path12.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
|
|
2115
1865
|
pagesBundleBuildId: pagesBundle.buildId,
|
|
2116
1866
|
domains: [...akanConfig.domains],
|
|
2117
1867
|
subRoutes: Object.fromEntries(Array.from(akanConfig.subRoutes.entries()).map(([basePath, domains]) => [basePath, [...domains]])),
|
|
@@ -2127,18 +1877,18 @@ class SsrBaseArtifactBuilder {
|
|
|
2127
1877
|
androidSha256CertFingerprints: target.deepLinks?.android?.sha256CertFingerprints
|
|
2128
1878
|
}))
|
|
2129
1879
|
};
|
|
2130
|
-
await Bun.write(
|
|
1880
|
+
await Bun.write(path12.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
|
|
2131
1881
|
`);
|
|
2132
1882
|
this.#app.verbose(`[base-artifact] complete in ${Date.now() - this.#started}ms`);
|
|
2133
1883
|
return { artifact, seedIndex, cssCompiler, optimizedFonts };
|
|
2134
1884
|
}
|
|
2135
1885
|
async#buildRuntimeClientEntries() {
|
|
2136
1886
|
const akanServerPath = await this.#resolveAkanServerPath();
|
|
2137
|
-
const rscClientEntry =
|
|
2138
|
-
const rscSegmentOutletEntry =
|
|
1887
|
+
const rscClientEntry = path12.resolve(akanServerPath, "rscClient.tsx");
|
|
1888
|
+
const rscSegmentOutletEntry = path12.resolve(akanServerPath, "rscSegmentOutlet.tsx");
|
|
2139
1889
|
const vendorEntries = VENDOR_SPECIFIERS.map((specifier) => ({
|
|
2140
1890
|
specifier,
|
|
2141
|
-
absPath:
|
|
1891
|
+
absPath: path12.resolve(akanServerPath, "vendor", `${specifier.replaceAll("/", "-").replaceAll(".", "-")}.ts`)
|
|
2142
1892
|
}));
|
|
2143
1893
|
const entries = [rscClientEntry, rscSegmentOutletEntry, ...vendorEntries.map((v) => v.absPath)];
|
|
2144
1894
|
const clientBundle = await new ClientEntriesBundler({ app: this.#app, entries, command: this.#command }).bundle();
|
|
@@ -2175,15 +1925,15 @@ class SsrBaseArtifactBuilder {
|
|
|
2175
1925
|
async#resolveAkanServerPath() {
|
|
2176
1926
|
const candidates = [];
|
|
2177
1927
|
try {
|
|
2178
|
-
candidates.push(
|
|
1928
|
+
candidates.push(path12.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
|
|
2179
1929
|
} catch {}
|
|
2180
|
-
candidates.push(
|
|
1930
|
+
candidates.push(path12.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path12.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
|
|
2181
1931
|
try {
|
|
2182
|
-
candidates.push(
|
|
1932
|
+
candidates.push(path12.dirname(Bun.resolveSync("akanjs/server", path12.dirname(Bun.main))));
|
|
2183
1933
|
} catch {}
|
|
2184
|
-
candidates.push(
|
|
1934
|
+
candidates.push(path12.join(path12.dirname(Bun.main), "node_modules/akanjs/server"), path12.join(path12.dirname(Bun.main), "../../akanjs/server"), path12.resolve(import.meta.dir, "../../server"), path12.resolve(import.meta.dir, "../server"));
|
|
2185
1935
|
for (const candidate of candidates) {
|
|
2186
|
-
if (await Bun.file(
|
|
1936
|
+
if (await Bun.file(path12.join(candidate, "rscClient.tsx")).exists())
|
|
2187
1937
|
return candidate;
|
|
2188
1938
|
}
|
|
2189
1939
|
throw new Error(`[base-artifact] failed to locate akanjs/server; looked in: ${candidates.join(", ")}`);
|
|
@@ -2212,7 +1962,7 @@ ${preparedCssText}`).toString(36);
|
|
|
2212
1962
|
`styles/${cssAssetName}-${cssHash}.css`,
|
|
2213
1963
|
`/_akan/styles/${cssAssetName}-${cssHash}.css`
|
|
2214
1964
|
];
|
|
2215
|
-
await Bun.write(
|
|
1965
|
+
await Bun.write(path12.join(this.#absArtifactDir, cssRelPath), preparedCssText);
|
|
2216
1966
|
this.#app.verbose(`[base-artifact] wrote ${preparedCssText.length} bytes of CSS for ${basePath} -> ${cssRelPath}`);
|
|
2217
1967
|
return [basePath, { cssUrl, cssRelPath }];
|
|
2218
1968
|
}
|