odoro 1.0.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +94 -0
  2. package/client.d.ts +90 -16
  3. package/dist/build-LZAUDJST.js +5 -0
  4. package/dist/{chunk-34RGOZFA.js → chunk-4D56Z7G3.js} +49 -50
  5. package/dist/{chunk-JMEHF3KN.js → chunk-7ZB5MAM6.js} +4 -4
  6. package/dist/{chunk-LHZGX5ML.js → chunk-OMHEQVIW.js} +295 -160
  7. package/dist/{chunk-3SZIN6VG.js → chunk-P3DJITWE.js} +10 -10
  8. package/dist/{chunk-ZVL7EXJO.js → chunk-PRWVZ2SM.js} +22 -14
  9. package/dist/chunk-Q2KCMTB5.js +741 -0
  10. package/dist/chunk-QOVBLN7A.js +241 -0
  11. package/dist/chunk-WWTDEV4Y.js +604 -0
  12. package/dist/cli.d.ts +12 -13
  13. package/dist/cli.js +84 -63
  14. package/dist/{commands-4JRBD55Z.js → commands-EUGVLQWL.js} +44 -45
  15. package/dist/{commands-AHMXBWQQ.js → commands-GYA7NTCX.js} +124 -124
  16. package/dist/{create-CDKS7KZ3.js → create-QX5LEWMS.js} +158 -154
  17. package/dist/index.d.ts +603 -151
  18. package/dist/index.js +6 -6
  19. package/dist/{package-NBP5NDX6.js → package-T4Z7OBOH.js} +5 -5
  20. package/dist/preview-P4WY5GEY.js +4 -0
  21. package/dist/registry/index.d.ts +75 -76
  22. package/dist/registry/index.js +1 -1
  23. package/dist/{server-4UGN3SFS.js → server-2WP562EV.js} +3 -3
  24. package/package.json +5 -5
  25. package/templates/react-ts/README.md +71 -35
  26. package/templates/react-ts/_env.example +9 -0
  27. package/templates/react-ts/_variants/with-engine/src/background.tsx +118 -0
  28. package/templates/react-ts/_variants/without-libs/src/App.tsx +380 -0
  29. package/templates/react-ts/_variants/without-libs/src/background.tsx +24 -0
  30. package/templates/react-ts/_variants/without-libs/src/entry-server.tsx +39 -0
  31. package/templates/react-ts/_variants/without-libs/src/main.tsx +26 -0
  32. package/templates/{react-ts-server/_variantes/sans-libs/client → react-ts/_variants/without-libs}/src/styles.css +137 -137
  33. package/templates/react-ts/{_variantes/sans-routeur → _variants/without-router}/src/App.tsx +141 -141
  34. package/templates/react-ts/_variants/without-router/src/entry-server.tsx +39 -0
  35. package/templates/react-ts/index.html +4 -4
  36. package/templates/react-ts/odoro.config.ts +5 -0
  37. package/templates/react-ts/src/App.tsx +219 -209
  38. package/templates/react-ts/src/background.tsx +66 -0
  39. package/templates/react-ts/src/entry-server.tsx +85 -0
  40. package/templates/react-ts/src/main.tsx +13 -4
  41. package/templates/react-ts/src/router.tsx +65 -45
  42. package/templates/react-ts/src/styles.css +5 -5
  43. package/templates/react-ts-server/Dockerfile +9 -9
  44. package/templates/react-ts-server/README.md +97 -45
  45. package/templates/react-ts-server/_env.example +31 -33
  46. package/templates/react-ts-server/_variants/with-engine/client/src/background.tsx +118 -0
  47. package/templates/react-ts-server/_variants/without-libs/client/src/App.tsx +380 -0
  48. package/templates/react-ts-server/_variants/without-libs/client/src/background.tsx +24 -0
  49. package/templates/react-ts-server/_variants/without-libs/client/src/entry-server.tsx +39 -0
  50. package/templates/react-ts-server/_variants/without-libs/client/src/main.tsx +26 -0
  51. package/templates/{react-ts/_variantes/sans-libs → react-ts-server/_variants/without-libs/client}/src/styles.css +137 -137
  52. package/templates/react-ts-server/{_variantes/sans-routeur → _variants/without-router}/client/src/App.tsx +141 -141
  53. package/templates/react-ts-server/_variants/without-router/client/src/entry-server.tsx +39 -0
  54. package/templates/react-ts-server/client/index.html +4 -4
  55. package/templates/react-ts-server/client/src/App.tsx +228 -210
  56. package/templates/react-ts-server/client/src/account.tsx +267 -0
  57. package/templates/react-ts-server/client/src/auth.tsx +139 -0
  58. package/templates/react-ts-server/client/src/background.tsx +66 -0
  59. package/templates/react-ts-server/client/src/entry-server.tsx +92 -0
  60. package/templates/react-ts-server/client/src/main.tsx +17 -5
  61. package/templates/react-ts-server/client/src/router.tsx +77 -45
  62. package/templates/react-ts-server/client/src/styles.css +5 -5
  63. package/templates/react-ts-server/odoro.config.ts +7 -4
  64. package/templates/react-ts-server/package.json +2 -0
  65. package/templates/react-ts-server/scripts/dev.mjs +14 -14
  66. package/templates/react-ts-server/server/src/main.ts +119 -45
  67. package/templates/react-ts-server/server/src/modules/auth/index.ts +238 -0
  68. package/templates/react-ts-server/server/src/modules/auth/password.ts +122 -0
  69. package/templates/react-ts-server/server/src/modules/auth/store.ts +193 -0
  70. package/templates/react-ts-server/server/src/modules/health/index.ts +45 -46
  71. package/dist/build-JFQHODAT.js +0 -5
  72. package/dist/chunk-22KJTV2R.js +0 -380
  73. package/dist/chunk-DL3NPC4H.js +0 -113
  74. package/dist/chunk-TQUJ3MFS.js +0 -268
  75. package/dist/preview-7DKEAQOQ.js +0 -4
  76. package/templates/react-ts/_variantes/avec-moteur/src/fond.tsx +0 -118
  77. package/templates/react-ts/_variantes/sans-libs/src/App.tsx +0 -382
  78. package/templates/react-ts/_variantes/sans-libs/src/fond.tsx +0 -23
  79. package/templates/react-ts/_variantes/sans-libs/src/main.tsx +0 -17
  80. package/templates/react-ts/src/fond.tsx +0 -42
  81. package/templates/react-ts-server/_variantes/avec-moteur/client/src/fond.tsx +0 -118
  82. package/templates/react-ts-server/_variantes/sans-libs/client/src/App.tsx +0 -382
  83. package/templates/react-ts-server/_variantes/sans-libs/client/src/fond.tsx +0 -23
  84. package/templates/react-ts-server/_variantes/sans-libs/client/src/main.tsx +0 -17
  85. package/templates/react-ts-server/client/src/fond.tsx +0 -42
@@ -0,0 +1,604 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from 'child_process';
3
+ import { existsSync, statSync, readdirSync } from 'fs';
4
+ import { resolve, dirname, extname, relative, join } from 'path';
5
+ import { readFile } from 'fs/promises';
6
+ import { build } from 'esbuild';
7
+
8
+ // src/plugins.ts
9
+ async function transformWith(plugins, code, context) {
10
+ let current = code;
11
+ let touched = false;
12
+ for (const plugin of plugins) {
13
+ if (plugin.transform === void 0) continue;
14
+ try {
15
+ const rendered = await plugin.transform(current, context);
16
+ if (rendered === null || rendered === void 0) continue;
17
+ current = rendered;
18
+ touched = true;
19
+ } catch (cause) {
20
+ throw new Error(
21
+ `[odoro] Plugin "${plugin.name}" failed on ${context.id}: ` + (cause instanceof Error ? cause.message : String(cause)),
22
+ { cause }
23
+ );
24
+ }
25
+ }
26
+ return touched ? current : void 0;
27
+ }
28
+ async function transformHtmlWith(plugins, html, context) {
29
+ let current = html;
30
+ for (const plugin of plugins) {
31
+ if (plugin.transformIndexHtml === void 0) continue;
32
+ try {
33
+ current = await plugin.transformIndexHtml(current, context);
34
+ } catch (cause) {
35
+ throw new Error(
36
+ `[odoro] Plugin "${plugin.name}" failed on the document: ` + (cause instanceof Error ? cause.message : String(cause)),
37
+ { cause }
38
+ );
39
+ }
40
+ }
41
+ return current;
42
+ }
43
+ function esbuildPluginsFrom(plugins) {
44
+ return plugins.flatMap((plugin) => plugin.esbuild ?? []);
45
+ }
46
+
47
+ // src/shared/listen.ts
48
+ var ATTEMPTS = 10;
49
+ async function listen(server, port, host, attempts = ATTEMPTS) {
50
+ for (let offset = 0; offset < attempts; offset += 1) {
51
+ const candidate = port + offset;
52
+ const taken = await new Promise((resolve3, reject) => {
53
+ const onError = (cause) => {
54
+ server.removeListener("listening", onListening);
55
+ if (cause.code === "EADDRINUSE") {
56
+ resolve3(true);
57
+ return;
58
+ }
59
+ reject(cause);
60
+ };
61
+ const onListening = () => {
62
+ server.removeListener("error", onError);
63
+ resolve3(false);
64
+ };
65
+ server.once("error", onError);
66
+ server.once("listening", onListening);
67
+ server.listen(candidate, host);
68
+ });
69
+ if (!taken) {
70
+ const address = server.address();
71
+ const obtained = typeof address === "object" && address !== null ? address.port : candidate;
72
+ return offset === 0 ? { port: obtained } : { port: obtained, requested: port };
73
+ }
74
+ }
75
+ throw new Error(
76
+ `[odoro] No free port between ${String(port)} and ${String(port + attempts - 1)}.`
77
+ );
78
+ }
79
+ function openBrowser(url) {
80
+ const [command, ...arguments_] = process.platform === "win32" ? (
81
+ // `start` is a built-in command: it goes through the interpreter. The
82
+ // empty title that follows is mandatory, otherwise a quoted address
83
+ // would be taken for the window title.
84
+ ["cmd", "/c", "start", '""', url.replace(/&/g, "^&")]
85
+ ) : process.platform === "darwin" ? ["open", url] : ["xdg-open", url];
86
+ if (command === void 0) return;
87
+ try {
88
+ const child = spawn(command, arguments_, { stdio: "ignore", detached: true });
89
+ child.on("error", () => void 0);
90
+ child.unref();
91
+ } catch {
92
+ }
93
+ }
94
+
95
+ // src/shared/suffixes.ts
96
+ var MARKER = /\?(worker|raw|url)$/;
97
+ function readSuffix(specifier) {
98
+ const found = MARKER.exec(specifier);
99
+ const suffix = found?.[1];
100
+ if (suffix === void 0) return void 0;
101
+ return {
102
+ suffix,
103
+ path: specifier.slice(0, specifier.length - suffix.length - 1)
104
+ };
105
+ }
106
+ function workerModule(url) {
107
+ return `const source = ${JSON.stringify(url)}
108
+
109
+ export default class OdoroWorker extends Worker {
110
+ constructor(options) {
111
+ super(source, { type: 'module', ...options })
112
+ }
113
+ }
114
+ `;
115
+ }
116
+ function textModule(content) {
117
+ return `export default ${JSON.stringify(content)}
118
+ `;
119
+ }
120
+ function urlModule(url) {
121
+ return `export default ${JSON.stringify(url)}
122
+ `;
123
+ }
124
+ var IGNORED = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".odoro"]);
125
+ var SPECIALS = /[.*+?^${}()|[\]\\]/g;
126
+ function toRegex(pattern) {
127
+ let source = "";
128
+ for (let index = 0; index < pattern.length; index += 1) {
129
+ const letter = pattern[index];
130
+ if (letter === void 0) continue;
131
+ if (letter === "*") {
132
+ if (pattern[index + 1] === "*") {
133
+ if (pattern[index + 2] === "/") {
134
+ source += "(?:.*/)?";
135
+ index += 2;
136
+ continue;
137
+ }
138
+ source += ".*";
139
+ index += 1;
140
+ continue;
141
+ }
142
+ source += "[^/]*";
143
+ continue;
144
+ }
145
+ if (letter === "?") {
146
+ source += "[^/]";
147
+ continue;
148
+ }
149
+ if (letter === "{") {
150
+ const closing = pattern.indexOf("}", index);
151
+ if (closing !== -1) {
152
+ const choices = pattern.slice(index + 1, closing).split(",").map((part) => part.replace(SPECIALS, "\\$&"));
153
+ source += `(?:${choices.join("|")})`;
154
+ index = closing;
155
+ continue;
156
+ }
157
+ }
158
+ source += letter.replace(SPECIALS, "\\$&");
159
+ }
160
+ return new RegExp(`^${source}$`);
161
+ }
162
+ function groupEnd(code, opening) {
163
+ let depth = 0;
164
+ let quote;
165
+ for (let index = opening; index < code.length; index += 1) {
166
+ const letter = code[index];
167
+ if (quote !== void 0) {
168
+ if (letter === "\\") index += 1;
169
+ else if (letter === quote) quote = void 0;
170
+ continue;
171
+ }
172
+ if (letter === '"' || letter === "'" || letter === "`") {
173
+ quote = letter;
174
+ continue;
175
+ }
176
+ if (letter === "(") depth += 1;
177
+ else if (letter === ")") {
178
+ depth -= 1;
179
+ if (depth === 0) return index;
180
+ }
181
+ }
182
+ return -1;
183
+ }
184
+ function stringsIn(fragment) {
185
+ const rendered = [];
186
+ for (const found of fragment.matchAll(/(['"`])((?:\\.|(?!\1).)*)\1/g)) {
187
+ const value = found[2];
188
+ if (value !== void 0) rendered.push(value);
189
+ }
190
+ return rendered;
191
+ }
192
+ function patternsIn(code) {
193
+ const patterns = [];
194
+ for (const found of code.matchAll(/import\.meta\.glob\s*\(/g)) {
195
+ const start = found.index;
196
+ const opening = start + found[0].length - 1;
197
+ const end = groupEnd(code, opening);
198
+ if (end === -1) continue;
199
+ const arguments_ = code.slice(opening + 1, end);
200
+ const brace = arguments_.indexOf("{");
201
+ const cut = brace === -1 ? -1 : arguments_.slice(0, brace).lastIndexOf(",");
202
+ const first = cut === -1 ? arguments_ : arguments_.slice(0, cut);
203
+ const second = cut === -1 ? "" : arguments_.slice(cut + 1);
204
+ const all = stringsIn(first);
205
+ if (all.length === 0) continue;
206
+ patterns.push({
207
+ start,
208
+ end: end + 1,
209
+ included: all.filter((pattern) => !pattern.startsWith("!")),
210
+ excluded: all.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1)),
211
+ options: {
212
+ eager: /["']?eager["']?\s*:\s*true/.test(second),
213
+ named: /["']?import["']?\s*:\s*["']([^"']+)["']/.exec(second)?.[1]
214
+ }
215
+ });
216
+ }
217
+ return patterns;
218
+ }
219
+ function fixedRootOf(pattern) {
220
+ const fixed = [];
221
+ for (const segment of pattern.split("/")) {
222
+ if (/[*?{}[\]]/.test(segment)) break;
223
+ fixed.push(segment);
224
+ }
225
+ return fixed.join("/") || ".";
226
+ }
227
+ function filesUnder(directory) {
228
+ if (!existsSync(directory) || !statSync(directory).isDirectory()) return [];
229
+ const rendered = [];
230
+ const stack = [directory];
231
+ while (stack.length > 0) {
232
+ const current = stack.pop();
233
+ if (current === void 0) continue;
234
+ for (const entry of readdirSync(current)) {
235
+ if (IGNORED.has(entry) || entry.startsWith(".")) continue;
236
+ const path = join(current, entry);
237
+ if (statSync(path).isDirectory()) stack.push(path);
238
+ else rendered.push(path);
239
+ }
240
+ }
241
+ return rendered;
242
+ }
243
+ function toUrlPath(path) {
244
+ return path.split("\\").join("/");
245
+ }
246
+ function resolvePattern(pattern, file, projectRoot) {
247
+ const sourceDirectory = dirname(file);
248
+ const found = /* @__PURE__ */ new Set();
249
+ for (const included of pattern.included) {
250
+ const absolute = included.startsWith("/");
251
+ const base = absolute ? join(projectRoot, fixedRootOf(included.slice(1))) : resolve(sourceDirectory, fixedRootOf(included));
252
+ const regex = toRegex(included);
253
+ for (const path of filesUnder(base)) {
254
+ const relativePath = absolute ? `/${toUrlPath(relative(projectRoot, path))}` : toUrlPath(relative(sourceDirectory, path)).replace(/^(?!\.\.\/)/, "./");
255
+ if (!regex.test(relativePath)) continue;
256
+ if (pattern.excluded.some((excluded) => toRegex(excluded).test(relativePath)))
257
+ continue;
258
+ if (path === resolve(file)) continue;
259
+ found.add(relativePath);
260
+ }
261
+ }
262
+ return [...found].sort();
263
+ }
264
+ function hasGlob(code) {
265
+ return code.includes("import.meta.glob");
266
+ }
267
+ function transformGlob(code, file, projectRoot) {
268
+ if (!hasGlob(code)) return void 0;
269
+ const patterns = patternsIn(code);
270
+ if (patterns.length === 0) return void 0;
271
+ const prelude = [];
272
+ const files = [];
273
+ let rendered = "";
274
+ let cursor = 0;
275
+ let counter = 0;
276
+ for (const pattern of patterns) {
277
+ const entries = [];
278
+ for (const path of resolvePattern(pattern, file, projectRoot)) {
279
+ files.push(resolve(dirname(file), path));
280
+ const key = JSON.stringify(path);
281
+ const target = JSON.stringify(path);
282
+ if (pattern.options.eager) {
283
+ const alias = `__odoro_glob_${String(counter)}`;
284
+ counter += 1;
285
+ prelude.push(`import * as ${alias} from ${target}`);
286
+ entries.push(
287
+ `${key}: ${pattern.options.named === void 0 ? alias : `${alias}[${JSON.stringify(pattern.options.named)}]`}`
288
+ );
289
+ continue;
290
+ }
291
+ const importation = `import(${target})`;
292
+ entries.push(
293
+ `${key}: ${pattern.options.named === void 0 ? `() => ${importation}` : `() => ${importation}.then((m) => m[${JSON.stringify(pattern.options.named)}])`}`
294
+ );
295
+ }
296
+ rendered += code.slice(cursor, pattern.start);
297
+ rendered += entries.length === 0 ? "{}" : `{${entries.join(", ")}}`;
298
+ cursor = pattern.end;
299
+ }
300
+ rendered += code.slice(cursor);
301
+ return {
302
+ code: prelude.length === 0 ? rendered : `${prelude.join("\n")}
303
+ ${rendered}`,
304
+ files
305
+ };
306
+ }
307
+ var LOADERS = {
308
+ ".ts": "ts",
309
+ ".tsx": "tsx",
310
+ ".js": "js",
311
+ ".jsx": "jsx",
312
+ ".mjs": "js",
313
+ ".cjs": "js"
314
+ };
315
+ function sourcePlugin(options) {
316
+ const transforms = options.plugins.some((plugin) => plugin.transform !== void 0);
317
+ return {
318
+ name: "odoro-source",
319
+ setup(builder) {
320
+ builder.onLoad({ filter: /\.[cm]?[jt]sx?$/ }, async (args) => {
321
+ if (args.path.includes("node_modules")) return null;
322
+ const source = await readFile(args.path, "utf8");
323
+ let code = source;
324
+ if (hasGlob(code)) {
325
+ const resolved = transformGlob(code, args.path, options.root);
326
+ if (resolved !== void 0) {
327
+ code = resolved.code;
328
+ for (const file of resolved.files) options.onMatch?.(file);
329
+ }
330
+ }
331
+ if (transforms) {
332
+ const rendered = await transformWith(options.plugins, code, {
333
+ id: args.path,
334
+ dev: options.dev,
335
+ ssr: options.ssr ?? false
336
+ });
337
+ if (rendered !== void 0) code = rendered;
338
+ }
339
+ if (code === source) return null;
340
+ return { contents: code, loader: LOADERS[extname(args.path).toLowerCase()] };
341
+ });
342
+ }
343
+ };
344
+ }
345
+ var DEPS_PREFIX = "/@deps/";
346
+ var INTERNAL_PREFIX = "/@odoro/";
347
+ var SOURCE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
348
+ var STYLE_EXTENSIONS = [".css"];
349
+ var ASSET_EXTENSIONS = [
350
+ ".svg",
351
+ ".png",
352
+ ".jpg",
353
+ ".jpeg",
354
+ ".gif",
355
+ ".webp",
356
+ ".avif",
357
+ ".ico",
358
+ ".woff",
359
+ ".woff2",
360
+ ".mp4",
361
+ ".webm"
362
+ ];
363
+ function depFileName(specifier) {
364
+ return `${specifier.replace(/^@/, "").split("/").join("_")}.js`;
365
+ }
366
+ function isBareSpecifier(specifier) {
367
+ return !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("\\") && !/^[a-zA-Z]:[\\/]/.test(specifier) && !specifier.startsWith("data:") && !specifier.startsWith("http:") && !specifier.startsWith("https:");
368
+ }
369
+ function hasExtension(path, extensions) {
370
+ const clean = path.split("?")[0] ?? path;
371
+ return extensions.some((extension) => clean.toLowerCase().endsWith(extension));
372
+ }
373
+ function fileToUrl(file, root) {
374
+ const relativePath = relative(root, file).split("\\").join("/");
375
+ if (!relativePath.startsWith("..")) return `/${relativePath}`;
376
+ return `/@fs/${file.split("\\").join("/").replace(/^\//, "")}`;
377
+ }
378
+ function urlToFile(url, root) {
379
+ const path = (url.split("?")[0] ?? url).split("#")[0] ?? url;
380
+ if (path.startsWith("/@fs/")) {
381
+ const absolute = path.slice("/@fs/".length);
382
+ return /^[a-zA-Z]:/.test(absolute) ? absolute : `/${absolute}`;
383
+ }
384
+ return resolve(root, `.${path}`);
385
+ }
386
+ function applyAlias(specifier, config) {
387
+ for (const [prefix, target] of Object.entries(config.alias)) {
388
+ if (specifier === prefix || specifier.startsWith(`${prefix}/`)) {
389
+ return resolve(
390
+ config.root,
391
+ target,
392
+ specifier.slice(prefix.length).replace(/^\//, "")
393
+ );
394
+ }
395
+ }
396
+ return specifier;
397
+ }
398
+ function externalizeImports(config, dependencies) {
399
+ return {
400
+ name: "odoro-externalize",
401
+ setup(builder) {
402
+ builder.onResolve({ filter: /.*/ }, async (args) => {
403
+ if (args.kind === "entry-point") return null;
404
+ if (args.pluginData?.resolving === true) {
405
+ return null;
406
+ }
407
+ if (args.path.startsWith(INTERNAL_PREFIX) || args.path.startsWith(DEPS_PREFIX)) {
408
+ return { path: args.path, external: true };
409
+ }
410
+ const suffixed = readSuffix(args.path);
411
+ if (suffixed !== void 0) {
412
+ const target = await builder.resolve(applyAlias(suffixed.path, config), {
413
+ kind: "import-statement",
414
+ resolveDir: args.resolveDir,
415
+ importer: args.importer,
416
+ pluginData: { resolving: true }
417
+ });
418
+ if (target.errors.length === 0) {
419
+ dependencies.add(target.path);
420
+ return {
421
+ path: `${fileToUrl(target.path, config.root)}?${suffixed.suffix}`,
422
+ external: true
423
+ };
424
+ }
425
+ }
426
+ const aliased = applyAlias(args.path, config);
427
+ const isFileLike = hasExtension(aliased, STYLE_EXTENSIONS) || hasExtension(aliased, ASSET_EXTENSIONS);
428
+ if (isBareSpecifier(aliased) && !isFileLike) {
429
+ return { path: `${DEPS_PREFIX}${depFileName(aliased)}`, external: true };
430
+ }
431
+ const resolved = await builder.resolve(aliased, {
432
+ kind: "import-statement",
433
+ resolveDir: args.resolveDir,
434
+ importer: args.importer,
435
+ pluginData: { resolving: true }
436
+ });
437
+ if (resolved.errors.length > 0) {
438
+ return { path: args.path, external: true };
439
+ }
440
+ dependencies.add(resolved.path);
441
+ const url = fileToUrl(resolved.path, config.root);
442
+ return {
443
+ path: hasExtension(url, ASSET_EXTENSIONS) ? `${url}?import` : url,
444
+ external: true
445
+ };
446
+ });
447
+ }
448
+ };
449
+ }
450
+ async function transformModule(file, config, env) {
451
+ const dependencies = /* @__PURE__ */ new Set();
452
+ const onMatch = (matched) => {
453
+ dependencies.add(matched);
454
+ };
455
+ const result = await build({
456
+ entryPoints: [file],
457
+ bundle: true,
458
+ write: false,
459
+ format: "esm",
460
+ platform: "browser",
461
+ target: "es2022",
462
+ sourcemap: "inline",
463
+ jsx: "automatic",
464
+ jsxDev: true,
465
+ logLevel: "silent",
466
+ absWorkingDir: config.root,
467
+ define: {
468
+ "import.meta.env": JSON.stringify(env),
469
+ "process.env.NODE_ENV": JSON.stringify("development"),
470
+ ...config.define
471
+ },
472
+ plugins: [
473
+ externalizeImports(config, dependencies),
474
+ sourcePlugin({
475
+ root: config.root,
476
+ plugins: config.plugins,
477
+ dev: true,
478
+ onMatch
479
+ }),
480
+ ...esbuildPluginsFrom(config.plugins)
481
+ ]
482
+ });
483
+ const code = result.outputFiles[0]?.text;
484
+ if (code === void 0) {
485
+ throw new Error(`[odoro] The build of "${file}" produced no code.`);
486
+ }
487
+ return { code, dependencies: [...dependencies] };
488
+ }
489
+ var IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
490
+ var RESERVED = /* @__PURE__ */ new Set([
491
+ "arguments",
492
+ "await",
493
+ "break",
494
+ "case",
495
+ "catch",
496
+ "class",
497
+ "const",
498
+ "continue",
499
+ "debugger",
500
+ "default",
501
+ "delete",
502
+ "do",
503
+ "else",
504
+ "enum",
505
+ "eval",
506
+ "export",
507
+ "extends",
508
+ "false",
509
+ "finally",
510
+ "for",
511
+ "function",
512
+ "if",
513
+ "implements",
514
+ "import",
515
+ "in",
516
+ "instanceof",
517
+ "interface",
518
+ "let",
519
+ "new",
520
+ "null",
521
+ "package",
522
+ "private",
523
+ "protected",
524
+ "public",
525
+ "return",
526
+ "static",
527
+ "super",
528
+ "switch",
529
+ "this",
530
+ "throw",
531
+ "true",
532
+ "try",
533
+ "typeof",
534
+ "var",
535
+ "void",
536
+ "while",
537
+ "with",
538
+ "yield"
539
+ ]);
540
+ function wrapJson(json) {
541
+ let value;
542
+ try {
543
+ value = JSON.parse(json);
544
+ } catch {
545
+ return 'throw new SyntaxError("unreadable JSON")';
546
+ }
547
+ const lines = ["export default " + json.trim()];
548
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
549
+ for (const [key, content] of Object.entries(value)) {
550
+ if (!IDENTIFIER.test(key) || RESERVED.has(key)) continue;
551
+ lines.push("export const " + key + " = " + JSON.stringify(content));
552
+ }
553
+ }
554
+ return lines.join("\n");
555
+ }
556
+ var ASSET_DESTINATIONS = /* @__PURE__ */ new Set([
557
+ "script",
558
+ "style",
559
+ "image",
560
+ "font",
561
+ "audio",
562
+ "video",
563
+ "track",
564
+ "manifest",
565
+ "worker",
566
+ "sharedworker",
567
+ "serviceworker"
568
+ ]);
569
+ function isAssetRequest(headers) {
570
+ const destination = headers["sec-fetch-dest"];
571
+ return typeof destination === "string" && ASSET_DESTINATIONS.has(destination);
572
+ }
573
+ function wantsStylesheet(headers, url) {
574
+ if (url.includes("?direct")) return true;
575
+ if (headers["sec-fetch-dest"] === "style") return true;
576
+ const accepted = headers["accept"];
577
+ return typeof accepted === "string" && accepted.includes("text/css");
578
+ }
579
+ function wrapStyle(url, css) {
580
+ return `const id = ${JSON.stringify(`odoro-style:${url}`)}
581
+ const css = ${JSON.stringify(css)}
582
+
583
+ let element = document.querySelector(\`style[data-odoro-id="\${id}"]\`)
584
+ if (element === null) {
585
+ element = document.createElement('style')
586
+ element.setAttribute('data-odoro-id', id)
587
+ document.head.appendChild(element)
588
+ }
589
+ element.textContent = css
590
+
591
+ import.meta.hot?.accept()
592
+ import.meta.hot?.dispose(() => {
593
+ // The next stylesheet will recreate the element: removing it avoids stacking
594
+ // dead rules on every reload.
595
+ element?.remove()
596
+ })
597
+ `;
598
+ }
599
+ function wrapAsset(url) {
600
+ return `export default ${JSON.stringify(url)}
601
+ `;
602
+ }
603
+
604
+ export { ASSET_EXTENSIONS, DEPS_PREFIX, INTERNAL_PREFIX, SOURCE_EXTENSIONS, STYLE_EXTENSIONS, applyAlias, depFileName, esbuildPluginsFrom, fileToUrl, hasExtension, hasGlob, isAssetRequest, isBareSpecifier, listen, openBrowser, readSuffix, sourcePlugin, textModule, transformGlob, transformHtmlWith, transformModule, urlModule, urlToFile, wantsStylesheet, workerModule, wrapAsset, wrapJson, wrapStyle };
package/dist/cli.d.ts CHANGED
@@ -1,26 +1,25 @@
1
1
  /**
2
- * Entree en ligne de commande du moteur Odoro.
2
+ * Command line entry of the Odoro engine.
3
3
  *
4
- * L'analyse des arguments est ecrite a la main : elle tient en quarante
5
- * lignes, et le binaire est telecharge a chaque `npm create odoro`, donc son
6
- * poids compte.
4
+ * The argument parsing is written by hand: it fits in forty lines, and the
5
+ * binary is downloaded on every `npm create odoro`, so its weight counts.
7
6
  *
8
7
  * @module
9
8
  */
10
- /** Arguments analyses. */
9
+ /** Parsed arguments. */
11
10
  interface ParsedArgs {
12
- /** Sous-commande demandee. */
11
+ /** Subcommand requested. */
13
12
  command: string;
14
- /** Arguments positionnels restants. */
13
+ /** Remaining positional arguments. */
15
14
  positional: string[];
16
- /** Options nommees. */
15
+ /** Named options. */
17
16
  flags: Record<string, string | boolean>;
18
17
  }
19
18
  /**
20
- * Analyse une ligne de commande.
19
+ * Parses a command line.
21
20
  *
22
- * Reconnait `--option`, `--option=valeur`, `--option valeur`, `--no-option`
23
- * et les alias courts `-h` et `-v`.
21
+ * Recognises `--option`, `--option=value`, `--option value`, `--no-option` and
22
+ * the short aliases `-h` and `-v`.
24
23
  *
25
24
  * @example
26
25
  * parseArgs(['create', 'site', '--template=react-ts', '--no-git'])
@@ -28,9 +27,9 @@ interface ParsedArgs {
28
27
  */
29
28
  declare function parseArgs(argv: readonly string[]): ParsedArgs;
30
29
  /**
31
- * Point d'entree du binaire.
30
+ * Entry point of the binary.
32
31
  *
33
- * @returns Le code de sortie du processus.
32
+ * @returns The exit code of the process.
34
33
  *
35
34
  * @example
36
35
  * const code = await run(['dev', '--port', '3000'])