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.
Files changed (88) hide show
  1. package/README.md +94 -0
  2. package/client.d.ts +90 -16
  3. package/dist/build-XJIP4GNT.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-DF67LADH.js +735 -0
  7. package/dist/{chunk-LHZGX5ML.js → chunk-HS7NGZLM.js} +307 -196
  8. package/dist/chunk-LIKVHWB4.js +231 -0
  9. package/dist/chunk-QOVBLN7A.js +241 -0
  10. package/dist/chunk-RTWJ5GFB.js +729 -0
  11. package/dist/chunk-TONYIKCN.js +57 -0
  12. package/dist/cli.d.ts +12 -13
  13. package/dist/cli.js +86 -63
  14. package/dist/{commands-AHMXBWQQ.js → commands-GYA7NTCX.js} +124 -124
  15. package/dist/commands-UOWN3IK4.js +181 -0
  16. package/dist/{create-CYVSVDAD.js → create-B2TLV6XI.js} +198 -160
  17. package/dist/index.d.ts +603 -151
  18. package/dist/index.js +6 -6
  19. package/dist/{package-EIDLKAA6.js → package-3ZJOEXM4.js} +6 -5
  20. package/dist/preview-3IRG7MHV.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-ZB3P3EGS.js} +3 -3
  24. package/package.json +6 -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-3SZIN6VG.js +0 -64
  74. package/dist/chunk-DL3NPC4H.js +0 -113
  75. package/dist/chunk-TQUJ3MFS.js +0 -268
  76. package/dist/chunk-ZVL7EXJO.js +0 -66
  77. package/dist/commands-4JRBD55Z.js +0 -245
  78. package/dist/preview-7DKEAQOQ.js +0 -4
  79. package/templates/react-ts/_variantes/avec-moteur/src/fond.tsx +0 -118
  80. package/templates/react-ts/_variantes/sans-libs/src/App.tsx +0 -382
  81. package/templates/react-ts/_variantes/sans-libs/src/fond.tsx +0 -23
  82. package/templates/react-ts/_variantes/sans-libs/src/main.tsx +0 -17
  83. package/templates/react-ts/src/fond.tsx +0 -66
  84. package/templates/react-ts-server/_variantes/avec-moteur/client/src/fond.tsx +0 -118
  85. package/templates/react-ts-server/_variantes/sans-libs/client/src/App.tsx +0 -382
  86. package/templates/react-ts-server/_variantes/sans-libs/client/src/fond.tsx +0 -23
  87. package/templates/react-ts-server/_variantes/sans-libs/client/src/main.tsx +0 -17
  88. package/templates/react-ts-server/client/src/fond.tsx +0 -66
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { writeDatabaseUrl, assertEnvIgnored, PROVIDER_PENDING, checkDatabaseUrl } from './chunk-3SZIN6VG.js';
2
+ import { writeDatabaseUrl, assertEnvIgnored, PROVIDER_PENDING, checkDatabaseUrl, loadSdk, ensureToken, DEFAULT_API_URL, cancelled, chooseEnvironment, chooseRegion, provision } from './chunk-LIKVHWB4.js';
3
3
  import { execSync, spawn } from 'child_process';
4
4
  import { existsSync, statSync, readdirSync, readFileSync } from 'fs';
5
5
  import { resolve, basename, dirname, join } from 'path';
@@ -14,86 +14,86 @@ var MODULES = [
14
14
  id: "libs",
15
15
  label: "Libraries",
16
16
  hint: "styles, tokens, UI and motion",
17
- defaut: true,
18
- paquet: "@odoro-cli/libs"
17
+ ticked: true,
18
+ packageName: "@odoro-cli/libs"
19
19
  },
20
20
  {
21
21
  id: "router",
22
22
  label: "Router",
23
23
  hint: "ships with the libraries \u2014 wires up the pages",
24
- defaut: true
24
+ ticked: true
25
25
  },
26
26
  {
27
27
  id: "icons",
28
28
  label: "Icons",
29
29
  hint: "five families, imported one by one",
30
- defaut: true,
31
- paquet: "@odoro-cli/icons"
30
+ ticked: true,
31
+ packageName: "@odoro-cli/icons"
32
32
  },
33
33
  {
34
34
  id: "engine",
35
35
  label: "Engine",
36
36
  hint: "WebGL, surfaces and motion policy",
37
- defaut: false,
38
- paquet: "@odoro-cli/engine"
37
+ ticked: false,
38
+ packageName: "@odoro-cli/engine"
39
39
  },
40
40
  {
41
41
  id: "registre",
42
42
  label: "Component registry",
43
43
  hint: "copied by `odoro add` \u2014 pulls in the engine",
44
- defaut: false
44
+ ticked: false
45
45
  }
46
46
  ];
47
- var MODULE_IDS = MODULES.map((m) => m.id);
48
- var MODULES_PAR_DEFAUT = MODULES.filter(
49
- (m) => m.defaut
50
- ).map((m) => m.id);
51
- function resoudre(selection) {
52
- const choisis = new Set(selection);
53
- const avertissements = [];
54
- if (choisis.has("router") && !choisis.has("libs")) {
55
- choisis.delete("router");
56
- avertissements.push(
47
+ var MODULE_IDS = MODULES.map((module) => module.id);
48
+ var DEFAULT_MODULES = MODULES.filter(
49
+ (module) => module.ticked
50
+ ).map((module) => module.id);
51
+ function resolveModules(selection) {
52
+ const chosen = new Set(selection);
53
+ const warnings = [];
54
+ if (chosen.has("router") && !chosen.has("libs")) {
55
+ chosen.delete("router");
56
+ warnings.push(
57
57
  "The router lives in the libraries (@odoro-cli/libs/router) \u2014 without them it is dropped."
58
58
  );
59
59
  }
60
- if (choisis.has("registre") && !choisis.has("engine")) {
61
- choisis.add("engine");
62
- avertissements.push(
60
+ if (chosen.has("registre") && !chosen.has("engine")) {
61
+ chosen.add("engine");
62
+ warnings.push(
63
63
  "Almost every registry entry imports @odoro-cli/engine, so the engine was added."
64
64
  );
65
65
  }
66
- return { modules: MODULE_IDS.filter((id) => choisis.has(id)), avertissements };
66
+ return { modules: MODULE_IDS.filter((id) => chosen.has(id)), warnings };
67
67
  }
68
- function paquetsDe(modules) {
69
- const choisis = new Set(modules);
70
- return MODULES.filter((m) => m.paquet !== void 0 && choisis.has(m.id)).map(
71
- (m) => m.paquet
72
- );
68
+ function packagesFor(modules) {
69
+ const chosen = new Set(modules);
70
+ return MODULES.filter(
71
+ (module) => module.packageName !== void 0 && chosen.has(module.id)
72
+ ).map((module) => module.packageName);
73
73
  }
74
- function variantesDe(modules) {
75
- const choisis = new Set(modules);
76
- const variantes = [];
77
- if (!choisis.has("libs")) variantes.push("sans-libs");
78
- else if (!choisis.has("router")) variantes.push("sans-routeur");
79
- if (choisis.has("engine")) variantes.push("avec-moteur");
80
- return variantes;
74
+ function variantsFor(modules) {
75
+ const chosen = new Set(modules);
76
+ const variants = [];
77
+ if (!chosen.has("libs")) variants.push("without-libs");
78
+ else if (!chosen.has("router")) variants.push("without-router");
79
+ if (chosen.has("engine")) variants.push("with-engine");
80
+ return variants;
81
81
  }
82
- function gardeLesRoutes(modules) {
82
+ function keepsRoutes(modules) {
83
83
  return modules.includes("router");
84
84
  }
85
- function lireModules(valeur) {
86
- const brut = valeur.split(",").map((part) => part.trim()).filter((part) => part !== "");
87
- if (brut.length === 1 && (brut[0] === "none" || brut[0] === "aucun")) {
85
+ function readModules(value) {
86
+ const raw = value.split(",").map((part) => part.trim()).filter((part) => part !== "");
87
+ if (raw.length === 1 && (raw[0] === "none" || raw[0] === "aucun")) {
88
88
  return { modules: [] };
89
89
  }
90
- const inconnu = brut.find((part) => !MODULE_IDS.includes(part));
91
- if (inconnu !== void 0) {
90
+ const unknown = raw.find((part) => !MODULE_IDS.includes(part));
91
+ if (unknown !== void 0) {
92
92
  return {
93
- erreur: `Unknown module: "${inconnu}". Available: ${MODULE_IDS.join(", ")}, or "none".`
93
+ error: `Unknown module: "${unknown}". Available: ${MODULE_IDS.join(", ")}, or "none".`
94
94
  };
95
95
  }
96
- return { modules: brut };
96
+ return { modules: raw };
97
97
  }
98
98
  var PACKAGE_MANAGERS = ["pnpm", "npm", "yarn", "bun"];
99
99
  function detectPackageManager(userAgent = process.env["npm_config_user_agent"]) {
@@ -111,18 +111,18 @@ function toPackageName(input) {
111
111
  return input.trim().toLowerCase().replace(/^[._]+/, "").replace(/[^a-z0-9\-~]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 214) || "odoro-app";
112
112
  }
113
113
  function validatePackageName(name) {
114
- if (name.trim() === "") return "Le nom du projet ne peut pas etre vide.";
115
- if (name.length > 214) return "Le nom du projet ne peut pas depasser 214 caracteres.";
116
- if (/^[._]/.test(name)) return 'Le nom du projet ne peut pas commencer par "." ou "_".';
114
+ if (name.trim() === "") return "The project name cannot be empty.";
115
+ if (name.length > 214) return "The project name cannot exceed 214 characters.";
116
+ if (/^[._]/.test(name)) return 'The project name cannot start with "." or "_".';
117
117
  if (!/^[a-z0-9\-~][a-z0-9\-._~]*$/.test(name)) {
118
- return "Le nom doit etre en minuscules, sans espace ni caractere special.";
118
+ return "The name must be lowercase, without spaces or special characters.";
119
119
  }
120
120
  return void 0;
121
121
  }
122
122
  function inspectTarget(directory) {
123
123
  if (!existsSync(directory)) return "absent";
124
124
  const entries = readdirSync(directory).filter((entry) => entry !== ".git");
125
- return entries.length === 0 ? "vide" : "occupe";
125
+ return entries.length === 0 ? "empty" : "occupied";
126
126
  }
127
127
  function targetFileName(name) {
128
128
  return name.startsWith("_") ? `.${name.slice(1)}` : name;
@@ -136,29 +136,29 @@ function templatesRoot(from = fileURLToPath(import.meta.url)) {
136
136
  if (parent === directory) break;
137
137
  directory = parent;
138
138
  }
139
- throw new Error("[odoro] Dossier des templates introuvable depuis " + from);
139
+ throw new Error("[odoro] Templates directory not found from " + from);
140
140
  }
141
141
  function availableTemplates(root = templatesRoot()) {
142
142
  return readdirSync(root).filter((entry) => statSync(resolve(root, entry)).isDirectory()).sort();
143
143
  }
144
144
 
145
- // src/scaffold/versions-famille.generated.ts
146
- var VERSIONS_FAMILLE = {
147
- "@odoro-cli/engine": "1.0.2",
148
- "@odoro-cli/icons": "1.0.2",
149
- "@odoro-cli/libs": "1.0.2",
150
- "@odoro-cli/server": "1.0.2",
151
- "create-odoro": "1.0.9",
152
- "odoro": "1.0.9"
145
+ // src/scaffold/family-versions.generated.ts
146
+ var FAMILY_VERSIONS = {
147
+ "@odoro-cli/engine": "2.0.0",
148
+ "@odoro-cli/icons": "2.0.0",
149
+ "@odoro-cli/libs": "2.1.0",
150
+ "@odoro-cli/server": "1.1.0",
151
+ "create-odoro": "1.0.11",
152
+ "odoro": "2.1.0"
153
153
  };
154
154
 
155
155
  // src/scaffold/scaffold.ts
156
- var DOSSIER_VARIANTES = "_variantes";
157
- var PAQUETS_OPTIONNELS = ["@odoro-cli/libs", "@odoro-cli/icons", "@odoro-cli/engine"];
156
+ var VARIANTS_DIRECTORY = "_variants";
157
+ var OPTIONAL_PACKAGES = ["@odoro-cli/libs", "@odoro-cli/icons", "@odoro-cli/engine"];
158
158
  function cliVersion() {
159
159
  try {
160
- const manifeste = join(dirname(templatesRoot()), "package.json");
161
- const { version } = JSON.parse(readFileSync(manifeste, "utf8"));
160
+ const manifest = join(dirname(templatesRoot()), "package.json");
161
+ const { version } = JSON.parse(readFileSync(manifest, "utf8"));
162
162
  return version;
163
163
  } catch {
164
164
  return "latest";
@@ -167,7 +167,7 @@ function cliVersion() {
167
167
  async function copyDirectory(from, to, written, prefix = "") {
168
168
  await mkdir(to, { recursive: true });
169
169
  for (const entry of await readdir(from, { withFileTypes: true })) {
170
- if (prefix === "" && entry.name === DOSSIER_VARIANTES) continue;
170
+ if (prefix === "" && entry.name === VARIANTS_DIRECTORY) continue;
171
171
  const source = join(from, entry.name);
172
172
  const name = targetFileName(entry.name);
173
173
  const destination = join(to, name);
@@ -183,11 +183,11 @@ async function copyDirectory(from, to, written, prefix = "") {
183
183
  function isOdoroPackage(name) {
184
184
  return name === "odoro" || name.startsWith("@odoro-cli/");
185
185
  }
186
- function versionDemandee(nom, versionCli2) {
187
- if (versionCli2 === "latest") return "latest";
188
- if (nom === "odoro") return `^${versionCli2}`;
189
- const relevee = VERSIONS_FAMILLE[nom];
190
- return relevee === void 0 ? "latest" : `^${relevee}`;
186
+ function requestedVersion(name, cli) {
187
+ if (cli === "latest") return "latest";
188
+ if (name === "odoro") return `^${cli}`;
189
+ const collected = FAMILY_VERSIONS[name];
190
+ return collected === void 0 ? "latest" : `^${collected}`;
191
191
  }
192
192
  function alignOdoroVersions(manifest, version) {
193
193
  const aligned = { ...manifest };
@@ -196,18 +196,18 @@ function alignOdoroVersions(manifest, version) {
196
196
  if (typeof deps !== "object" || deps === null) continue;
197
197
  const next = {};
198
198
  for (const [name, range] of Object.entries(deps)) {
199
- next[name] = isOdoroPackage(name) ? versionDemandee(name, version) : range;
199
+ next[name] = isOdoroPackage(name) ? requestedVersion(name, version) : range;
200
200
  }
201
201
  aligned[field] = next;
202
202
  }
203
203
  return aligned;
204
204
  }
205
- function ajusterModules(manifest, modules) {
206
- const voulus = new Set(paquetsDe(modules));
205
+ function adjustModules(manifest, modules) {
206
+ const wanted = new Set(packagesFor(modules));
207
207
  const deps = { ...manifest["dependencies"] ?? {} };
208
- for (const paquet of PAQUETS_OPTIONNELS) {
209
- if (voulus.has(paquet)) deps[paquet] ??= "latest";
210
- else delete deps[paquet];
208
+ for (const packageName of OPTIONAL_PACKAGES) {
209
+ if (wanted.has(packageName)) deps[packageName] ??= "latest";
210
+ else delete deps[packageName];
211
211
  }
212
212
  return {
213
213
  ...manifest,
@@ -216,21 +216,21 @@ function ajusterModules(manifest, modules) {
216
216
  )
217
217
  };
218
218
  }
219
- async function poserVariante(source, target, nom) {
220
- const racine = join(source, DOSSIER_VARIANTES, nom);
221
- if (!existsSync(racine)) {
222
- throw new Error(`[odoro] Variante de gabarit introuvable : "${nom}".`);
219
+ async function layVariant(source, target, name) {
220
+ const root = join(source, VARIANTS_DIRECTORY, name);
221
+ if (!existsSync(root)) {
222
+ throw new Error(`[odoro] Template variant not found: "${name}".`);
223
223
  }
224
- const poses = [];
225
- await copyDirectory(racine, target, poses);
226
- return poses;
224
+ const laid = [];
225
+ await copyDirectory(root, target, laid);
226
+ return laid;
227
227
  }
228
228
  async function renamePackage(target, packageName, version, modules) {
229
229
  const file = join(target, "package.json");
230
230
  if (!existsSync(file)) return;
231
231
  const manifest = JSON.parse(await readFile(file, "utf8"));
232
- const ajuste = ajusterModules({ ...manifest, name: packageName }, modules);
233
- const renamed = alignOdoroVersions(ajuste, version);
232
+ const adjusted = adjustModules({ ...manifest, name: packageName }, modules);
233
+ const renamed = alignOdoroVersions(adjusted, version);
234
234
  await writeFile(file, `${JSON.stringify(renamed, null, 2)}
235
235
  `, "utf8");
236
236
  }
@@ -238,7 +238,7 @@ async function scaffold(options) {
238
238
  const root = options.root ?? templatesRoot();
239
239
  const source = join(root, options.template);
240
240
  if (!existsSync(source)) {
241
- throw new Error(`[odoro] Template inconnu : "${options.template}".`);
241
+ throw new Error(`[odoro] Unknown template: "${options.template}".`);
242
242
  }
243
243
  if (options.overwrite === "ecraser" && existsSync(options.target)) {
244
244
  for (const entry of await readdir(options.target)) {
@@ -246,17 +246,17 @@ async function scaffold(options) {
246
246
  await rm(join(options.target, entry), { recursive: true, force: true });
247
247
  }
248
248
  }
249
- const modules = options.modules ?? MODULES_PAR_DEFAUT;
249
+ const modules = options.modules ?? DEFAULT_MODULES;
250
250
  const files = [];
251
251
  await copyDirectory(source, options.target, files);
252
- if (!gardeLesRoutes(modules)) {
253
- for (const fichier of ["src/router.tsx", "client/src/router.tsx"]) {
254
- await rm(join(options.target, fichier), { force: true });
252
+ if (!keepsRoutes(modules)) {
253
+ for (const file of ["src/router.tsx", "client/src/router.tsx"]) {
254
+ await rm(join(options.target, file), { force: true });
255
255
  }
256
256
  }
257
- const poses = [];
258
- for (const variante of variantesDe(modules)) {
259
- poses.push(...await poserVariante(source, options.target, variante));
257
+ const laid = [];
258
+ for (const variant of variantsFor(modules)) {
259
+ laid.push(...await layVariant(source, options.target, variant));
260
260
  }
261
261
  await renamePackage(
262
262
  options.target,
@@ -264,131 +264,169 @@ async function scaffold(options) {
264
264
  options.version ?? cliVersion(),
265
265
  modules
266
266
  );
267
- const retires = /* @__PURE__ */ new Set(["src/router.tsx", "client/src/router.tsx"]);
268
- const listes = /* @__PURE__ */ new Set([
269
- ...files.filter((f) => gardeLesRoutes(modules) || !retires.has(f)),
270
- ...poses
267
+ const removed = /* @__PURE__ */ new Set(["src/router.tsx", "client/src/router.tsx"]);
268
+ const listed = /* @__PURE__ */ new Set([
269
+ ...files.filter((file) => keepsRoutes(modules) || !removed.has(file)),
270
+ ...laid
271
271
  ]);
272
- return { files: [...listes].sort() };
272
+ return { files: [...listed].sort() };
273
273
  }
274
274
 
275
275
  // src/commands/create.ts
276
- var DERNIERES_LIGNES = 8;
277
- var LARGEUR_LIGNE = 64;
276
+ var LAST_LINES = 8;
277
+ var LINE_WIDTH = 64;
278
278
  var TEMPLATE_LABELS = {
279
279
  "react-ts": "Single-page app \u2014 React, TypeScript, Odoro router and motion",
280
280
  "react-ts-server": "Client and server \u2014 the same app, plus a modular @odoro-cli/server base and a Dockerfile"
281
281
  };
282
- async function askDatabase() {
282
+ async function provisionOnPlatform(projectName) {
283
+ const load = await loadSdk();
284
+ if (!load.ok) {
285
+ prompts.log.warn(load.reason);
286
+ return void 0;
287
+ }
288
+ const token = await ensureToken(prompts, DEFAULT_API_URL);
289
+ if (cancelled(token)) return void 0;
290
+ const client = load.sdk.createClient({ baseUrl: DEFAULT_API_URL, token });
291
+ const environment = await chooseEnvironment(prompts, client);
292
+ if (cancelled(environment) || environment === void 0) return void 0;
293
+ const region = await chooseRegion(prompts, client);
294
+ if (cancelled(region)) return void 0;
295
+ const spinner2 = prompts.spinner();
296
+ spinner2.start(`Provisioning in ${region ?? "the default region"}`);
297
+ const result = await provision({
298
+ client,
299
+ environmentId: environment.id,
300
+ ...region === void 0 ? {} : { region },
301
+ name: projectName
302
+ });
303
+ if (!result.ok) {
304
+ spinner2.stop("Provisioning did not finish");
305
+ prompts.log.warn(result.reason);
306
+ return void 0;
307
+ }
308
+ spinner2.stop(`Database ready in ${environment.label}`);
309
+ return {
310
+ choice: "provider",
311
+ url: result.connectionString,
312
+ note: `Database provisioned on ${environment.label}. DATABASE_URL is in .env \u2014 do not commit it.`
313
+ };
314
+ }
315
+ async function askDatabase(projectName) {
283
316
  const choice = ensure(
284
317
  await prompts.select({
285
318
  message: "Database",
286
- initialValue: "url",
319
+ initialValue: "provider",
287
320
  options: [
288
321
  {
289
322
  value: "provider",
290
323
  label: "Odoro provider",
291
- hint: "automatic provisioning \u2014 coming soon"
324
+ hint: "provisioned now, PostgreSQL, region of your choosing"
292
325
  },
293
326
  {
294
327
  value: "url",
295
328
  label: "Existing PostgreSQL URL",
296
- hint: "Neon, Supabase, RDS, your own"
329
+ hint: "bring your own"
297
330
  },
298
331
  { value: "later", label: "Set up later", hint: ".env.example only" }
299
332
  ]
300
333
  })
301
334
  );
302
335
  if (choice === "provider") {
303
- prompts.log.warn(PROVIDER_PENDING);
304
- return { choice, note: "Lancez `odoro db:create` des que la plateforme est la." };
336
+ const provisioned = await provisionOnPlatform(projectName);
337
+ if (provisioned !== void 0) return provisioned;
338
+ return { choice, note: PROVIDER_PENDING };
305
339
  }
306
340
  if (choice === "later") {
307
341
  return {
308
342
  choice,
309
- note: "Aucune base : le client demarrera, et /api/ready repondra 503 en disant ce qui manque."
343
+ note: "No database: the client will start, and /api/ready will answer 503 saying what is missing."
310
344
  };
311
345
  }
312
346
  const url = ensure(
313
347
  await prompts.text({
314
348
  message: "PostgreSQL URL",
315
- placeholder: "postgres://utilisateur:motdepasse@hote:5432/base?sslmode=require",
349
+ placeholder: "postgres://user:password@host:5432/database?sslmode=require",
316
350
  validate: (value) => checkDatabaseUrl(value ?? "")
317
351
  })
318
352
  );
319
353
  return {
320
354
  choice,
321
355
  url: url.trim(),
322
- // Seule la forme a ete verifiee : le dire, plutot que de laisser croire
323
- // que la connexion a ete etablie.
324
- note: "Forme de l URL verifiee. La connexion sera etablie au premier demarrage."
356
+ // Only the shape was checked: say so, rather than letting one believe the
357
+ // connection was established.
358
+ note: "URL shape checked. The connection will be established on the first start."
325
359
  };
326
360
  }
327
361
  async function askModules(options) {
328
362
  if (options.modules !== void 0) {
329
- const lu = lireModules(options.modules);
330
- if (lu.erreur !== void 0) {
331
- prompts.cancel(lu.erreur);
363
+ const read = readModules(options.modules);
364
+ if (read.error !== void 0) {
365
+ prompts.cancel(read.error);
332
366
  return void 0;
333
367
  }
334
- return annoncer(resoudre(lu.modules));
368
+ return announce(resolveModules(read.modules));
335
369
  }
336
- if (options.yes === true) return MODULES_PAR_DEFAUT;
337
- const choisis = ensure(
370
+ if (options.yes === true) return DEFAULT_MODULES;
371
+ const chosen = ensure(
338
372
  await prompts.multiselect({
339
373
  message: "What goes in the project?",
340
- initialValues: [...MODULES_PAR_DEFAUT],
374
+ initialValues: [...DEFAULT_MODULES],
341
375
  required: false,
342
- options: MODULES.map((m) => ({ value: m.id, label: m.label, hint: m.hint }))
376
+ options: MODULES.map((module) => ({
377
+ value: module.id,
378
+ label: module.label,
379
+ hint: module.hint
380
+ }))
343
381
  })
344
382
  );
345
- return annoncer(resoudre(choisis));
383
+ return announce(resolveModules(chosen));
346
384
  }
347
- function annoncer(resolution) {
348
- for (const mot of resolution.avertissements) prompts.log.warn(mot);
385
+ function announce(resolution) {
386
+ for (const warning of resolution.warnings) prompts.log.warn(warning);
349
387
  return resolution.modules;
350
388
  }
351
- async function installerDependances(target, manager) {
352
- const [commande, ...args] = installCommand(manager).split(" ");
353
- if (commande === void 0) return false;
354
- const barre = prompts.spinner({ indicator: "timer" });
355
- barre.start(`Installing dependencies with ${manager}`);
356
- const fin = [];
357
- const garder = (bloc) => {
358
- for (const ligne of bloc.split("\n")) {
359
- const propre = ligne.trim();
360
- if (propre === "" || !/[a-z0-9]/i.test(propre)) continue;
361
- fin.push(propre);
362
- if (fin.length > DERNIERES_LIGNES) fin.shift();
363
- barre.message(`${manager} \xB7 ${propre.slice(0, LARGEUR_LIGNE)}`);
389
+ async function installDependencies(target, manager) {
390
+ const [command, ...args] = installCommand(manager).split(" ");
391
+ if (command === void 0) return false;
392
+ const bar = prompts.spinner({ indicator: "timer" });
393
+ bar.start(`Installing dependencies with ${manager}`);
394
+ const tail = [];
395
+ const keep = (block) => {
396
+ for (const line of block.split("\n")) {
397
+ const clean = line.trim();
398
+ if (clean === "" || !/[a-z0-9]/i.test(clean)) continue;
399
+ tail.push(clean);
400
+ if (tail.length > LAST_LINES) tail.shift();
401
+ bar.message(`${manager} \xB7 ${clean.slice(0, LINE_WIDTH)}`);
364
402
  }
365
403
  };
366
404
  const code = await new Promise((resolve_) => {
367
- const processus = spawn(commande, args, {
405
+ const child = spawn(command, args, {
368
406
  cwd: target,
369
407
  shell: process.platform === "win32"
370
408
  });
371
- processus.stdout?.setEncoding("utf8").on("data", garder);
372
- processus.stderr?.setEncoding("utf8").on("data", garder);
373
- processus.on("error", () => {
409
+ child.stdout?.setEncoding("utf8").on("data", keep);
410
+ child.stderr?.setEncoding("utf8").on("data", keep);
411
+ child.on("error", () => {
374
412
  resolve_(-1);
375
413
  });
376
- processus.on("close", (sortie) => {
377
- resolve_(sortie ?? -1);
414
+ child.on("close", (status) => {
415
+ resolve_(status ?? -1);
378
416
  });
379
417
  });
380
418
  if (code === 0) {
381
- barre.stop(`Dependencies installed with ${manager}`);
419
+ bar.stop(`Dependencies installed with ${manager}`);
382
420
  return true;
383
421
  }
384
- barre.stop(`${manager} install failed`, 1);
385
- for (const ligne of fin) prompts.log.error(colors.dim(ligne));
422
+ bar.stop(`${manager} install failed`, 1);
423
+ for (const line of tail) prompts.log.error(colors.dim(line));
386
424
  return false;
387
425
  }
388
- function versionCli() {
426
+ function cliVersion2() {
389
427
  try {
390
- const manifeste = join(dirname(templatesRoot()), "package.json");
391
- const { version } = JSON.parse(readFileSync(manifeste, "utf8"));
428
+ const manifest = join(dirname(templatesRoot()), "package.json");
429
+ const { version } = JSON.parse(readFileSync(manifest, "utf8"));
392
430
  return version;
393
431
  } catch {
394
432
  return "?";
@@ -406,12 +444,12 @@ async function createCommand(options) {
406
444
  const templates = availableTemplates(root);
407
445
  const defaultTemplate = templates[0] ?? "react-ts";
408
446
  prompts.intro(
409
- `${colors.bgBlue(colors.black(" ODORO "))} ${colors.dim(`v${versionCli()}`)}`
447
+ `${colors.bgBlue(colors.black(" ODORO "))} ${colors.dim(`v${cliVersion2()}`)}`
410
448
  );
411
449
  const rawName = options.name ?? (options.yes === true ? "odoro-app" : ensure(
412
450
  await prompts.text({
413
451
  message: "Project name",
414
- placeholder: "mon-site",
452
+ placeholder: "my-site",
415
453
  defaultValue: "odoro-app",
416
454
  validate: (value) => value === "" ? void 0 : validatePackageName(toPackageName(value))
417
455
  })
@@ -425,7 +463,7 @@ async function createCommand(options) {
425
463
  }
426
464
  let overwrite = options.overwrite;
427
465
  const state = inspectTarget(target);
428
- if (state === "occupe" && overwrite === void 0) {
466
+ if (state === "occupied" && overwrite === void 0) {
429
467
  if (options.yes === true) {
430
468
  prompts.cancel(
431
469
  `Folder "${basename(target)}" is not empty. Pass --overwrite or --merge.`
@@ -436,14 +474,14 @@ async function createCommand(options) {
436
474
  await prompts.select({
437
475
  message: `Folder "${basename(target)}" is not empty.`,
438
476
  options: [
439
- { value: "annuler", label: "Cancel" },
477
+ { value: "cancel", label: "Cancel" },
440
478
  { value: "fusionner", label: "Merge \u2014 overwrites files of the same name" },
441
479
  { value: "ecraser", label: "Empty the folder, then create the project" }
442
480
  ]
443
481
  })
444
482
  );
445
- if (choice === "annuler") {
446
- prompts.cancel("Creation annulee.");
483
+ if (choice === "cancel") {
484
+ prompts.cancel("Creation cancelled.");
447
485
  return 0;
448
486
  }
449
487
  overwrite = choice;
@@ -481,7 +519,7 @@ async function createCommand(options) {
481
519
  prompts.cancel(`Unknown package manager: "${manager}".`);
482
520
  return 1;
483
521
  }
484
- const database = template === "react-ts-server" && options.yes !== true ? await askDatabase() : void 0;
522
+ const database = template === "react-ts-server" && options.yes !== true ? await askDatabase(packageName) : void 0;
485
523
  const withGit = options.git ?? (options.yes === true ? true : ensure(await prompts.confirm({ message: "Initialize a git repository?" })));
486
524
  const withInstall = options.install ?? (options.yes === true ? true : ensure(
487
525
  await prompts.confirm({
@@ -513,12 +551,12 @@ async function createCommand(options) {
513
551
  if (database?.url !== void 0) {
514
552
  await writeDatabaseUrl(target, database.url);
515
553
  prompts.log.success("Database URL written to .env");
516
- const risque = await assertEnvIgnored(target);
517
- if (risque !== void 0) prompts.log.warn(risque);
554
+ const risk = await assertEnvIgnored(target);
555
+ if (risk !== void 0) prompts.log.warn(risk);
518
556
  }
519
557
  if (database !== void 0) prompts.log.info(database.note);
520
558
  if (modules.includes("registre")) {
521
- const { initCommand } = await import('./commands-AHMXBWQQ.js');
559
+ const { initCommand } = await import('./commands-GYA7NTCX.js');
522
560
  const code = await initCommand({ root: target, yes: true });
523
561
  if (code !== 0) {
524
562
  prompts.log.warn(
@@ -526,14 +564,14 @@ async function createCommand(options) {
526
564
  );
527
565
  }
528
566
  }
529
- const installe = withInstall ? await installerDependances(target, manager) : false;
567
+ const installed = withInstall ? await installDependencies(target, manager) : false;
530
568
  const steps = [
531
569
  `cd ${basename(target)}`,
532
- // Si l'installation a echoue, la commande revient dans les etapes : le
533
- // projet est ecrit, il ne lui manque que ses dependances.
534
- ...installe ? [] : [installCommand(manager)],
535
- // `odoro.json` vient d'etre ecrit : ce qui reste a montrer, c'est la
536
- // commande qui s'en sert.
570
+ // When the install failed, the command comes back into the steps: the
571
+ // project is written, it is only missing its dependencies.
572
+ ...installed ? [] : [installCommand(manager)],
573
+ // `odoro.json` has just been written: what remains to show is the command
574
+ // that uses it.
537
575
  ...modules.includes("registre") ? ["odoro add text/count-up"] : [],
538
576
  runCommand(manager, "dev")
539
577
  ];