@igoruehara/canvas-flow 0.1.10 → 0.1.11
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/bin/canvas-flow.js +80 -6
- package/package.json +1 -1
- package/public/assets/{index-qV8twxcq.js → index-CAYKh0bn.js} +78 -78
- package/public/index.html +1 -1
- package/server/auth/auth-controller.d.ts +2 -0
- package/server/auth/auth-service.d.ts +2 -0
- package/server/auth/auth-service.js +5 -0
- package/server/auth/auth-service.js.map +1 -1
package/bin/canvas-flow.js
CHANGED
|
@@ -465,6 +465,19 @@ function joinCorsOrigins(config, publicUrl, port) {
|
|
|
465
465
|
].join(',');
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
+
function isLoopbackUrl(value) {
|
|
469
|
+
try {
|
|
470
|
+
const hostname = new URL(value).hostname.toLowerCase();
|
|
471
|
+
return hostname === 'localhost'
|
|
472
|
+
|| hostname === '::1'
|
|
473
|
+
|| hostname === '[::1]'
|
|
474
|
+
|| hostname === '0.0.0.0'
|
|
475
|
+
|| hostname.startsWith('127.');
|
|
476
|
+
} catch {
|
|
477
|
+
return false;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
468
481
|
function applyEnvironment(config, paths, flags) {
|
|
469
482
|
const port = Number(flags.port || config.server.port || 3333);
|
|
470
483
|
const publicUrl = String(flags['public-url'] || config.server.publicUrl || `http://localhost:${port}`).replace(/\/$/, '');
|
|
@@ -515,11 +528,18 @@ function applyEnvironment(config, paths, flags) {
|
|
|
515
528
|
setEnv('MONGO_SERVER_SELECTION_TIMEOUT_MS', config.database.mongoServerSelectionTimeoutMs);
|
|
516
529
|
setEnv('MONGO_CONNECT_TIMEOUT_MS', config.database.mongoConnectTimeoutMs);
|
|
517
530
|
|
|
518
|
-
|
|
531
|
+
const loginRequired = asBool(config.auth.login);
|
|
532
|
+
const exposeApiTokenToFrontend = config.auth.exposeApiTokenToFrontend === true
|
|
533
|
+
|| (!loginRequired && isLoopbackUrl(publicUrl));
|
|
534
|
+
setBoolEnv('CANVAS_FLOW_LOGIN', loginRequired);
|
|
519
535
|
setEnv('CANVAS_FLOW_LOGIN_TTL_HOURS', config.auth.loginTtlHours);
|
|
520
536
|
setEnv('CANVAS_FLOW_LOGIN_THROTTLE_WINDOW_MS', config.auth.loginThrottleWindowMs || 600000);
|
|
521
537
|
setEnv('CANVAS_FLOW_LOGIN_MAX_ATTEMPTS', config.auth.loginMaxAttempts || 8);
|
|
522
538
|
setEnv('CANVAS_FLOW_API_TOKEN', config.auth.apiToken);
|
|
539
|
+
delete process.env.CANVAS_FLOW_FRONTEND_API_TOKEN;
|
|
540
|
+
if (!loginRequired && exposeApiTokenToFrontend) {
|
|
541
|
+
setEnv('CANVAS_FLOW_FRONTEND_API_TOKEN', config.auth.apiToken);
|
|
542
|
+
}
|
|
523
543
|
setEnv('CANVAS_FLOW_JWT_SECRET', config.auth.jwtSecret);
|
|
524
544
|
setEnv('CANVAS_FLOW_MEDIA_PROXY_SECRET', config.auth.mediaProxySecret);
|
|
525
545
|
setEnv('CANVAS_FLOW_MEDIA_PROXY_TTL_SECONDS', config.auth.mediaProxyTtlSeconds);
|
|
@@ -815,6 +835,59 @@ function sleep(ms) {
|
|
|
815
835
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
816
836
|
}
|
|
817
837
|
|
|
838
|
+
async function checkHttpOk(url, timeoutMs = 1200) {
|
|
839
|
+
const controller = new AbortController();
|
|
840
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
841
|
+
try {
|
|
842
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
843
|
+
return response.ok;
|
|
844
|
+
} catch {
|
|
845
|
+
return false;
|
|
846
|
+
} finally {
|
|
847
|
+
clearTimeout(timer);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
function startStartupStatus(publicUrl, options = {}) {
|
|
852
|
+
const healthUrl = `${String(publicUrl || '').replace(/\/$/, '')}/health`;
|
|
853
|
+
const startedAt = Date.now();
|
|
854
|
+
let stopped = false;
|
|
855
|
+
|
|
856
|
+
console.log('Canvas Flow startup: loading application bundle...');
|
|
857
|
+
console.log(`Canvas Flow startup: waiting for backend health at ${healthUrl}`);
|
|
858
|
+
|
|
859
|
+
const interval = setInterval(() => {
|
|
860
|
+
const elapsedSeconds = Math.max(1, Math.round((Date.now() - startedAt) / 1000));
|
|
861
|
+
console.log(`Canvas Flow startup: still starting (${elapsedSeconds}s elapsed)...`);
|
|
862
|
+
}, 2500);
|
|
863
|
+
|
|
864
|
+
const stop = () => {
|
|
865
|
+
if (stopped) return;
|
|
866
|
+
stopped = true;
|
|
867
|
+
clearInterval(interval);
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
void (async () => {
|
|
871
|
+
const deadline = Date.now() + 90000;
|
|
872
|
+
while (!stopped && Date.now() < deadline) {
|
|
873
|
+
if (await checkHttpOk(healthUrl)) {
|
|
874
|
+
stop();
|
|
875
|
+
console.log(`Canvas Flow ready: ${publicUrl}`);
|
|
876
|
+
if (options.openBrowser) openBrowser(publicUrl);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
await sleep(500);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
if (!stopped) {
|
|
883
|
+
stop();
|
|
884
|
+
console.log('Canvas Flow startup: health check is still pending. Keep this terminal open and watch the backend logs above.');
|
|
885
|
+
}
|
|
886
|
+
})();
|
|
887
|
+
|
|
888
|
+
return { stop };
|
|
889
|
+
}
|
|
890
|
+
|
|
818
891
|
function mongoConnectionOptions(config) {
|
|
819
892
|
return {
|
|
820
893
|
serverSelectionTimeoutMS: Number(config.database?.mongoServerSelectionTimeoutMs || 8000),
|
|
@@ -1147,12 +1220,13 @@ async function start(flags) {
|
|
|
1147
1220
|
}
|
|
1148
1221
|
|
|
1149
1222
|
const shouldOpen = flags.open === true || (flags.open !== false && config.server.openBrowser === true);
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1223
|
+
const startupStatus = startStartupStatus(runtime.publicUrl, { openBrowser: shouldOpen });
|
|
1224
|
+
try {
|
|
1225
|
+
require(SERVER_ENTRY);
|
|
1226
|
+
} catch (error) {
|
|
1227
|
+
startupStatus.stop();
|
|
1228
|
+
throw error;
|
|
1153
1229
|
}
|
|
1154
|
-
|
|
1155
|
-
require(SERVER_ENTRY);
|
|
1156
1230
|
}
|
|
1157
1231
|
|
|
1158
1232
|
async function main() {
|
package/package.json
CHANGED