sporades 0.6.3 → 0.6.5
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/CHANGES.md +3 -173
- package/bin/sporades-host-helper.js +1 -1
- package/bin/sporades.js +173 -4
- package/dist/cli/cli-version.d.ts +1 -1
- package/dist/cli/cli-version.js +1 -1
- package/dist/client-toolchain.js +103 -2
- package/dist/client-toolchain.js.map +1 -1
- package/dist/server-runtime-source.d.ts +13 -0
- package/dist/server-runtime-source.d.ts.map +1 -1
- package/dist/server-runtime-source.js +48 -1
- package/dist/server-runtime-source.js.map +1 -1
- package/dist/templates/client-runtime-template.d.ts.map +1 -1
- package/dist/templates/client-runtime-template.js +14 -0
- package/dist/templates/client-runtime-template.js.map +1 -1
- package/package.json +3 -1
- package/src/types/client.d.ts +5 -0
- package/src/types/server.d.ts +14 -0
package/CHANGES.md
CHANGED
|
@@ -1,179 +1,9 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
-
## Unreleased - 2026-08-
|
|
3
|
+
## Unreleased - 2026-08-04
|
|
4
4
|
|
|
5
|
-
Changes since v0.6.
|
|
6
|
-
|
|
7
|
-
### 🚀 Features
|
|
8
|
-
|
|
9
|
-
- Add scriptable sealed env key management (742ac99).
|
|
10
|
-
- Add Microsoft OpenID Connect sign-in (affeed9).
|
|
11
|
-
- Complete SMTP runtime production parity (3237d21).
|
|
12
|
-
- Add Sign in with Apple (11b22ff).
|
|
13
|
-
- Add Facebook OAuth sign-in (3e166fc).
|
|
14
|
-
- Support portable SMTP relay modes (59817d3).
|
|
15
|
-
- Add multi-provider OAuth configuration (e9f388f).
|
|
16
|
-
- Add Mailgun SMTP extensions (c71314c).
|
|
17
|
-
- Add Postmark SMTP extensions (768b078).
|
|
18
|
-
- Add generic SMTP mail runtime (420d8b0).
|
|
19
|
-
- Add stable provider identities (2d5be36).
|
|
5
|
+
Changes since v0.6.4.
|
|
20
6
|
|
|
21
7
|
### 🐛 Bug Fixes
|
|
22
8
|
|
|
23
|
-
-
|
|
24
|
-
- Guard SMTP error and close traps (203724b).
|
|
25
|
-
- Harden SMTP failure and shutdown boundaries (2a77579).
|
|
26
|
-
- Preserve Facebook body timeouts (bbbb5b5).
|
|
27
|
-
- Harden Facebook OAuth transport (c8ddcc6).
|
|
28
|
-
- Harden portable SMTP configuration (edaf97e).
|
|
29
|
-
|
|
30
|
-
### 🔧 Improvements
|
|
31
|
-
|
|
32
|
-
- Complete multi-provider OAuth implementation swarm (83217df).
|
|
33
|
-
- Accept OAuth coexistence issue 07 (df102b9).
|
|
34
|
-
- Final review for OAuth coexistence issue 07 (fa1c3e0).
|
|
35
|
-
- Request Apple JWKS taxonomy fix for OAuth issue 07 (63328b1).
|
|
36
|
-
- Re-review OAuth endpoint confinement (3a5f38a).
|
|
37
|
-
- Request JWKS confinement rework for OAuth issue 07 (fbcc0e6).
|
|
38
|
-
- Re-review OAuth coexistence issue 07 (609aa56).
|
|
39
|
-
- Request rework for OAuth coexistence issue 07 (e03ef29).
|
|
40
|
-
- Review OAuth coexistence issue 07 (81b8cb2).
|
|
41
|
-
- Dispatch multi-provider OAuth issue 07 (2c54c36).
|
|
42
|
-
- Complete Microsoft OAuth issue 04 (b18dae7).
|
|
43
|
-
- Accept Microsoft OAuth issue 04 integration (6c6b7db).
|
|
44
|
-
- Record SMTP swarm final verification (291cb7c).
|
|
45
|
-
- Review three-provider OAuth integration (df527e8).
|
|
46
|
-
- Accept Microsoft OAuth issue 04 candidate (b63b4b1).
|
|
47
|
-
- Complete SMTP mail issue 05 (cedc452).
|
|
48
|
-
- Accept SMTP mail issue 05 (39684a1).
|
|
49
|
-
- Re-review Microsoft OAuth cache saturation (487686a).
|
|
50
|
-
- Re-review third replacement for SMTP mail issue 05 (6f64f23).
|
|
51
|
-
- Clean up Apple OAuth worktree (40ceac4).
|
|
52
|
-
- Request saturation rework for Microsoft OAuth cache (9fb94d5).
|
|
53
|
-
- Request third rework for SMTP mail issue 05 (cd611fd).
|
|
54
|
-
- Re-review Microsoft OAuth cache lifecycle (c2d5a95).
|
|
55
|
-
- Re-review second replacement for SMTP mail issue 05 (b2f455b).
|
|
56
|
-
- Complete Apple OAuth issue 05 (ac9eacf).
|
|
57
|
-
- Request second rework for SMTP mail issue 05 (f036856).
|
|
58
|
-
- Accept Apple OAuth issue 05 integration (06d6af7).
|
|
59
|
-
- Request lifecycle rework for Microsoft OAuth cache (5ec1cff).
|
|
60
|
-
- Re-review SMTP mail issue 05 (137d31a).
|
|
61
|
-
- Review Apple and Facebook OAuth integration (15408ad).
|
|
62
|
-
- Re-review Microsoft OAuth cache handling (a2814b4).
|
|
63
|
-
- Request rework for SMTP mail issue 05 (55876a9).
|
|
64
|
-
- Complete Facebook OAuth issue 06 (49471f2).
|
|
65
|
-
- Accept Facebook OAuth issue 06 (e73b98e).
|
|
66
|
-
- Re-review Apple OAuth callback parser (b258d8f).
|
|
67
|
-
- Re-review Facebook OAuth timeout handling (fc9d1e5).
|
|
68
|
-
- Review SMTP mail issue 05 (ebc29e8).
|
|
69
|
-
- Request cache rework for Microsoft OAuth issue 04 (2261ffc).
|
|
70
|
-
- Request parser rework for Apple OAuth issue 05 (1a4af01).
|
|
71
|
-
- Advance Microsoft and Facebook OAuth rework (9c488f6).
|
|
72
|
-
- Re-review Apple OAuth issue 05 (d2cc161).
|
|
73
|
-
- Re-review Facebook OAuth issue 06 (4a48c7e).
|
|
74
|
-
- Dispatch SMTP mail issue 05 (3675858).
|
|
75
|
-
- Complete SMTP mail issue 04 (630b589).
|
|
76
|
-
- Accept SMTP mail issue 04 (1381dbd).
|
|
77
|
-
- Re-review second replacement for SMTP mail issue 04 (3041f53).
|
|
78
|
-
- Request second rework for SMTP mail issue 04 (e94dabd).
|
|
79
|
-
- Request rework for Facebook OAuth issue 06 (a84fd43).
|
|
80
|
-
- Re-review SMTP mail issue 04 (ea9df9e).
|
|
81
|
-
- Request rework for Microsoft OAuth issue 04 (8a7b75e).
|
|
82
|
-
- Review Facebook OAuth issue 06 (af9f4e8).
|
|
83
|
-
- Request rework for SMTP mail issue 04 (8140e85).
|
|
84
|
-
- Review Microsoft OAuth issue 04 (6a02358).
|
|
85
|
-
- Request rework for Apple OAuth issue 05 (f60ad7b).
|
|
86
|
-
- Review Apple OAuth issue 05 (274f085).
|
|
87
|
-
- Review SMTP mail issue 04 (3d67ba2).
|
|
88
|
-
- Dispatch provider OAuth implementation frontier (a53d2aa).
|
|
89
|
-
- Complete multi-provider OAuth issue 03 (1dc0371).
|
|
90
|
-
- Accept multi-provider OAuth issue 03 (32e289c).
|
|
91
|
-
- Re-review invariant-safe OAuth issue 03 (4257dbb).
|
|
92
|
-
- Dispatch SMTP mail issue 04 (ff61b3e).
|
|
93
|
-
- Complete SMTP mail issue 03 (f7e9916).
|
|
94
|
-
- Accept SMTP mail issue 03 (54ab22c).
|
|
95
|
-
- Re-review third replacement for SMTP mail issue 03 (50495c8).
|
|
96
|
-
- Request invariant rework for multi-provider OAuth issue 03 (ad54e22).
|
|
97
|
-
- Request third rework for SMTP mail issue 03 (31da8bc).
|
|
98
|
-
- Re-review atomic multi-provider OAuth issue 03 (cb94846).
|
|
99
|
-
- Re-review second replacement for SMTP mail issue 03 (a4614cd).
|
|
100
|
-
- Request second rework for SMTP mail issue 03 (53b0d36).
|
|
101
|
-
- Re-review SMTP mail issue 03 (ec21ea5).
|
|
102
|
-
- Request atomic rework for multi-provider OAuth issue 03 (15a9336).
|
|
103
|
-
- Re-review multi-provider OAuth issue 03 (c58107a).
|
|
104
|
-
- Request rework for SMTP mail issue 03 (fbf0fc2).
|
|
105
|
-
- Review SMTP mail issue 03 (7f8623a).
|
|
106
|
-
- Request rework for multi-provider OAuth issue 03 (8295165).
|
|
107
|
-
- Dispatch SMTP mail issue 03 (239f016).
|
|
108
|
-
- Complete SMTP mail issue 02 (912a1ac).
|
|
109
|
-
- Review multi-provider OAuth issue 03 (fe44a93).
|
|
110
|
-
- Accept SMTP mail issue 02 (8e91a6e).
|
|
111
|
-
- Re-review SMTP mail issue 02 (9944346).
|
|
112
|
-
- Request rework for SMTP mail issue 02 (855ecbf).
|
|
113
|
-
- Review SMTP mail issue 02 (2708b4f).
|
|
114
|
-
- Dispatch SMTP mail issue 02 (9339ad0).
|
|
115
|
-
- Complete SMTP mail issue 01 (6b0d35f).
|
|
116
|
-
- Accept SMTP mail issue 01 (86c590c).
|
|
117
|
-
- Re-review encoded address fix for SMTP mail issue 01 (fc30f8f).
|
|
118
|
-
- Request third rework for SMTP mail issue 01 (8befa61).
|
|
119
|
-
- Re-review RFC 2047 fix for SMTP mail issue 01 (99dd6ac).
|
|
120
|
-
- Request second rework for SMTP mail issue 01 (f864623).
|
|
121
|
-
- Dispatch multi-provider OAuth issue 03 (7d345e9).
|
|
122
|
-
- Complete multi-provider OAuth issue 02 (c3da4ab).
|
|
123
|
-
- Accept multi-provider OAuth issue 02 (cc6d385).
|
|
124
|
-
- Re-review SMTP mail issue 01 (486fed4).
|
|
125
|
-
- Re-review multi-provider OAuth issue 02 (2e632ae).
|
|
126
|
-
- Request rework for SMTP mail issue 01 (075813f).
|
|
127
|
-
- Request rework for multi-provider OAuth issue 02 (dbffa22).
|
|
128
|
-
- Dispatch review for SMTP mail issue 01 (34d9960).
|
|
129
|
-
- Review SMTP mail issue 01 (4271868).
|
|
130
|
-
- Review multi-provider OAuth issue 02 (bb0292c).
|
|
131
|
-
- Dispatch SMTP mail issue 01 (a51c647).
|
|
132
|
-
- Initialize SMTP mail swarm ledger (ac20cf1).
|
|
133
|
-
- Clean up multi-provider OAuth issue 01 worktree (4297774).
|
|
134
|
-
- Dispatch multi-provider OAuth issue 02 (d059d44).
|
|
135
|
-
- Complete multi-provider OAuth issue 01 (da7602c).
|
|
136
|
-
- Accept multi-provider OAuth issue 01 (e925fa0).
|
|
137
|
-
- Re-review multi-provider OAuth issue 01 (6595fa4).
|
|
138
|
-
- Re-review multi-provider OAuth issue 01 (33decb6).
|
|
139
|
-
- Plan SMTP mail support (35e1519).
|
|
140
|
-
- Request rework for multi-provider OAuth issue 01 (0f08d69).
|
|
141
|
-
- Review multi-provider OAuth issue 01 (b4f5d58).
|
|
142
|
-
- Dispatch multi-provider OAuth issue 01 (ab58692).
|
|
143
|
-
- Initialize multi-provider OAuth swarm ledger (716075b).
|
|
144
|
-
- Plan multi-provider OAuth expansion (1cc5f60).
|
|
145
|
-
|
|
146
|
-
### 📝 Documentation
|
|
147
|
-
|
|
148
|
-
- Contract provider-neutral OAuth runtime (df4901f).
|
|
149
|
-
- Fail closed on Microsoft OIDC cache saturation (5889257).
|
|
150
|
-
- Bound Microsoft OIDC cache lifecycle (9e3aeff).
|
|
151
|
-
- Coalesce Microsoft OIDC cache refreshes (7b54d69).
|
|
152
|
-
- Harden Microsoft OIDC network and token parsing (13774fe).
|
|
153
|
-
- Reject malformed OAuth form callbacks (1817519).
|
|
154
|
-
- Harden Sign in with Apple boundaries (301ff15).
|
|
155
|
-
- Reject duplicate file transaction targets (3cabaf0).
|
|
156
|
-
- Make OAuth configuration updates failure-atomic (b94bb52).
|
|
157
|
-
- Harden multi-provider OAuth configuration (56a1f14).
|
|
158
|
-
- Make Mailgun header boundaries exact (378ca69).
|
|
159
|
-
- Validate Mailgun headers before delivery (66080b0).
|
|
160
|
-
- Harden Mailgun SMTP header encoding (9436714).
|
|
161
|
-
- Update generated SMTP API docs (0cf6139).
|
|
162
|
-
- Harden SMTP MIME and TLS errors (89536c1).
|
|
163
|
-
- Harden OAuth state and identity validation (6ef5d6a).
|
|
164
|
-
- Deepen runtime OAuth provider seam (210aeb2).
|
|
165
|
-
- Harden legacy provider identity claims (39e9e7a).
|
|
166
|
-
|
|
167
|
-
### 🧪 Tests
|
|
168
|
-
|
|
169
|
-
- Integrate Microsoft OAuth with sibling providers (11bf24e).
|
|
170
|
-
- Prove implicit TLS fails closed (24f10b2).
|
|
171
|
-
- Define portable SMTP security contract (81698b3).
|
|
172
|
-
- Harden Postmark provider data objects (3940fd5).
|
|
173
|
-
- Fold encoded address headers at 76 columns (ab731ed).
|
|
174
|
-
- Bound MIME encoded-word lines (b78ca71).
|
|
175
|
-
|
|
176
|
-
### 📦 Packaging
|
|
177
|
-
|
|
178
|
-
- Release v0.6.2 (3d21e1a).
|
|
179
|
-
- Align esbuild script approval version (613f597).
|
|
9
|
+
- Password reset and logout for email/password accounts (1cbe35f).
|
|
@@ -391,7 +391,7 @@ function writeEnvelope(result, failed = false) {
|
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
// src/cli/cli-version.ts
|
|
394
|
-
var CLI_VERSION = "0.6.
|
|
394
|
+
var CLI_VERSION = "0.6.5";
|
|
395
395
|
|
|
396
396
|
// src/cli/schedule-inspection-envelope.ts
|
|
397
397
|
function sanitizeScheduleInspectionEnvelope(envelope, invalid) {
|
package/bin/sporades.js
CHANGED
|
@@ -82,6 +82,9 @@ export const auth = {
|
|
|
82
82
|
signOut() {
|
|
83
83
|
return connect().signOut();
|
|
84
84
|
},
|
|
85
|
+
setPassword(email, newPassword) {
|
|
86
|
+
return connect().setPassword(email, newPassword);
|
|
87
|
+
},
|
|
85
88
|
};
|
|
86
89
|
|
|
87
90
|
export const files = {
|
|
@@ -162,6 +165,9 @@ export function createHooks(primitives) {
|
|
|
162
165
|
signOut() {
|
|
163
166
|
return connect().signOut();
|
|
164
167
|
},
|
|
168
|
+
setPassword(email, newPassword) {
|
|
169
|
+
return connect().setPassword(email, newPassword);
|
|
170
|
+
},
|
|
165
171
|
};
|
|
166
172
|
}
|
|
167
173
|
|
|
@@ -217,6 +223,7 @@ export function createVueComposables(primitives) {
|
|
|
217
223
|
state.signUp = (provider, credentials) => connect().signUp(provider, credentials);
|
|
218
224
|
state.signIn = (provider, credentials) => connect().signIn(provider, credentials);
|
|
219
225
|
state.signOut = () => connect().signOut();
|
|
226
|
+
state.setPassword = (email, newPassword) => connect().setPassword(email, newPassword);
|
|
220
227
|
return state;
|
|
221
228
|
}
|
|
222
229
|
|
|
@@ -268,6 +275,7 @@ export function createSolidPrimitives(primitives) {
|
|
|
268
275
|
signUp: (provider, credentials) => connect().signUp(provider, credentials),
|
|
269
276
|
signIn: (provider, credentials) => connect().signIn(provider, credentials),
|
|
270
277
|
signOut: () => connect().signOut(),
|
|
278
|
+
setPassword: (email, newPassword) => connect().setPassword(email, newPassword),
|
|
271
279
|
};
|
|
272
280
|
}
|
|
273
281
|
|
|
@@ -365,6 +373,7 @@ export function createLitControllers() {
|
|
|
365
373
|
controller.signUp = (provider, credentials) => connect().signUp(provider, credentials);
|
|
366
374
|
controller.signIn = (provider, credentials) => connect().signIn(provider, credentials);
|
|
367
375
|
controller.signOut = () => connect().signOut();
|
|
376
|
+
controller.setPassword = (email, newPassword) => connect().setPassword(email, newPassword);
|
|
368
377
|
return controller;
|
|
369
378
|
}
|
|
370
379
|
|
|
@@ -437,6 +446,7 @@ export function createInfernoAdapters() {
|
|
|
437
446
|
adapter.signUp = (provider, credentials) => connect().signUp(provider, credentials);
|
|
438
447
|
adapter.signIn = (provider, credentials) => connect().signIn(provider, credentials);
|
|
439
448
|
adapter.signOut = () => connect().signOut();
|
|
449
|
+
adapter.setPassword = (email, newPassword) => connect().setPassword(email, newPassword);
|
|
440
450
|
return adapter;
|
|
441
451
|
}
|
|
442
452
|
return { queryAdapter, mutationAdapter, authAdapter };
|
|
@@ -486,6 +496,7 @@ export function createSvelteStores() {
|
|
|
486
496
|
signUp: (provider, credentials) => connect().signUp(provider, credentials),
|
|
487
497
|
signIn: (provider, credentials) => connect().signIn(provider, credentials),
|
|
488
498
|
signOut: () => connect().signOut(),
|
|
499
|
+
setPassword: (email, newPassword) => connect().setPassword(email, newPassword),
|
|
489
500
|
};
|
|
490
501
|
}
|
|
491
502
|
|
|
@@ -990,6 +1001,9 @@ function createConnection() {
|
|
|
990
1001
|
return result;
|
|
991
1002
|
});
|
|
992
1003
|
},
|
|
1004
|
+
setPassword(email, newPassword) {
|
|
1005
|
+
return request("auth.setPassword", { email, newPassword });
|
|
1006
|
+
},
|
|
993
1007
|
subscribeQuery(name, listener) {
|
|
994
1008
|
if (typeof name !== "string" || !name) throw new TypeError("queries.subscribe requires a query name.");
|
|
995
1009
|
if (typeof listener !== "function") throw new TypeError("queries.subscribe requires a listener function.");
|
|
@@ -1311,6 +1325,8 @@ async function buildVite(options) {
|
|
|
1311
1325
|
let projectRoot = path.resolve(options.projectDir);
|
|
1312
1326
|
try {
|
|
1313
1327
|
projectRoot = await realpath(options.projectDir);
|
|
1328
|
+
const canonicalIndexHtmlPath = path.join(projectRoot, path.basename(options.indexHtmlPath));
|
|
1329
|
+
const projectConfigFile = await findProjectViteConfig(projectRoot);
|
|
1314
1330
|
if (options.frameworkConfig.framework === "vue") {
|
|
1315
1331
|
const { plugin, compiler } = await loadProjectVueToolchain(projectRoot);
|
|
1316
1332
|
frameworkPlugins.push(plugin({ compiler }));
|
|
@@ -1327,9 +1343,10 @@ async function buildVite(options) {
|
|
|
1327
1343
|
root: projectRoot,
|
|
1328
1344
|
base: "/",
|
|
1329
1345
|
publicDir: false,
|
|
1330
|
-
configFile:
|
|
1346
|
+
configFile: projectConfigFile,
|
|
1331
1347
|
envFile: false,
|
|
1332
1348
|
envPrefix: "\0",
|
|
1349
|
+
mode: "production",
|
|
1333
1350
|
define: {
|
|
1334
1351
|
"import.meta.env": JSON.stringify({ BASE_URL: "/", MODE: "production", DEV: false, PROD: true, SSR: false })
|
|
1335
1352
|
},
|
|
@@ -1338,14 +1355,25 @@ async function buildVite(options) {
|
|
|
1338
1355
|
logLevel: "silent",
|
|
1339
1356
|
esbuild: options.frameworkConfig.framework === "inferno" ? { jsx: "transform", jsxFactory: "createElement" } : { jsx: "automatic", jsxImportSource: options.frameworkConfig.jsxImportSource ?? void 0 },
|
|
1340
1357
|
css: { postcss: { plugins: [] } },
|
|
1341
|
-
plugins: [
|
|
1358
|
+
plugins: [
|
|
1359
|
+
...frameworkPlugins,
|
|
1360
|
+
sporadesViteClientPlugin(options.devRefresh === true),
|
|
1361
|
+
sporadesViteBuildInvariants(canonicalIndexHtmlPath, options.frameworkConfig)
|
|
1362
|
+
],
|
|
1342
1363
|
build: {
|
|
1343
1364
|
write: false,
|
|
1344
1365
|
emptyOutDir: false,
|
|
1345
1366
|
sourcemap: true,
|
|
1346
1367
|
cssCodeSplit: true,
|
|
1347
1368
|
assetsInlineLimit: 0,
|
|
1369
|
+
watch: null,
|
|
1370
|
+
lib: false,
|
|
1371
|
+
ssr: false,
|
|
1372
|
+
manifest: false,
|
|
1373
|
+
ssrManifest: false,
|
|
1348
1374
|
rollupOptions: {
|
|
1375
|
+
input: canonicalIndexHtmlPath,
|
|
1376
|
+
external: [],
|
|
1349
1377
|
output: {
|
|
1350
1378
|
entryFileNames: "assets/[name]-[hash].js",
|
|
1351
1379
|
chunkFileNames: "assets/[name]-[hash].js",
|
|
@@ -1378,6 +1406,40 @@ async function buildVite(options) {
|
|
|
1378
1406
|
throw viteBuildError(error, [options.projectDir, projectRoot], options.frameworkConfig.framework);
|
|
1379
1407
|
}
|
|
1380
1408
|
}
|
|
1409
|
+
var VITE_CONFIG_NAMES = [
|
|
1410
|
+
"vite.config.js",
|
|
1411
|
+
"vite.config.mjs",
|
|
1412
|
+
"vite.config.ts",
|
|
1413
|
+
"vite.config.cjs",
|
|
1414
|
+
"vite.config.mts",
|
|
1415
|
+
"vite.config.cts"
|
|
1416
|
+
];
|
|
1417
|
+
async function findProjectViteConfig(projectRoot) {
|
|
1418
|
+
for (const name of VITE_CONFIG_NAMES) {
|
|
1419
|
+
const candidate = path.join(projectRoot, name);
|
|
1420
|
+
try {
|
|
1421
|
+
const metadata = await lstat(candidate);
|
|
1422
|
+
if (!metadata.isFile() || metadata.isSymbolicLink()) {
|
|
1423
|
+
throw clientToolchainError(
|
|
1424
|
+
`Vite configuration must be a regular file inside the Capsule: ${name}.`,
|
|
1425
|
+
`Replace ${name} with a regular project-owned file, then retry.`
|
|
1426
|
+
);
|
|
1427
|
+
}
|
|
1428
|
+
const canonical = await realpath(candidate);
|
|
1429
|
+
if (!isCanonicalDescendant(projectRoot, canonical)) {
|
|
1430
|
+
throw clientToolchainError(
|
|
1431
|
+
`Vite configuration escaped the Capsule project: ${name}.`,
|
|
1432
|
+
`Move ${name} inside the Capsule project, then retry.`
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1435
|
+
return canonical;
|
|
1436
|
+
} catch (error) {
|
|
1437
|
+
if (errorDetails(error).code === "ENOENT") continue;
|
|
1438
|
+
throw error;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
return false;
|
|
1442
|
+
}
|
|
1381
1443
|
async function loadProjectVueToolchain(projectRoot) {
|
|
1382
1444
|
const loaded = await loadProjectCompilerToolchain(projectRoot, {
|
|
1383
1445
|
framework: "Vue",
|
|
@@ -1547,6 +1609,66 @@ function sporadesViteClientPlugin(devRefresh = false) {
|
|
|
1547
1609
|
}
|
|
1548
1610
|
};
|
|
1549
1611
|
}
|
|
1612
|
+
function sporadesViteBuildInvariants(indexHtmlPath, frameworkConfig) {
|
|
1613
|
+
return {
|
|
1614
|
+
name: "sporades-build-invariants",
|
|
1615
|
+
enforce: "post",
|
|
1616
|
+
config() {
|
|
1617
|
+
return {
|
|
1618
|
+
root: path.dirname(indexHtmlPath),
|
|
1619
|
+
base: "/",
|
|
1620
|
+
publicDir: false,
|
|
1621
|
+
envFile: false,
|
|
1622
|
+
envPrefix: "\0",
|
|
1623
|
+
mode: "production",
|
|
1624
|
+
define: {
|
|
1625
|
+
"import.meta.env": JSON.stringify({ BASE_URL: "/", MODE: "production", DEV: false, PROD: true, SSR: false })
|
|
1626
|
+
},
|
|
1627
|
+
appType: "mpa",
|
|
1628
|
+
clearScreen: false,
|
|
1629
|
+
logLevel: "silent",
|
|
1630
|
+
esbuild: frameworkConfig.framework === "inferno" ? { jsx: "transform", jsxFactory: "createElement" } : { jsx: "automatic", jsxImportSource: frameworkConfig.jsxImportSource ?? void 0 },
|
|
1631
|
+
css: { postcss: { plugins: [] } },
|
|
1632
|
+
build: {
|
|
1633
|
+
write: false,
|
|
1634
|
+
emptyOutDir: false,
|
|
1635
|
+
sourcemap: true,
|
|
1636
|
+
cssCodeSplit: true,
|
|
1637
|
+
assetsInlineLimit: 0,
|
|
1638
|
+
watch: null,
|
|
1639
|
+
lib: false,
|
|
1640
|
+
ssr: false,
|
|
1641
|
+
manifest: false,
|
|
1642
|
+
ssrManifest: false,
|
|
1643
|
+
rollupOptions: {
|
|
1644
|
+
input: indexHtmlPath,
|
|
1645
|
+
external: [],
|
|
1646
|
+
output: {
|
|
1647
|
+
entryFileNames: "assets/[name]-[hash].js",
|
|
1648
|
+
chunkFileNames: "assets/[name]-[hash].js",
|
|
1649
|
+
assetFileNames: "assets/[name]-[hash][extname]"
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
},
|
|
1655
|
+
configResolved(config) {
|
|
1656
|
+
const pluginNames = new Set(config.plugins.map((plugin) => plugin.name));
|
|
1657
|
+
if (!pluginNames.has("sporades-client-runtime") || !pluginNames.has("sporades-build-invariants")) {
|
|
1658
|
+
throw new Error("Sporades mandatory Vite plugins were not preserved.");
|
|
1659
|
+
}
|
|
1660
|
+
const requiredFrameworkPlugin = {
|
|
1661
|
+
vue: "vite:vue",
|
|
1662
|
+
svelte: "vite-plugin-svelte",
|
|
1663
|
+
solid: "solid",
|
|
1664
|
+
inferno: "sporades-inferno-project-jsx"
|
|
1665
|
+
}[frameworkConfig.framework];
|
|
1666
|
+
if (requiredFrameworkPlugin && !pluginNames.has(requiredFrameworkPlugin)) {
|
|
1667
|
+
throw new Error(`Sporades mandatory ${frameworkConfig.framework} Vite plugin was not preserved.`);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1550
1672
|
function referencesLegacyClientShell(html) {
|
|
1551
1673
|
return /<script\b[^>]*\bsrc\s*=\s*["']\/?client\.js(?:\?[^"']*)?["'][^>]*>/i.test(html);
|
|
1552
1674
|
}
|
|
@@ -5172,6 +5294,11 @@ async function createSqliteDatabaseAdapter(databasePath, options = {}) {
|
|
|
5172
5294
|
"INSERT INTO sporades_auth_email_credentials (email, userId, passwordHash, passwordSalt, createdAt) VALUES (?, ?, ?, ?, ?)"
|
|
5173
5295
|
).run(row.email, row.userId, row.passwordHash, row.passwordSalt, row.createdAt);
|
|
5174
5296
|
},
|
|
5297
|
+
updateEmailCredentialPassword(email, passwordHash, passwordSalt) {
|
|
5298
|
+
return this.prepare(
|
|
5299
|
+
"UPDATE sporades_auth_email_credentials SET passwordHash = ?, passwordSalt = ? WHERE email = ?"
|
|
5300
|
+
).run(passwordHash, passwordSalt, email);
|
|
5301
|
+
},
|
|
5175
5302
|
findEmailCredentialWithUser(email) {
|
|
5176
5303
|
const row = this.prepare(
|
|
5177
5304
|
"SELECT c.email, c.userId, c.passwordHash, c.passwordSalt, u.displayName, u.picture, u.isAuthenticated, u.isGuest FROM sporades_auth_email_credentials c JOIN sporades_auth_users u ON u.id = c.userId WHERE c.email = ?"
|
|
@@ -8764,8 +8891,9 @@ async function readEndpointRequest(database, requestUrl, request) {
|
|
|
8764
8891
|
};
|
|
8765
8892
|
}
|
|
8766
8893
|
function createEndpointContext(database, endpointRequest, session) {
|
|
8894
|
+
const auth = session.auth;
|
|
8767
8895
|
const context = {
|
|
8768
|
-
auth
|
|
8896
|
+
auth,
|
|
8769
8897
|
env: database.serverEnv,
|
|
8770
8898
|
log: createEndpointLogger(database, {
|
|
8771
8899
|
request: {
|
|
@@ -8786,6 +8914,12 @@ function createEndpointContext(database, endpointRequest, session) {
|
|
|
8786
8914
|
context.privileged = createContextPrivilegedApi(database, () => holder.current);
|
|
8787
8915
|
context.jobs = createCurrentUserJobApi(database, () => holder.current);
|
|
8788
8916
|
context.mail = database.mail;
|
|
8917
|
+
context.serverAuth = {
|
|
8918
|
+
async setEmailPassword(email, newPassword) {
|
|
8919
|
+
const result = await setEmailPassword(database, { auth }, email, newPassword);
|
|
8920
|
+
if (!result.ok) throw new Error(result.error?.message ?? "Could not set password.");
|
|
8921
|
+
}
|
|
8922
|
+
};
|
|
8789
8923
|
return context;
|
|
8790
8924
|
}
|
|
8791
8925
|
function createContextHolder(context) {
|
|
@@ -10355,6 +10489,16 @@ function createWebSocketHub(getDatabase, trustedRefresh = null) {
|
|
|
10355
10489
|
});
|
|
10356
10490
|
return;
|
|
10357
10491
|
}
|
|
10492
|
+
if (message.type === "auth.setPassword") {
|
|
10493
|
+
const result = await setEmailPassword(database, client.session, message.email ?? "", message.newPassword ?? "");
|
|
10494
|
+
sendJson(client, {
|
|
10495
|
+
id: message.id ?? null,
|
|
10496
|
+
type: result.ok ? "auth.setPassword.result" : "error",
|
|
10497
|
+
data: result.ok ? { ok: true } : null,
|
|
10498
|
+
error: result.error ?? null
|
|
10499
|
+
});
|
|
10500
|
+
return;
|
|
10501
|
+
}
|
|
10358
10502
|
if (message.type === "auth.signUp") {
|
|
10359
10503
|
const result = await signUpWithEmail(database, client.session, message.provider, message.credentials ?? {});
|
|
10360
10504
|
if (result.ok) {
|
|
@@ -12474,6 +12618,25 @@ function writeRedirect(response, location) {
|
|
|
12474
12618
|
response.writeHead(302, { location });
|
|
12475
12619
|
response.end();
|
|
12476
12620
|
}
|
|
12621
|
+
async function setEmailPassword(database, _session, email, newPassword) {
|
|
12622
|
+
if (!database.authConfig.providers.email.enabled) {
|
|
12623
|
+
return { ok: false, error: emailAuthDisabledError() };
|
|
12624
|
+
}
|
|
12625
|
+
const cleanEmail = typeof email === "string" ? email.trim().toLowerCase() : "";
|
|
12626
|
+
if (!cleanEmail) {
|
|
12627
|
+
return { ok: false, error: { message: "Email is required.", hint: "Provide the email address for the account whose password is being changed." } };
|
|
12628
|
+
}
|
|
12629
|
+
if (typeof newPassword !== "string" || newPassword.length < 8) {
|
|
12630
|
+
return { ok: false, error: { message: "Password is too short.", hint: "Use a password with at least 8 characters." } };
|
|
12631
|
+
}
|
|
12632
|
+
const existing = await database.sqlite.findEmailCredentialWithUser(cleanEmail);
|
|
12633
|
+
if (!existing) {
|
|
12634
|
+
return { ok: false, error: { message: "No email account found for that address.", hint: "Check the email address or register a new account." } };
|
|
12635
|
+
}
|
|
12636
|
+
const password = hashEmailPassword(newPassword);
|
|
12637
|
+
await database.sqlite.updateEmailCredentialPassword(cleanEmail, password.hash, password.salt);
|
|
12638
|
+
return { ok: true };
|
|
12639
|
+
}
|
|
12477
12640
|
async function signUpWithEmail(database, session, provider, credentials) {
|
|
12478
12641
|
if (provider !== "email") {
|
|
12479
12642
|
return {
|
|
@@ -13411,6 +13574,12 @@ function createMutationContext(database, auth) {
|
|
|
13411
13574
|
context.privileged = createContextPrivilegedApi(database, () => holder.current);
|
|
13412
13575
|
context.jobs = createCurrentUserJobApi(database, () => holder.current);
|
|
13413
13576
|
context.mail = database.mail;
|
|
13577
|
+
context.serverAuth = {
|
|
13578
|
+
async setEmailPassword(email, newPassword) {
|
|
13579
|
+
const result = await setEmailPassword(database, { auth }, email, newPassword);
|
|
13580
|
+
if (!result.ok) throw new Error(result.error?.message ?? "Could not set password.");
|
|
13581
|
+
}
|
|
13582
|
+
};
|
|
13414
13583
|
return context;
|
|
13415
13584
|
}
|
|
13416
13585
|
function createCurrentUserJobApi(database, contextGetter) {
|
|
@@ -21737,7 +21906,7 @@ jobs:
|
|
|
21737
21906
|
}
|
|
21738
21907
|
|
|
21739
21908
|
// src/cli/cli-version.ts
|
|
21740
|
-
var CLI_VERSION = "0.6.
|
|
21909
|
+
var CLI_VERSION = "0.6.5";
|
|
21741
21910
|
|
|
21742
21911
|
// src/cli/sporades.ts
|
|
21743
21912
|
var SUPPORTED_TEMPLATES = new Set(CLIENT_TEMPLATES);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "0.6.
|
|
1
|
+
export declare const CLI_VERSION = "0.6.5";
|
|
2
2
|
//# sourceMappingURL=cli-version.d.ts.map
|
package/dist/cli/cli-version.js
CHANGED
package/dist/client-toolchain.js
CHANGED
|
@@ -96,6 +96,8 @@ async function buildVite(options) {
|
|
|
96
96
|
let projectRoot = path.resolve(options.projectDir);
|
|
97
97
|
try {
|
|
98
98
|
projectRoot = await realpath(options.projectDir);
|
|
99
|
+
const canonicalIndexHtmlPath = path.join(projectRoot, path.basename(options.indexHtmlPath));
|
|
100
|
+
const projectConfigFile = await findProjectViteConfig(projectRoot);
|
|
99
101
|
if (options.frameworkConfig.framework === "vue") {
|
|
100
102
|
const { plugin, compiler } = await loadProjectVueToolchain(projectRoot);
|
|
101
103
|
frameworkPlugins.push(plugin({ compiler }));
|
|
@@ -115,9 +117,10 @@ async function buildVite(options) {
|
|
|
115
117
|
root: projectRoot,
|
|
116
118
|
base: "/",
|
|
117
119
|
publicDir: false,
|
|
118
|
-
configFile:
|
|
120
|
+
configFile: projectConfigFile,
|
|
119
121
|
envFile: false,
|
|
120
122
|
envPrefix: "\0",
|
|
123
|
+
mode: "production",
|
|
121
124
|
define: {
|
|
122
125
|
"import.meta.env": JSON.stringify({ BASE_URL: "/", MODE: "production", DEV: false, PROD: true, SSR: false }),
|
|
123
126
|
},
|
|
@@ -128,14 +131,25 @@ async function buildVite(options) {
|
|
|
128
131
|
? { jsx: "transform", jsxFactory: "createElement" }
|
|
129
132
|
: { jsx: "automatic", jsxImportSource: options.frameworkConfig.jsxImportSource ?? undefined },
|
|
130
133
|
css: { postcss: { plugins: [] } },
|
|
131
|
-
plugins: [
|
|
134
|
+
plugins: [
|
|
135
|
+
...frameworkPlugins,
|
|
136
|
+
sporadesViteClientPlugin(options.devRefresh === true),
|
|
137
|
+
sporadesViteBuildInvariants(canonicalIndexHtmlPath, options.frameworkConfig),
|
|
138
|
+
],
|
|
132
139
|
build: {
|
|
133
140
|
write: false,
|
|
134
141
|
emptyOutDir: false,
|
|
135
142
|
sourcemap: true,
|
|
136
143
|
cssCodeSplit: true,
|
|
137
144
|
assetsInlineLimit: 0,
|
|
145
|
+
watch: null,
|
|
146
|
+
lib: false,
|
|
147
|
+
ssr: false,
|
|
148
|
+
manifest: false,
|
|
149
|
+
ssrManifest: false,
|
|
138
150
|
rollupOptions: {
|
|
151
|
+
input: canonicalIndexHtmlPath,
|
|
152
|
+
external: [],
|
|
139
153
|
output: {
|
|
140
154
|
entryFileNames: "assets/[name]-[hash].js",
|
|
141
155
|
chunkFileNames: "assets/[name]-[hash].js",
|
|
@@ -173,6 +187,31 @@ async function buildVite(options) {
|
|
|
173
187
|
throw viteBuildError(error, [options.projectDir, projectRoot], options.frameworkConfig.framework);
|
|
174
188
|
}
|
|
175
189
|
}
|
|
190
|
+
const VITE_CONFIG_NAMES = [
|
|
191
|
+
"vite.config.js", "vite.config.mjs", "vite.config.ts", "vite.config.cjs", "vite.config.mts", "vite.config.cts",
|
|
192
|
+
];
|
|
193
|
+
async function findProjectViteConfig(projectRoot) {
|
|
194
|
+
for (const name of VITE_CONFIG_NAMES) {
|
|
195
|
+
const candidate = path.join(projectRoot, name);
|
|
196
|
+
try {
|
|
197
|
+
const metadata = await lstat(candidate);
|
|
198
|
+
if (!metadata.isFile() || metadata.isSymbolicLink()) {
|
|
199
|
+
throw clientToolchainError(`Vite configuration must be a regular file inside the Capsule: ${name}.`, `Replace ${name} with a regular project-owned file, then retry.`);
|
|
200
|
+
}
|
|
201
|
+
const canonical = await realpath(candidate);
|
|
202
|
+
if (!isCanonicalDescendant(projectRoot, canonical)) {
|
|
203
|
+
throw clientToolchainError(`Vite configuration escaped the Capsule project: ${name}.`, `Move ${name} inside the Capsule project, then retry.`);
|
|
204
|
+
}
|
|
205
|
+
return canonical;
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
if (errorDetails(error).code === "ENOENT")
|
|
209
|
+
continue;
|
|
210
|
+
throw error;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
176
215
|
async function loadProjectVueToolchain(projectRoot) {
|
|
177
216
|
const loaded = await loadProjectCompilerToolchain(projectRoot, {
|
|
178
217
|
framework: "Vue",
|
|
@@ -340,6 +379,68 @@ function sporadesViteClientPlugin(devRefresh = false) {
|
|
|
340
379
|
load(id) { return id === runtimeId ? createClientRuntimeSource({ devRefresh }) : null; },
|
|
341
380
|
};
|
|
342
381
|
}
|
|
382
|
+
function sporadesViteBuildInvariants(indexHtmlPath, frameworkConfig) {
|
|
383
|
+
return {
|
|
384
|
+
name: "sporades-build-invariants",
|
|
385
|
+
enforce: "post",
|
|
386
|
+
config() {
|
|
387
|
+
return {
|
|
388
|
+
root: path.dirname(indexHtmlPath),
|
|
389
|
+
base: "/",
|
|
390
|
+
publicDir: false,
|
|
391
|
+
envFile: false,
|
|
392
|
+
envPrefix: "\0",
|
|
393
|
+
mode: "production",
|
|
394
|
+
define: {
|
|
395
|
+
"import.meta.env": JSON.stringify({ BASE_URL: "/", MODE: "production", DEV: false, PROD: true, SSR: false }),
|
|
396
|
+
},
|
|
397
|
+
appType: "mpa",
|
|
398
|
+
clearScreen: false,
|
|
399
|
+
logLevel: "silent",
|
|
400
|
+
esbuild: frameworkConfig.framework === "inferno"
|
|
401
|
+
? { jsx: "transform", jsxFactory: "createElement" }
|
|
402
|
+
: { jsx: "automatic", jsxImportSource: frameworkConfig.jsxImportSource ?? undefined },
|
|
403
|
+
css: { postcss: { plugins: [] } },
|
|
404
|
+
build: {
|
|
405
|
+
write: false,
|
|
406
|
+
emptyOutDir: false,
|
|
407
|
+
sourcemap: true,
|
|
408
|
+
cssCodeSplit: true,
|
|
409
|
+
assetsInlineLimit: 0,
|
|
410
|
+
watch: null,
|
|
411
|
+
lib: false,
|
|
412
|
+
ssr: false,
|
|
413
|
+
manifest: false,
|
|
414
|
+
ssrManifest: false,
|
|
415
|
+
rollupOptions: {
|
|
416
|
+
input: indexHtmlPath,
|
|
417
|
+
external: [],
|
|
418
|
+
output: {
|
|
419
|
+
entryFileNames: "assets/[name]-[hash].js",
|
|
420
|
+
chunkFileNames: "assets/[name]-[hash].js",
|
|
421
|
+
assetFileNames: "assets/[name]-[hash][extname]",
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
};
|
|
426
|
+
},
|
|
427
|
+
configResolved(config) {
|
|
428
|
+
const pluginNames = new Set(config.plugins.map((plugin) => plugin.name));
|
|
429
|
+
if (!pluginNames.has("sporades-client-runtime") || !pluginNames.has("sporades-build-invariants")) {
|
|
430
|
+
throw new Error("Sporades mandatory Vite plugins were not preserved.");
|
|
431
|
+
}
|
|
432
|
+
const requiredFrameworkPlugin = {
|
|
433
|
+
vue: "vite:vue",
|
|
434
|
+
svelte: "vite-plugin-svelte",
|
|
435
|
+
solid: "solid",
|
|
436
|
+
inferno: "sporades-inferno-project-jsx",
|
|
437
|
+
}[frameworkConfig.framework];
|
|
438
|
+
if (requiredFrameworkPlugin && !pluginNames.has(requiredFrameworkPlugin)) {
|
|
439
|
+
throw new Error(`Sporades mandatory ${frameworkConfig.framework} Vite plugin was not preserved.`);
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
}
|
|
343
444
|
function referencesLegacyClientShell(html) {
|
|
344
445
|
return /<script\b[^>]*\bsrc\s*=\s*["']\/?client\.js(?:\?[^"']*)?["'][^>]*>/i.test(html);
|
|
345
446
|
}
|