@revos/cli 0.2.1 → 0.2.3

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 (162) hide show
  1. package/README.md +289 -77
  2. package/dist/adapters/oclif/commands/action-runs/get.mjs +1 -1
  3. package/dist/adapters/oclif/commands/action-runs/list.mjs +8 -2
  4. package/dist/adapters/oclif/commands/actions/get-input-schema.mjs +2 -2
  5. package/dist/adapters/oclif/commands/actions/get-params-schema.mjs +2 -2
  6. package/dist/adapters/oclif/commands/actions/get.mjs +1 -1
  7. package/dist/adapters/oclif/commands/actions/list.mjs +8 -4
  8. package/dist/adapters/oclif/commands/ai-instructions/create.mjs +1 -1
  9. package/dist/adapters/oclif/commands/ai-instructions/delete.mjs +1 -1
  10. package/dist/adapters/oclif/commands/ai-instructions/get.mjs +1 -1
  11. package/dist/adapters/oclif/commands/ai-instructions/list.mjs +8 -2
  12. package/dist/adapters/oclif/commands/ai-instructions/update.mjs +1 -1
  13. package/dist/adapters/oclif/commands/api.d.mts +11 -0
  14. package/dist/adapters/oclif/commands/api.mjs +112 -0
  15. package/dist/adapters/oclif/commands/apply.d.mts +29 -0
  16. package/dist/adapters/oclif/commands/apply.mjs +77 -0
  17. package/dist/adapters/oclif/commands/auth/login.d.mts +6 -4
  18. package/dist/adapters/oclif/commands/auth/login.mjs +23 -11
  19. package/dist/adapters/oclif/commands/auth/logout.d.mts +2 -1
  20. package/dist/adapters/oclif/commands/auth/logout.mjs +3 -2
  21. package/dist/adapters/oclif/commands/auth/status.d.mts +4 -2
  22. package/dist/adapters/oclif/commands/auth/status.mjs +23 -3
  23. package/dist/adapters/oclif/commands/connections/create.d.mts +6 -0
  24. package/dist/adapters/oclif/commands/connections/create.mjs +8 -0
  25. package/dist/adapters/oclif/commands/connections/delete.d.mts +6 -0
  26. package/dist/adapters/oclif/commands/connections/delete.mjs +8 -0
  27. package/dist/adapters/oclif/commands/connections/get.d.mts +6 -0
  28. package/dist/adapters/oclif/commands/connections/get.mjs +8 -0
  29. package/dist/adapters/oclif/commands/connections/list.d.mts +6 -0
  30. package/dist/adapters/oclif/commands/connections/list.mjs +14 -0
  31. package/dist/adapters/oclif/commands/connections/update.d.mts +6 -0
  32. package/dist/adapters/oclif/commands/connections/update.mjs +8 -0
  33. package/dist/adapters/oclif/commands/cubes/create.d.mts +6 -0
  34. package/dist/adapters/oclif/commands/cubes/create.mjs +8 -0
  35. package/dist/adapters/oclif/commands/cubes/delete.d.mts +6 -0
  36. package/dist/adapters/oclif/commands/cubes/delete.mjs +8 -0
  37. package/dist/adapters/oclif/commands/cubes/get.d.mts +6 -0
  38. package/dist/adapters/oclif/commands/cubes/get.mjs +8 -0
  39. package/dist/adapters/oclif/commands/cubes/list.d.mts +6 -0
  40. package/dist/adapters/oclif/commands/cubes/list.mjs +13 -0
  41. package/dist/adapters/oclif/commands/cubes/update.d.mts +6 -0
  42. package/dist/adapters/oclif/commands/cubes/update.mjs +8 -0
  43. package/dist/adapters/oclif/commands/diff.d.mts +28 -0
  44. package/dist/adapters/oclif/commands/diff.mjs +66 -0
  45. package/dist/adapters/oclif/commands/gservice-account-keys/get.mjs +1 -1
  46. package/dist/adapters/oclif/commands/gservice-account-keys/reveal.mjs +2 -2
  47. package/dist/adapters/oclif/commands/gservice-accounts/create.mjs +1 -1
  48. package/dist/adapters/oclif/commands/gservice-accounts/delete.mjs +1 -1
  49. package/dist/adapters/oclif/commands/gservice-accounts/get.mjs +1 -1
  50. package/dist/adapters/oclif/commands/gservice-accounts/list.mjs +7 -2
  51. package/dist/adapters/oclif/commands/init.d.mts +3 -1
  52. package/dist/adapters/oclif/commands/init.mjs +27 -23
  53. package/dist/adapters/oclif/commands/org/create.mjs +3 -2
  54. package/dist/adapters/oclif/commands/org/current.d.mts +12 -3
  55. package/dist/adapters/oclif/commands/org/current.mjs +27 -2
  56. package/dist/adapters/oclif/commands/org/get.mjs +3 -2
  57. package/dist/adapters/oclif/commands/org/list.d.mts +3 -11
  58. package/dist/adapters/oclif/commands/org/list.mjs +35 -26
  59. package/dist/adapters/oclif/commands/org/switch.d.mts +4 -2
  60. package/dist/adapters/oclif/commands/org/switch.mjs +16 -3
  61. package/dist/adapters/oclif/commands/pull.d.mts +29 -0
  62. package/dist/adapters/oclif/commands/pull.mjs +88 -0
  63. package/dist/adapters/oclif/commands/score-groups/create.mjs +3 -2
  64. package/dist/adapters/oclif/commands/score-groups/delete.mjs +1 -1
  65. package/dist/adapters/oclif/commands/score-groups/get.mjs +1 -1
  66. package/dist/adapters/oclif/commands/score-groups/list.mjs +3 -2
  67. package/dist/adapters/oclif/commands/score-groups/update.mjs +1 -1
  68. package/dist/adapters/oclif/commands/scores/create.mjs +3 -2
  69. package/dist/adapters/oclif/commands/scores/delete.mjs +1 -1
  70. package/dist/adapters/oclif/commands/scores/list.mjs +3 -2
  71. package/dist/adapters/oclif/commands/scores/update.mjs +1 -1
  72. package/dist/adapters/oclif/commands/segments/create.mjs +1 -1
  73. package/dist/adapters/oclif/commands/segments/delete.mjs +1 -1
  74. package/dist/adapters/oclif/commands/segments/evaluate.mjs +2 -2
  75. package/dist/adapters/oclif/commands/segments/get-evaluation-history.mjs +2 -2
  76. package/dist/adapters/oclif/commands/segments/get-version.mjs +2 -2
  77. package/dist/adapters/oclif/commands/segments/get.mjs +1 -1
  78. package/dist/adapters/oclif/commands/segments/list-versions.mjs +16 -5
  79. package/dist/adapters/oclif/commands/segments/list.mjs +9 -2
  80. package/dist/adapters/oclif/commands/segments/restore-version.mjs +2 -2
  81. package/dist/adapters/oclif/commands/segments/update.mjs +1 -1
  82. package/dist/adapters/oclif/commands/sources/create.d.mts +11 -0
  83. package/dist/adapters/oclif/commands/sources/create.mjs +16 -0
  84. package/dist/adapters/oclif/commands/sources/delete.d.mts +6 -0
  85. package/dist/adapters/oclif/commands/sources/delete.mjs +8 -0
  86. package/dist/adapters/oclif/commands/sources/get.d.mts +6 -0
  87. package/dist/adapters/oclif/commands/sources/get.mjs +8 -0
  88. package/dist/adapters/oclif/commands/sources/list-streams.d.mts +6 -0
  89. package/dist/adapters/oclif/commands/sources/list-streams.mjs +31 -0
  90. package/dist/adapters/oclif/commands/sources/list.d.mts +6 -0
  91. package/dist/adapters/oclif/commands/sources/list.mjs +13 -0
  92. package/dist/adapters/oclif/commands/{integrations/get.d.mts → sources/update.d.mts} +4 -4
  93. package/dist/adapters/oclif/commands/sources/update.mjs +21 -0
  94. package/dist/adapters/oclif/commands/status.d.mts +27 -0
  95. package/dist/adapters/oclif/commands/status.mjs +77 -0
  96. package/dist/adapters/oclif/commands/table-views/create.mjs +3 -2
  97. package/dist/adapters/oclif/commands/table-views/delete.mjs +1 -1
  98. package/dist/adapters/oclif/commands/table-views/list.mjs +3 -2
  99. package/dist/adapters/oclif/commands/table-views/update.mjs +1 -1
  100. package/dist/adapters/oclif/commands/tables/create.mjs +1 -1
  101. package/dist/adapters/oclif/commands/tables/delete.mjs +1 -1
  102. package/dist/adapters/oclif/commands/tables/get.mjs +1 -1
  103. package/dist/adapters/oclif/commands/tables/list.mjs +3 -2
  104. package/dist/adapters/oclif/commands/tables/update.mjs +1 -1
  105. package/dist/{base.command-d7VW6WTp.d.mts → base.command-BmddDbHa.d.mts} +4 -1
  106. package/dist/base.command-D8taHOFF.mjs +83 -0
  107. package/dist/chunk-CfYAbeIz.mjs +13 -0
  108. package/dist/context-D5uelKLe.d.mts +62 -0
  109. package/dist/core-B-IdeRNl.mjs +2448 -0
  110. package/dist/{factory-BrFKT8t-.mjs → factory-CCcimDhl.mjs} +45 -10
  111. package/dist/iac-render-BSZZEP0n.mjs +17 -0
  112. package/dist/index-D0ax2I61.d.mts +581 -0
  113. package/dist/index.d.mts +4 -4
  114. package/dist/index.mjs +2 -2
  115. package/dist/{presets-D9b6IWKy.mjs → presets-Bb9gwgeh.mjs} +40 -8
  116. package/dist/templates/.claude/settings.json +39 -0
  117. package/dist/templates/.devcontainer/Dockerfile +9 -0
  118. package/dist/templates/.devcontainer/devcontainer.json +4 -1
  119. package/dist/templates/.devcontainer/setup.sh +3 -0
  120. package/dist/templates/AGENTS.md +33 -20
  121. package/dist/templates/dbt/dbt_project.yml +2 -2
  122. package/dist/templates/gitignore +3 -1
  123. package/dist/templates/skills/create-connections/SKILL.md +210 -0
  124. package/dist/templates/skills/create-connections/references/mappers.md +152 -0
  125. package/dist/templates/skills/{create-semantic-model → create-cubes}/SKILL.md +20 -18
  126. package/dist/templates/skills/create-cubes/references/bq-pk-fk-conventions.md +183 -0
  127. package/dist/templates/skills/{create-semantic-model → create-cubes}/references/cube-examples.md +2 -2
  128. package/dist/templates/skills/create-cubes/references/hubspot-entities.md +289 -0
  129. package/dist/templates/skills/create-cubes/references/jira-entities.md +201 -0
  130. package/dist/templates/skills/create-cubes/references/netsuite-entities.md +121 -0
  131. package/dist/templates/skills/create-cubes/references/stripe-entities.md +114 -0
  132. package/dist/templates/skills/create-dbt-transformations/SKILL.md +43 -22
  133. package/dist/templates/skills/create-dbt-transformations/references/edge-cases.md +20 -2
  134. package/dist/templates/skills/create-dbt-transformations/references/schema-conventions.md +21 -7
  135. package/dist/templates/skills/create-dbt-transformations/references/sql-templates.md +34 -20
  136. package/dist/templates/skills/explore-lakehouse/SKILL.md +3 -3
  137. package/dist/templates/skills/load-sample-data/SKILL.md +1 -1
  138. package/dist/templates/skills/visualize-semantic-model/SKILL.md +159 -0
  139. package/dist/templates/skills/visualize-semantic-model/scripts/render_graph.py +186 -0
  140. package/dist/{types-Y_ht_ja5.d.mts → types-Bk2Cb5yt.d.mts} +9 -0
  141. package/package.json +44 -7
  142. package/dist/adapters/oclif/commands/integrations/create.d.mts +0 -11
  143. package/dist/adapters/oclif/commands/integrations/create.mjs +0 -16
  144. package/dist/adapters/oclif/commands/integrations/get.mjs +0 -21
  145. package/dist/adapters/oclif/commands/integrations/list.d.mts +0 -11
  146. package/dist/adapters/oclif/commands/integrations/list.mjs +0 -16
  147. package/dist/adapters/oclif/commands/integrations/update.d.mts +0 -15
  148. package/dist/adapters/oclif/commands/integrations/update.mjs +0 -21
  149. package/dist/adapters/oclif/commands/overlays/diff.d.mts +0 -19
  150. package/dist/adapters/oclif/commands/overlays/diff.mjs +0 -80
  151. package/dist/adapters/oclif/commands/overlays/pull.d.mts +0 -15
  152. package/dist/adapters/oclif/commands/overlays/pull.mjs +0 -45
  153. package/dist/adapters/oclif/commands/overlays/push.d.mts +0 -18
  154. package/dist/adapters/oclif/commands/overlays/push.mjs +0 -59
  155. package/dist/adapters/oclif/commands/overlays/status.d.mts +0 -18
  156. package/dist/adapters/oclif/commands/overlays/status.mjs +0 -53
  157. package/dist/base.command-YiwlGlKs.mjs +0 -62
  158. package/dist/core-jpFPylBb.mjs +0 -997
  159. package/dist/index-DD2Vr-pu.d.mts +0 -193
  160. package/dist/types-C_p_6rkj.d.mts +0 -69
  161. /package/dist/templates/skills/{create-semantic-model → create-cubes}/references/key-patterns.md +0 -0
  162. /package/dist/templates/skills/{create-semantic-model → create-cubes}/references/validation-queries.md +0 -0
@@ -0,0 +1,66 @@
1
+ import { E as getConfig, _ as buildIacRegistry, b as createApiClient, h as formatDiffLine, m as apply, v as discoverProject, y as projectRoot } from "../../../core-B-IdeRNl.mjs";
2
+ import { t as BaseCommand } from "../../../base.command-D8taHOFF.mjs";
3
+ import { n as renderIacErrors, t as APPLY_ACTION_LABELS } from "../../../iac-render-BSZZEP0n.mjs";
4
+ import chalk from "chalk";
5
+ import { Args, Flags } from "@oclif/core";
6
+ //#region src/adapters/oclif/commands/diff.ts
7
+ var Diff = class extends BaseCommand {
8
+ static description = "Show the drift between local YAML and the API without making changes";
9
+ static flags = {
10
+ project: Flags.string({ description: "Path to the project root (defaults to walking up from cwd)" }),
11
+ parallelism: Flags.integer({ description: "Max concurrent API calls within a single dependency level (default 4)" })
12
+ };
13
+ static args = { path: Args.string({
14
+ description: "Restrict scan to a sub-path within the project",
15
+ required: false
16
+ }) };
17
+ async run() {
18
+ const project = discoverProject({
19
+ cwd: process.cwd(),
20
+ projectPath: this.flags.project
21
+ });
22
+ const config = await getConfig();
23
+ const result = await apply({
24
+ project,
25
+ registry: buildIacRegistry(createApiClient({
26
+ apiUrl: config.apiUrl,
27
+ token: config.token,
28
+ organizationId: project.metadata.orgId
29
+ })),
30
+ startPath: this.args.path ?? projectRoot(project),
31
+ dryRun: true,
32
+ parallelism: this.flags.parallelism
33
+ });
34
+ if (!this.jsonEnabled()) this.renderHuman(result);
35
+ if (result.errors.length > 0) this.exit(2);
36
+ return {
37
+ project: {
38
+ path: project.path,
39
+ orgId: project.metadata.orgId
40
+ },
41
+ applied: result.applied,
42
+ errors: result.errors
43
+ };
44
+ }
45
+ renderHuman(result) {
46
+ if (result.errors.length > 0) {
47
+ renderIacErrors(result.errors, (msg) => this.log(msg));
48
+ return;
49
+ }
50
+ if (result.applied.length === 0) {
51
+ this.log(chalk.dim("No resources found."));
52
+ return;
53
+ }
54
+ let drift = 0;
55
+ for (const r of result.applied) {
56
+ if (r.action === "unchanged") continue;
57
+ drift++;
58
+ const label = APPLY_ACTION_LABELS[r.action] ?? r.action;
59
+ this.log(`${label} ${r.address}`);
60
+ if (r.diff && r.diff.length > 0) for (const change of r.diff) this.log(formatDiffLine(change));
61
+ }
62
+ if (drift === 0) this.log(chalk.dim("No drift. All resources match the API."));
63
+ }
64
+ };
65
+ //#endregion
66
+ export { Diff as default };
@@ -1,4 +1,4 @@
1
- import { r as getCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { r as getCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/gservice-account-keys/get.ts
3
3
  var get_default = getCommand({
4
4
  resource: "gserviceAccountKeys",
@@ -1,5 +1,5 @@
1
- import { m as unwrap } from "../../../../core-jpFPylBb.mjs";
2
- import { n as defineApiCommand } from "../../../../factory-BrFKT8t-.mjs";
1
+ import { x as unwrap } from "../../../../core-B-IdeRNl.mjs";
2
+ import { r as defineApiCommand } from "../../../../factory-CCcimDhl.mjs";
3
3
  import { Args } from "@oclif/core";
4
4
  //#region src/adapters/oclif/commands/gservice-account-keys/reveal.ts
5
5
  var reveal_default = defineApiCommand({
@@ -1,4 +1,4 @@
1
- import { t as createCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { t as createCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/gservice-accounts/create.ts
3
3
  var create_default = createCommand({
4
4
  resource: "gserviceAccounts",
@@ -1,4 +1,4 @@
1
- import { n as deleteCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { n as deleteCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/gservice-accounts/delete.ts
3
3
  var delete_default = deleteCommand({
4
4
  resource: "gserviceAccounts",
@@ -1,4 +1,4 @@
1
- import { r as getCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { r as getCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/gservice-accounts/get.ts
3
3
  var get_default = getCommand({
4
4
  resource: "gserviceAccounts",
@@ -1,8 +1,13 @@
1
- import { i as listCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { i as listCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/gservice-accounts/list.ts
3
3
  var list_default = listCommand({
4
4
  resource: "gserviceAccounts",
5
- description: "List Google service accounts"
5
+ description: "List Google service accounts",
6
+ defaultColumns: [
7
+ "id",
8
+ "name",
9
+ "email"
10
+ ]
6
11
  });
7
12
  //#endregion
8
13
  export { list_default as default };
@@ -1,15 +1,17 @@
1
- import { t as BaseCommand } from "../../../base.command-d7VW6WTp.mjs";
1
+ import { t as BaseCommand } from "../../../base.command-BmddDbHa.mjs";
2
2
  import * as _$_oclif_core_interfaces0 from "@oclif/core/interfaces";
3
3
 
4
4
  //#region src/adapters/oclif/commands/init.d.ts
5
5
  declare class Init extends BaseCommand<typeof Init> {
6
6
  static description: string;
7
+ static projectContextMode: "relaxed";
7
8
  static args: {
8
9
  destination: _$_oclif_core_interfaces0.Arg<string | undefined, Record<string, unknown>>;
9
10
  };
10
11
  static flags: {
11
12
  yes: _$_oclif_core_interfaces0.BooleanFlag<boolean>;
12
13
  "dry-run": _$_oclif_core_interfaces0.BooleanFlag<boolean>;
14
+ "no-pull": _$_oclif_core_interfaces0.BooleanFlag<boolean>;
13
15
  };
14
16
  run(): Promise<void>;
15
17
  }
@@ -1,17 +1,18 @@
1
- import { F as ApiError, b as getConfig, t as InitService } from "../../../core-jpFPylBb.mjs";
1
+ import { E as getConfig, U as ApiError, t as InitService } from "../../../core-B-IdeRNl.mjs";
2
2
  import { TEMPLATES_DIR } from "../../../templates/index.mjs";
3
- import { t as BaseCommand } from "../../../base.command-YiwlGlKs.mjs";
3
+ import { t as BaseCommand } from "../../../base.command-D8taHOFF.mjs";
4
4
  import * as fs from "fs";
5
5
  import * as path from "path";
6
- import select from "@inquirer/select";
7
6
  import chalk from "chalk";
8
7
  import { Args, Flags } from "@oclif/core";
8
+ import select from "@inquirer/select";
9
9
  //#region src/adapters/oclif/commands/init.ts
10
10
  function isDirEmpty(dirPath) {
11
11
  return fs.readdirSync(dirPath).length === 0;
12
12
  }
13
13
  var Init = class extends BaseCommand {
14
14
  static description = "Scaffold a new RevOS data engineering project";
15
+ static projectContextMode = "relaxed";
15
16
  static args = { destination: Args.string({
16
17
  description: "Path or project name (default: current directory name). Supports relative and absolute paths.",
17
18
  required: false
@@ -25,26 +26,18 @@ var Init = class extends BaseCommand {
25
26
  "dry-run": Flags.boolean({
26
27
  description: "Show what would be created without making any changes",
27
28
  default: false
29
+ }),
30
+ "no-pull": Flags.boolean({
31
+ description: "Skip discovering existing remote Sources, Connections, and Cubes from the org",
32
+ default: false
28
33
  })
29
34
  };
30
35
  async run() {
31
36
  const { apiUrl, token, organizationId } = await getConfig();
32
- let projectName;
33
- let targetDir;
34
- if (this.args.destination) {
35
- const resolved = path.resolve(this.args.destination);
36
- projectName = path.basename(resolved);
37
- targetDir = path.dirname(resolved);
38
- } else {
39
- const cwd = process.cwd();
40
- projectName = path.basename(cwd);
41
- targetDir = path.dirname(cwd);
42
- }
43
- if (!projectName) this.error("Could not determine project name from path", { exit: 1 });
44
- const projectDir = path.join(targetDir, projectName);
37
+ const projectDir = this.args.destination ? path.resolve(this.args.destination) : process.cwd();
45
38
  if (fs.existsSync(projectDir) && !isDirEmpty(projectDir) && !this.flags.yes) {
46
39
  if (await select({
47
- message: `Directory "${projectName}" already exists and is not empty. What would you like to do?`,
40
+ message: `Directory "${path.basename(projectDir)}" already exists and is not empty. What would you like to do?`,
48
41
  choices: [{
49
42
  name: "Initialize in this directory",
50
43
  value: "init"
@@ -63,8 +56,8 @@ var Init = class extends BaseCommand {
63
56
  this.error(message, { exit: 1 });
64
57
  });
65
58
  if (this.flags["dry-run"]) {
66
- const preview = service.dryRun(projectName, targetDir);
67
- this.log(`\nWould create project ${chalk.bold(projectName)} for organization ${chalk.bold(org.name)}`);
59
+ const preview = service.dryRun(projectDir);
60
+ this.log(`\nWould create RevOS project for organization ${chalk.bold(`"${org.name}"`)}`);
68
61
  this.log(` Path: ${chalk.dim(preview.projectDir)}\n`);
69
62
  this.log("Directories:");
70
63
  for (const dir of preview.dirs) this.log(` ${dir}/`);
@@ -73,16 +66,16 @@ var Init = class extends BaseCommand {
73
66
  this.log(chalk.dim("\nNo files created, no GCP resources provisioned."));
74
67
  return;
75
68
  }
76
- this.log(`\nCreating project ${chalk.bold(projectName)} for organization ${chalk.bold(org.name)}`);
69
+ this.log(`\nCreating RevOS project for organization ${chalk.bold(`"${org.name}"`)}...`);
77
70
  this.log(` Path: ${chalk.dim(projectDir)}\n`);
78
71
  const result = await service.run({
79
- projectName,
80
- targetDir,
72
+ projectDir,
81
73
  apiUrl,
82
74
  token,
83
75
  organizationId,
84
76
  organization: org,
85
- allowExistingDir: true
77
+ allowExistingDir: true,
78
+ pullIac: !this.flags["no-pull"]
86
79
  }).catch((err) => {
87
80
  if (err instanceof ApiError) {
88
81
  this.log(chalk.red(`\nAPI error: ${err.status} ${err.statusText}`));
@@ -95,6 +88,17 @@ var Init = class extends BaseCommand {
95
88
  this.log(chalk.green(`\nProject created at ${result.projectDir}`));
96
89
  this.log("\nGenerated files:");
97
90
  for (const f of result.createdFiles) this.log(` ${f}`);
91
+ const iacPull = result.pulledIac;
92
+ const discovered = iacPull.pulled.filter((p) => p.action === "discovered");
93
+ const byKind = discovered.reduce((acc, p) => {
94
+ acc[p.kind] = (acc[p.kind] ?? 0) + 1;
95
+ return acc;
96
+ }, {});
97
+ if (discovered.length > 0) {
98
+ const summary = Object.entries(byKind).map(([k, v]) => `${v} ${k.toLowerCase()}${v === 1 ? "" : "s"}`).join(", ");
99
+ this.log(`\nDiscovered ${summary} from the API.`);
100
+ }
101
+ if (iacPull.errors.length > 0) this.log(chalk.yellow(`\nWarning: could not discover remote resources — ${iacPull.errors[0].message}`));
98
102
  this.log(`\nNext step: open ${chalk.bold(result.projectDir)} in VS Code and click ${chalk.bold("Reopen in Container")}.`);
99
103
  this.log(`\n${chalk.dim("Tip: once inside the Dev Container, ask Claude to \"load sample data\" if you need example datasets.")}\n`);
100
104
  }
@@ -1,8 +1,9 @@
1
- import { t as createCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { t as createCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/org/create.ts
3
3
  var create_default = createCommand({
4
4
  resource: "organizations",
5
- description: "Create a new organization"
5
+ description: "Create a new organization",
6
+ projectContextMode: "relaxed"
6
7
  });
7
8
  //#endregion
8
9
  export { create_default as default };
@@ -1,14 +1,23 @@
1
- import { s as OrganizationInfo } from "../../../../types-Y_ht_ja5.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-d7VW6WTp.mjs";
1
+ import { s as OrganizationInfo } from "../../../../types-Bk2Cb5yt.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-BmddDbHa.mjs";
3
3
 
4
4
  //#region src/adapters/oclif/commands/org/current.d.ts
5
5
  interface CurrentOrgResult {
6
6
  organizationId: string | null;
7
7
  organization: OrganizationInfo | null;
8
- source: "env" | "credentials" | null;
8
+ source: "env" | "credentials" | "project" | null;
9
+ project?: {
10
+ name?: string;
11
+ path: string;
12
+ orgId: string;
13
+ };
14
+ globalDefault?: {
15
+ organizationId: string | null;
16
+ };
9
17
  }
10
18
  declare class OrgCurrent extends BaseCommand<typeof OrgCurrent> {
11
19
  static description: string;
20
+ static projectContextMode: "relaxed";
12
21
  run(): Promise<CurrentOrgResult>;
13
22
  }
14
23
  //#endregion
@@ -1,11 +1,36 @@
1
- import { N as loadCredentials, b as getConfig, m as unwrap, p as createApiClient } from "../../../../core-jpFPylBb.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-YiwlGlKs.mjs";
1
+ import { E as getConfig, V as loadCredentials, b as createApiClient, l as resolveProjectContext, x as unwrap } from "../../../../core-B-IdeRNl.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-D8taHOFF.mjs";
3
+ import chalk from "chalk";
3
4
  //#region src/adapters/oclif/commands/org/current.ts
4
5
  var OrgCurrent = class extends BaseCommand {
5
6
  static description = "Show currently selected organization";
7
+ static projectContextMode = "relaxed";
6
8
  async run() {
7
9
  const credentials = loadCredentials();
10
+ const projectContext = resolveProjectContext();
8
11
  const envOrgId = process.env.REVOS_ORG_ID;
12
+ if (projectContext) {
13
+ let organization = null;
14
+ try {
15
+ organization = unwrap(await createApiClient(await getConfig()).organizations.list()).find((o) => o.id === projectContext.orgId) ?? null;
16
+ } catch {}
17
+ if (!this.jsonEnabled()) {
18
+ const orgDisplay = organization ? `${organization.name} (${projectContext.orgId})` : projectContext.orgId;
19
+ this.log(`Current organization (from ${chalk.cyan("revos.yaml")}): ${orgDisplay}`);
20
+ if (credentials?.organizationId && credentials.organizationId !== projectContext.orgId) this.log(chalk.gray(`Global default differs: ${credentials.organizationId}`));
21
+ }
22
+ return {
23
+ organizationId: projectContext.orgId,
24
+ organization,
25
+ source: "project",
26
+ project: {
27
+ name: projectContext.projectFile.metadata.name,
28
+ path: projectContext.projectFile.path,
29
+ orgId: projectContext.orgId
30
+ },
31
+ globalDefault: { organizationId: credentials?.organizationId ?? null }
32
+ };
33
+ }
9
34
  if (envOrgId) {
10
35
  if (!this.jsonEnabled()) this.log(`Current organization (from REVOS_ORG_ID): ${envOrgId}`);
11
36
  return {
@@ -1,8 +1,9 @@
1
- import { r as getCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { r as getCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/org/get.ts
3
3
  var get_default = getCommand({
4
4
  resource: "organizations",
5
- description: "Get an organization by ID"
5
+ description: "Get an organization by ID",
6
+ projectContextMode: "relaxed"
6
7
  });
7
8
  //#endregion
8
9
  export { get_default as default };
@@ -1,14 +1,6 @@
1
- import { a as OrgListResult } from "../../../../types-Y_ht_ja5.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-d7VW6WTp.mjs";
3
- import * as _$_oclif_core_interfaces0 from "@oclif/core/interfaces";
1
+ import * as _$_oclif_core0 from "@oclif/core";
4
2
 
5
3
  //#region src/adapters/oclif/commands/org/list.d.ts
6
- declare class OrgList extends BaseCommand<typeof OrgList> {
7
- static description: string;
8
- static flags: {
9
- columns: _$_oclif_core_interfaces0.OptionFlag<string | undefined, _$_oclif_core_interfaces0.CustomOptions>;
10
- };
11
- run(): Promise<OrgListResult>;
12
- }
4
+ declare const _default: typeof _$_oclif_core0.Command;
13
5
  //#endregion
14
- export { OrgList as default };
6
+ export { _default as default };
@@ -1,34 +1,43 @@
1
- import { b as getConfig, m as unwrap, p as createApiClient } from "../../../../core-jpFPylBb.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-YiwlGlKs.mjs";
1
+ import { l as resolveProjectContext, x as unwrap } from "../../../../core-B-IdeRNl.mjs";
2
+ import { a as resolveColumns, i as renderList, r as defineApiCommand } from "../../../../factory-CCcimDhl.mjs";
3
3
  import chalk from "chalk";
4
4
  import { Flags } from "@oclif/core";
5
5
  //#region src/adapters/oclif/commands/org/list.ts
6
- const ALL_COLUMNS = ["name", "id"];
7
- var OrgList = class extends BaseCommand {
8
- static description = "List organizations you belong to";
9
- static flags = { columns: Flags.string({
10
- description: `Columns to display (comma-separated). Available: ${ALL_COLUMNS.join(", ")}`,
11
- helpValue: "name,id"
12
- }) };
13
- async run() {
14
- const { flags } = this;
15
- const config = await getConfig();
16
- const organizations = unwrap(await createApiClient(config).organizations.list());
17
- const result = {
18
- organizations,
6
+ const DEFAULT_COLUMNS = ["id", "name"];
7
+ var list_default = defineApiCommand({
8
+ description: "List organizations you belong to",
9
+ projectContextMode: "relaxed",
10
+ flags: { columns: Flags.string({
11
+ description: "Columns to display in table output (comma-separated). Overrides the resource default. Ignored with --json.",
12
+ helpValue: "a,b,c"
13
+ }) },
14
+ call: async ({ api, config }) => {
15
+ return {
16
+ organizations: unwrap(await api.organizations.list()),
19
17
  currentOrgId: config.organizationId
20
18
  };
21
- if (!this.jsonEnabled()) if (organizations.length === 0) this.warn("You don't belong to any organizations.");
22
- else {
23
- const cols = flags.columns?.split(",").map((c) => c.trim()).filter((c) => ALL_COLUMNS.includes(c)) ?? [...ALL_COLUMNS];
24
- const rows = organizations.map((org) => ({
25
- name: org.id === config.organizationId ? `${org.name} ${chalk.green("✓")}` : org.name,
26
- id: org.id
27
- }));
28
- this.table(rows, { columns: cols.map((c) => ({ key: c })) });
19
+ },
20
+ render: (data, command) => {
21
+ const { organizations, currentOrgId } = data;
22
+ if (organizations.length === 0) {
23
+ command.warn("You don't belong to any organizations.");
24
+ return;
29
25
  }
30
- return result;
26
+ const projectOrgId = resolveProjectContext()?.orgId;
27
+ const rows = organizations.map((org) => {
28
+ const annotations = [];
29
+ if (org.id === projectOrgId) annotations.push(chalk.cyan("project"));
30
+ if (org.id === currentOrgId && org.id !== projectOrgId) annotations.push(chalk.green("current"));
31
+ const suffix = annotations.length ? ` ${annotations.join(" ")}` : "";
32
+ return {
33
+ id: org.id,
34
+ name: `${org.name}${suffix}`
35
+ };
36
+ });
37
+ const flags = command.flags;
38
+ renderList(command, rows, { columns: resolveColumns(flags.columns, DEFAULT_COLUMNS) });
39
+ if (projectOrgId && projectOrgId !== currentOrgId) command.log(chalk.gray(`\nThis directory is anchored to the project org; the global default differs.`));
31
40
  }
32
- };
41
+ });
33
42
  //#endregion
34
- export { OrgList as default };
43
+ export { list_default as default };
@@ -1,13 +1,15 @@
1
- import { t as BaseCommand } from "../../../../base.command-d7VW6WTp.mjs";
1
+ import { o as OrgSwitchResult } from "../../../../types-Bk2Cb5yt.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-BmddDbHa.mjs";
2
3
  import * as _$_oclif_core_interfaces0 from "@oclif/core/interfaces";
3
4
 
4
5
  //#region src/adapters/oclif/commands/org/switch.d.ts
5
6
  declare class OrgSwitch extends BaseCommand<typeof OrgSwitch> {
6
7
  static description: string;
8
+ static projectContextMode: "relaxed";
7
9
  static args: {
8
10
  id: _$_oclif_core_interfaces0.Arg<string | undefined, Record<string, unknown>>;
9
11
  };
10
- run(): Promise<void>;
12
+ run(): Promise<OrgSwitchResult>;
11
13
  }
12
14
  //#endregion
13
15
  export { OrgSwitch as default };
@@ -1,17 +1,20 @@
1
- import { N as loadCredentials, P as saveCredentials, b as getConfig, m as unwrap, n as selectOrganization, p as createApiClient } from "../../../../core-jpFPylBb.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-YiwlGlKs.mjs";
1
+ import { E as getConfig, H as saveCredentials, V as loadCredentials, a as formatInProjectSwitchWarning, b as createApiClient, l as resolveProjectContext, n as selectOrganization, x as unwrap } from "../../../../core-B-IdeRNl.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-D8taHOFF.mjs";
3
3
  import * as os from "os";
4
4
  import chalk from "chalk";
5
5
  import { Args } from "@oclif/core";
6
6
  //#region src/adapters/oclif/commands/org/switch.ts
7
7
  var OrgSwitch = class extends BaseCommand {
8
8
  static description = "Switch to a different organization";
9
+ static projectContextMode = "relaxed";
9
10
  static args = { id: Args.string({
10
11
  description: "Organization ID",
11
12
  required: false
12
13
  }) };
13
14
  async run() {
14
15
  const { args } = this;
16
+ const json = this.jsonEnabled();
17
+ if (json && !args.id) this.error("Pass an organization id when using --json (interactive selection requires a TTY).", { exit: 1 });
15
18
  const organizations = unwrap(await createApiClient(await getConfig()).organizations.list());
16
19
  if (organizations.length === 0) this.error("You don't belong to any organizations.", { exit: 1 });
17
20
  let selected;
@@ -27,7 +30,17 @@ var OrgSwitch = class extends BaseCommand {
27
30
  ...credentials,
28
31
  organizationId: selected.id
29
32
  });
30
- this.log(chalk.green(`Switched to organization: ${selected.name}`));
33
+ const projectContext = resolveProjectContext();
34
+ if (projectContext && projectContext.orgId !== selected.id && !json) this.warn(formatInProjectSwitchWarning({
35
+ projectName: projectContext.projectFile.metadata.name,
36
+ projectOrgId: projectContext.orgId
37
+ }));
38
+ if (!json) this.log(chalk.green(`Switched to organization: ${selected.name}`));
39
+ return {
40
+ success: true,
41
+ organizationId: selected.id,
42
+ organizationName: selected.name
43
+ };
31
44
  }
32
45
  };
33
46
  //#endregion
@@ -0,0 +1,29 @@
1
+ import { d as PulledResource } from "../../../index-D0ax2I61.mjs";
2
+ import { c as IacError } from "../../../context-D5uelKLe.mjs";
3
+ import { t as BaseCommand } from "../../../base.command-BmddDbHa.mjs";
4
+ import * as _$_oclif_core_interfaces0 from "@oclif/core/interfaces";
5
+
6
+ //#region src/adapters/oclif/commands/pull.d.ts
7
+ interface PullJsonOutput {
8
+ project: {
9
+ path: string;
10
+ orgId: string;
11
+ };
12
+ pulled: PulledResource[];
13
+ errors: IacError[];
14
+ }
15
+ declare class Pull extends BaseCommand<typeof Pull> {
16
+ static description: string;
17
+ static flags: {
18
+ project: _$_oclif_core_interfaces0.OptionFlag<string | undefined, _$_oclif_core_interfaces0.CustomOptions>;
19
+ "dry-run": _$_oclif_core_interfaces0.BooleanFlag<boolean>;
20
+ force: _$_oclif_core_interfaces0.BooleanFlag<boolean>;
21
+ };
22
+ static args: {
23
+ path: _$_oclif_core_interfaces0.Arg<string | undefined, Record<string, unknown>>;
24
+ };
25
+ run(): Promise<PullJsonOutput>;
26
+ private renderHuman;
27
+ }
28
+ //#endregion
29
+ export { PullJsonOutput, Pull as default };
@@ -0,0 +1,88 @@
1
+ import { E as getConfig, _ as buildIacRegistry, b as createApiClient, p as pull, v as discoverProject, y as projectRoot } from "../../../core-B-IdeRNl.mjs";
2
+ import { t as BaseCommand } from "../../../base.command-D8taHOFF.mjs";
3
+ import { n as renderIacErrors } from "../../../iac-render-BSZZEP0n.mjs";
4
+ import chalk from "chalk";
5
+ import { Args, Flags } from "@oclif/core";
6
+ //#region src/adapters/oclif/commands/pull.ts
7
+ const ACTION_LABELS = {
8
+ pulled: chalk.green("pulled"),
9
+ discovered: chalk.cyan("discovered"),
10
+ unchanged: chalk.dim("unchanged"),
11
+ "skipped-dirty": chalk.yellow("skipped (dirty)"),
12
+ "skipped-no-id": chalk.dim("skipped (no id)"),
13
+ "skipped-not-found": chalk.red("skipped (not found)")
14
+ };
15
+ var Pull = class extends BaseCommand {
16
+ static description = "Reconcile local YAML to match the API. Lists every remote resource for each registered kind: known resources (matched by metadata.id) get their spec rewritten in place; previously-unknown resources are discovered and a new YAML file is written under <kind>s/<name>.yaml. Refuses to overwrite local files with uncommitted changes unless --force; new files are always created.";
17
+ static flags = {
18
+ project: Flags.string({ description: "Path to the project root (defaults to walking up from cwd)" }),
19
+ "dry-run": Flags.boolean({
20
+ description: "Show what would be pulled without writing files",
21
+ default: false
22
+ }),
23
+ force: Flags.boolean({
24
+ description: "Pull even when the target file has uncommitted git changes",
25
+ default: false
26
+ })
27
+ };
28
+ static args = { path: Args.string({
29
+ description: "Restrict scan to a sub-path within the project",
30
+ required: false
31
+ }) };
32
+ async run() {
33
+ const project = discoverProject({
34
+ cwd: process.cwd(),
35
+ projectPath: this.flags.project
36
+ });
37
+ const config = await getConfig();
38
+ const result = await pull({
39
+ project,
40
+ registry: buildIacRegistry(createApiClient({
41
+ apiUrl: config.apiUrl,
42
+ token: config.token,
43
+ organizationId: project.metadata.orgId
44
+ })),
45
+ startPath: this.args.path ?? projectRoot(project),
46
+ force: this.flags.force,
47
+ dryRun: this.flags["dry-run"]
48
+ });
49
+ if (!this.jsonEnabled()) this.renderHuman(result);
50
+ if (result.errors.length > 0) this.exit(2);
51
+ return {
52
+ project: {
53
+ path: project.path,
54
+ orgId: project.metadata.orgId
55
+ },
56
+ pulled: result.pulled,
57
+ errors: result.errors
58
+ };
59
+ }
60
+ renderHuman(result) {
61
+ if (result.errors.length > 0) {
62
+ renderIacErrors(result.errors, (msg) => this.log(msg));
63
+ return;
64
+ }
65
+ if (result.pulled.length === 0) {
66
+ this.log(chalk.dim("No resources found."));
67
+ return;
68
+ }
69
+ this.table(result.pulled.map((p) => ({
70
+ address: p.address,
71
+ action: ACTION_LABELS[p.action] ?? p.action,
72
+ id: p.id ?? chalk.dim("—")
73
+ })), { columns: [
74
+ { key: "address" },
75
+ { key: "action" },
76
+ { key: "id" }
77
+ ] });
78
+ const counts = result.pulled.reduce((acc, p) => {
79
+ acc[p.action] = (acc[p.action] ?? 0) + 1;
80
+ return acc;
81
+ }, {});
82
+ const summary = Object.entries(counts).map(([k, v]) => `${k}: ${v}`).join(", ");
83
+ this.log(chalk.dim(`\n${summary}`));
84
+ if (counts["skipped-dirty"]) this.log(chalk.yellow("\nSome files have uncommitted changes and were skipped. Commit or stash them, or re-run with --force to overwrite."));
85
+ }
86
+ };
87
+ //#endregion
88
+ export { Pull as default };
@@ -1,8 +1,9 @@
1
- import { t as createCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { t as createCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/score-groups/create.ts
3
3
  var create_default = createCommand({
4
4
  resource: "scoreGroups",
5
- description: "Create a new score group"
5
+ description: "Create a new score group",
6
+ pathParams: ["tableId"]
6
7
  });
7
8
  //#endregion
8
9
  export { create_default as default };
@@ -1,4 +1,4 @@
1
- import { n as deleteCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { n as deleteCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/score-groups/delete.ts
3
3
  var delete_default = deleteCommand({
4
4
  resource: "scoreGroups",
@@ -1,4 +1,4 @@
1
- import { r as getCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { r as getCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/score-groups/get.ts
3
3
  var get_default = getCommand({
4
4
  resource: "scoreGroups",
@@ -1,8 +1,9 @@
1
- import { i as listCommand } from "../../../../presets-D9b6IWKy.mjs";
1
+ import { i as listCommand } from "../../../../presets-Bb9gwgeh.mjs";
2
2
  //#region src/adapters/oclif/commands/score-groups/list.ts
3
3
  var list_default = listCommand({
4
4
  resource: "scoreGroups",
5
- description: "List score groups"
5
+ description: "List score groups",
6
+ pathParams: ["tableId"]
6
7
  });
7
8
  //#endregion
8
9
  export { list_default as default };