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, "_globalDataPromise");
|
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("created with %o files", this.config.files.length);
|
34 | if (isCLI) {
|
35 | runCLI(this);
|
36 | }
|
37 | }
|
38 | |
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 | lookup(path) {
|
49 | const pathWithExtension = pathToRouterPath(path);
|
50 | debugRouter("looking up %o (%o)", path, pathWithExtension);
|
51 | const maybeMatch = this.getRouter().lookup(pathWithExtension);
|
52 | if (!maybeMatch || !maybeMatch.file) {
|
53 | debugRouter("not found %o", path);
|
54 | throw new NotFoundError(path);
|
55 | }
|
56 | return {
|
57 | ...maybeMatch,
|
58 | path
|
59 | };
|
60 | }
|
61 | |
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 | async render(match) {
|
71 | debugRender("rendering %o...", match.path);
|
72 | const params = match.params || {};
|
73 | const globalData = await this.getGlobalDataPromise();
|
74 | try {
|
75 | const content = await match.file.render({
|
76 | path: match.path,
|
77 | params,
|
78 | globalData
|
79 | });
|
80 | debugRender("rendered %o", match.path);
|
81 | return content;
|
82 | } catch (error) {
|
83 | if (error instanceof NotFoundError) {
|
84 | throw error;
|
85 | }
|
86 | debugRender("could not render %o", match.path);
|
87 | throw new NotFoundError(match.path, { cause: error });
|
88 | }
|
89 | }
|
90 | |
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 | async renderAll() {
|
97 | debugRender("rendering all files...");
|
98 | const globalData = await this.getGlobalDataPromise();
|
99 | const renderAll = async (akteFiles) => {
|
100 | try {
|
101 | const files2 = await akteFiles.renderAll({ globalData });
|
102 | return files2;
|
103 | } catch (error) {
|
104 | debug.error("Akte → Failed to build %o\n", akteFiles.path);
|
105 | throw error;
|
106 | }
|
107 | };
|
108 | const promises = [];
|
109 | for (const akteFiles of this.config.files) {
|
110 | promises.push(renderAll(akteFiles));
|
111 | }
|
112 | const rawFilesArray = await Promise.all(promises);
|
113 | const files = {};
|
114 | for (const rawFiles of rawFilesArray) {
|
115 | for (const path in rawFiles) {
|
116 | if (path in files) {
|
117 | debug.warn(" Multiple files built %o, only the first one is preserved", path);
|
118 | continue;
|
119 | }
|
120 | files[path] = rawFiles[path];
|
121 | }
|
122 | }
|
123 | const rendered = Object.keys(files).length;
|
124 | debugRender(`done, %o ${rendered > 1 ? "files" : "file"} rendered`, rendered);
|
125 | return files;
|
126 | }
|
127 | |
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 | async writeAll(args) {
|
135 | var _a;
|
136 | debugWrite("writing all files...");
|
137 | const outDir = args.outDir ?? ((_a = this.config.build) == null ? void 0 : _a.outDir) ?? "dist";
|
138 | const outDirPath = resolve(outDir);
|
139 | const controller = new AbortController();
|
140 | const write = async (path, content) => {
|
141 | const filePath = join(outDirPath, path);
|
142 | const fileDir = dirname(filePath);
|
143 | try {
|
144 | await mkdir(fileDir, { recursive: true });
|
145 | await writeFile(filePath, content, {
|
146 | encoding: "utf-8",
|
147 | signal: controller.signal
|
148 | });
|
149 | } catch (error) {
|
150 | if (controller.signal.aborted) {
|
151 | return;
|
152 | }
|
153 | controller.abort();
|
154 | debug.error("Akte → Failed to write %o\n", path);
|
155 | throw error;
|
156 | }
|
157 | debugWrite("%o", path);
|
158 | debugWrite.log(" %o", path);
|
159 | };
|
160 | const promises = [];
|
161 | for (const path in args.files) {
|
162 | promises.push(write(path, args.files[path]));
|
163 | }
|
164 | await Promise.all(promises);
|
165 | debugWrite(`done, %o ${promises.length > 1 ? "files" : "file"} written`, promises.length);
|
166 | }
|
167 | |
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 | async buildAll(args) {
|
176 | const files = await this.renderAll();
|
177 | await this.writeAll({ ...args, files });
|
178 | return Object.keys(files);
|
179 | }
|
180 | |
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 | clearCache(alsoClearFileCache = false) {
|
188 | debugCache("clearing...");
|
189 | this._globalDataPromise = void 0;
|
190 | this._router = void 0;
|
191 | if (alsoClearFileCache) {
|
192 | for (const file of this.config.files) {
|
193 | file.clearCache();
|
194 | }
|
195 | }
|
196 | debugCache("cleared");
|
197 | }
|
198 | getGlobalDataPromise() {
|
199 | var _a, _b;
|
200 | if (!this._globalDataPromise) {
|
201 | debugCache("retrieving global data...");
|
202 | const globalDataPromise = ((_b = (_a = this.config).globalData) == null ? void 0 : _b.call(_a)) ?? void 0;
|
203 | if (globalDataPromise instanceof Promise) {
|
204 | globalDataPromise.then(() => {
|
205 | debugCache("retrieved global data");
|
206 | });
|
207 | } else {
|
208 | debugCache("retrieved global data");
|
209 | }
|
210 | this._globalDataPromise = globalDataPromise;
|
211 | } else {
|
212 | debugCache("using cached global data");
|
213 | }
|
214 | return this._globalDataPromise;
|
215 | }
|
216 | getRouter() {
|
217 | if (!this._router) {
|
218 | debugCache("creating router...");
|
219 | const router = createRouter();
|
220 | for (const file of this.config.files) {
|
221 | const path = pathToRouterPath(file.path);
|
222 | router.insert(pathToRouterPath(file.path), { file });
|
223 | debugRouter("registered %o", path);
|
224 | if (file.path.endsWith("/**")) {
|
225 | const catchAllPath = pathToRouterPath(file.path.replace(/\/\*\*$/, ""));
|
226 | router.insert(catchAllPath, {
|
227 | file
|
228 | });
|
229 | debugRouter("registered %o", catchAllPath);
|
230 | debugCache(pathToRouterPath(file.path.replace(/\/\*\*$/, "")));
|
231 | }
|
232 | }
|
233 | this._router = router;
|
234 | debugCache("created router");
|
235 | } else {
|
236 | debugCache("using cached router");
|
237 | }
|
238 | return this._router;
|
239 | }
|
240 | }
|
241 | export {
|
242 | AkteApp
|
243 | };
|
244 |
|