1 | var __defProp = Object.defineProperty;
|
2 | var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
3 | var __publicField = (obj, key, value) => {
|
4 | __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
5 | return value;
|
6 | };
|
7 | import { resolve, join, dirname } from "node:path";
|
8 | import { mkdir, writeFile } from "node:fs/promises";
|
9 | import { createRouter } from "radix3";
|
10 | import { NotFoundError } from "./errors.js";
|
11 | import { runCLI } from "./runCLI.js";
|
12 | import { akteWelcome } from "./akteWelcome.js";
|
13 | import { __PRODUCTION__ } from "./lib/__PRODUCTION__.js";
|
14 | import { createDebugger } from "./lib/createDebugger.js";
|
15 | import { pathToRouterPath } from "./lib/pathToRouterPath.js";
|
16 | import { isCLI } from "./lib/isCLI.js";
|
17 | const debug = createDebugger("akte:app");
|
18 | const debugWrite = createDebugger("akte:app:write");
|
19 | const debugRender = createDebugger("akte:app:render");
|
20 | const debugRouter = createDebugger("akte:app:router");
|
21 | const debugCache = createDebugger("akte:app:cache");
|
22 | class AkteApp {
|
23 | constructor(config) {
|
24 | __publicField(this, "config");
|
25 | __publicField(this, "_globalDataCache");
|
26 | __publicField(this, "_router");
|
27 | if (!__PRODUCTION__) {
|
28 | if (config.files.length === 0 && akteWelcome) {
|
29 | config.files.push(akteWelcome);
|
30 | }
|
31 | }
|
32 | this.config = config;
|
33 | debug("defined with %o files", this.config.files.length);
|
34 | if (isCLI) {
|
35 | runCLI(this);
|
36 | }
|
37 | }
|
38 | |
39 |
|
40 |
|
41 |
|
42 |
|
43 | get files() {
|
44 | return this.config.files;
|
45 | }
|
46 | |
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | lookup(path) {
|
57 | const pathWithExtension = pathToRouterPath(path);
|
58 | debugRouter("looking up %o (%o)", path, pathWithExtension);
|
59 | const maybeMatch = this.getRouter().lookup(pathWithExtension);
|
60 | if (!maybeMatch || !maybeMatch.file) {
|
61 | debugRouter("not found %o", path);
|
62 | throw new NotFoundError(path);
|
63 | }
|
64 | return {
|
65 | ...maybeMatch,
|
66 | path
|
67 | };
|
68 | }
|
69 | |
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | async render(match) {
|
79 | debugRender("rendering %o...", match.path);
|
80 | const params = match.params || {};
|
81 | const globalData = match.globalData || await this.getGlobalData();
|
82 | try {
|
83 | const content = await match.file.render({
|
84 | path: match.path,
|
85 | params,
|
86 | globalData,
|
87 | data: match.data
|
88 | });
|
89 | debugRender("rendered %o", match.path);
|
90 | return content;
|
91 | } catch (error) {
|
92 | if (error instanceof NotFoundError) {
|
93 | throw error;
|
94 | }
|
95 | debugRender("could not render %o", match.path);
|
96 | throw new NotFoundError(match.path, { cause: error });
|
97 | }
|
98 | }
|
99 | |
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 | async renderAll() {
|
106 | debugRender("rendering all files...");
|
107 | const globalData = await this.getGlobalData();
|
108 | const renderAll = async (akteFiles) => {
|
109 | try {
|
110 | const files2 = await akteFiles.renderAll({ globalData });
|
111 | return files2;
|
112 | } catch (error) {
|
113 | debug.error("Akte → Failed to build %o\n", akteFiles.path);
|
114 | throw error;
|
115 | }
|
116 | };
|
117 | const promises = [];
|
118 | for (const akteFiles of this.config.files) {
|
119 | promises.push(renderAll(akteFiles));
|
120 | }
|
121 | const rawFilesArray = await Promise.all(promises);
|
122 | const files = {};
|
123 | for (const rawFiles of rawFilesArray) {
|
124 | for (const path in rawFiles) {
|
125 | if (path in files) {
|
126 | debug.warn(" Multiple files built %o, only the first one is preserved", path);
|
127 | continue;
|
128 | }
|
129 | files[path] = rawFiles[path];
|
130 | }
|
131 | }
|
132 | const rendered = Object.keys(files).length;
|
133 | debugRender(`done, %o ${rendered > 1 ? "files" : "file"} rendered`, rendered);
|
134 | return files;
|
135 | }
|
136 | |
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 | async writeAll(args) {
|
144 | var _a;
|
145 | debugWrite("writing all files...");
|
146 | const outDir = args.outDir ?? ((_a = this.config.build) == null ? void 0 : _a.outDir) ?? "dist";
|
147 | const outDirPath = resolve(outDir);
|
148 | const controller = new AbortController();
|
149 | const write = async (path, content) => {
|
150 | const filePath = join(outDirPath, path);
|
151 | const fileDir = dirname(filePath);
|
152 | try {
|
153 | await mkdir(fileDir, { recursive: true });
|
154 | await writeFile(filePath, content, {
|
155 | encoding: "utf-8",
|
156 | signal: controller.signal
|
157 | });
|
158 | } catch (error) {
|
159 | if (controller.signal.aborted) {
|
160 | return;
|
161 | }
|
162 | controller.abort();
|
163 | debug.error("Akte → Failed to write %o\n", path);
|
164 | throw error;
|
165 | }
|
166 | debugWrite("%o", path);
|
167 | debugWrite.log(" %o", path);
|
168 | };
|
169 | const promises = [];
|
170 | for (const path in args.files) {
|
171 | promises.push(write(path, args.files[path]));
|
172 | }
|
173 | await Promise.all(promises);
|
174 | debugWrite(`done, %o ${promises.length > 1 ? "files" : "file"} written`, promises.length);
|
175 | }
|
176 | |
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 | async buildAll(args) {
|
185 | const files = await this.renderAll();
|
186 | await this.writeAll({ ...args, files });
|
187 | return Object.keys(files);
|
188 | }
|
189 | |
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 | clearCache(alsoClearFileCache = false) {
|
197 | debugCache("clearing...");
|
198 | this._globalDataCache = void 0;
|
199 | this._router = void 0;
|
200 | if (alsoClearFileCache) {
|
201 | for (const file of this.config.files) {
|
202 | file.clearCache();
|
203 | }
|
204 | }
|
205 | debugCache("cleared");
|
206 | }
|
207 | |
208 |
|
209 |
|
210 |
|
211 |
|
212 | get globalDataCache() {
|
213 | return this._globalDataCache;
|
214 | }
|
215 | |
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 | getGlobalData() {
|
224 | var _a, _b;
|
225 | if (!this._globalDataCache) {
|
226 | debugCache("retrieving global data...");
|
227 | const globalDataPromise = ((_b = (_a = this.config).globalData) == null ? void 0 : _b.call(_a)) ?? void 0;
|
228 | if (globalDataPromise instanceof Promise) {
|
229 | globalDataPromise.then(() => {
|
230 | debugCache("retrieved global data");
|
231 | });
|
232 | } else {
|
233 | debugCache("retrieved global data");
|
234 | }
|
235 | this._globalDataCache = globalDataPromise;
|
236 | } else {
|
237 | debugCache("using cached global data");
|
238 | }
|
239 | return this._globalDataCache;
|
240 | }
|
241 | getRouter() {
|
242 | if (!this._router) {
|
243 | debugCache("creating router...");
|
244 | const router = createRouter();
|
245 | for (const file of this.config.files) {
|
246 | const path = pathToRouterPath(file.path);
|
247 | router.insert(pathToRouterPath(file.path), { file });
|
248 | debugRouter("registered %o", path);
|
249 | if (file.path.endsWith("/**")) {
|
250 | const catchAllPath = pathToRouterPath(file.path.replace(/\/\*\*$/, ""));
|
251 | router.insert(catchAllPath, {
|
252 | file
|
253 | });
|
254 | debugRouter("registered %o", catchAllPath);
|
255 | debugCache(pathToRouterPath(file.path.replace(/\/\*\*$/, "")));
|
256 | }
|
257 | }
|
258 | this._router = router;
|
259 | debugCache("created router");
|
260 | } else {
|
261 | debugCache("using cached router");
|
262 | }
|
263 | return this._router;
|
264 | }
|
265 | }
|
266 | export {
|
267 | AkteApp
|
268 | };
|
269 |
|