@edge-base/cli 0.1.5 → 0.2.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.
@@ -41,8 +41,7 @@ async function verifyAdminJwt(token, secret) {
41
41
  }
42
42
  }
43
43
  async function verifyAuth(req, adminSecret) {
44
- const internalSecret = req.headers['x-edgebase-internal-secret'] ??
45
- req.headers['X-EdgeBase-Internal-Secret'];
44
+ const internalSecret = req.headers['x-edgebase-internal-secret'] ?? req.headers['X-EdgeBase-Internal-Secret'];
46
45
  const internalValue = Array.isArray(internalSecret) ? internalSecret[0] : internalSecret;
47
46
  if (internalValue && internalValue === adminSecret) {
48
47
  return true;
@@ -81,6 +80,14 @@ function readBody(req) {
81
80
  function parsePath(urlPath) {
82
81
  return urlPath.split('/').filter(Boolean);
83
82
  }
83
+ function sanitizeForLog(value) {
84
+ const escape = String.fromCharCode(27);
85
+ const ansiPattern = new RegExp(`${escape}\\[[0-9;]*[A-Za-z]`, 'g');
86
+ const cleaned = value
87
+ .replace(ansiPattern, '')
88
+ .replace(/[\r\n\t]+/g, ' ');
89
+ return cleaned.replace(/[^ -~]/g, '?');
90
+ }
84
91
  function isDynamicDbBlock(dbBlock) {
85
92
  if (!dbBlock)
86
93
  return false;
@@ -96,8 +103,8 @@ function parseAuthSettingsTarget(value) {
96
103
  return value === 'release' ? 'release' : 'development';
97
104
  }
98
105
  function isManagedAuthEnvKey(key) {
99
- return MANAGED_AUTH_ENV_KEYS.includes(key)
100
- || MANAGED_AUTH_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
106
+ return (MANAGED_AUTH_ENV_KEYS.includes(key) ||
107
+ MANAGED_AUTH_ENV_PREFIXES.some((prefix) => key.startsWith(prefix)));
101
108
  }
102
109
  function readAuthEnvValues(projectDir, target) {
103
110
  if (target === 'release') {
@@ -150,10 +157,12 @@ function getOAuthEnvKeys(provider) {
150
157
  }
151
158
  function getEnvTargets(projectDir, target) {
152
159
  if (target === 'release') {
153
- return [{
160
+ return [
161
+ {
154
162
  filePath: join(projectDir, '.env.release'),
155
163
  header: RELEASE_ENV_HEADER,
156
- }];
164
+ },
165
+ ];
157
166
  }
158
167
  const envDevelopmentPath = join(projectDir, '.env.development');
159
168
  const devVarsPath = join(projectDir, '.dev.vars');
@@ -195,7 +204,10 @@ function syncOAuthSecretsToLocalEnv(projectDir, target, allowedOAuthProviders, o
195
204
  }
196
205
  if (envKeys.scopes) {
197
206
  const scopesValue = Array.isArray(config.scopes)
198
- ? config.scopes.map((scope) => scope.trim()).filter(Boolean).join(',')
207
+ ? config.scopes
208
+ .map((scope) => scope.trim())
209
+ .filter(Boolean)
210
+ .join(',')
199
211
  : null;
200
212
  updateEnvValue(projectDir, target, envKeys.scopes, scopesValue && scopesValue.length > 0 ? scopesValue : null);
201
213
  }
@@ -231,10 +243,14 @@ function readAuthSettings(config) {
231
243
  };
232
244
  }
233
245
  return {
234
- providers: Array.isArray(authConfig.allowedOAuthProviders) ? authConfig.allowedOAuthProviders : [],
246
+ providers: Array.isArray(authConfig.allowedOAuthProviders)
247
+ ? authConfig.allowedOAuthProviders
248
+ : [],
235
249
  emailAuth: authConfig.emailAuth !== false,
236
250
  anonymousAuth: !!authConfig.anonymousAuth,
237
- allowedRedirectUrls: Array.isArray(authConfig.allowedRedirectUrls) ? authConfig.allowedRedirectUrls : [],
251
+ allowedRedirectUrls: Array.isArray(authConfig.allowedRedirectUrls)
252
+ ? authConfig.allowedRedirectUrls
253
+ : [],
238
254
  session: {
239
255
  accessTokenTTL: authConfig.session?.accessTokenTTL ?? null,
240
256
  refreshTokenTTL: authConfig.session?.refreshTokenTTL ?? null,
@@ -348,7 +364,7 @@ async function executeWorkerSql(opts, authorization, namespace, sql, params = []
348
364
  }
349
365
  let message = `SQL execution failed with ${response.status}`;
350
366
  try {
351
- const payload = await response.json();
367
+ const payload = (await response.json());
352
368
  if (payload.message) {
353
369
  message = payload.message;
354
370
  }
@@ -370,7 +386,7 @@ async function callWorkerAdmin(opts, authorization, path, body) {
370
386
  if (!response.ok) {
371
387
  let message = `${path} failed with ${response.status}`;
372
388
  try {
373
- const payload = await response.json();
389
+ const payload = (await response.json());
374
390
  if (payload.message) {
375
391
  message = payload.message;
376
392
  }
@@ -449,9 +465,11 @@ function readCurrentSchema(configPath) {
449
465
  try {
450
466
  // Use a quick approach: read config via tsx eval
451
467
  const projectDir = resolve(configPath, '..');
468
+ const moduleUrl = pathToFileURL(resolve(configPath)).href;
452
469
  const result = execTsxSync([
453
470
  '-e',
454
- `import c from ${JSON.stringify(configPath)}; const d=c.default??c; const s={}; for (const [ns,b] of Object.entries(d.databases??{})) { for (const [t,tc] of Object.entries((b as any).tables??{})) { s[t]={namespace:ns,fields:(tc as any).schema??{},fts:(tc as any).fts??[]}; } } console.log(JSON.stringify(s));`,
471
+ `(async()=>{const moduleUrl=process.argv[1];const mod=await import(moduleUrl);const d=mod.default??mod;const s={};for(const [ns,b] of Object.entries(d.databases??{})){for(const [t,tc] of Object.entries((b as any).tables??{})){s[t]={namespace:ns,fields:(tc as any).schema??{},fts:(tc as any).fts??[]};}}console.log(JSON.stringify(s));})().catch((error)=>{console.error(error instanceof Error?error.message:String(error));process.exit(1);});`,
472
+ moduleUrl,
455
473
  ], { cwd: projectDir, encoding: 'utf-8', timeout: 10000, stdio: ['pipe', 'pipe', 'ignore'] }).trim();
456
474
  return JSON.parse(result);
457
475
  }
@@ -471,7 +489,10 @@ async function handleRoute(req, res, opts) {
471
489
  return;
472
490
  }
473
491
  // POST /postgres/query — pooled local PostgreSQL query bridge for Worker dev mode
474
- if (method === 'POST' && segments[0] === 'postgres' && segments[1] === 'query' && segments.length === 2) {
492
+ if (method === 'POST' &&
493
+ segments[0] === 'postgres' &&
494
+ segments[1] === 'query' &&
495
+ segments.length === 2) {
475
496
  const body = await readBody(req);
476
497
  const namespace = body.namespace;
477
498
  const sql = body.sql;
@@ -492,7 +513,10 @@ async function handleRoute(req, res, opts) {
492
513
  return;
493
514
  }
494
515
  // POST /postgres/ensure-schema — persistent local PostgreSQL schema warmup/cache
495
- if (method === 'POST' && segments[0] === 'postgres' && segments[1] === 'ensure-schema' && segments.length === 2) {
516
+ if (method === 'POST' &&
517
+ segments[0] === 'postgres' &&
518
+ segments[1] === 'ensure-schema' &&
519
+ segments.length === 2) {
496
520
  const body = await readBody(req);
497
521
  const namespace = body.namespace;
498
522
  if (!namespace)
@@ -508,7 +532,10 @@ async function handleRoute(req, res, opts) {
508
532
  return;
509
533
  }
510
534
  // POST /schema/tables — create table
511
- if (method === 'POST' && segments[0] === 'schema' && segments[1] === 'tables' && segments.length === 2) {
535
+ if (method === 'POST' &&
536
+ segments[0] === 'schema' &&
537
+ segments[1] === 'tables' &&
538
+ segments.length === 2) {
512
539
  const body = await readBody(req);
513
540
  const dbKey = body.dbKey || 'shared';
514
541
  const name = body.name;
@@ -520,7 +547,10 @@ async function handleRoute(req, res, opts) {
520
547
  return;
521
548
  }
522
549
  // POST /schema/databases — create database block
523
- if (method === 'POST' && segments[0] === 'schema' && segments[1] === 'databases' && segments.length === 2) {
550
+ if (method === 'POST' &&
551
+ segments[0] === 'schema' &&
552
+ segments[1] === 'databases' &&
553
+ segments.length === 2) {
524
554
  const body = await readBody(req);
525
555
  const name = body.name;
526
556
  const topology = body.topology ?? 'single';
@@ -543,14 +573,18 @@ async function handleRoute(req, res, opts) {
543
573
  return;
544
574
  }
545
575
  // POST /integrations/neon/databases — create postgres DB block + configure Neon envs
546
- if (method === 'POST' && segments[0] === 'integrations' && segments[1] === 'neon' && segments[2] === 'databases' && segments.length === 3) {
576
+ if (method === 'POST' &&
577
+ segments[0] === 'integrations' &&
578
+ segments[1] === 'neon' &&
579
+ segments[2] === 'databases' &&
580
+ segments.length === 3) {
547
581
  const body = await readBody(req);
548
582
  const name = body.name;
549
583
  const topology = body.topology ?? 'single';
550
584
  const envKey = body.envKey;
551
585
  const projectName = body.projectName;
552
586
  const projectId = body.projectId;
553
- const mode = (body.mode ?? 'reuse');
587
+ const mode = body.mode ?? 'reuse';
554
588
  const targetLabel = body.targetLabel;
555
589
  const placeholder = body.placeholder;
556
590
  const helperText = body.helperText;
@@ -588,12 +622,16 @@ async function handleRoute(req, res, opts) {
588
622
  return;
589
623
  }
590
624
  // POST /integrations/neon/connect — configure Neon envs for an existing postgres DB block
591
- if (method === 'POST' && segments[0] === 'integrations' && segments[1] === 'neon' && segments[2] === 'connect' && segments.length === 3) {
625
+ if (method === 'POST' &&
626
+ segments[0] === 'integrations' &&
627
+ segments[1] === 'neon' &&
628
+ segments[2] === 'connect' &&
629
+ segments.length === 3) {
592
630
  const body = await readBody(req);
593
631
  const namespace = body.namespace;
594
632
  const envKey = body.envKey;
595
633
  const projectId = body.projectId;
596
- const mode = (body.mode ?? 'reuse');
634
+ const mode = body.mode ?? 'reuse';
597
635
  if (!namespace)
598
636
  throw new Error('namespace is required.');
599
637
  const config = loadSidecarConfig(opts);
@@ -628,13 +666,17 @@ async function handleRoute(req, res, opts) {
628
666
  return;
629
667
  }
630
668
  // POST /integrations/neon/upgrade — migrate a D1 single DB block to Neon-backed postgres
631
- if (method === 'POST' && segments[0] === 'integrations' && segments[1] === 'neon' && segments[2] === 'upgrade' && segments.length === 3) {
669
+ if (method === 'POST' &&
670
+ segments[0] === 'integrations' &&
671
+ segments[1] === 'neon' &&
672
+ segments[2] === 'upgrade' &&
673
+ segments.length === 3) {
632
674
  const body = await readBody(req);
633
675
  const namespace = body.namespace;
634
676
  const envKey = body.envKey;
635
677
  const projectName = body.projectName;
636
678
  const projectId = body.projectId;
637
- const mode = (body.mode ?? 'reuse');
679
+ const mode = body.mode ?? 'reuse';
638
680
  const authorization = req.headers.authorization;
639
681
  if (!namespace)
640
682
  throw new Error('namespace is required.');
@@ -646,8 +688,9 @@ async function handleRoute(req, res, opts) {
646
688
  throw new Error(`Only D1-backed single database blocks can be upgraded automatically. '${namespace}' is on '${provider}'.`);
647
689
  }
648
690
  const effectiveEnvKey = resolveRequestedPostgresEnvKey(namespace, envKey);
691
+ const namespaceLabel = sanitizeForLog(namespace);
649
692
  console.log();
650
- console.log(chalk.blue(`📦 Starting D1 -> Postgres migration for database block '${namespace}'...`));
693
+ console.log(chalk.blue(`📦 Starting D1 -> Postgres migration for database block '${namespaceLabel}'...`));
651
694
  console.log(chalk.dim(' This migrates every table in the block, not just the current table.'));
652
695
  console.log(chalk.dim(' 1/4 Exporting all tables from D1...'));
653
696
  const dump = await callWorkerAdmin(opts, authorization, 'data/backup/dump-data', { namespace });
@@ -675,7 +718,7 @@ async function handleRoute(req, res, opts) {
675
718
  tables: dump.tables,
676
719
  skipWipe: false,
677
720
  });
678
- console.log(chalk.green(`✓ Database block '${namespace}' is now running on Postgres (${dumpedTableCount} table${dumpedTableCount === 1 ? '' : 's'} restored).`));
721
+ console.log(chalk.green(`✓ Database block '${namespaceLabel}' is now running on Postgres (${dumpedTableCount} table${dumpedTableCount === 1 ? '' : 's'} restored).`));
679
722
  json(res, 200, {
680
723
  ok: true,
681
724
  mode,
@@ -687,12 +730,16 @@ async function handleRoute(req, res, opts) {
687
730
  return;
688
731
  }
689
732
  // GET /integrations/neon/projects — list existing Neon projects for dashboard selection
690
- if (method === 'GET' && segments[0] === 'integrations' && segments[1] === 'neon' && segments[2] === 'projects' && segments.length === 3) {
733
+ if (method === 'GET' &&
734
+ segments[0] === 'integrations' &&
735
+ segments[1] === 'neon' &&
736
+ segments[2] === 'projects' &&
737
+ segments.length === 3) {
691
738
  const forceRefresh = url.searchParams.get('refresh') === '1';
692
- const isCacheFresh = !forceRefresh
693
- && neonProjectsCache
694
- && (Date.now() - neonProjectsCache.loadedAt) < NEON_PROJECT_CACHE_TTL_MS;
695
- const items = (isCacheFresh && neonProjectsCache)
739
+ const isCacheFresh = !forceRefresh &&
740
+ neonProjectsCache &&
741
+ Date.now() - neonProjectsCache.loadedAt < NEON_PROJECT_CACHE_TTL_MS;
742
+ const items = isCacheFresh && neonProjectsCache
696
743
  ? neonProjectsCache.items
697
744
  : await listAvailableNeonProjects({
698
745
  projectDir: opts.projectDir,
@@ -707,7 +754,11 @@ async function handleRoute(req, res, opts) {
707
754
  return;
708
755
  }
709
756
  // POST /schema/storage/buckets — create storage bucket
710
- if (method === 'POST' && segments[0] === 'schema' && segments[1] === 'storage' && segments[2] === 'buckets' && segments.length === 3) {
757
+ if (method === 'POST' &&
758
+ segments[0] === 'schema' &&
759
+ segments[1] === 'storage' &&
760
+ segments[2] === 'buckets' &&
761
+ segments.length === 3) {
711
762
  const body = await readBody(req);
712
763
  const name = body.name;
713
764
  if (!name)
@@ -717,7 +768,10 @@ async function handleRoute(req, res, opts) {
717
768
  return;
718
769
  }
719
770
  // DELETE /schema/tables/:name — delete table
720
- if (method === 'DELETE' && segments[0] === 'schema' && segments[1] === 'tables' && segments.length === 3) {
771
+ if (method === 'DELETE' &&
772
+ segments[0] === 'schema' &&
773
+ segments[1] === 'tables' &&
774
+ segments.length === 3) {
721
775
  const tableName = segments[2];
722
776
  const body = await readBody(req);
723
777
  const dbKey = body.dbKey || 'shared';
@@ -726,7 +780,11 @@ async function handleRoute(req, res, opts) {
726
780
  return;
727
781
  }
728
782
  // PUT /schema/tables/:name/rename — rename table
729
- if (method === 'PUT' && segments[0] === 'schema' && segments[1] === 'tables' && segments[3] === 'rename' && segments.length === 4) {
783
+ if (method === 'PUT' &&
784
+ segments[0] === 'schema' &&
785
+ segments[1] === 'tables' &&
786
+ segments[3] === 'rename' &&
787
+ segments.length === 4) {
730
788
  const tableName = segments[2];
731
789
  const body = await readBody(req);
732
790
  const dbKey = body.dbKey || 'shared';
@@ -753,7 +811,11 @@ async function handleRoute(req, res, opts) {
753
811
  return;
754
812
  }
755
813
  // POST /schema/tables/:name/columns — add column
756
- if (method === 'POST' && segments[0] === 'schema' && segments[1] === 'tables' && segments[3] === 'columns' && segments.length === 4) {
814
+ if (method === 'POST' &&
815
+ segments[0] === 'schema' &&
816
+ segments[1] === 'tables' &&
817
+ segments[3] === 'columns' &&
818
+ segments.length === 4) {
757
819
  const tableName = segments[2];
758
820
  const body = await readBody(req);
759
821
  const dbKey = body.dbKey || 'shared';
@@ -768,7 +830,11 @@ async function handleRoute(req, res, opts) {
768
830
  return;
769
831
  }
770
832
  // PUT /schema/tables/:name/columns/:col — update column
771
- if (method === 'PUT' && segments[0] === 'schema' && segments[1] === 'tables' && segments[3] === 'columns' && segments.length === 5) {
833
+ if (method === 'PUT' &&
834
+ segments[0] === 'schema' &&
835
+ segments[1] === 'tables' &&
836
+ segments[3] === 'columns' &&
837
+ segments.length === 5) {
772
838
  const tableName = segments[2];
773
839
  const columnName = segments[4];
774
840
  const body = await readBody(req);
@@ -781,7 +847,11 @@ async function handleRoute(req, res, opts) {
781
847
  return;
782
848
  }
783
849
  // DELETE /schema/tables/:name/columns/:col — remove column
784
- if (method === 'DELETE' && segments[0] === 'schema' && segments[1] === 'tables' && segments[3] === 'columns' && segments.length === 5) {
850
+ if (method === 'DELETE' &&
851
+ segments[0] === 'schema' &&
852
+ segments[1] === 'tables' &&
853
+ segments[3] === 'columns' &&
854
+ segments.length === 5) {
785
855
  const tableName = segments[2];
786
856
  const columnName = segments[4];
787
857
  const body = await readBody(req);
@@ -791,7 +861,11 @@ async function handleRoute(req, res, opts) {
791
861
  return;
792
862
  }
793
863
  // POST /schema/tables/:name/indexes — add index
794
- if (method === 'POST' && segments[0] === 'schema' && segments[1] === 'tables' && segments[3] === 'indexes' && segments.length === 4) {
864
+ if (method === 'POST' &&
865
+ segments[0] === 'schema' &&
866
+ segments[1] === 'tables' &&
867
+ segments[3] === 'indexes' &&
868
+ segments.length === 4) {
795
869
  const tableName = segments[2];
796
870
  const body = await readBody(req);
797
871
  const dbKey = body.dbKey || 'shared';
@@ -803,7 +877,11 @@ async function handleRoute(req, res, opts) {
803
877
  return;
804
878
  }
805
879
  // DELETE /schema/tables/:name/indexes/:idx — remove index
806
- if (method === 'DELETE' && segments[0] === 'schema' && segments[1] === 'tables' && segments[3] === 'indexes' && segments.length === 5) {
880
+ if (method === 'DELETE' &&
881
+ segments[0] === 'schema' &&
882
+ segments[1] === 'tables' &&
883
+ segments[3] === 'indexes' &&
884
+ segments.length === 5) {
807
885
  const tableName = segments[2];
808
886
  const indexIdx = parseInt(segments[4], 10);
809
887
  const body = await readBody(req);
@@ -813,7 +891,11 @@ async function handleRoute(req, res, opts) {
813
891
  return;
814
892
  }
815
893
  // PUT /schema/tables/:name/fts — set FTS fields
816
- if (method === 'PUT' && segments[0] === 'schema' && segments[1] === 'tables' && segments[3] === 'fts' && segments.length === 4) {
894
+ if (method === 'PUT' &&
895
+ segments[0] === 'schema' &&
896
+ segments[1] === 'tables' &&
897
+ segments[3] === 'fts' &&
898
+ segments.length === 4) {
817
899
  const tableName = segments[2];
818
900
  const body = await readBody(req);
819
901
  const dbKey = body.dbKey || 'shared';
@@ -824,14 +906,20 @@ async function handleRoute(req, res, opts) {
824
906
  }
825
907
  // ─── Auth Settings Editing ───
826
908
  // GET /auth/settings — read current auth config
827
- if (method === 'GET' && segments[0] === 'auth' && segments[1] === 'settings' && segments.length === 2) {
909
+ if (method === 'GET' &&
910
+ segments[0] === 'auth' &&
911
+ segments[1] === 'settings' &&
912
+ segments.length === 2) {
828
913
  const target = parseAuthSettingsTarget(url.searchParams.get('target'));
829
914
  const config = loadSidecarConfig(opts, target);
830
915
  json(res, 200, { ok: true, target, ...readAuthSettings(config) });
831
916
  return;
832
917
  }
833
918
  // PUT /auth/settings — save auth config
834
- if (method === 'PUT' && segments[0] === 'auth' && segments[1] === 'settings' && segments.length === 2) {
919
+ if (method === 'PUT' &&
920
+ segments[0] === 'auth' &&
921
+ segments[1] === 'settings' &&
922
+ segments.length === 2) {
835
923
  const target = parseAuthSettingsTarget(url.searchParams.get('target'));
836
924
  const body = await readBody(req);
837
925
  const session = body.session;
@@ -903,7 +991,10 @@ async function handleRoute(req, res, opts) {
903
991
  }
904
992
  // ─── Email Template Editing ───
905
993
  // PUT /email/templates — save email subject/template override (with optional locale)
906
- if (method === 'PUT' && segments[0] === 'email' && segments[1] === 'templates' && segments.length === 2) {
994
+ if (method === 'PUT' &&
995
+ segments[0] === 'email' &&
996
+ segments[1] === 'templates' &&
997
+ segments.length === 2) {
907
998
  const body = await readBody(req);
908
999
  const type = body.type;
909
1000
  const locale = body.locale ?? 'en';
@@ -953,13 +1044,18 @@ async function handleRoute(req, res, opts) {
953
1044
  return;
954
1045
  }
955
1046
  // GET /email/templates — read current email config
956
- if (method === 'GET' && segments[0] === 'email' && segments[1] === 'templates' && segments.length === 2) {
1047
+ if (method === 'GET' &&
1048
+ segments[0] === 'email' &&
1049
+ segments[1] === 'templates' &&
1050
+ segments.length === 2) {
957
1051
  // Re-read the full config to get email section
958
1052
  try {
959
1053
  const projectDir = resolve(opts.configPath, '..');
1054
+ const moduleUrl = pathToFileURL(resolve(opts.configPath)).href;
960
1055
  const result = execTsxSync([
961
1056
  '-e',
962
- `import c from ${JSON.stringify(opts.configPath)}; const d=c.default??c; const e=d.email??{}; console.log(JSON.stringify({appName:e.appName||'EdgeBase',subjects:e.subjects||{},templates:e.templates||{}}));`,
1057
+ `(async()=>{const moduleUrl=process.argv[1];const mod=await import(moduleUrl);const d=mod.default??mod;const e=d.email??{};console.log(JSON.stringify({appName:e.appName||'EdgeBase',subjects:e.subjects||{},templates:e.templates||{}}));})().catch((error)=>{console.error(error instanceof Error?error.message:String(error));process.exit(1);});`,
1058
+ moduleUrl,
963
1059
  ], { cwd: projectDir, encoding: 'utf-8', timeout: 10000, stdio: ['pipe', 'pipe', 'ignore'] }).trim();
964
1060
  const emailConfig = JSON.parse(result);
965
1061
  json(res, 200, { ok: true, ...emailConfig });
@@ -1002,7 +1098,7 @@ export function startSidecar(opts) {
1002
1098
  console.log(chalk.dim(` 📐 Schema Editor sidecar skipped (:${opts.port} already in use)`));
1003
1099
  return;
1004
1100
  }
1005
- console.log(chalk.dim(' 📐 Schema Editor sidecar skipped:'), err.message);
1101
+ console.log(chalk.dim(' 📐 Schema Editor sidecar skipped:'), sanitizeForLog(err.message));
1006
1102
  });
1007
1103
  server.listen(opts.port, () => {
1008
1104
  console.log(chalk.dim(` 📐 Schema Editor sidecar on :${opts.port}`));
@@ -1034,7 +1130,8 @@ export function parseEnvFile(filePath) {
1034
1130
  const key = trimmed.slice(0, eqIdx).trim();
1035
1131
  let value = trimmed.slice(eqIdx + 1).trim();
1036
1132
  // Strip surrounding quotes
1037
- if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
1133
+ if ((value.startsWith('"') && value.endsWith('"')) ||
1134
+ (value.startsWith("'") && value.endsWith("'"))) {
1038
1135
  value = value.slice(1, -1);
1039
1136
  }
1040
1137
  vars[key] = value;