@revos/cli 0.1.0 → 0.1.2

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 (30) hide show
  1. package/README.md +24 -2
  2. package/bin/revos.js +1 -1
  3. package/dist/adapters/oclif/commands/auth/login.mjs +2 -2
  4. package/dist/adapters/oclif/commands/auth/logout.mjs +2 -2
  5. package/dist/adapters/oclif/commands/auth/status.mjs +2 -2
  6. package/dist/adapters/oclif/commands/init.d.mts +5 -1
  7. package/dist/adapters/oclif/commands/init.mjs +74 -13
  8. package/dist/adapters/oclif/commands/org/current.mjs +3 -3
  9. package/dist/adapters/oclif/commands/org/list.mjs +3 -3
  10. package/dist/adapters/oclif/commands/org/switch.mjs +3 -3
  11. package/dist/adapters/oclif/commands/overlays/diff.mjs +3 -3
  12. package/dist/adapters/oclif/commands/overlays/pull.mjs +3 -3
  13. package/dist/adapters/oclif/commands/overlays/push.mjs +3 -3
  14. package/dist/adapters/oclif/commands/overlays/status.mjs +3 -3
  15. package/dist/{base.command-BGM225ik.mjs → base.command-DDSLyx5v.mjs} +1 -1
  16. package/dist/{core-Bif-kxlo.mjs → core-EJgxP-x5.mjs} +106 -218
  17. package/dist/{index-C0e8MXGP.d.mts → index-DH6vy050.d.mts} +12 -9
  18. package/dist/index.d.mts +1 -1
  19. package/dist/index.mjs +1 -1
  20. package/dist/templates/.devcontainer/Dockerfile +14 -0
  21. package/dist/templates/.devcontainer/devcontainer.json +54 -0
  22. package/dist/templates/.devcontainer/setup.sh +32 -0
  23. package/dist/templates/AGENTS.md +2 -3
  24. package/dist/templates/CLAUDE.md +0 -16
  25. package/dist/templates/README.md +23 -0
  26. package/dist/templates/dbt/dbt_project.yml +22 -0
  27. package/dist/templates/index.ts +4 -0
  28. package/dist/templates/skills/create-semantic-model/SKILL.md +1611 -0
  29. package/dist/templates/skills/explore-lakehouse/SKILL.md +131 -0
  30. package/package.json +10 -4
package/README.md CHANGED
@@ -26,10 +26,32 @@ revos [command] [options]
26
26
  ### Project Initialization
27
27
 
28
28
  ```bash
29
- revos init [project-name]
29
+ revos init [destination] [--yes] [--dry-run]
30
30
  ```
31
31
 
32
- Scaffolds a new RevOS data engineering project. If `project-name` is omitted, uses the current directory name.
32
+ Scaffolds a new RevOS data engineering project. If `destination` is omitted, initializes in the current directory.
33
+
34
+ **Arguments:**
35
+
36
+ ```
37
+ destination Path or project name (default: current directory)
38
+ Examples:
39
+ my-project → creates ./my-project/
40
+ ./my-project → same as above
41
+ ../my-project → one level up
42
+ /home/user/my-project → absolute path
43
+ ```
44
+
45
+ **Flags:**
46
+
47
+ ```
48
+ -y, --yes Skip confirmation prompts, use defaults
49
+ --dry-run Show what would be created without creating files or GCP resources
50
+ ```
51
+
52
+ **Non-empty directory behavior:**
53
+
54
+ If the destination already exists and is not empty, you will be prompted to confirm before proceeding. Use `--yes` to skip this prompt.
33
55
 
34
56
  **What it does:**
35
57
 
package/bin/revos.js CHANGED
@@ -3,5 +3,5 @@
3
3
  import { run, flush, handle } from "@oclif/core";
4
4
 
5
5
  await run(process.argv.slice(2), import.meta.url)
6
- .then(flush)
6
+ .then(() => flush())
7
7
  .catch(handle);
@@ -1,5 +1,5 @@
1
- import { A as getCredentialsPath, C as getUserInfo, D as tokenResponseToCredentials, N as saveCredentials, O as startOAuthServer, S as generatePKCEChallenge, T as setClerkConfig, b as buildAuthorizationUrl, m as unwrap, n as selectOrganization, p as createApiClient, x as exchangeCodeForTokens } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { A as getCredentialsPath, C as getUserInfo, D as tokenResponseToCredentials, N as saveCredentials, O as startOAuthServer, S as generatePKCEChallenge, T as setClerkConfig, b as buildAuthorizationUrl, m as unwrap, n as selectOrganization, p as createApiClient, x as exchangeCodeForTokens } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  import chalk from "chalk";
4
4
  import { Flags } from "@oclif/core";
5
5
  import open from "open";
@@ -1,5 +1,5 @@
1
- import { k as deleteCredentials } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { k as deleteCredentials } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  //#region src/adapters/oclif/commands/auth/logout.ts
4
4
  var AuthLogout = class extends BaseCommand {
5
5
  static description = "Remove stored authentication credentials";
@@ -1,5 +1,5 @@
1
- import { A as getCredentialsPath, M as loadCredentials, j as isTokenExpired } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { A as getCredentialsPath, M as loadCredentials, j as isTokenExpired } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  import chalk from "chalk";
4
4
  //#region src/adapters/oclif/commands/auth/status.ts
5
5
  var AuthStatus = class extends BaseCommand {
@@ -5,7 +5,11 @@ import * as _$_oclif_core_interfaces0 from "@oclif/core/interfaces";
5
5
  declare class Init extends BaseCommand<typeof Init> {
6
6
  static description: string;
7
7
  static args: {
8
- name: _$_oclif_core_interfaces0.Arg<string | undefined, Record<string, unknown>>;
8
+ destination: _$_oclif_core_interfaces0.Arg<string | undefined, Record<string, unknown>>;
9
+ };
10
+ static flags: {
11
+ yes: _$_oclif_core_interfaces0.BooleanFlag<boolean>;
12
+ "dry-run": _$_oclif_core_interfaces0.BooleanFlag<boolean>;
9
13
  };
10
14
  run(): Promise<void>;
11
15
  }
@@ -1,26 +1,88 @@
1
- import { P as ApiError, t as InitService, y as getConfig } from "../../../core-Bif-kxlo.mjs";
1
+ import { P as ApiError, t as InitService, y as getConfig } from "../../../core-EJgxP-x5.mjs";
2
2
  import { TEMPLATES_DIR } from "../../../templates/index.mjs";
3
- import { t as BaseCommand } from "../../../base.command-BGM225ik.mjs";
3
+ import { t as BaseCommand } from "../../../base.command-DDSLyx5v.mjs";
4
+ import * as fs from "fs";
4
5
  import * as path from "path";
6
+ import select from "@inquirer/select";
5
7
  import chalk from "chalk";
6
- import { Args } from "@oclif/core";
8
+ import { Args, Flags } from "@oclif/core";
7
9
  //#region src/adapters/oclif/commands/init.ts
10
+ function isDirEmpty(dirPath) {
11
+ return fs.readdirSync(dirPath).length === 0;
12
+ }
8
13
  var Init = class extends BaseCommand {
9
14
  static description = "Scaffold a new RevOS data engineering project";
10
- static args = { name: Args.string({
11
- description: "Project name (used as directory name)",
15
+ static args = { destination: Args.string({
16
+ description: "Path or project name (default: current directory name). Supports relative and absolute paths.",
12
17
  required: false
13
18
  }) };
19
+ static flags = {
20
+ yes: Flags.boolean({
21
+ char: "y",
22
+ description: "Non-interactive mode, use defaults",
23
+ default: false
24
+ }),
25
+ "dry-run": Flags.boolean({
26
+ description: "Show what would be created without making any changes",
27
+ default: false
28
+ })
29
+ };
14
30
  async run() {
15
- const { apiUrl, token } = getConfig();
16
- const projectName = this.args.name ?? path.basename(process.cwd());
17
- if (!projectName || projectName.includes("/") || projectName.includes("\\") || projectName === "..") this.error(`Invalid project name: "${projectName}"`, { exit: 1 });
18
- this.log(`\nInitializing project ${chalk.bold(projectName)}...\n`);
19
- const result = await new InitService(TEMPLATES_DIR).run({
31
+ 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);
45
+ if (fs.existsSync(projectDir) && !isDirEmpty(projectDir) && !this.flags.yes) {
46
+ if (await select({
47
+ message: `Directory "${projectName}" already exists and is not empty. What would you like to do?`,
48
+ choices: [{
49
+ name: "Initialize in this directory",
50
+ value: "init"
51
+ }, {
52
+ name: "Cancel",
53
+ value: "cancel"
54
+ }]
55
+ }) === "cancel") {
56
+ this.log("Cancelled.");
57
+ return;
58
+ }
59
+ }
60
+ const service = new InitService(TEMPLATES_DIR);
61
+ const org = await service.resolveOrganization(apiUrl, token, organizationId).catch((err) => {
62
+ const message = err instanceof Error ? err.message : String(err);
63
+ this.error(message, { exit: 1 });
64
+ });
65
+ 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)}`);
68
+ this.log(` Path: ${chalk.dim(preview.projectDir)}\n`);
69
+ this.log("Directories:");
70
+ for (const dir of preview.dirs) this.log(` ${dir}/`);
71
+ this.log("\nFiles:");
72
+ for (const file of preview.files) this.log(` ${file}`);
73
+ this.log(chalk.dim("\nNo files created, no GCP resources provisioned."));
74
+ return;
75
+ }
76
+ this.log(`\nCreating project ${chalk.bold(projectName)} for organization ${chalk.bold(org.name)}`);
77
+ this.log(` Path: ${chalk.dim(projectDir)}\n`);
78
+ const result = await service.run({
20
79
  projectName,
21
- targetDir: process.cwd(),
80
+ targetDir,
22
81
  apiUrl,
23
- token
82
+ token,
83
+ organizationId,
84
+ organization: org,
85
+ allowExistingDir: true
24
86
  }).catch((err) => {
25
87
  if (err instanceof ApiError) {
26
88
  this.log(chalk.red(`\nAPI error: ${err.status} ${err.statusText}`));
@@ -30,7 +92,6 @@ var Init = class extends BaseCommand {
30
92
  const message = err instanceof Error ? err.message : String(err);
31
93
  this.error(message, { exit: 1 });
32
94
  });
33
- this.log(chalk.green(`\nOrganization: ${result.organization.name}`));
34
95
  this.log(chalk.green(`\nProject created at ${result.projectDir}`));
35
96
  this.log("\nGenerated files:");
36
97
  for (const f of result.createdFiles) this.log(` ${f}`);
@@ -1,5 +1,5 @@
1
- import { M as loadCredentials, m as unwrap, p as createApiClient, y as getConfig } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { M as loadCredentials, m as unwrap, p as createApiClient, y as getConfig } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  //#region src/adapters/oclif/commands/org/current.ts
4
4
  var OrgCurrent = class extends BaseCommand {
5
5
  static description = "Show currently selected organization";
@@ -23,7 +23,7 @@ var OrgCurrent = class extends BaseCommand {
23
23
  };
24
24
  }
25
25
  try {
26
- const current = unwrap(await createApiClient(getConfig()).organizations.list()).find((o) => o.id === credentials.organizationId) ?? null;
26
+ const current = unwrap(await createApiClient(await getConfig()).organizations.list()).find((o) => o.id === credentials.organizationId) ?? null;
27
27
  if (!this.jsonEnabled()) if (current) this.log(`Current organization: ${current.name} (${current.id})`);
28
28
  else this.log(`Current organization ID: ${credentials.organizationId}`);
29
29
  return {
@@ -1,5 +1,5 @@
1
- import { m as unwrap, p as createApiClient, y as getConfig } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { m as unwrap, p as createApiClient, y as getConfig } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  import chalk from "chalk";
4
4
  import { Flags } from "@oclif/core";
5
5
  //#region src/adapters/oclif/commands/org/list.ts
@@ -12,7 +12,7 @@ var OrgList = class extends BaseCommand {
12
12
  }) };
13
13
  async run() {
14
14
  const { flags } = this;
15
- const config = getConfig();
15
+ const config = await getConfig();
16
16
  const organizations = unwrap(await createApiClient(config).organizations.list());
17
17
  const result = {
18
18
  organizations,
@@ -1,5 +1,5 @@
1
- import { M as loadCredentials, N as saveCredentials, m as unwrap, n as selectOrganization, p as createApiClient, y as getConfig } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { M as loadCredentials, N as saveCredentials, m as unwrap, n as selectOrganization, p as createApiClient, y as getConfig } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  import chalk from "chalk";
4
4
  import { Args } from "@oclif/core";
5
5
  //#region src/adapters/oclif/commands/org/switch.ts
@@ -11,7 +11,7 @@ var OrgSwitch = class extends BaseCommand {
11
11
  }) };
12
12
  async run() {
13
13
  const { args } = this;
14
- const organizations = unwrap(await createApiClient(getConfig()).organizations.list());
14
+ const organizations = unwrap(await createApiClient(await getConfig()).organizations.list());
15
15
  if (organizations.length === 0) this.error("You don't belong to any organizations.", { exit: 1 });
16
16
  let selected;
17
17
  if (args.id) {
@@ -1,5 +1,5 @@
1
- import { p as createApiClient, r as DiffService, y as getConfig } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { p as createApiClient, r as DiffService, y as getConfig } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  import chalk from "chalk";
4
4
  import { Args, Flags } from "@oclif/core";
5
5
  //#region src/adapters/oclif/commands/overlays/diff.ts
@@ -18,7 +18,7 @@ var OverlaysDiff = class extends BaseCommand {
18
18
  async run() {
19
19
  const { flags, args } = this;
20
20
  const files = args.files ?? [];
21
- const result = await new DiffService({ api: createApiClient(getConfig()) }).execute({
21
+ const result = await new DiffService({ api: createApiClient(await getConfig()) }).execute({
22
22
  dir: flags.dir,
23
23
  files: files.length > 0 ? files : void 0
24
24
  });
@@ -1,5 +1,5 @@
1
- import { a as PullService, p as createApiClient, y as getConfig } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { a as PullService, p as createApiClient, y as getConfig } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  import chalk from "chalk";
4
4
  import { Flags } from "@oclif/core";
5
5
  //#region src/adapters/oclif/commands/overlays/pull.ts
@@ -19,7 +19,7 @@ var OverlaysPull = class extends BaseCommand {
19
19
  };
20
20
  async run() {
21
21
  const { flags } = this;
22
- const result = await new PullService({ api: createApiClient(getConfig()) }).execute({
22
+ const result = await new PullService({ api: createApiClient(await getConfig()) }).execute({
23
23
  dir: flags.dir,
24
24
  names: flags.name
25
25
  });
@@ -1,5 +1,5 @@
1
- import { o as PushService, p as createApiClient, y as getConfig } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { o as PushService, p as createApiClient, y as getConfig } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  import chalk from "chalk";
4
4
  import { Args, Flags } from "@oclif/core";
5
5
  //#region src/adapters/oclif/commands/overlays/push.ts
@@ -25,7 +25,7 @@ var OverlaysPush = class extends BaseCommand {
25
25
  async run() {
26
26
  const { flags, args } = this;
27
27
  const files = args.files ?? [];
28
- const result = await new PushService({ api: createApiClient(getConfig()) }).execute({
28
+ const result = await new PushService({ api: createApiClient(await getConfig()) }).execute({
29
29
  dir: flags.dir,
30
30
  force: flags.force,
31
31
  files: files.length > 0 ? files : void 0
@@ -1,5 +1,5 @@
1
- import { i as StatusService, p as createApiClient, y as getConfig } from "../../../../core-Bif-kxlo.mjs";
2
- import { t as BaseCommand } from "../../../../base.command-BGM225ik.mjs";
1
+ import { i as StatusService, p as createApiClient, y as getConfig } from "../../../../core-EJgxP-x5.mjs";
2
+ import { t as BaseCommand } from "../../../../base.command-DDSLyx5v.mjs";
3
3
  import chalk from "chalk";
4
4
  import { Args, Flags } from "@oclif/core";
5
5
  //#region src/adapters/oclif/commands/overlays/status.ts
@@ -32,7 +32,7 @@ var OverlaysStatus = class extends BaseCommand {
32
32
  async run() {
33
33
  const { flags, args } = this;
34
34
  const files = args.files ?? [];
35
- const result = await new StatusService({ api: createApiClient(getConfig()) }).execute({
35
+ const result = await new StatusService({ api: createApiClient(await getConfig()) }).execute({
36
36
  dir: flags.dir,
37
37
  files: files.length > 0 ? files : void 0
38
38
  });
@@ -1,4 +1,4 @@
1
- import { E as setClerkEnv, P as ApiError } from "./core-Bif-kxlo.mjs";
1
+ import { E as setClerkEnv, P as ApiError } from "./core-EJgxP-x5.mjs";
2
2
  import { Command, Flags } from "@oclif/core";
3
3
  import { makeTable } from "@oclif/table";
4
4
  //#region src/adapters/oclif/base.command.ts