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
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env node
2
+ import { storeToken, chooseEnvironment, cancelled, chooseRegion, writeDatabaseUrl, assertEnvIgnored, SDK_PACKAGE, loadSdk, findToken } from './chunk-LIKVHWB4.js';
3
+ import { info, success, colors, warn, error } from './chunk-7ZB5MAM6.js';
4
+ import { randomBytes } from 'crypto';
5
+
6
+ var DEFAULT_API_URL = "https://db.odoro.dev";
7
+ function idempotencyKey() {
8
+ return randomBytes(24).toString("hex");
9
+ }
10
+ async function connect(options) {
11
+ const apiUrl = options.apiUrl ?? DEFAULT_API_URL;
12
+ const load = await loadSdk();
13
+ if (!load.ok) {
14
+ error(load.reason);
15
+ return void 0;
16
+ }
17
+ const token = await findToken(apiUrl);
18
+ if (token === void 0) {
19
+ error(
20
+ `No token for ${apiUrl}.
21
+
22
+ odoro db:login
23
+
24
+ Or provide it through the ODORO_TOKEN variable, which is what a
25
+ continuous integration does.`
26
+ );
27
+ return void 0;
28
+ }
29
+ return { client: load.sdk.createClient({ baseUrl: apiUrl, token }), sdk: load.sdk };
30
+ }
31
+ async function loginCommand(options) {
32
+ const apiUrl = options.apiUrl ?? DEFAULT_API_URL;
33
+ const prompts = await import('@clack/prompts');
34
+ const value = await prompts.password({
35
+ message: `Token for ${apiUrl}`,
36
+ validate: (input) => input.startsWith("odk_") ? void 0 : "A token starts with odk_live_ or odk_test_"
37
+ });
38
+ if (prompts.isCancel(value)) {
39
+ info("Cancelled.");
40
+ return 0;
41
+ }
42
+ const report = await storeToken(apiUrl, value);
43
+ success(`Token recorded in ${colors.dim(report.path)}`);
44
+ if (!report.restricted) {
45
+ warn(
46
+ "The restrictive file permissions could not be set on this system: check that this directory is neither shared nor synchronised."
47
+ );
48
+ }
49
+ return 0;
50
+ }
51
+ async function statusCommand(options) {
52
+ const connection = await connect(options);
53
+ if (connection === void 0) return 1;
54
+ const { databases } = await connection.client.databases.list(
55
+ options.env === void 0 ? {} : { environmentId: options.env }
56
+ );
57
+ if (databases.length === 0) {
58
+ info("No database. `odoro db:create` provisions one.");
59
+ return 0;
60
+ }
61
+ for (const database of databases) {
62
+ const state = database.state === "ready" ? colors.green(database.state) : database.state === "failed" || database.state === "quarantined" ? colors.red(database.state) : colors.dim(database.state);
63
+ console.log(` ${database.id} ${state} ${colors.dim(database.region)}`);
64
+ }
65
+ return 0;
66
+ }
67
+ async function createCommand(options) {
68
+ const connection = await connect(options);
69
+ if (connection === void 0) return 1;
70
+ const prompts = await import('@clack/prompts');
71
+ let environmentId = options.env;
72
+ if (environmentId === void 0) {
73
+ const chosen = await chooseEnvironment(prompts, connection.client);
74
+ if (cancelled(chosen) || chosen === void 0) return 1;
75
+ environmentId = chosen.id;
76
+ }
77
+ let region = options.region;
78
+ if (region === void 0) {
79
+ const chosen = await chooseRegion(prompts, connection.client);
80
+ if (cancelled(chosen)) return 1;
81
+ region = chosen;
82
+ }
83
+ const spinner = prompts.spinner();
84
+ spinner.start(`Provisioning in ${region ?? "the default region"}`);
85
+ const abort = new AbortController();
86
+ const onInterrupt = () => abort.abort();
87
+ process.once("SIGINT", onInterrupt);
88
+ try {
89
+ const finished = await connection.client.databases.createAndWait(
90
+ {
91
+ idempotencyKey: idempotencyKey(),
92
+ environmentId,
93
+ ...region === void 0 ? {} : { region }
94
+ },
95
+ { signal: abort.signal }
96
+ );
97
+ spinner.stop("Database provisioned");
98
+ const databaseId = finished.subject;
99
+ if (databaseId === void 0) {
100
+ warn(
101
+ "The operation succeeded without naming the created database. `odoro db:status` will show it."
102
+ );
103
+ return 0;
104
+ }
105
+ const { connectionString } = await connection.client.credentials.rotate({
106
+ databaseId
107
+ });
108
+ await writeDatabaseUrl(options.root, connectionString);
109
+ success("DATABASE_URL written to .env");
110
+ const risk = await assertEnvIgnored(options.root);
111
+ if (risk !== void 0) warn(risk);
112
+ return 0;
113
+ } catch (cause) {
114
+ spinner.stop("Provisioning interrupted");
115
+ if (abort.signal.aborted) {
116
+ info(
117
+ "Wait abandoned. The provisioning carries on: `odoro db:status` will show its outcome."
118
+ );
119
+ return 0;
120
+ }
121
+ error(describe(cause, connection.sdk));
122
+ return 1;
123
+ } finally {
124
+ process.off("SIGINT", onInterrupt);
125
+ }
126
+ }
127
+ async function branchCommand(options) {
128
+ const connection = await connect(options);
129
+ if (connection === void 0) return 1;
130
+ if (options.from === void 0 || options.name === void 0) {
131
+ error("Usage: `odoro db:branch --from production --name preview-42`");
132
+ return 1;
133
+ }
134
+ const prompts = await import('@clack/prompts');
135
+ const spinner = prompts.spinner();
136
+ spinner.start(`Branching from ${options.from}`);
137
+ try {
138
+ const finished = await connection.client.databases.branchAndWait({
139
+ idempotencyKey: idempotencyKey(),
140
+ parentEnvironmentId: options.from,
141
+ name: options.name,
142
+ // Without a declared rule, the platform refuses. We do not guess in its
143
+ // place: a rule invented here would anonymise the wrong column, or none.
144
+ anonymization: []
145
+ });
146
+ spinner.stop("Branch created");
147
+ info(`Database: ${finished.subject ?? "see odoro db:status"}`);
148
+ return 0;
149
+ } catch (cause) {
150
+ spinner.stop("Branch refused");
151
+ error(describe(cause, connection.sdk));
152
+ return 1;
153
+ }
154
+ }
155
+ function describe(cause, sdk) {
156
+ if (sdk.isApiError(cause, "VALIDATION")) {
157
+ const errors = cause.options?.errors;
158
+ return [
159
+ "The request was refused:",
160
+ ...(errors ?? []).map(({ field, message }) => ` ${field} \u2014 ${message}`)
161
+ ].join("\n");
162
+ }
163
+ if (sdk.isApiError(cause, "RATE_LIMIT")) {
164
+ return "Too many requests. The routes that provision are deliberately rate limited: every creation costs.";
165
+ }
166
+ if (sdk.isApiError(cause, "UNAUTHORIZED")) {
167
+ return `Token refused. \`odoro db:login\` records another one.`;
168
+ }
169
+ return cause instanceof Error ? cause.message : String(cause);
170
+ }
171
+ var DB_HELP = [
172
+ " db:login Record a platform token",
173
+ " db:status List the databases of the project",
174
+ " db:create Provision a database and write .env",
175
+ " (--env and --region skip the questions)",
176
+ " db:branch --from <e> --name <n>",
177
+ " Create a per-branch preview",
178
+ ` (requires ${SDK_PACKAGE})`
179
+ ].join("\n");
180
+
181
+ export { DB_HELP, branchCommand, createCommand, loginCommand, statusCommand };