@authrim/setup 0.1.141 → 0.1.142
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/dist/__tests__/keys.test.js.map +1 -1
- package/dist/__tests__/migrate.test.js +4 -4
- package/dist/__tests__/migrate.test.js.map +1 -1
- package/dist/__tests__/paths.test.js.map +1 -1
- package/dist/cli/commands/deploy.d.ts.map +1 -1
- package/dist/cli/commands/deploy.js +57 -63
- package/dist/cli/commands/deploy.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +231 -171
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/core/admin.d.ts.map +1 -1
- package/dist/core/admin.js +13 -3
- package/dist/core/admin.js.map +1 -1
- package/dist/core/cloudflare.d.ts +38 -1
- package/dist/core/cloudflare.d.ts.map +1 -1
- package/dist/core/cloudflare.js +729 -115
- package/dist/core/cloudflare.js.map +1 -1
- package/dist/core/config.d.ts +136 -28
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +58 -11
- package/dist/core/config.js.map +1 -1
- package/dist/core/deploy.d.ts +18 -0
- package/dist/core/deploy.d.ts.map +1 -1
- package/dist/core/deploy.js +126 -25
- package/dist/core/deploy.js.map +1 -1
- package/dist/core/keys.d.ts.map +1 -1
- package/dist/core/keys.js +2 -0
- package/dist/core/keys.js.map +1 -1
- package/dist/core/login-ui-client.d.ts.map +1 -1
- package/dist/core/login-ui-client.js +43 -7
- package/dist/core/login-ui-client.js.map +1 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +5 -5
- package/dist/core/paths.js.map +1 -1
- package/dist/core/tenant-mode.d.ts +4 -0
- package/dist/core/tenant-mode.d.ts.map +1 -0
- package/dist/core/tenant-mode.js +17 -0
- package/dist/core/tenant-mode.js.map +1 -0
- package/dist/core/ui-deployment.d.ts +21 -0
- package/dist/core/ui-deployment.d.ts.map +1 -0
- package/dist/core/ui-deployment.js +90 -0
- package/dist/core/ui-deployment.js.map +1 -0
- package/dist/core/ui-env.d.ts +17 -0
- package/dist/core/ui-env.d.ts.map +1 -1
- package/dist/core/ui-env.js +16 -0
- package/dist/core/ui-env.js.map +1 -1
- package/dist/core/url-config.d.ts +16 -0
- package/dist/core/url-config.d.ts.map +1 -0
- package/dist/core/url-config.js +46 -0
- package/dist/core/url-config.js.map +1 -0
- package/dist/core/wrangler.d.ts +50 -1
- package/dist/core/wrangler.d.ts.map +1 -1
- package/dist/core/wrangler.js +169 -55
- package/dist/core/wrangler.js.map +1 -1
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +37 -0
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +37 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +37 -0
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +37 -0
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/id.d.ts.map +1 -1
- package/dist/i18n/locales/id.js +37 -0
- package/dist/i18n/locales/id.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +37 -0
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/ko.d.ts.map +1 -1
- package/dist/i18n/locales/ko.js +37 -0
- package/dist/i18n/locales/ko.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +37 -0
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +37 -0
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
- package/dist/i18n/locales/zh-CN.js +37 -0
- package/dist/i18n/locales/zh-CN.js.map +1 -1
- package/dist/i18n/locales/zh-TW.d.ts.map +1 -1
- package/dist/i18n/locales/zh-TW.js +37 -0
- package/dist/i18n/locales/zh-TW.js.map +1 -1
- package/dist/i18n/types.d.ts +8 -0
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/index.js +38 -29
- package/dist/index.js.map +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +207 -95
- package/dist/web/api.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +506 -109
- package/dist/web/ui.js.map +1 -1
- package/migrations/000_fresh_schema.sql +227 -9
- package/migrations/admin/006_admin_setup_tokens.sql +91 -91
- package/migrations/admin/007_admin_role_inheritance.sql +32 -0
- package/migrations/admin/008_admin_rebac_definitions.sql +117 -0
- package/migrations/admin/009_optimize_admin_audit_indexes.sql +15 -0
- package/package.json +5 -5
package/dist/web/api.js
CHANGED
|
@@ -21,12 +21,16 @@ import { createLockFile, saveLockFile } from '../core/lock.js';
|
|
|
21
21
|
import { getEnvironmentPaths, getExternalKeysDir, findKeysDirectory, resolvePaths, listEnvironments, findAuthrimBaseDir, } from '../core/paths.js';
|
|
22
22
|
import { generateWranglerConfig, toToml } from '../core/wrangler.js';
|
|
23
23
|
import { syncWranglerConfigs } from '../core/wrangler-sync.js';
|
|
24
|
+
import { buildUrlsConfig } from '../core/url-config.js';
|
|
25
|
+
import { normalizeTenantConfigForApiDomain } from '../core/tenant-mode.js';
|
|
24
26
|
import { deployAll, uploadSecrets, buildApiPackages, deployAllPages, deployPagesComponent, deployWorker, PAGES_COMPONENTS, } from '../core/deploy.js';
|
|
25
27
|
import { getEnabledComponents, WORKER_COMPONENTS } from '../core/naming.js';
|
|
26
28
|
import { getLocalPackageVersions, compareVersions, getComponentsToUpdate, } from '../core/version.js';
|
|
27
29
|
import { completeInitialSetup } from '../core/admin.js';
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
+
import { resolveUiDeploymentSettings } from '../core/ui-deployment.js';
|
|
31
|
+
import { saveUiEnv, buildInitialUiEnvConfig } from '../core/ui-env.js';
|
|
32
|
+
import { writeFile, chmod, mkdir } from 'node:fs/promises';
|
|
33
|
+
import { join, dirname } from 'node:path';
|
|
30
34
|
// =============================================================================
|
|
31
35
|
// Session & Security
|
|
32
36
|
// =============================================================================
|
|
@@ -117,6 +121,29 @@ export function createApiRoutes() {
|
|
|
117
121
|
api.use('/deploy', validateSession);
|
|
118
122
|
api.use('/reset', validateSession);
|
|
119
123
|
api.use('/admin/*', validateSession);
|
|
124
|
+
api.use('/cloudflare/*', validateSession);
|
|
125
|
+
// ==========================================================================
|
|
126
|
+
// Cloudflare Zone Check
|
|
127
|
+
// ==========================================================================
|
|
128
|
+
api.post('/cloudflare/check-zone', async (c) => {
|
|
129
|
+
try {
|
|
130
|
+
const body = (await c.req.json());
|
|
131
|
+
const { domain } = body;
|
|
132
|
+
if (!domain || typeof domain !== 'string') {
|
|
133
|
+
return c.json({ found: false, error: 'domain is required' }, 400);
|
|
134
|
+
}
|
|
135
|
+
if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*\.[a-z]{2,}$/.test(domain)) {
|
|
136
|
+
return c.json({ found: false, error: 'Invalid domain format' }, 400);
|
|
137
|
+
}
|
|
138
|
+
const { checkZoneExists } = await import('../core/cloudflare.js');
|
|
139
|
+
const result = await checkZoneExists(domain);
|
|
140
|
+
return c.json(result);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
144
|
+
return c.json({ found: false, error: message }, 500);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
120
147
|
// Get current state (no auth required - read-only)
|
|
121
148
|
api.get('/state', (c) => {
|
|
122
149
|
return c.json(state);
|
|
@@ -248,10 +275,13 @@ export function createApiRoutes() {
|
|
|
248
275
|
// Use new structure for saving
|
|
249
276
|
const envPaths = getEnvironmentPaths({ baseDir, env });
|
|
250
277
|
// Ensure directory exists
|
|
251
|
-
const { mkdir } = await import('node:fs/promises');
|
|
252
278
|
await mkdir(envPaths.root, { recursive: true });
|
|
253
279
|
// Save config
|
|
254
280
|
await writeFile(envPaths.config, JSON.stringify(config, null, 2));
|
|
281
|
+
const initialUiEnv = buildInitialUiEnvConfig(config);
|
|
282
|
+
if (initialUiEnv) {
|
|
283
|
+
await saveUiEnv(envPaths.uiEnv, initialUiEnv);
|
|
284
|
+
}
|
|
255
285
|
state.config = config;
|
|
256
286
|
return c.json({ success: true, configPath: envPaths.config, structure: 'new' });
|
|
257
287
|
}
|
|
@@ -268,34 +298,21 @@ export function createApiRoutes() {
|
|
|
268
298
|
return withLock(async () => {
|
|
269
299
|
try {
|
|
270
300
|
const body = await c.req.json();
|
|
271
|
-
const { env = 'prod', apiDomain, loginUiDomain, adminUiDomain, tenant, components } = body;
|
|
301
|
+
const { env = 'prod', apiDomain, loginUiDomain, adminUiDomain, tenant, components, zoneId, customDomainBinding, } = body;
|
|
272
302
|
const config = createDefaultConfig(env);
|
|
273
303
|
// Update tenant configuration
|
|
274
304
|
if (tenant) {
|
|
275
|
-
config.tenant =
|
|
276
|
-
name: tenant.name || 'default',
|
|
277
|
-
displayName: tenant.displayName || 'Default Tenant',
|
|
278
|
-
multiTenant: tenant.multiTenant || false,
|
|
279
|
-
baseDomain: tenant.baseDomain,
|
|
280
|
-
};
|
|
305
|
+
config.tenant = normalizeTenantConfigForApiDomain(tenant);
|
|
281
306
|
}
|
|
282
307
|
// Update URLs with domain configuration
|
|
283
|
-
config.urls = {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
sameAsApi: false,
|
|
292
|
-
},
|
|
293
|
-
adminUi: {
|
|
294
|
-
custom: adminUiDomain || null,
|
|
295
|
-
auto: `https://${env}-ar-admin-ui.pages.dev`,
|
|
296
|
-
sameAsApi: false,
|
|
297
|
-
},
|
|
298
|
-
};
|
|
308
|
+
config.urls = buildUrlsConfig({
|
|
309
|
+
env,
|
|
310
|
+
apiDomain,
|
|
311
|
+
loginUiDomain,
|
|
312
|
+
adminUiDomain,
|
|
313
|
+
zoneId: zoneId || null,
|
|
314
|
+
customDomainBinding: customDomainBinding ?? false,
|
|
315
|
+
});
|
|
299
316
|
// Update components if provided
|
|
300
317
|
if (components) {
|
|
301
318
|
config.components = {
|
|
@@ -385,7 +402,6 @@ export function createApiRoutes() {
|
|
|
385
402
|
const baseDir = findAuthrimBaseDir(keysBaseDir);
|
|
386
403
|
const envPaths = getEnvironmentPaths({ baseDir, env, keysBaseDir });
|
|
387
404
|
// Ensure directory exists with restrictive permissions
|
|
388
|
-
const { mkdir } = await import('node:fs/promises');
|
|
389
405
|
await mkdir(keysDir, { recursive: true, mode: 0o700 });
|
|
390
406
|
// Save API key with restrictive permissions
|
|
391
407
|
await writeFile(envPaths.keyFiles.resendApiKey, apiKey.trim());
|
|
@@ -475,6 +491,8 @@ export function createApiRoutes() {
|
|
|
475
491
|
addProgress('Creating lock file...');
|
|
476
492
|
const lock = createLockFile(env, resources);
|
|
477
493
|
const rootDir = findAuthrimBaseDir(process.cwd());
|
|
494
|
+
const envPaths = getEnvironmentPaths({ baseDir: rootDir, env });
|
|
495
|
+
addProgress(`Saving lock.json to ${envPaths.lock} ...`);
|
|
478
496
|
await saveLockFile(lock, { env, baseDir: rootDir });
|
|
479
497
|
// Save config.json
|
|
480
498
|
addProgress('Saving config.json...');
|
|
@@ -497,16 +515,32 @@ export function createApiRoutes() {
|
|
|
497
515
|
const apiUrl = workersSubdomain
|
|
498
516
|
? `https://${env}-ar-router.${workersSubdomain}.workers.dev`
|
|
499
517
|
: `https://${env}-ar-router.workers.dev`;
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
518
|
+
config.urls = buildUrlsConfig({
|
|
519
|
+
env,
|
|
520
|
+
apiDomain: config.urls?.api?.custom || null,
|
|
521
|
+
loginUiDomain: config.urls?.loginUi?.custom || null,
|
|
522
|
+
adminUiDomain: config.urls?.adminUi?.custom || null,
|
|
523
|
+
zoneId: config.urls?.api?.zoneId ?? null,
|
|
524
|
+
customDomainBinding: config.urls?.api?.customDomainBinding ?? false,
|
|
525
|
+
workersSubdomain,
|
|
526
|
+
existingUrls: {
|
|
527
|
+
api: {
|
|
528
|
+
...config.urls?.api,
|
|
529
|
+
auto: apiUrl,
|
|
530
|
+
},
|
|
531
|
+
loginUi: config.urls?.loginUi,
|
|
532
|
+
adminUi: config.urls?.adminUi,
|
|
533
|
+
},
|
|
534
|
+
});
|
|
507
535
|
addProgress(`Configured URLs: API=${apiUrl}`);
|
|
508
|
-
|
|
536
|
+
// Explicitly ensure directory exists (defense in depth; saveLockFile also creates it)
|
|
537
|
+
await mkdir(dirname(envPaths.config), { recursive: true });
|
|
538
|
+
addProgress(`Saving config.json to ${envPaths.config} ...`);
|
|
509
539
|
await writeFile(envPaths.config, JSON.stringify(config, null, 2), 'utf-8');
|
|
540
|
+
const initialUiEnv = buildInitialUiEnvConfig(config);
|
|
541
|
+
if (initialUiEnv) {
|
|
542
|
+
await saveUiEnv(envPaths.uiEnv, initialUiEnv);
|
|
543
|
+
}
|
|
510
544
|
state.config = config;
|
|
511
545
|
// Generate wrangler.toml files
|
|
512
546
|
addProgress('Generating wrangler.toml files...');
|
|
@@ -535,11 +569,18 @@ export function createApiRoutes() {
|
|
|
535
569
|
}
|
|
536
570
|
state.status = 'configuring';
|
|
537
571
|
addProgress('Provisioning complete!');
|
|
572
|
+
addProgress(`📁 Config saved: ${envPaths.config}`);
|
|
573
|
+
addProgress(`📁 Lock saved: ${envPaths.lock}`);
|
|
538
574
|
return c.json({
|
|
539
575
|
success: true,
|
|
540
576
|
resources,
|
|
541
577
|
lock,
|
|
542
578
|
config,
|
|
579
|
+
savedPaths: {
|
|
580
|
+
config: envPaths.config,
|
|
581
|
+
lock: envPaths.lock,
|
|
582
|
+
root: envPaths.root,
|
|
583
|
+
},
|
|
543
584
|
});
|
|
544
585
|
}
|
|
545
586
|
catch (error) {
|
|
@@ -644,7 +685,11 @@ export function createApiRoutes() {
|
|
|
644
685
|
const baseDir = findAuthrimBaseDir(process.cwd());
|
|
645
686
|
const resolved = resolvePaths({ baseDir, env });
|
|
646
687
|
let keysDir;
|
|
647
|
-
const foundKeys = findKeysDirectory({
|
|
688
|
+
const foundKeys = findKeysDirectory({
|
|
689
|
+
env,
|
|
690
|
+
sourceDir: baseDir,
|
|
691
|
+
keysBaseDir: process.cwd(),
|
|
692
|
+
});
|
|
648
693
|
if (foundKeys) {
|
|
649
694
|
keysDir = foundKeys.path;
|
|
650
695
|
}
|
|
@@ -659,6 +704,7 @@ export function createApiRoutes() {
|
|
|
659
704
|
const secrets = {};
|
|
660
705
|
const secretFiles = [
|
|
661
706
|
{ file: join(keysDir, 'private.pem'), name: 'PRIVATE_KEY_PEM' },
|
|
707
|
+
{ file: join(keysDir, 'public.jwk.json'), name: 'PUBLIC_JWK_JSON' },
|
|
662
708
|
{ file: join(keysDir, 'rp_token_encryption_key.txt'), name: 'RP_TOKEN_ENCRYPTION_KEY' },
|
|
663
709
|
{ file: join(keysDir, 'admin_api_secret.txt'), name: 'ADMIN_API_SECRET' },
|
|
664
710
|
{ file: join(keysDir, 'key_manager_secret.txt'), name: 'KEY_MANAGER_SECRET' },
|
|
@@ -802,45 +848,70 @@ export function createApiRoutes() {
|
|
|
802
848
|
const apiBaseUrl = cfg?.urls?.api?.custom ||
|
|
803
849
|
cfg?.urls?.api?.auto ||
|
|
804
850
|
`https://${env}-ar-router.workers.dev`;
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
851
|
+
let loginUiClientId;
|
|
852
|
+
if (cfg?.components?.loginUi && !dryRun) {
|
|
853
|
+
const loginUiUrl = cfg?.urls?.loginUi?.custom ||
|
|
854
|
+
cfg?.urls?.loginUi?.auto ||
|
|
855
|
+
`https://${env}-ar-login-ui.pages.dev`;
|
|
856
|
+
const foundKeys = findKeysDirectory({
|
|
857
|
+
env,
|
|
858
|
+
sourceDir: rootDir,
|
|
859
|
+
keysBaseDir: process.cwd(),
|
|
860
|
+
});
|
|
861
|
+
const adminApiSecretPath = foundKeys
|
|
862
|
+
? join(foundKeys.path, 'admin_api_secret.txt')
|
|
863
|
+
: resolved.paths.keyFiles.adminApiSecret;
|
|
864
|
+
const { ensureLoginUiClient } = await import('../core/login-ui-client.js');
|
|
865
|
+
const clientResult = await ensureLoginUiClient({
|
|
866
|
+
apiBaseUrl,
|
|
867
|
+
loginUiUrl,
|
|
868
|
+
adminApiSecretPath,
|
|
869
|
+
onProgress: addProgress,
|
|
870
|
+
});
|
|
871
|
+
if (clientResult.success && clientResult.clientId) {
|
|
872
|
+
loginUiClientId = clientResult.clientId;
|
|
873
|
+
if (clientResult.alreadyExists) {
|
|
874
|
+
addProgress(` ✓ Login UI client exists: ${loginUiClientId}`);
|
|
824
875
|
}
|
|
825
876
|
else {
|
|
826
|
-
|
|
827
|
-
PUBLIC_API_BASE_URL: '', // Empty for proxy mode (same-origin)
|
|
828
|
-
API_BACKEND_URL: apiBaseUrl, // Server-side proxy target
|
|
829
|
-
});
|
|
830
|
-
addProgress(`ui.env synced (proxy mode: ${apiBaseUrl})`);
|
|
877
|
+
addProgress(` ✓ Login UI client created: ${loginUiClientId}`);
|
|
831
878
|
}
|
|
832
879
|
}
|
|
833
|
-
|
|
834
|
-
addProgress(
|
|
880
|
+
else {
|
|
881
|
+
addProgress(` ⚠️ Login UI client creation skipped: ${clientResult.error}`);
|
|
835
882
|
}
|
|
836
883
|
}
|
|
884
|
+
const loginUiSettings = resolveUiDeploymentSettings({
|
|
885
|
+
component: 'ar-login-ui',
|
|
886
|
+
config: cfg,
|
|
887
|
+
apiBaseUrl,
|
|
888
|
+
loginUiClientId,
|
|
889
|
+
});
|
|
890
|
+
const adminUiSettings = resolveUiDeploymentSettings({
|
|
891
|
+
component: 'ar-admin-ui',
|
|
892
|
+
config: cfg,
|
|
893
|
+
apiBaseUrl,
|
|
894
|
+
});
|
|
837
895
|
pagesSummary = await deployAllPages({
|
|
838
896
|
env,
|
|
839
897
|
rootDir: resolve(rootDir),
|
|
840
898
|
dryRun,
|
|
841
899
|
onProgress: addProgress,
|
|
842
900
|
apiBaseUrl,
|
|
843
|
-
|
|
901
|
+
perComponent: {
|
|
902
|
+
'ar-login-ui': {
|
|
903
|
+
apiBaseUrl: loginUiSettings.apiBaseUrl,
|
|
904
|
+
runtimeApiBackendUrl: loginUiSettings.runtimeApiBackendUrl,
|
|
905
|
+
uiEnvConfig: loginUiSettings.uiEnv,
|
|
906
|
+
serviceBindingName: loginUiSettings.serviceBindingName,
|
|
907
|
+
},
|
|
908
|
+
'ar-admin-ui': {
|
|
909
|
+
apiBaseUrl: adminUiSettings.apiBaseUrl,
|
|
910
|
+
runtimeApiBackendUrl: adminUiSettings.runtimeApiBackendUrl,
|
|
911
|
+
uiEnvConfig: adminUiSettings.uiEnv,
|
|
912
|
+
serviceBindingName: adminUiSettings.serviceBindingName,
|
|
913
|
+
},
|
|
914
|
+
},
|
|
844
915
|
}, {
|
|
845
916
|
loginUi: cfg?.components?.loginUi ?? true,
|
|
846
917
|
adminUi: cfg?.components?.adminUi ?? true,
|
|
@@ -865,10 +936,13 @@ export function createApiRoutes() {
|
|
|
865
936
|
// Update lock file with deployed workers information
|
|
866
937
|
if (workersSuccess && !dryRun && summary.successCount > 0) {
|
|
867
938
|
try {
|
|
868
|
-
const { loadLockFileAuto, saveLockFile: saveLock } = await import('../core/lock.js');
|
|
939
|
+
const { loadLockFileAuto, saveLockFile: saveLock, AuthrimLockSchema, } = await import('../core/lock.js');
|
|
869
940
|
const { lock: currentLock, path: lockPath } = await loadLockFileAuto(rootDir, env);
|
|
870
|
-
if (
|
|
871
|
-
|
|
941
|
+
if (lockPath) {
|
|
942
|
+
// Use existing lock or create minimal one (recovery scenario: lock deleted/missing)
|
|
943
|
+
const now = new Date().toISOString();
|
|
944
|
+
const baseLock = currentLock ?? AuthrimLockSchema.parse({ env, createdAt: now });
|
|
945
|
+
const workers = { ...baseLock.workers };
|
|
872
946
|
for (const result of summary.results) {
|
|
873
947
|
if (result.success && result.deployedAt) {
|
|
874
948
|
workers[result.component] = {
|
|
@@ -879,9 +953,9 @@ export function createApiRoutes() {
|
|
|
879
953
|
}
|
|
880
954
|
}
|
|
881
955
|
const updatedLock = {
|
|
882
|
-
...
|
|
956
|
+
...baseLock,
|
|
883
957
|
workers,
|
|
884
|
-
updatedAt:
|
|
958
|
+
updatedAt: now,
|
|
885
959
|
};
|
|
886
960
|
await saveLock(updatedLock, lockPath);
|
|
887
961
|
addProgress('Lock file updated with deployment info');
|
|
@@ -975,7 +1049,11 @@ export function createApiRoutes() {
|
|
|
975
1049
|
const resolved = resolvePaths({ baseDir, env });
|
|
976
1050
|
const isLegacy = resolved.type === 'legacy';
|
|
977
1051
|
// Detect actual token path using 3-tier fallback (external → internal → legacy)
|
|
978
|
-
const foundKeys = findKeysDirectory({
|
|
1052
|
+
const foundKeys = findKeysDirectory({
|
|
1053
|
+
env,
|
|
1054
|
+
sourceDir: baseDir,
|
|
1055
|
+
keysBaseDir: process.cwd(),
|
|
1056
|
+
});
|
|
979
1057
|
const tokenPath = foundKeys
|
|
980
1058
|
? join(foundKeys.path, 'setup_token.txt')
|
|
981
1059
|
: isLegacy
|
|
@@ -1047,7 +1125,7 @@ export function createApiRoutes() {
|
|
|
1047
1125
|
return withLock(async () => {
|
|
1048
1126
|
try {
|
|
1049
1127
|
const body = await c.req.json();
|
|
1050
|
-
const { kvNamespaceId, baseUrl } = body;
|
|
1128
|
+
const { kvNamespaceId, baseUrl, env: envName } = body;
|
|
1051
1129
|
if (!kvNamespaceId || !/^[a-f0-9]{32}$/i.test(kvNamespaceId)) {
|
|
1052
1130
|
return c.json({ success: false, error: 'Invalid KV namespace ID' }, 400);
|
|
1053
1131
|
}
|
|
@@ -1068,8 +1146,29 @@ export function createApiRoutes() {
|
|
|
1068
1146
|
if (!result.success || !result.token) {
|
|
1069
1147
|
return c.json({ success: false, error: result.error || 'Failed to generate token' }, 500);
|
|
1070
1148
|
}
|
|
1149
|
+
// Resolve the best base URL: prefer custom API domain from config
|
|
1150
|
+
let resolvedBaseUrl = baseUrl;
|
|
1151
|
+
if (envName) {
|
|
1152
|
+
try {
|
|
1153
|
+
const baseDir = findAuthrimBaseDir(process.cwd());
|
|
1154
|
+
const resolved = resolvePaths({ baseDir, env: envName });
|
|
1155
|
+
const configPath = resolved.type === 'new'
|
|
1156
|
+
? resolved.paths.config
|
|
1157
|
+
: resolved.paths.config;
|
|
1158
|
+
if (existsSync(configPath)) {
|
|
1159
|
+
const cfg = JSON.parse(await readFile(configPath, 'utf-8'));
|
|
1160
|
+
const configBaseUrl = cfg?.urls?.api?.custom || cfg?.urls?.api?.auto;
|
|
1161
|
+
if (configBaseUrl) {
|
|
1162
|
+
resolvedBaseUrl = configBaseUrl;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
catch {
|
|
1167
|
+
// Config not available, use the provided baseUrl
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1071
1170
|
// Construct setup URL
|
|
1072
|
-
const cleanBaseUrl =
|
|
1171
|
+
const cleanBaseUrl = resolvedBaseUrl.replace(/\/+$/, '');
|
|
1073
1172
|
const setupUrl = `${cleanBaseUrl}/admin-init-setup?token=${result.token}`;
|
|
1074
1173
|
return c.json({
|
|
1075
1174
|
success: true,
|
|
@@ -1455,40 +1554,53 @@ export function createApiRoutes() {
|
|
|
1455
1554
|
const apiBaseUrl = cfg?.urls?.api?.custom ||
|
|
1456
1555
|
cfg?.urls?.api?.auto ||
|
|
1457
1556
|
`https://${env}-ar-router.workers.dev`;
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
const
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1557
|
+
let loginUiClientId;
|
|
1558
|
+
if (componentName === 'ar-login-ui' && !dryRun) {
|
|
1559
|
+
const loginUiUrl = cfg?.urls?.loginUi?.custom ||
|
|
1560
|
+
cfg?.urls?.loginUi?.auto ||
|
|
1561
|
+
`https://${env}-ar-login-ui.pages.dev`;
|
|
1562
|
+
const foundKeys = findKeysDirectory({
|
|
1563
|
+
env,
|
|
1564
|
+
sourceDir: rootDir,
|
|
1565
|
+
keysBaseDir: process.cwd(),
|
|
1566
|
+
});
|
|
1567
|
+
const adminApiSecretPath = foundKeys
|
|
1568
|
+
? join(foundKeys.path, 'admin_api_secret.txt')
|
|
1569
|
+
: resolved.paths.keyFiles.adminApiSecret;
|
|
1570
|
+
const { ensureLoginUiClient } = await import('../core/login-ui-client.js');
|
|
1571
|
+
const clientResult = await ensureLoginUiClient({
|
|
1572
|
+
apiBaseUrl,
|
|
1573
|
+
loginUiUrl,
|
|
1574
|
+
adminApiSecretPath,
|
|
1575
|
+
onProgress: addProgress,
|
|
1576
|
+
});
|
|
1577
|
+
if (clientResult.success && clientResult.clientId) {
|
|
1578
|
+
loginUiClientId = clientResult.clientId;
|
|
1579
|
+
if (clientResult.alreadyExists) {
|
|
1580
|
+
addProgress(` ✓ Login UI client exists: ${loginUiClientId}`);
|
|
1473
1581
|
}
|
|
1474
1582
|
else {
|
|
1475
|
-
|
|
1476
|
-
PUBLIC_API_BASE_URL: '',
|
|
1477
|
-
API_BACKEND_URL: apiBaseUrl,
|
|
1478
|
-
});
|
|
1583
|
+
addProgress(` ✓ Login UI client created: ${loginUiClientId}`);
|
|
1479
1584
|
}
|
|
1480
|
-
addProgress(`ui.env synced for ${componentName}`);
|
|
1481
1585
|
}
|
|
1482
|
-
|
|
1483
|
-
addProgress(`
|
|
1586
|
+
else {
|
|
1587
|
+
addProgress(` ⚠️ Login UI client creation skipped: ${clientResult.error}`);
|
|
1484
1588
|
}
|
|
1485
1589
|
}
|
|
1590
|
+
const uiSettings = resolveUiDeploymentSettings({
|
|
1591
|
+
component: componentName,
|
|
1592
|
+
config: cfg,
|
|
1593
|
+
apiBaseUrl,
|
|
1594
|
+
loginUiClientId,
|
|
1595
|
+
});
|
|
1486
1596
|
const result = await deployPagesComponent(componentName, {
|
|
1487
1597
|
env,
|
|
1488
1598
|
rootDir,
|
|
1489
1599
|
dryRun,
|
|
1490
|
-
apiBaseUrl,
|
|
1491
|
-
|
|
1600
|
+
apiBaseUrl: uiSettings.apiBaseUrl,
|
|
1601
|
+
runtimeApiBackendUrl: uiSettings.runtimeApiBackendUrl,
|
|
1602
|
+
uiEnvConfig: uiSettings.uiEnv,
|
|
1603
|
+
serviceBindingName: uiSettings.serviceBindingName,
|
|
1492
1604
|
onProgress: addProgress,
|
|
1493
1605
|
});
|
|
1494
1606
|
if (result.success) {
|