odoro 1.0.9 → 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.
- package/README.md +94 -0
- package/client.d.ts +90 -16
- package/dist/build-LZAUDJST.js +5 -0
- package/dist/{chunk-34RGOZFA.js → chunk-4D56Z7G3.js} +49 -50
- package/dist/{chunk-JMEHF3KN.js → chunk-7ZB5MAM6.js} +4 -4
- package/dist/{chunk-LHZGX5ML.js → chunk-OMHEQVIW.js} +295 -160
- package/dist/{chunk-3SZIN6VG.js → chunk-P3DJITWE.js} +10 -10
- package/dist/{chunk-ZVL7EXJO.js → chunk-PRWVZ2SM.js} +22 -14
- package/dist/chunk-Q2KCMTB5.js +741 -0
- package/dist/chunk-QOVBLN7A.js +241 -0
- package/dist/chunk-WWTDEV4Y.js +604 -0
- package/dist/cli.d.ts +12 -13
- package/dist/cli.js +84 -63
- package/dist/{commands-4JRBD55Z.js → commands-EUGVLQWL.js} +44 -45
- package/dist/{commands-AHMXBWQQ.js → commands-GYA7NTCX.js} +124 -124
- package/dist/{create-CYVSVDAD.js → create-QX5LEWMS.js} +158 -154
- package/dist/index.d.ts +603 -151
- package/dist/index.js +6 -6
- package/dist/{package-EIDLKAA6.js → package-T4Z7OBOH.js} +5 -5
- package/dist/preview-P4WY5GEY.js +4 -0
- package/dist/registry/index.d.ts +75 -76
- package/dist/registry/index.js +1 -1
- package/dist/{server-4UGN3SFS.js → server-2WP562EV.js} +3 -3
- package/package.json +5 -5
- package/templates/react-ts/README.md +71 -35
- package/templates/react-ts/_env.example +9 -0
- package/templates/react-ts/_variants/with-engine/src/background.tsx +118 -0
- package/templates/react-ts/_variants/without-libs/src/App.tsx +380 -0
- package/templates/react-ts/_variants/without-libs/src/background.tsx +24 -0
- package/templates/react-ts/_variants/without-libs/src/entry-server.tsx +39 -0
- package/templates/react-ts/_variants/without-libs/src/main.tsx +26 -0
- package/templates/{react-ts-server/_variantes/sans-libs/client → react-ts/_variants/without-libs}/src/styles.css +137 -137
- package/templates/react-ts/{_variantes/sans-routeur → _variants/without-router}/src/App.tsx +141 -141
- package/templates/react-ts/_variants/without-router/src/entry-server.tsx +39 -0
- package/templates/react-ts/index.html +4 -4
- package/templates/react-ts/odoro.config.ts +5 -0
- package/templates/react-ts/src/App.tsx +219 -209
- package/templates/react-ts/src/background.tsx +66 -0
- package/templates/react-ts/src/entry-server.tsx +85 -0
- package/templates/react-ts/src/main.tsx +13 -4
- package/templates/react-ts/src/router.tsx +65 -45
- package/templates/react-ts/src/styles.css +5 -5
- package/templates/react-ts-server/Dockerfile +9 -9
- package/templates/react-ts-server/README.md +97 -45
- package/templates/react-ts-server/_env.example +31 -33
- package/templates/react-ts-server/_variants/with-engine/client/src/background.tsx +118 -0
- package/templates/react-ts-server/_variants/without-libs/client/src/App.tsx +380 -0
- package/templates/react-ts-server/_variants/without-libs/client/src/background.tsx +24 -0
- package/templates/react-ts-server/_variants/without-libs/client/src/entry-server.tsx +39 -0
- package/templates/react-ts-server/_variants/without-libs/client/src/main.tsx +26 -0
- package/templates/{react-ts/_variantes/sans-libs → react-ts-server/_variants/without-libs/client}/src/styles.css +137 -137
- package/templates/react-ts-server/{_variantes/sans-routeur → _variants/without-router}/client/src/App.tsx +141 -141
- package/templates/react-ts-server/_variants/without-router/client/src/entry-server.tsx +39 -0
- package/templates/react-ts-server/client/index.html +4 -4
- package/templates/react-ts-server/client/src/App.tsx +228 -210
- package/templates/react-ts-server/client/src/account.tsx +267 -0
- package/templates/react-ts-server/client/src/auth.tsx +139 -0
- package/templates/react-ts-server/client/src/background.tsx +66 -0
- package/templates/react-ts-server/client/src/entry-server.tsx +92 -0
- package/templates/react-ts-server/client/src/main.tsx +17 -5
- package/templates/react-ts-server/client/src/router.tsx +77 -45
- package/templates/react-ts-server/client/src/styles.css +5 -5
- package/templates/react-ts-server/odoro.config.ts +7 -4
- package/templates/react-ts-server/package.json +2 -0
- package/templates/react-ts-server/scripts/dev.mjs +14 -14
- package/templates/react-ts-server/server/src/main.ts +119 -45
- package/templates/react-ts-server/server/src/modules/auth/index.ts +238 -0
- package/templates/react-ts-server/server/src/modules/auth/password.ts +122 -0
- package/templates/react-ts-server/server/src/modules/auth/store.ts +193 -0
- package/templates/react-ts-server/server/src/modules/health/index.ts +45 -46
- package/dist/build-JFQHODAT.js +0 -5
- package/dist/chunk-22KJTV2R.js +0 -380
- package/dist/chunk-DL3NPC4H.js +0 -113
- package/dist/chunk-TQUJ3MFS.js +0 -268
- package/dist/preview-7DKEAQOQ.js +0 -4
- package/templates/react-ts/_variantes/avec-moteur/src/fond.tsx +0 -118
- package/templates/react-ts/_variantes/sans-libs/src/App.tsx +0 -382
- package/templates/react-ts/_variantes/sans-libs/src/fond.tsx +0 -23
- package/templates/react-ts/_variantes/sans-libs/src/main.tsx +0 -17
- package/templates/react-ts/src/fond.tsx +0 -66
- package/templates/react-ts-server/_variantes/avec-moteur/client/src/fond.tsx +0 -118
- package/templates/react-ts-server/_variantes/sans-libs/client/src/App.tsx +0 -382
- package/templates/react-ts-server/_variantes/sans-libs/client/src/fond.tsx +0 -23
- package/templates/react-ts-server/_variantes/sans-libs/client/src/main.tsx +0 -17
- package/templates/react-ts-server/client/src/fond.tsx +0 -66
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { guessAliasPaths } from './chunk-T6RLHSCW.js';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { readFile, mkdir, writeFile, rm } from 'fs/promises';
|
|
5
|
+
import { join, resolve } from 'path';
|
|
6
|
+
import { pathToFileURL } from 'url';
|
|
7
|
+
import { build } from 'esbuild';
|
|
8
|
+
|
|
9
|
+
var LINE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/;
|
|
10
|
+
var REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
11
|
+
function parseEnvDetailed(text) {
|
|
12
|
+
const values = {};
|
|
13
|
+
const literals = /* @__PURE__ */ new Set();
|
|
14
|
+
const lines = text.split(/\r?\n/);
|
|
15
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
16
|
+
const line = lines[index];
|
|
17
|
+
if (line === void 0) continue;
|
|
18
|
+
if (line.trim() === "" || line.trimStart().startsWith("#")) continue;
|
|
19
|
+
const found = LINE.exec(line);
|
|
20
|
+
const key = found?.[1];
|
|
21
|
+
if (key === void 0) continue;
|
|
22
|
+
const raw = (found?.[2] ?? "").trim();
|
|
23
|
+
const quote = raw[0];
|
|
24
|
+
if (quote !== '"' && quote !== "'" && quote !== "`") {
|
|
25
|
+
const comment = raw.search(/\s#/);
|
|
26
|
+
values[key] = comment === -1 ? raw : raw.slice(0, comment).trimEnd();
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
let body = raw.slice(1);
|
|
30
|
+
while (body.length === 0 || !body.endsWith(quote)) {
|
|
31
|
+
const next = lines[index + 1];
|
|
32
|
+
if (next === void 0) break;
|
|
33
|
+
index += 1;
|
|
34
|
+
body = `${body}
|
|
35
|
+
${next}`;
|
|
36
|
+
}
|
|
37
|
+
const content = body.endsWith(quote) ? body.slice(0, -1) : body;
|
|
38
|
+
if (quote === "'") {
|
|
39
|
+
values[key] = content;
|
|
40
|
+
literals.add(key);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
values[key] = content.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
44
|
+
}
|
|
45
|
+
return { values, literals };
|
|
46
|
+
}
|
|
47
|
+
function expand(values, environment, literals) {
|
|
48
|
+
const rendered = {};
|
|
49
|
+
for (const [key, value] of Object.entries(values)) {
|
|
50
|
+
if (literals.has(key)) {
|
|
51
|
+
rendered[key] = value;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
rendered[key] = value.replace(REFERENCE, (whole, braced, bare) => {
|
|
55
|
+
const name = braced ?? bare;
|
|
56
|
+
if (name === void 0) return whole;
|
|
57
|
+
return rendered[name] ?? values[name] ?? environment[name] ?? "";
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return rendered;
|
|
61
|
+
}
|
|
62
|
+
function envFilesFor(mode) {
|
|
63
|
+
return [".env", ".env.local", `.env.${mode}`, `.env.${mode}.local`];
|
|
64
|
+
}
|
|
65
|
+
async function loadEnv(directory, mode, prefix) {
|
|
66
|
+
const stacked = {};
|
|
67
|
+
const literals = /* @__PURE__ */ new Set();
|
|
68
|
+
const files = [];
|
|
69
|
+
for (const name of envFilesFor(mode)) {
|
|
70
|
+
const path = join(directory, name);
|
|
71
|
+
if (!existsSync(path)) continue;
|
|
72
|
+
files.push(name);
|
|
73
|
+
const read = parseEnvDetailed(await readFile(path, "utf8"));
|
|
74
|
+
Object.assign(stacked, read.values);
|
|
75
|
+
for (const key of Object.keys(read.values)) {
|
|
76
|
+
if (read.literals.has(key)) literals.add(key);
|
|
77
|
+
else literals.delete(key);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const all = expand(stacked, process.env, literals);
|
|
81
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
82
|
+
if (value !== void 0 && key in all) all[key] = value;
|
|
83
|
+
}
|
|
84
|
+
const client = {};
|
|
85
|
+
for (const [key, value] of Object.entries(all)) {
|
|
86
|
+
if (key.startsWith(prefix)) client[key] = value;
|
|
87
|
+
}
|
|
88
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
89
|
+
if (value !== void 0 && key.startsWith(prefix)) client[key] = value;
|
|
90
|
+
}
|
|
91
|
+
return { all, client, files };
|
|
92
|
+
}
|
|
93
|
+
function clientEnv(variables, mode, base) {
|
|
94
|
+
return {
|
|
95
|
+
MODE: mode,
|
|
96
|
+
// `DEV` and `PROD` cannot be deduced from the mode name alone: a `staging`
|
|
97
|
+
// mode builds as production and must behave like it.
|
|
98
|
+
DEV: mode === "development",
|
|
99
|
+
PROD: mode !== "development",
|
|
100
|
+
BASE_URL: base,
|
|
101
|
+
...variables
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function defineConfig(config) {
|
|
105
|
+
return config;
|
|
106
|
+
}
|
|
107
|
+
var CONFIG_FILES = ["odoro.config.ts", "odoro.config.js", "odoro.config.mjs"];
|
|
108
|
+
async function importConfigFile(file, root) {
|
|
109
|
+
const directory = join(root, "node_modules", ".odoro");
|
|
110
|
+
const output = join(directory, `config.${Date.now().toString(36)}.mjs`);
|
|
111
|
+
await mkdir(directory, { recursive: true });
|
|
112
|
+
try {
|
|
113
|
+
const result = await build({
|
|
114
|
+
entryPoints: [file],
|
|
115
|
+
bundle: true,
|
|
116
|
+
format: "esm",
|
|
117
|
+
platform: "node",
|
|
118
|
+
target: "node20",
|
|
119
|
+
write: false,
|
|
120
|
+
// Only the project code is inlined; its dependencies stay external,
|
|
121
|
+
// otherwise the whole node_modules would have to be resolved to read
|
|
122
|
+
// three lines.
|
|
123
|
+
packages: "external",
|
|
124
|
+
// `packages: 'external'` is not enough: a `baseUrl` in the
|
|
125
|
+
// `tsconfig.json` makes bare imports be looked up from the project root,
|
|
126
|
+
// where `odoro.json` — the registry file — is found before the package.
|
|
127
|
+
// The import then stops being a package import, the rule above no longer
|
|
128
|
+
// applies, and the build fails on a `defineConfig` missing from a
|
|
129
|
+
// configuration file.
|
|
130
|
+
//
|
|
131
|
+
// Naming it explicitly puts it out of reach of that resolution. The list
|
|
132
|
+
// matters for projects already created: they still carry a `baseUrl`, and
|
|
133
|
+
// their tsconfig cannot be rewritten.
|
|
134
|
+
external: ["odoro"]
|
|
135
|
+
});
|
|
136
|
+
const code = result.outputFiles[0]?.text;
|
|
137
|
+
if (code === void 0) {
|
|
138
|
+
throw new Error(`[odoro] Configuration "${file}" produced no code.`);
|
|
139
|
+
}
|
|
140
|
+
await writeFile(output, code, "utf8");
|
|
141
|
+
const module = await import(pathToFileURL(output).href);
|
|
142
|
+
if (module.default === void 0) {
|
|
143
|
+
throw new Error(`[odoro] Configuration "${file}" must have a default export.`);
|
|
144
|
+
}
|
|
145
|
+
return module.default;
|
|
146
|
+
} finally {
|
|
147
|
+
await rm(output, { force: true });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function resolvePrerender(requested, root) {
|
|
151
|
+
if (requested === void 0 || requested === false) return void 0;
|
|
152
|
+
const raw = requested === true ? {} : Array.isArray(requested) ? { routes: requested } : requested;
|
|
153
|
+
return {
|
|
154
|
+
routes: raw.routes ?? [],
|
|
155
|
+
entry: resolve(root, raw.entry ?? "src/entry-server.tsx")
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
async function loadConfig(root, overrides = {}, defaultMode = "production") {
|
|
159
|
+
const absoluteRoot = resolve(root);
|
|
160
|
+
let file;
|
|
161
|
+
let loaded = {};
|
|
162
|
+
for (const candidate of CONFIG_FILES) {
|
|
163
|
+
const path = join(absoluteRoot, candidate);
|
|
164
|
+
if (existsSync(path)) {
|
|
165
|
+
file = path;
|
|
166
|
+
loaded = await importConfigFile(path, absoluteRoot);
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const merged = {
|
|
171
|
+
...loaded,
|
|
172
|
+
...overrides,
|
|
173
|
+
server: { ...loaded.server, ...overrides.server },
|
|
174
|
+
build: { ...loaded.build, ...overrides.build },
|
|
175
|
+
alias: { ...loaded.alias, ...overrides.alias },
|
|
176
|
+
define: { ...loaded.define, ...overrides.define }
|
|
177
|
+
};
|
|
178
|
+
const base = merged.base ?? "/";
|
|
179
|
+
const projectRoot = merged.root === void 0 ? absoluteRoot : resolve(absoluteRoot, merged.root);
|
|
180
|
+
const mode = merged.mode ?? defaultMode;
|
|
181
|
+
const envPrefix = merged.envPrefix ?? "ODORO_";
|
|
182
|
+
const envDir = merged.envDir === void 0 ? projectRoot : resolve(projectRoot, merged.envDir);
|
|
183
|
+
const environment = await loadEnv(envDir, mode, envPrefix);
|
|
184
|
+
for (const [key, value] of Object.entries(environment.all)) {
|
|
185
|
+
process.env[key] ??= value;
|
|
186
|
+
}
|
|
187
|
+
const https = merged.server?.https;
|
|
188
|
+
return {
|
|
189
|
+
root: projectRoot,
|
|
190
|
+
base: base.endsWith("/") ? base : `${base}/`,
|
|
191
|
+
publicDir: resolve(projectRoot, merged.publicDir ?? "public"),
|
|
192
|
+
outDir: resolve(projectRoot, merged.build?.outDir ?? "dist"),
|
|
193
|
+
server: {
|
|
194
|
+
port: merged.server?.port ?? 5180,
|
|
195
|
+
host: merged.server?.host ?? "localhost",
|
|
196
|
+
proxy: merged.server?.proxy ?? {},
|
|
197
|
+
https: https === void 0 ? void 0 : { ...https },
|
|
198
|
+
strictPort: merged.server?.strictPort ?? false,
|
|
199
|
+
open: merged.server?.open ?? false
|
|
200
|
+
},
|
|
201
|
+
build: {
|
|
202
|
+
outDir: merged.build?.outDir ?? "dist",
|
|
203
|
+
minify: merged.build?.minify ?? true,
|
|
204
|
+
sourcemap: merged.build?.sourcemap ?? true,
|
|
205
|
+
target: merged.build?.target ?? "es2022",
|
|
206
|
+
// On by default: a stylesheet holding every possible class is a
|
|
207
|
+
// generation accident, not an intention.
|
|
208
|
+
prune: merged.build?.prune ?? true,
|
|
209
|
+
safelist: merged.build?.safelist ?? [],
|
|
210
|
+
// On by default: the manifest only costs a file of a few lines, and
|
|
211
|
+
// preloading removes a cascade of requests nobody sees on a local machine
|
|
212
|
+
// and everybody suffers elsewhere.
|
|
213
|
+
manifest: merged.build?.manifest ?? true,
|
|
214
|
+
preload: merged.build?.preload ?? true,
|
|
215
|
+
prerender: resolvePrerender(merged.build?.prerender, projectRoot)
|
|
216
|
+
},
|
|
217
|
+
// The aliases declared in `tsconfig.json` are picked up automatically.
|
|
218
|
+
// Without that, a project following `odoro init` — which infers its prefix
|
|
219
|
+
// from the tsconfig — would have to redeclare the same alias here for the
|
|
220
|
+
// server to resolve it. Two places for the same truth, and an error that
|
|
221
|
+
// only shows up on the first import.
|
|
222
|
+
//
|
|
223
|
+
// The configuration wins: it is what you write to fix a case the inference
|
|
224
|
+
// does not catch.
|
|
225
|
+
alias: { ...await guessAliasPaths(projectRoot), ...merged.alias },
|
|
226
|
+
define: merged.define ?? {},
|
|
227
|
+
envPrefix,
|
|
228
|
+
envDir,
|
|
229
|
+
mode,
|
|
230
|
+
env: environment.all,
|
|
231
|
+
envClient: clientEnv(
|
|
232
|
+
environment.client,
|
|
233
|
+
mode,
|
|
234
|
+
base.endsWith("/") ? base : `${base}/`
|
|
235
|
+
),
|
|
236
|
+
plugins: merged.plugins ?? [],
|
|
237
|
+
configFile: file
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export { clientEnv, defineConfig, loadConfig, loadEnv };
|