@construct-space/cli 1.8.1 → 1.9.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.
Files changed (2) hide show
  1. package/dist/index.js +113 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3090,6 +3090,83 @@ var init_whoami = __esm(() => {
3090
3090
  init_auth();
3091
3091
  });
3092
3092
 
3093
+ // src/commands/org.ts
3094
+ var exports_org = {};
3095
+ __export(exports_org, {
3096
+ orgStatus: () => orgStatus
3097
+ });
3098
+ async function orgStatus() {
3099
+ let creds;
3100
+ try {
3101
+ creds = load2();
3102
+ } catch {
3103
+ console.error(source_default.red("Not signed in."));
3104
+ console.error(source_default.dim("Run 'construct login' first."));
3105
+ process.exit(1);
3106
+ }
3107
+ let s;
3108
+ try {
3109
+ const res = await fetch(ACCOUNTS_SCOPE_URL3, {
3110
+ headers: { Authorization: `Bearer ${creds.token}`, Accept: "application/json" }
3111
+ });
3112
+ if (!res.ok) {
3113
+ console.error(source_default.red(`Scope lookup failed (${res.status}).`));
3114
+ console.error(source_default.dim("Token may be expired. Try: construct login"));
3115
+ process.exit(1);
3116
+ }
3117
+ s = await res.json();
3118
+ } catch (err) {
3119
+ console.error(source_default.red(`Could not reach accounts service: ${err?.message || err}`));
3120
+ process.exit(1);
3121
+ }
3122
+ if (!s.authenticated || !s.user) {
3123
+ console.error(source_default.red("Token rejected."));
3124
+ process.exit(1);
3125
+ }
3126
+ if (s.scope === "org" && s.org) {
3127
+ console.log(source_default.cyan("Scope: ") + source_default.bold(`org \u2014 ${s.org.name || s.org.slug || s.org.id}`));
3128
+ if (s.org.slug)
3129
+ console.log(source_default.dim(` slug: ${s.org.slug}`));
3130
+ if (s.org.id)
3131
+ console.log(source_default.dim(` id: ${s.org.id}`));
3132
+ if (s.roles && s.roles.length) {
3133
+ console.log(source_default.dim(` roles: ${s.roles.join(", ")}`));
3134
+ }
3135
+ } else {
3136
+ console.log(source_default.cyan("Scope: ") + source_default.bold("personal"));
3137
+ console.log(source_default.dim(" (switch to an org at https://my.construct.space)"));
3138
+ }
3139
+ console.log();
3140
+ console.log(source_default.cyan("Signed in as"));
3141
+ console.log(` ${s.user.email || s.user.username || s.user.uuid || "(unknown)"}`);
3142
+ if (s.user.uuid)
3143
+ console.log(source_default.dim(` ${s.user.uuid}`));
3144
+ console.log();
3145
+ console.log(source_default.cyan("Publisher (from auth.json)"));
3146
+ if (creds.publisherKey) {
3147
+ const kind = creds.publisherKind || "user";
3148
+ const expected = s.scope === "org" ? "org" : "user";
3149
+ const matches = kind === expected;
3150
+ console.log(` ${source_default.bold(creds.publisherName || "(unnamed)")} ${source_default.dim(`[${kind}]`)}`);
3151
+ console.log(source_default.dim(` key: ${creds.publisherKey.slice(0, 14)}\u2026`));
3152
+ if (!matches) {
3153
+ console.log(source_default.yellow(` \u26A0 publisher kind (${kind}) doesn't match active scope (${expected}).`));
3154
+ console.log(source_default.dim(" Restart the desktop app or run 'construct login' to re-sync."));
3155
+ }
3156
+ } else {
3157
+ console.log(source_default.dim(" (none \u2014 enroll as a developer to get a publisher key)"));
3158
+ }
3159
+ if (s.developer) {
3160
+ console.log();
3161
+ console.log(source_default.dim("developer capability: ") + source_default.green("enabled"));
3162
+ }
3163
+ }
3164
+ var ACCOUNTS_SCOPE_URL3 = "https://my.construct.space/api/accounts/me/scope";
3165
+ var init_org = __esm(() => {
3166
+ init_source();
3167
+ init_auth();
3168
+ });
3169
+
3093
3170
  // src/lib/graphClient.ts
3094
3171
  function graphBaseURL() {
3095
3172
  return process.env.GRAPH_URL || "https://graph.construct.space";
@@ -10468,6 +10545,13 @@ async function publish(options) {
10468
10545
  const yes = options?.yes ?? false;
10469
10546
  const wantPrivate = options?.private ?? false;
10470
10547
  const wantPublic = options?.public ?? false;
10548
+ const scopeOpt = options?.scope ? options.scope.toLowerCase() : undefined;
10549
+ if (scopeOpt && scopeOpt !== "user" && scopeOpt !== "org") {
10550
+ console.error(source_default.red(`--scope must be 'user' or 'org', got '${options?.scope}'.`));
10551
+ process.exit(1);
10552
+ }
10553
+ const wantOrgScope = scopeOpt === "org";
10554
+ const wantUserScope = scopeOpt === "user";
10471
10555
  if (wantPrivate && wantPublic) {
10472
10556
  console.error(source_default.red("Cannot combine --private and --public. Pick one."));
10473
10557
  process.exit(1);
@@ -10561,10 +10645,19 @@ async function publish(options) {
10561
10645
  console.log(source_default.dim(" (Org Settings \u2192 Developer), then re-run this command."));
10562
10646
  console.log();
10563
10647
  }
10564
- if (wantPrivate && creds.publisherKind !== "org") {
10648
+ if (wantUserScope && creds.publisherKind === "org" && !options?.apiKey) {
10649
+ console.error(source_default.red("--scope=user, but the active publisher in auth.json is an org publisher."));
10650
+ console.error(source_default.dim(" Switch context to personal in the desktop app, or pass --api-key with a personal key."));
10651
+ process.exit(1);
10652
+ }
10653
+ if (wantOrgScope && creds.publisherKind === "user" && !options?.apiKey) {
10654
+ creds = { ...creds, publisherKey: undefined, publisherKind: undefined, publisherName: undefined };
10655
+ }
10656
+ if (wantPrivate && creds.publisherKind !== "org" && !wantOrgScope) {
10565
10657
  console.error(source_default.red("--private requires an org publisher key."));
10566
10658
  console.error(source_default.dim(" Personal publishes are always public."));
10567
- console.error(source_default.dim(" Enrol an org from the desktop app (Org Settings \u2192 Developer) and re-run."));
10659
+ console.error(source_default.dim(" Pass --scope=org to publish as your active org, or enrol an org"));
10660
+ console.error(source_default.dim(" from the desktop app (Org Settings \u2192 Developer) first."));
10568
10661
  process.exit(1);
10569
10662
  }
10570
10663
  console.log();
@@ -10609,12 +10702,24 @@ async function publish(options) {
10609
10702
  const uploadSpinner = ora("Uploading & building...").start();
10610
10703
  try {
10611
10704
  const explicitKey = options?.apiKey || process.env.CONSTRUCT_PUBLISHER_KEY;
10612
- const initialKey = explicitKey || creds.publisherKey;
10705
+ let initialKey = explicitKey || creds.publisherKey;
10706
+ if (wantOrgScope && !explicitKey && !initialKey) {
10707
+ uploadSpinner.text = "Fetching org publisher key\u2026";
10708
+ const orgKey = await fetchOrgPublisherKey(creds.portal, creds.token);
10709
+ if (!orgKey) {
10710
+ uploadSpinner.fail("No org publisher available for --scope=org");
10711
+ console.error(source_default.dim(" Switch into an org context in the desktop app, or pass --api-key"));
10712
+ console.error(source_default.dim(" with a csk_live_* key the org owns."));
10713
+ unlinkSync2(tarballPath);
10714
+ process.exit(1);
10715
+ }
10716
+ initialKey = orgKey;
10717
+ }
10613
10718
  let result;
10614
10719
  try {
10615
10720
  result = await uploadSource(creds.portal, creds.token, initialKey, tarballPath, m, { private: wantPrivate, public: wantPublic });
10616
10721
  } catch (e) {
10617
- if (e?.ownerKind === "org" && !creds.publisherKey) {
10722
+ if (e?.ownerKind === "org" && !creds.publisherKey && !wantUserScope) {
10618
10723
  uploadSpinner.text = "Fetching org publisher key\u2026";
10619
10724
  const orgKey = await fetchOrgPublisherKey(creds.portal, creds.token);
10620
10725
  if (!orgKey)
@@ -11593,7 +11698,7 @@ function graphFork(newSpaceID) {
11593
11698
  // package.json
11594
11699
  var package_default = {
11595
11700
  name: "@construct-space/cli",
11596
- version: "1.8.1",
11701
+ version: "1.9.0",
11597
11702
  description: "Construct CLI \u2014 scaffold, build, develop, and publish spaces",
11598
11703
  type: "module",
11599
11704
  bin: {
@@ -11645,7 +11750,7 @@ program2.command("scaffold [name]").alias("new").alias("create").description("Cr
11645
11750
  program2.command("build").description("Build the space (generate entry + run Vite)").option("--entry-only", "Only generate src/entry.ts").action(async (opts) => build(opts));
11646
11751
  program2.command("dev").description("Start dev mode with file watching and live reload").action(async () => dev());
11647
11752
  program2.command("install").alias("run").description("Install built space to Construct spaces directory").action(() => install());
11648
- program2.command("publish").description("Publish a space to the Construct registry").option("-y, --yes", "Skip all confirmation prompts").option("--bump <type>", "Auto-bump version (patch, minor, major)").option("--private", "Publish as org-private (catalog-listed only inside the owning org). Requires an org publisher key.").option("--public", "Flip a previously-private space back to the public catalog on this publish. Without --private or --public, visibility is preserved on update (and defaults to public on first publish).").option("--api-key <key>", "Publisher API key (csk_live_\u2026). Overrides any key stored in the active profile. Also reads CONSTRUCT_PUBLISHER_KEY.").action(async (opts) => publish(opts));
11753
+ program2.command("publish").description("Publish a space to the Construct registry").option("-y, --yes", "Skip all confirmation prompts").option("--bump <type>", "Auto-bump version (patch, minor, major)").option("--private", "Publish as org-private (catalog-listed only inside the owning org). Requires an org publisher key.").option("--public", "Flip a previously-private space back to the public catalog on this publish. Without --private or --public, visibility is preserved on update (and defaults to public on first publish).").option("--scope <scope>", "Publish as 'user' (personal) or 'org'. Without this flag, the active publisher in auth.json decides.").option("--api-key <key>", "Publisher API key (csk_live_\u2026). Overrides any key stored in the active profile. Also reads CONSTRUCT_PUBLISHER_KEY.").action(async (opts) => publish(opts));
11649
11754
  program2.command("validate").description("Validate space.manifest.json").action(() => validate3());
11650
11755
  program2.command("check").description("Run type-check (vue-tsc) and linter (eslint)").action(() => check());
11651
11756
  program2.command("clean").description("Remove build artifacts").option("--all", "Also remove node_modules and lockfiles").action((opts) => clean(opts));
@@ -11653,6 +11758,8 @@ program2.command("login").description("Authenticate with Construct").option("--p
11653
11758
  program2.command("logout").description("Sign out").action(() => logout());
11654
11759
  program2.command("update").description("Update the CLI to the latest version").action(() => update());
11655
11760
  program2.command("whoami").alias("status").description("Show the signed-in user + current org scope").action(async () => (await Promise.resolve().then(() => (init_whoami(), exports_whoami))).whoami());
11761
+ var org = program2.command("org").description("Inspect the active organization context");
11762
+ org.command("status").description("Show active scope, publisher, and roles").action(async () => (await Promise.resolve().then(() => (init_org(), exports_org))).orgStatus());
11656
11763
  var graph = program2.command("graph").description("Construct Graph \u2014 data models and GraphQL");
11657
11764
  graph.command("init").description("Initialize Graph in a space project").action(() => graphInit());
11658
11765
  graph.command("generate <model> [fields...]").alias("g").description("Generate a data model").option("--access <rules>", "Access rules (e.g. read:member,create:member,update:owner,delete:admin)").action((model, fields, opts) => generate2(model, fields, opts));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@construct-space/cli",
3
- "version": "1.8.1",
3
+ "version": "1.9.0",
4
4
  "description": "Construct CLI — scaffold, build, develop, and publish spaces",
5
5
  "type": "module",
6
6
  "bin": {