odoro 1.0.9 → 2.1.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-XJIP4GNT.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-DF67LADH.js +735 -0
- package/dist/{chunk-LHZGX5ML.js → chunk-HS7NGZLM.js} +307 -196
- package/dist/chunk-LIKVHWB4.js +231 -0
- package/dist/chunk-QOVBLN7A.js +241 -0
- package/dist/chunk-RTWJ5GFB.js +729 -0
- package/dist/chunk-TONYIKCN.js +57 -0
- package/dist/cli.d.ts +12 -13
- package/dist/cli.js +86 -63
- package/dist/{commands-AHMXBWQQ.js → commands-GYA7NTCX.js} +124 -124
- package/dist/commands-UOWN3IK4.js +181 -0
- package/dist/{create-CYVSVDAD.js → create-B2TLV6XI.js} +198 -160
- package/dist/index.d.ts +603 -151
- package/dist/index.js +6 -6
- package/dist/{package-EIDLKAA6.js → package-3ZJOEXM4.js} +6 -5
- package/dist/preview-3IRG7MHV.js +4 -0
- package/dist/registry/index.d.ts +75 -76
- package/dist/registry/index.js +1 -1
- package/dist/{server-4UGN3SFS.js → server-ZB3P3EGS.js} +3 -3
- package/package.json +6 -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-3SZIN6VG.js +0 -64
- package/dist/chunk-DL3NPC4H.js +0 -113
- package/dist/chunk-TQUJ3MFS.js +0 -268
- package/dist/chunk-ZVL7EXJO.js +0 -66
- package/dist/commands-4JRBD55Z.js +0 -245
- 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
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { startPreviewServer } from './chunk-
|
|
3
|
-
export { defineConfig, loadConfig } from './chunk-
|
|
2
|
+
export { startPreviewServer } from './chunk-TONYIKCN.js';
|
|
3
|
+
export { clientEnv, defineConfig, loadConfig, loadEnv } from './chunk-QOVBLN7A.js';
|
|
4
4
|
import './chunk-T6RLHSCW.js';
|
|
5
|
-
export { buildProject, reportBuild } from './chunk-
|
|
6
|
-
export { ModuleGraph, detectSelfAccepting, optimizeDeps, scanDependencies, startDevServer } from './chunk-
|
|
7
|
-
export { depFileName } from './chunk-
|
|
8
|
-
import './chunk-
|
|
5
|
+
export { buildManifest, buildProject, chunksFor, prerender, reportBuild } from './chunk-DF67LADH.js';
|
|
6
|
+
export { ModuleGraph, detectSelfAccepting, optimizeDeps, scanDependencies, startDevServer } from './chunk-HS7NGZLM.js';
|
|
7
|
+
export { depFileName, hasGlob, transformGlob } from './chunk-RTWJ5GFB.js';
|
|
8
|
+
import './chunk-7ZB5MAM6.js';
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
// package.json
|
|
3
3
|
var package_default = {
|
|
4
4
|
name: "odoro",
|
|
5
|
-
version: "1.0
|
|
5
|
+
version: "2.1.0",
|
|
6
6
|
type: "module",
|
|
7
7
|
license: "UNLICENSED",
|
|
8
8
|
author: "BouBouw",
|
|
9
|
-
description: "
|
|
9
|
+
description: "Odoro development engine and scaffolder: odoro create, dev, build, preview.",
|
|
10
10
|
engines: {
|
|
11
11
|
node: ">=20"
|
|
12
12
|
},
|
|
@@ -37,16 +37,17 @@ var package_default = {
|
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
scripts: {
|
|
40
|
-
build: "node scripts/versions
|
|
40
|
+
build: "node scripts/family-versions.mjs && tsup",
|
|
41
41
|
dev: "tsup --watch",
|
|
42
42
|
test: "vitest run",
|
|
43
|
-
typecheck: "node scripts/versions
|
|
43
|
+
typecheck: "node scripts/family-versions.mjs && tsc --noEmit",
|
|
44
44
|
prepublishOnly: "pnpm run build",
|
|
45
|
-
"versions:
|
|
45
|
+
"versions:family": "node scripts/family-versions.mjs"
|
|
46
46
|
},
|
|
47
47
|
dependencies: {
|
|
48
48
|
"@babel/core": "^7.29.7",
|
|
49
49
|
"@clack/prompts": "^0.11.0",
|
|
50
|
+
"@odoro-cli/cloud-sdk": "^0.1.0",
|
|
50
51
|
esbuild: "^0.28.2",
|
|
51
52
|
picocolors: "^1.1.1",
|
|
52
53
|
"react-refresh": "^0.18.0"
|
package/dist/registry/index.d.ts
CHANGED
|
@@ -1,46 +1,45 @@
|
|
|
1
1
|
import * as z from 'zod/mini';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Format
|
|
4
|
+
* Format of a registry entry.
|
|
5
5
|
*
|
|
6
|
-
* ##
|
|
6
|
+
* ## Why the schema lives here
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* l'utilisateur.
|
|
8
|
+
* The format is a **contract** between the registry that publishes and the
|
|
9
|
+
* client that downloads. Putting it on the client side is not arbitrary: that
|
|
10
|
+
* is where the validation matters most. The registry validates what it produces
|
|
11
|
+
* before publishing it; the client validates what it receives from a server it
|
|
12
|
+
* does not control, just before writing files into the user project.
|
|
14
13
|
*
|
|
15
|
-
*
|
|
14
|
+
* A single definition, therefore, used at both ends.
|
|
16
15
|
*
|
|
17
|
-
* ##
|
|
16
|
+
* ## The weight of the validation
|
|
18
17
|
*
|
|
19
|
-
*
|
|
18
|
+
* Two decisions, measured rather than assumed.
|
|
20
19
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* The library is **inlined at build time** rather than declared as a
|
|
21
|
+
* dependency: installed, it weighs close to six megabytes, while the surface
|
|
22
|
+
* actually used is a fraction of that.
|
|
24
23
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
24
|
+
* And it is its variant designed for splitting that is used, not its usual API:
|
|
25
|
+
* the first produces thirteen minified kilobytes, the second four hundred and
|
|
26
|
+
* twenty-seven. A factor of thirty-three for the same validation. Writing it is
|
|
27
|
+
* more verbose there — the checks are functions rather than chained methods —
|
|
28
|
+
* but pleading weight for the graphics engine and ignoring it here would be
|
|
29
|
+
* inconsistent.
|
|
31
30
|
*
|
|
32
31
|
* @module
|
|
33
32
|
*/
|
|
34
33
|
|
|
35
|
-
/**
|
|
34
|
+
/** Component categories of the registry. */
|
|
36
35
|
declare const CATEGORIES: readonly ["text", "background", "effect", "hero", "image", "ui", "section", "loader", "hooks"];
|
|
37
|
-
/**
|
|
36
|
+
/** Cost levels of a component. */
|
|
38
37
|
declare const PERF_TIERS: readonly ["light", "medium", "heavy"];
|
|
39
|
-
/**
|
|
38
|
+
/** Declarable graphics backends. */
|
|
40
39
|
declare const GL_BACKENDS: readonly ["ogl", "three"];
|
|
41
|
-
/** Nature
|
|
40
|
+
/** Nature of the visual fallback of a component. */
|
|
42
41
|
declare const FALLBACKS: readonly ["poster", "gradient", "static", "none"];
|
|
43
|
-
/**
|
|
42
|
+
/** Shape of an entry, before the rules that cross several fields. */
|
|
44
43
|
declare const baseSchema: z.ZodMiniObject<{
|
|
45
44
|
name: z.ZodMiniString<string>;
|
|
46
45
|
category: z.ZodMiniEnum<{
|
|
@@ -101,16 +100,16 @@ declare const baseSchema: z.ZodMiniObject<{
|
|
|
101
100
|
}>>;
|
|
102
101
|
}, z.core.$strip>;
|
|
103
102
|
}, z.core.$strip>;
|
|
104
|
-
/**
|
|
103
|
+
/** An entry as it comes out of the validation. */
|
|
105
104
|
type RegistryMeta = z.infer<typeof baseSchema>;
|
|
106
|
-
/**
|
|
105
|
+
/** Entry as it is written in a `meta.json`, before default values. */
|
|
107
106
|
type RegistryMetaInput = z.input<typeof baseSchema>;
|
|
108
107
|
/**
|
|
109
|
-
*
|
|
108
|
+
* Complete description of a registry entry.
|
|
110
109
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
110
|
+
* The rules that cross several fields are checked here rather than in the
|
|
111
|
+
* validation script: they are part of the format, and a third-party registry
|
|
112
|
+
* reusing this schema must be subject to them too.
|
|
114
113
|
*/
|
|
115
114
|
declare const metaSchema: z.ZodMiniObject<{
|
|
116
115
|
name: z.ZodMiniString<string>;
|
|
@@ -172,16 +171,16 @@ declare const metaSchema: z.ZodMiniObject<{
|
|
|
172
171
|
}>>;
|
|
173
172
|
}, z.core.$strip>;
|
|
174
173
|
}, z.core.$strip>;
|
|
175
|
-
/**
|
|
174
|
+
/** Full identifier of an entry, in the form `category/name`. */
|
|
176
175
|
declare function entryId(meta: Pick<RegistryMeta, 'category' | 'name'>): string;
|
|
177
|
-
/**
|
|
176
|
+
/** A published entry, source code inlined. */
|
|
178
177
|
interface PublishedEntry extends RegistryMeta {
|
|
179
|
-
/**
|
|
178
|
+
/** Full identifier. */
|
|
180
179
|
readonly id: string;
|
|
181
|
-
/**
|
|
180
|
+
/** Content of the files, indexed by their path inside the component. */
|
|
182
181
|
readonly sources: Readonly<Record<string, string>>;
|
|
183
182
|
}
|
|
184
|
-
/**
|
|
183
|
+
/** Summary of an entry, as it appears in the index. */
|
|
185
184
|
interface IndexEntry {
|
|
186
185
|
readonly id: string;
|
|
187
186
|
readonly name: string;
|
|
@@ -192,21 +191,21 @@ interface IndexEntry {
|
|
|
192
191
|
readonly backend: false | (typeof GL_BACKENDS)[number];
|
|
193
192
|
readonly registryDependencies: readonly string[];
|
|
194
193
|
}
|
|
195
|
-
/** Index
|
|
194
|
+
/** Index of the registry, served at the root. */
|
|
196
195
|
interface RegistryIndex {
|
|
197
|
-
/** Version
|
|
196
|
+
/** Version of the format, so that the client knows whether it can read it. */
|
|
198
197
|
readonly version: 1;
|
|
199
|
-
/**
|
|
198
|
+
/** Generation date, in ISO 8601. */
|
|
200
199
|
readonly generatedAt: string;
|
|
201
|
-
/**
|
|
200
|
+
/** Summary of each entry, without the source code. */
|
|
202
201
|
readonly entries: readonly IndexEntry[];
|
|
203
202
|
}
|
|
204
203
|
/**
|
|
205
|
-
*
|
|
204
|
+
* Validates an entry and returns readable messages on failure.
|
|
206
205
|
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
206
|
+
* The raw messages are exact but dry: they are reformatted as path plus
|
|
207
|
+
* explanation, so that a component author knows what to fix without having to
|
|
208
|
+
* read the schema.
|
|
210
209
|
*
|
|
211
210
|
* @example
|
|
212
211
|
* const result = parseMeta(JSON.parse(raw), 'text/split-reveal')
|
|
@@ -221,53 +220,53 @@ declare function parseMeta(value: unknown, origin: string): {
|
|
|
221
220
|
};
|
|
222
221
|
|
|
223
222
|
/**
|
|
224
|
-
* Resolution
|
|
223
|
+
* Resolution of the dependency graph of the registry.
|
|
225
224
|
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
225
|
+
* An entry may require others — a shared hook, a utility. Before writing
|
|
226
|
+
* anything into the user project, we therefore have to know exactly which
|
|
227
|
+
* entries to install and in what order.
|
|
229
228
|
*
|
|
230
|
-
* ##
|
|
229
|
+
* ## The cycles
|
|
231
230
|
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
231
|
+
* Nothing structurally forbids two entries from requiring each other, and a
|
|
232
|
+
* naive walk would get lost in them forever. The cycle is therefore detected,
|
|
233
|
+
* and **reported with the path that makes it up**: an error that says only
|
|
234
|
+
* "cycle detected" forces you to look for it by hand.
|
|
236
235
|
*
|
|
237
|
-
* ##
|
|
236
|
+
* ## The order
|
|
238
237
|
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
238
|
+
* The dependencies are installed before what requires them. That does not
|
|
239
|
+
* matter for writing files, which is independent, but it does matter for what
|
|
240
|
+
* the user sees scrolling by: a list where the dependencies appear after their
|
|
241
|
+
* consumer reads like an error.
|
|
243
242
|
*
|
|
244
243
|
* @module
|
|
245
244
|
*/
|
|
246
245
|
|
|
247
|
-
/**
|
|
246
|
+
/** What has to be known about an entry to resolve the graph. */
|
|
248
247
|
interface ResolvableEntry {
|
|
249
|
-
/**
|
|
248
|
+
/** Full identifier, in the form `category/name`. */
|
|
250
249
|
readonly id: string;
|
|
251
|
-
/**
|
|
250
|
+
/** Entries required by this one. */
|
|
252
251
|
readonly registryDependencies: readonly string[];
|
|
253
252
|
}
|
|
254
|
-
/**
|
|
253
|
+
/** Result of a successful resolution. */
|
|
255
254
|
interface ResolvedGraph {
|
|
256
|
-
/**
|
|
255
|
+
/** Entries to install, dependencies first. */
|
|
257
256
|
readonly order: readonly string[];
|
|
258
|
-
/**
|
|
257
|
+
/** Entries added that had not been asked for. */
|
|
259
258
|
readonly implied: readonly string[];
|
|
260
259
|
}
|
|
261
|
-
/**
|
|
260
|
+
/** What prevented the resolution. */
|
|
262
261
|
type ResolutionProblem = {
|
|
263
|
-
readonly kind: '
|
|
262
|
+
readonly kind: 'missing';
|
|
264
263
|
readonly id: string;
|
|
265
264
|
readonly requiredBy: string | null;
|
|
266
265
|
} | {
|
|
267
266
|
readonly kind: 'cycle';
|
|
268
267
|
readonly path: readonly string[];
|
|
269
268
|
};
|
|
270
|
-
/**
|
|
269
|
+
/** Result of a resolution. */
|
|
271
270
|
type ResolutionResult = {
|
|
272
271
|
readonly ok: true;
|
|
273
272
|
readonly graph: ResolvedGraph;
|
|
@@ -276,18 +275,18 @@ type ResolutionResult = {
|
|
|
276
275
|
readonly problems: readonly ResolutionProblem[];
|
|
277
276
|
};
|
|
278
277
|
/**
|
|
279
|
-
*
|
|
278
|
+
* Turns a resolution problem into a readable sentence.
|
|
280
279
|
*
|
|
281
280
|
* @example
|
|
282
281
|
* describeProblem({ kind: 'cycle', path: ['a', 'b', 'a'] })
|
|
283
|
-
* // '
|
|
282
|
+
* // 'Dependency cycle: a → b → a'
|
|
284
283
|
*/
|
|
285
284
|
declare function describeProblem(problem: ResolutionProblem): string;
|
|
286
285
|
/**
|
|
287
|
-
*
|
|
286
|
+
* Resolves the dependencies of a set of requested entries.
|
|
288
287
|
*
|
|
289
|
-
* @param requested
|
|
290
|
-
* @param available
|
|
288
|
+
* @param requested Identifiers requested by the user.
|
|
289
|
+
* @param available Every known entry, indexed by identifier.
|
|
291
290
|
*
|
|
292
291
|
* @example
|
|
293
292
|
* const result = resolveGraph(['hero/canopy'], catalogue)
|
|
@@ -295,10 +294,10 @@ declare function describeProblem(problem: ResolutionProblem): string;
|
|
|
295
294
|
*/
|
|
296
295
|
declare function resolveGraph(requested: readonly string[], available: ReadonlyMap<string, ResolvableEntry>): ResolutionResult;
|
|
297
296
|
/**
|
|
298
|
-
*
|
|
297
|
+
* Checks the integrity of a whole catalogue.
|
|
299
298
|
*
|
|
300
|
-
*
|
|
301
|
-
*
|
|
299
|
+
* Typical use: the validation of the registry before publication, where every
|
|
300
|
+
* entry is resolved at once rather than one by one.
|
|
302
301
|
*
|
|
303
302
|
* @example
|
|
304
303
|
* const problems = validateCatalogue(catalogue)
|
|
@@ -306,7 +305,7 @@ declare function resolveGraph(requested: readonly string[], available: ReadonlyM
|
|
|
306
305
|
*/
|
|
307
306
|
declare function validateCatalogue(available: ReadonlyMap<string, ResolvableEntry>): readonly ResolutionProblem[];
|
|
308
307
|
/**
|
|
309
|
-
*
|
|
308
|
+
* Builds a catalogue from complete entries.
|
|
310
309
|
*
|
|
311
310
|
* @example
|
|
312
311
|
* const catalogue = toCatalogue(metas)
|
package/dist/registry/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { CATEGORIES, FALLBACKS, GL_BACKENDS, PERF_TIERS, describeProblem, entryId, metaSchema, parseMeta, resolveGraph, toCatalogue, validateCatalogue } from '../chunk-
|
|
2
|
+
export { CATEGORIES, FALLBACKS, GL_BACKENDS, PERF_TIERS, describeProblem, entryId, metaSchema, parseMeta, resolveGraph, toCatalogue, validateCatalogue } from '../chunk-4D56Z7G3.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { extractEntries, injectClient, startDevServer } from './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import './chunk-
|
|
2
|
+
export { extractEntries, injectClient, startDevServer } from './chunk-HS7NGZLM.js';
|
|
3
|
+
import './chunk-RTWJ5GFB.js';
|
|
4
|
+
import './chunk-7ZB5MAM6.js';
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "odoro",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "BouBouw",
|
|
7
|
-
"description": "
|
|
7
|
+
"description": "Odoro development engine and scaffolder: odoro create, dev, build, preview.",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=20"
|
|
10
10
|
},
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@babel/core": "^7.29.7",
|
|
39
39
|
"@clack/prompts": "^0.11.0",
|
|
40
|
+
"@odoro-cli/cloud-sdk": "^0.1.0",
|
|
40
41
|
"esbuild": "^0.28.2",
|
|
41
42
|
"picocolors": "^1.1.1",
|
|
42
43
|
"react-refresh": "^0.18.0"
|
|
@@ -59,10 +60,10 @@
|
|
|
59
60
|
"url": "https://github.com/ODORO-CLI/OdoroKit/issues"
|
|
60
61
|
},
|
|
61
62
|
"scripts": {
|
|
62
|
-
"build": "node scripts/versions
|
|
63
|
+
"build": "node scripts/family-versions.mjs && tsup",
|
|
63
64
|
"dev": "tsup --watch",
|
|
64
65
|
"test": "vitest run",
|
|
65
|
-
"typecheck": "node scripts/versions
|
|
66
|
-
"versions:
|
|
66
|
+
"typecheck": "node scripts/family-versions.mjs && tsc --noEmit",
|
|
67
|
+
"versions:family": "node scripts/family-versions.mjs"
|
|
67
68
|
}
|
|
68
69
|
}
|
|
@@ -1,52 +1,88 @@
|
|
|
1
|
-
# Odoro — application
|
|
1
|
+
# Odoro — single-page application
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Project generated by `odoro create`. The router, the motion engine, the style
|
|
4
|
+
system and the interface components all come from `@odoro-cli/libs`; the
|
|
5
|
+
development server and the build come from the `odoro` engine.
|
|
6
6
|
|
|
7
7
|
## Structure
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
index.html Document
|
|
11
|
-
|
|
12
|
-
odoro.config.ts
|
|
13
|
-
|
|
10
|
+
index.html Document and entry point: the <script type="module"> tag
|
|
11
|
+
names the file to build.
|
|
12
|
+
odoro.config.ts Engine configuration: aliases, port, proxy, build.
|
|
13
|
+
.env.example The expected variables. Copy to `.env`, never committed.
|
|
14
|
+
public/ Files copied as-is to the root of the site.
|
|
14
15
|
src/
|
|
15
|
-
main.tsx
|
|
16
|
-
App.tsx
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
main.tsx React mounting and stylesheet imports.
|
|
17
|
+
App.tsx The whole page: nav, sections, footer.
|
|
18
|
+
router.tsx The route table — the only file that names the router.
|
|
19
|
+
entry-server.tsx Prerendering: which routes, and what they put in the head.
|
|
20
|
+
background.tsx The decorative background — the only piece tied to the
|
|
21
|
+
graphics engine.
|
|
22
|
+
styles.css Project styles and token overrides.
|
|
23
|
+
odoro-env.d.ts Ambient types (import.meta.env, asset imports).
|
|
20
24
|
```
|
|
21
25
|
|
|
22
26
|
## Scripts
|
|
23
27
|
|
|
24
|
-
|
|
|
25
|
-
| ----------- |
|
|
26
|
-
| `dev` |
|
|
27
|
-
| `build` |
|
|
28
|
-
| `preview` |
|
|
29
|
-
| `typecheck` |
|
|
28
|
+
| Command | Effect |
|
|
29
|
+
| ----------- | ----------------------------------------------- |
|
|
30
|
+
| `dev` | Development server with hot reloading. |
|
|
31
|
+
| `build` | Production build into `dist/`. |
|
|
32
|
+
| `preview` | Serves `dist/` the way a static host would. |
|
|
33
|
+
| `typecheck` | Type checking, without emitting. |
|
|
30
34
|
|
|
31
|
-
##
|
|
35
|
+
## Environment variables
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
Copy `.env.example` to `.env`. The files are read from the least specific to
|
|
38
|
+
the most specific — `.env`, `.env.local`, `.env.<mode>`, `.env.<mode>.local` —
|
|
39
|
+
and a variable already set in the environment is never overwritten by a file:
|
|
40
|
+
whatever your host injects wins.
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
**Only variables prefixed with `ODORO_` reach the browser**, through
|
|
43
|
+
`import.meta.env`. Anyone who opens the site can then read them. Everything
|
|
44
|
+
else stays on the machine.
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
```ts
|
|
47
|
+
const api = import.meta.env.ODORO_API
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`odoro build --mode staging` reads `.env.staging` and fills in
|
|
51
|
+
`import.meta.env.MODE`.
|
|
52
|
+
|
|
53
|
+
## Prerendering
|
|
54
|
+
|
|
55
|
+
`build.prerender` is on: `odoro build` renders every route of
|
|
56
|
+
`src/entry-server.tsx` as a complete HTML document, and `main.tsx` hydrates it
|
|
57
|
+
on load rather than rebuilding everything.
|
|
58
|
+
|
|
59
|
+
That is what lets a search engine, a link preview or a screen reader find text
|
|
60
|
+
in the very first response. `/about` becomes `dist/about/index.html`, which any
|
|
61
|
+
static host serves with no configuration — nothing runs in production.
|
|
62
|
+
|
|
63
|
+
Adding a route: one line in `routes`, and the matching entry in
|
|
64
|
+
`src/router.tsx`. Doing without: remove `prerender` from `odoro.config.ts`,
|
|
65
|
+
then delete `src/entry-server.tsx`.
|
|
66
|
+
|
|
67
|
+
## Customising
|
|
68
|
+
|
|
69
|
+
Every visual value goes through a CSS variable. Overriding
|
|
70
|
+
`--o-palette-brand-600` in `src/styles.css` rethemes the application **and**
|
|
71
|
+
the library components, without touching their code.
|
|
72
|
+
|
|
73
|
+
A single stylesheet: `@odoro-cli/libs/styles.css`, imported once at the root of
|
|
74
|
+
the application.
|
|
75
|
+
|
|
76
|
+
It carries only the base — variables, preflight, animations. The utilities are
|
|
77
|
+
produced at build time, for the classes your code actually uses: a few tens of
|
|
78
|
+
kilobytes in practice, with the whole palette available and nothing weighing it
|
|
79
|
+
down.
|
|
44
80
|
|
|
45
|
-
##
|
|
81
|
+
## Hot reloading
|
|
46
82
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
83
|
+
Editing a component swaps its code without unmounting the tree: the value of a
|
|
84
|
+
counter, the text typed into a field, the open tab all survive the edit. A
|
|
85
|
+
stylesheet is swapped with no reload at all.
|
|
50
86
|
|
|
51
|
-
|
|
52
|
-
correct
|
|
87
|
+
A module that exports more than components reloads the page, and that is
|
|
88
|
+
correct: nothing would let its change propagate safely.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Variables prefixed with ODORO_ go into the published bundle: anyone who opens
|
|
2
|
+
# the site can read them. Everything else — tokens, server-side API keys — stays
|
|
3
|
+
# on the machine, readable by the commands and by the back end.
|
|
4
|
+
#
|
|
5
|
+
# Copy this file to `.env` (ignored by git) and fill in what you need.
|
|
6
|
+
# `.env.production` only applies to `odoro build`, `.env.development` only to
|
|
7
|
+
# `odoro dev`.
|
|
8
|
+
|
|
9
|
+
ODORO_API=http://localhost:3001
|