@envmanager-cli/cli 0.1.2 → 0.1.4

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.
@@ -419,7 +419,7 @@ var whoamiCommand = new Command3("whoami").description("Show current user and te
419
419
  console.error(chalk3.red(userError?.message || "Unknown error"));
420
420
  return;
421
421
  }
422
- const { data: memberships, error: memberError } = await client.from("organization_members").select("role, organizations(name)");
422
+ const { data: memberships, error: memberError } = await client.from("organization_members").select("role, organizations(name)").eq("user_id", user.id);
423
423
  if (memberError) {
424
424
  spinner.fail("Failed to fetch memberships");
425
425
  console.error(chalk3.red(memberError.message));
@@ -506,12 +506,16 @@ function getConfigPath() {
506
506
 
507
507
  // src/lib/resolve.ts
508
508
  var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
509
+ function cleanProjectInput(input) {
510
+ return input.startsWith("#") ? input.slice(1) : input;
511
+ }
509
512
  async function resolveProjectId(input, client, organizationId) {
510
- if (UUID_REGEX.test(input)) {
511
- return input;
513
+ const cleaned = cleanProjectInput(input);
514
+ if (UUID_REGEX.test(cleaned)) {
515
+ return cleaned;
512
516
  }
513
- if (/^\d+$/.test(input)) {
514
- const friendlyId = parseInt(input, 10);
517
+ if (/^\d+$/.test(cleaned)) {
518
+ const friendlyId = parseInt(cleaned, 10);
515
519
  if (friendlyId < 1) {
516
520
  throw new Error("Project ID must be 1 or greater");
517
521
  }
@@ -521,35 +525,58 @@ async function resolveProjectId(input, client, organizationId) {
521
525
  }
522
526
  return data2.id;
523
527
  }
524
- const { data, error } = await client.from("projects").select("id").eq("organization_id", organizationId).ilike("name", input).single();
528
+ const { data, error } = await client.from("projects").select("id").eq("organization_id", organizationId).ilike("name", cleaned).single();
525
529
  if (error || !data) {
526
530
  throw new Error(`Project "${input}" not found in this organization`);
527
531
  }
528
532
  return data.id;
529
533
  }
530
- async function resolveOrganizationId(input, client) {
531
- const { data: memberships, error: memberError } = await client.from("organization_members").select("organization_id, organizations(id, name)");
534
+ async function resolveOrganizationId(input, client, projectHint) {
535
+ const { data: { user } } = await client.auth.getUser();
536
+ if (!user) throw new Error("Not authenticated");
537
+ const { data: memberships, error: memberError } = await client.from("organization_members").select("organization_id, organizations(id, name)").eq("user_id", user.id);
532
538
  if (memberError || !memberships || memberships.length === 0) {
533
539
  throw new Error("No organizations found. Create one at envmanager.dev");
534
540
  }
535
541
  if (memberships.length === 1 && !input) {
536
542
  return memberships[0].organization_id;
537
543
  }
538
- if (!input) {
539
- const orgList = memberships.map((m) => {
544
+ if (input) {
545
+ const match = memberships.find((m) => {
540
546
  const org = m.organizations;
541
- return org?.name || "Unknown";
542
- }).join(", ");
543
- throw new Error(`Multiple organizations found. Use --org to specify: ${orgList}`);
547
+ return org?.name?.toLowerCase() === input.toLowerCase();
548
+ });
549
+ if (!match) {
550
+ throw new Error(`Organization "${input}" not found or you don't have access`);
551
+ }
552
+ return match.organization_id;
544
553
  }
545
- const match = memberships.find((m) => {
554
+ if (projectHint) {
555
+ const orgId = await detectOrgFromProject(projectHint, client, memberships);
556
+ if (orgId) return orgId;
557
+ }
558
+ const orgList = memberships.map((m) => {
546
559
  const org = m.organizations;
547
- return org?.name?.toLowerCase() === input.toLowerCase();
548
- });
549
- if (!match) {
550
- throw new Error(`Organization "${input}" not found or you don't have access`);
560
+ return org?.name || "Unknown";
561
+ }).join(", ");
562
+ throw new Error(`Multiple organizations found. Use --org to specify: ${orgList}`);
563
+ }
564
+ async function detectOrgFromProject(projectInput, client, memberships) {
565
+ const cleaned = cleanProjectInput(projectInput);
566
+ const orgIds = memberships.map((m) => m.organization_id);
567
+ if (UUID_REGEX.test(cleaned)) {
568
+ const { data: data2 } = await client.from("projects").select("organization_id").eq("id", cleaned).in("organization_id", orgIds).single();
569
+ return data2?.organization_id ?? null;
570
+ }
571
+ if (/^\d+$/.test(cleaned)) {
572
+ const friendlyId = parseInt(cleaned, 10);
573
+ const { data: data2 } = await client.from("projects").select("organization_id").in("organization_id", orgIds).eq("friendly_id", friendlyId);
574
+ if (data2 && data2.length === 1) return data2[0].organization_id;
575
+ return null;
551
576
  }
552
- return match.organization_id;
577
+ const { data } = await client.from("projects").select("organization_id").in("organization_id", orgIds).ilike("name", cleaned);
578
+ if (data && data.length === 1) return data[0].organization_id;
579
+ return null;
553
580
  }
554
581
 
555
582
  // src/lib/variable-references.ts
@@ -731,7 +758,7 @@ var pullCommand = new Command4("pull").description("Pull environment variables f
731
758
  const client = await createClient();
732
759
  let organizationId;
733
760
  try {
734
- organizationId = await resolveOrganizationId(options.org, client);
761
+ organizationId = await resolveOrganizationId(options.org, client, projectInput);
735
762
  } catch (error) {
736
763
  spinner.fail(error instanceof Error ? error.message : "Failed to resolve organization");
737
764
  process.exit(1);
@@ -1026,7 +1053,7 @@ var pushCommand = new Command5("push").description("Push local .env file to EnvM
1026
1053
  const client = await createClient();
1027
1054
  let organizationId;
1028
1055
  try {
1029
- organizationId = await resolveOrganizationId(options.org, client);
1056
+ organizationId = await resolveOrganizationId(options.org, client, projectInput);
1030
1057
  } catch (error) {
1031
1058
  spinner.fail(error instanceof Error ? error.message : "Failed to resolve organization");
1032
1059
  process.exit(1);
@@ -1158,7 +1185,7 @@ var diffCommand = new Command6("diff").description("Show differences between loc
1158
1185
  const client = await createClient();
1159
1186
  let organizationId;
1160
1187
  try {
1161
- organizationId = await resolveOrganizationId(options.org, client);
1188
+ organizationId = await resolveOrganizationId(options.org, client, projectInput);
1162
1189
  } catch (error) {
1163
1190
  spinner.fail(error instanceof Error ? error.message : "Failed to resolve organization");
1164
1191
  process.exit(1);
@@ -1269,7 +1296,9 @@ var listCommand = new Command7("list").description("List projects, environments,
1269
1296
  case "projects":
1270
1297
  case "project": {
1271
1298
  spinner.text = "Fetching projects...";
1272
- const { data: memberships, error: memberError } = await client.from("organization_members").select("organization_id");
1299
+ const { data: { user: currentUser } } = await client.auth.getUser();
1300
+ if (!currentUser) throw new Error("Not authenticated");
1301
+ const { data: memberships, error: memberError } = await client.from("organization_members").select("organization_id").eq("user_id", currentUser.id);
1273
1302
  if (memberError) throw new Error(memberError.message);
1274
1303
  const orgIds = memberships?.map((m) => m.organization_id) || [];
1275
1304
  if (orgIds.length === 0) {
@@ -1310,7 +1339,7 @@ var listCommand = new Command7("list").description("List projects, environments,
1310
1339
  }
1311
1340
  let organizationId;
1312
1341
  try {
1313
- organizationId = await resolveOrganizationId(options.org, client);
1342
+ organizationId = await resolveOrganizationId(options.org, client, projectInput);
1314
1343
  } catch (error) {
1315
1344
  spinner.fail(error instanceof Error ? error.message : "Failed to resolve organization");
1316
1345
  process.exit(1);
@@ -1354,7 +1383,7 @@ var listCommand = new Command7("list").description("List projects, environments,
1354
1383
  }
1355
1384
  let organizationId;
1356
1385
  try {
1357
- organizationId = await resolveOrganizationId(options.org, client);
1386
+ organizationId = await resolveOrganizationId(options.org, client, projectInput);
1358
1387
  } catch (error) {
1359
1388
  spinner.fail(error instanceof Error ? error.message : "Failed to resolve organization");
1360
1389
  process.exit(1);
@@ -1678,7 +1707,7 @@ var devCommand = new Command9("dev").description("Start real-time sync daemon -
1678
1707
  const client = await createClient();
1679
1708
  let organizationId;
1680
1709
  try {
1681
- organizationId = await resolveOrganizationId(options.org, client);
1710
+ organizationId = await resolveOrganizationId(options.org, client, projectInput);
1682
1711
  } catch (error) {
1683
1712
  spinner.fail(error instanceof Error ? error.message : "Failed to resolve organization");
1684
1713
  process.exit(1);
@@ -2657,7 +2686,7 @@ var validateCommand = new Command12("validate").description("Validate local .env
2657
2686
  const client = await createClient();
2658
2687
  let organizationId;
2659
2688
  try {
2660
- organizationId = await resolveOrganizationId(options.org, client);
2689
+ organizationId = await resolveOrganizationId(options.org, client, projectInput);
2661
2690
  } catch (error) {
2662
2691
  spinner.fail(error instanceof Error ? error.message : "Failed to resolve organization");
2663
2692
  process.exit(1);
@@ -2875,7 +2904,9 @@ async function getProjectCompletions(prefix) {
2875
2904
  try {
2876
2905
  if (!getCredentials()) return [];
2877
2906
  const client = await createClient();
2878
- const { data: memberships } = await client.from("organization_members").select("organization_id");
2907
+ const { data: { user } } = await client.auth.getUser();
2908
+ if (!user) return [];
2909
+ const { data: memberships } = await client.from("organization_members").select("organization_id").eq("user_id", user.id);
2879
2910
  if (!memberships || memberships.length === 0) return [];
2880
2911
  const orgIds = memberships.map((m) => m.organization_id);
2881
2912
  const { data: projects } = await client.from("projects").select("name").in("organization_id", orgIds).order("name");