@revos/cli 0.2.3 → 0.3.1

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 (100) hide show
  1. package/README.md +42 -4
  2. package/dist/adapters/oclif/commands/action-runs/get.mjs +1 -1
  3. package/dist/adapters/oclif/commands/action-runs/list.mjs +1 -1
  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 +2 -2
  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 +1 -1
  12. package/dist/adapters/oclif/commands/ai-instructions/update.mjs +1 -1
  13. package/dist/adapters/oclif/commands/api.mjs +2 -2
  14. package/dist/adapters/oclif/commands/apply.d.mts +1 -1
  15. package/dist/adapters/oclif/commands/apply.mjs +2 -2
  16. package/dist/adapters/oclif/commands/auth/login.mjs +13 -28
  17. package/dist/adapters/oclif/commands/auth/logout.mjs +2 -2
  18. package/dist/adapters/oclif/commands/auth/status.mjs +2 -2
  19. package/dist/adapters/oclif/commands/connections/create.mjs +1 -1
  20. package/dist/adapters/oclif/commands/connections/delete.mjs +1 -1
  21. package/dist/adapters/oclif/commands/connections/get.mjs +1 -1
  22. package/dist/adapters/oclif/commands/connections/list.mjs +1 -1
  23. package/dist/adapters/oclif/commands/connections/update.mjs +1 -1
  24. package/dist/adapters/oclif/commands/cubes/create.mjs +1 -1
  25. package/dist/adapters/oclif/commands/cubes/delete.mjs +1 -1
  26. package/dist/adapters/oclif/commands/cubes/get.mjs +1 -1
  27. package/dist/adapters/oclif/commands/cubes/list.mjs +1 -1
  28. package/dist/adapters/oclif/commands/cubes/meta.d.mts +6 -0
  29. package/dist/adapters/oclif/commands/cubes/meta.mjs +45 -0
  30. package/dist/adapters/oclif/commands/cubes/query.d.mts +6 -0
  31. package/dist/adapters/oclif/commands/cubes/query.mjs +51 -0
  32. package/dist/adapters/oclif/commands/cubes/update.mjs +1 -1
  33. package/dist/adapters/oclif/commands/diff.d.mts +1 -1
  34. package/dist/adapters/oclif/commands/diff.mjs +2 -2
  35. package/dist/adapters/oclif/commands/gservice-account-keys/get.mjs +1 -1
  36. package/dist/adapters/oclif/commands/gservice-account-keys/reveal.mjs +2 -2
  37. package/dist/adapters/oclif/commands/gservice-accounts/create.mjs +1 -1
  38. package/dist/adapters/oclif/commands/gservice-accounts/delete.mjs +1 -1
  39. package/dist/adapters/oclif/commands/gservice-accounts/get.mjs +1 -1
  40. package/dist/adapters/oclif/commands/gservice-accounts/list.mjs +1 -1
  41. package/dist/adapters/oclif/commands/init.d.mts +2 -0
  42. package/dist/adapters/oclif/commands/init.mjs +92 -4
  43. package/dist/adapters/oclif/commands/org/create.mjs +1 -1
  44. package/dist/adapters/oclif/commands/org/current.mjs +2 -2
  45. package/dist/adapters/oclif/commands/org/get.mjs +1 -1
  46. package/dist/adapters/oclif/commands/org/list.mjs +2 -2
  47. package/dist/adapters/oclif/commands/org/switch.mjs +2 -2
  48. package/dist/adapters/oclif/commands/pull.d.mts +1 -1
  49. package/dist/adapters/oclif/commands/pull.mjs +2 -2
  50. package/dist/adapters/oclif/commands/score-groups/create.mjs +1 -1
  51. package/dist/adapters/oclif/commands/score-groups/delete.mjs +1 -1
  52. package/dist/adapters/oclif/commands/score-groups/get.mjs +1 -1
  53. package/dist/adapters/oclif/commands/score-groups/list.mjs +1 -1
  54. package/dist/adapters/oclif/commands/score-groups/update.mjs +1 -1
  55. package/dist/adapters/oclif/commands/scores/create.mjs +1 -1
  56. package/dist/adapters/oclif/commands/scores/delete.mjs +1 -1
  57. package/dist/adapters/oclif/commands/scores/list.mjs +1 -1
  58. package/dist/adapters/oclif/commands/scores/update.mjs +1 -1
  59. package/dist/adapters/oclif/commands/segments/create.mjs +1 -1
  60. package/dist/adapters/oclif/commands/segments/delete.mjs +1 -1
  61. package/dist/adapters/oclif/commands/segments/evaluate.mjs +2 -2
  62. package/dist/adapters/oclif/commands/segments/get-evaluation-history.mjs +2 -2
  63. package/dist/adapters/oclif/commands/segments/get-version.mjs +2 -2
  64. package/dist/adapters/oclif/commands/segments/get.mjs +1 -1
  65. package/dist/adapters/oclif/commands/segments/list-versions.mjs +2 -2
  66. package/dist/adapters/oclif/commands/segments/list.mjs +1 -1
  67. package/dist/adapters/oclif/commands/segments/restore-version.mjs +2 -2
  68. package/dist/adapters/oclif/commands/segments/update.mjs +1 -1
  69. package/dist/adapters/oclif/commands/sources/create.mjs +2 -2
  70. package/dist/adapters/oclif/commands/sources/delete.mjs +1 -1
  71. package/dist/adapters/oclif/commands/sources/get.mjs +1 -1
  72. package/dist/adapters/oclif/commands/sources/list-streams.mjs +2 -2
  73. package/dist/adapters/oclif/commands/sources/list.mjs +1 -1
  74. package/dist/adapters/oclif/commands/sources/update.mjs +2 -2
  75. package/dist/adapters/oclif/commands/status.d.mts +1 -1
  76. package/dist/adapters/oclif/commands/status.mjs +3 -3
  77. package/dist/adapters/oclif/commands/table-views/create.mjs +1 -1
  78. package/dist/adapters/oclif/commands/table-views/delete.mjs +1 -1
  79. package/dist/adapters/oclif/commands/table-views/list.mjs +1 -1
  80. package/dist/adapters/oclif/commands/table-views/update.mjs +1 -1
  81. package/dist/adapters/oclif/commands/tables/create.mjs +1 -1
  82. package/dist/adapters/oclif/commands/tables/delete.mjs +1 -1
  83. package/dist/adapters/oclif/commands/tables/get.mjs +1 -1
  84. package/dist/adapters/oclif/commands/tables/list.mjs +1 -1
  85. package/dist/adapters/oclif/commands/tables/update.mjs +1 -1
  86. package/dist/{base.command-D8taHOFF.mjs → base.command-CnVb4RG6.mjs} +1 -1
  87. package/dist/{core-B-IdeRNl.mjs → core-CY9pC37x.mjs} +68 -5
  88. package/dist/{factory-CCcimDhl.mjs → factory-DTqayaCF.mjs} +2 -2
  89. package/dist/{index-D0ax2I61.d.mts → index-Cbb9pLt6.d.mts} +26 -1
  90. package/dist/index.d.mts +2 -2
  91. package/dist/index.mjs +2 -2
  92. package/dist/{presets-Bb9gwgeh.mjs → presets-mJzFGMhG.mjs} +2 -2
  93. package/dist/templates/.devcontainer/Dockerfile +8 -0
  94. package/dist/templates/.devcontainer/devcontainer.json +10 -9
  95. package/dist/templates/.devcontainer/post-create.sh +46 -0
  96. package/dist/templates/.devcontainer/post-start.sh +61 -0
  97. package/dist/templates/.devcontainer/welcome.sh +26 -0
  98. package/dist/templates/README.md +80 -12
  99. package/package.json +1 -1
  100. package/dist/templates/.devcontainer/setup.sh +0 -35
@@ -25,6 +25,7 @@ declare class ApiError extends Error {
25
25
  //#endregion
26
26
  //#region src/core/config.d.ts
27
27
  declare const DEFAULT_API_URL = "https://api.revos.ai";
28
+ declare function resolveApiUrl(): string;
28
29
  declare function getConfig(): Promise<Config>;
29
30
  //#endregion
30
31
  //#region src/core/auth/credentials-store.d.ts
@@ -78,6 +79,18 @@ declare function getUserInfo(accessToken: string): Promise<ClerkUserInfo>;
78
79
  declare function tokenResponseToCredentials(tokenResponse: TokenResponse, userInfo: ClerkUserInfo): StoredCredentials;
79
80
  declare function refreshAccessToken(refreshToken: string): Promise<TokenResponse>;
80
81
  //#endregion
82
+ //#region src/core/auth/oauth-flow.d.ts
83
+ interface PerformOAuthLoginOptions {
84
+ apiUrl: string;
85
+ organizationId?: string;
86
+ log?: (msg: string) => void;
87
+ }
88
+ interface PerformOAuthLoginResult {
89
+ credentials: StoredCredentials;
90
+ userInfo: ClerkUserInfo;
91
+ }
92
+ declare function performOAuthLogin(opts: PerformOAuthLoginOptions): Promise<PerformOAuthLoginResult>;
93
+ //#endregion
81
94
  //#region src/core/utils.d.ts
82
95
  declare function formatError(error: unknown): string;
83
96
  declare function sanitizeFileName(name: string): string;
@@ -559,6 +572,16 @@ interface InitResult {
559
572
  createdFiles: string[];
560
573
  pulledIac: PullResult;
561
574
  }
575
+ interface EnsureGcpKeyOptions {
576
+ apiUrl: string;
577
+ token: string;
578
+ organization: OrganizationInfo;
579
+ projectSlug: string;
580
+ }
581
+ interface EnsureGcpKeyResult {
582
+ keyPath: string;
583
+ status: "exists" | "created";
584
+ }
562
585
  declare class InitService {
563
586
  private readonly templatesDir;
564
587
  private static readonly PROJECT_DIRS;
@@ -567,6 +590,8 @@ declare class InitService {
567
590
  run(options: InitOptions): Promise<InitResult>;
568
591
  private pullIacResources;
569
592
  resolveOrganization(apiUrl: string, token: string, organizationId?: string): Promise<OrganizationInfo>;
593
+ static gcpKeyPath(projectSlug: string): string;
594
+ ensureGcpKey(options: EnsureGcpKeyOptions): Promise<EnsureGcpKeyResult>;
570
595
  private downloadGcpKey;
571
596
  dryRun(projectDir: string): {
572
597
  projectDir: string;
@@ -578,4 +603,4 @@ declare class InitService {
578
603
  private renderTemplate;
579
604
  }
580
605
  //#endregion
581
- export { setAuthEnv as A, getConfig as B, buildAuthorizationUrl as C, getUserInfo as D, getActiveAuthConfig as E, getCredentialsPath as F, Config as H, isTokenExpired as I, loadCredentials as L, OAuthServerResult as M, startOAuthServer as N, refreshAccessToken as O, deleteCredentials as P, saveCredentials as R, PKCEChallenge as S, generatePKCEChallenge as T, ApiError as V, formatError as _, formatEnvMismatchError as a, AuthConfig as b, renderProjectContextLine as c, PulledResource as d, AppliedResource as f, resolveAppUrl as g, unwrap as h, formatCredentialsMismatchWarning as i, tokenResponseToCredentials as j, setAuthConfig as k, index_d_exports as l, createApiClient as m, InitResult as n, formatInProjectSwitchWarning as o, ApiClient as p, InitService as r, formatProjectOrgFlagError as s, InitOptions as t, ResourceStatus as u, sanitizeFileName as v, exchangeCodeForTokens as w, AuthEnv as x, AUTH_ENVS as y, DEFAULT_API_URL as z };
606
+ export { getUserInfo as A, loadCredentials as B, AuthConfig as C, exchangeCodeForTokens as D, buildAuthorizationUrl as E, OAuthServerResult as F, ApiError as G, DEFAULT_API_URL as H, startOAuthServer as I, Config as K, deleteCredentials as L, setAuthConfig as M, setAuthEnv as N, generatePKCEChallenge as O, tokenResponseToCredentials as P, getCredentialsPath as R, AUTH_ENVS as S, PKCEChallenge as T, getConfig as U, saveCredentials as V, resolveApiUrl as W, formatError as _, formatEnvMismatchError as a, PerformOAuthLoginResult as b, renderProjectContextLine as c, PulledResource as d, AppliedResource as f, resolveAppUrl as g, unwrap as h, formatCredentialsMismatchWarning as i, refreshAccessToken as j, getActiveAuthConfig as k, index_d_exports as l, createApiClient as m, InitResult as n, formatInProjectSwitchWarning as o, ApiClient as p, InitService as r, formatProjectOrgFlagError as s, InitOptions as t, ResourceStatus as u, sanitizeFileName as v, AuthEnv as w, performOAuthLogin as x, PerformOAuthLoginOptions as y, isTokenExpired as z };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as setAuthEnv, B as getConfig, C as buildAuthorizationUrl, D as getUserInfo, E as getActiveAuthConfig, F as getCredentialsPath, H as Config, I as isTokenExpired, L as loadCredentials, M as OAuthServerResult, N as startOAuthServer, O as refreshAccessToken, P as deleteCredentials, R as saveCredentials, S as PKCEChallenge, T as generatePKCEChallenge, V as ApiError, _ as formatError, a as formatEnvMismatchError, b as AuthConfig, c as renderProjectContextLine, g as resolveAppUrl, h as unwrap, i as formatCredentialsMismatchWarning, j as tokenResponseToCredentials, k as setAuthConfig, l as index_d_exports, m as createApiClient, n as InitResult, o as formatInProjectSwitchWarning, p as ApiClient, r as InitService, s as formatProjectOrgFlagError, t as InitOptions, v as sanitizeFileName, w as exchangeCodeForTokens, x as AuthEnv, y as AUTH_ENVS, z as DEFAULT_API_URL } from "./index-D0ax2I61.mjs";
1
+ import { A as getUserInfo, B as loadCredentials, C as AuthConfig, D as exchangeCodeForTokens, E as buildAuthorizationUrl, F as OAuthServerResult, G as ApiError, H as DEFAULT_API_URL, I as startOAuthServer, K as Config, L as deleteCredentials, M as setAuthConfig, N as setAuthEnv, O as generatePKCEChallenge, P as tokenResponseToCredentials, R as getCredentialsPath, S as AUTH_ENVS, T as PKCEChallenge, U as getConfig, V as saveCredentials, W as resolveApiUrl, _ as formatError, a as formatEnvMismatchError, b as PerformOAuthLoginResult, c as renderProjectContextLine, g as resolveAppUrl, h as unwrap, i as formatCredentialsMismatchWarning, j as refreshAccessToken, k as getActiveAuthConfig, l as index_d_exports, m as createApiClient, n as InitResult, o as formatInProjectSwitchWarning, p as ApiClient, r as InitService, s as formatProjectOrgFlagError, t as InitOptions, v as sanitizeFileName, w as AuthEnv, x as performOAuthLogin, y as PerformOAuthLoginOptions, z as isTokenExpired } from "./index-Cbb9pLt6.mjs";
2
2
  import { a as OrgListResult, c as StoredCredentials, i as OAuthCallbackResult, l as TokenResponse, n as AuthStatusInfo, o as OrgSwitchResult, r as ClerkUserInfo, s as OrganizationInfo, t as AuthResult } from "./types-Bk2Cb5yt.mjs";
3
3
  import { a as validateEnvAgainstProject, i as resolveProjectContext, n as ProjectContext, r as isInsideProject, t as EnvMismatch } from "./context-D5uelKLe.mjs";
4
- export { AUTH_ENVS, ApiClient, ApiError, AuthConfig, AuthEnv, AuthResult, AuthStatusInfo, ClerkUserInfo, Config, DEFAULT_API_URL, EnvMismatch, InitOptions, InitResult, InitService, OAuthCallbackResult, OAuthServerResult, OrgListResult, OrgSwitchResult, OrganizationInfo, PKCEChallenge, ProjectContext, StoredCredentials, TokenResponse, buildAuthorizationUrl, createApiClient, deleteCredentials, exchangeCodeForTokens, formatCredentialsMismatchWarning, formatEnvMismatchError, formatError, formatInProjectSwitchWarning, formatProjectOrgFlagError, generatePKCEChallenge, getActiveAuthConfig, getConfig, getCredentialsPath, getUserInfo, index_d_exports as iac, isInsideProject, isTokenExpired, loadCredentials, refreshAccessToken, renderProjectContextLine, resolveAppUrl, resolveProjectContext, sanitizeFileName, saveCredentials, setAuthConfig, setAuthEnv, startOAuthServer, tokenResponseToCredentials, unwrap, validateEnvAgainstProject };
4
+ export { AUTH_ENVS, ApiClient, ApiError, AuthConfig, AuthEnv, AuthResult, AuthStatusInfo, ClerkUserInfo, Config, DEFAULT_API_URL, EnvMismatch, InitOptions, InitResult, InitService, OAuthCallbackResult, OAuthServerResult, OrgListResult, OrgSwitchResult, OrganizationInfo, PKCEChallenge, PerformOAuthLoginOptions, PerformOAuthLoginResult, ProjectContext, StoredCredentials, TokenResponse, buildAuthorizationUrl, createApiClient, deleteCredentials, exchangeCodeForTokens, formatCredentialsMismatchWarning, formatEnvMismatchError, formatError, formatInProjectSwitchWarning, formatProjectOrgFlagError, generatePKCEChallenge, getActiveAuthConfig, getConfig, getCredentialsPath, getUserInfo, index_d_exports as iac, isInsideProject, isTokenExpired, loadCredentials, performOAuthLogin, refreshAccessToken, renderProjectContextLine, resolveApiUrl, resolveAppUrl, resolveProjectContext, sanitizeFileName, saveCredentials, setAuthConfig, setAuthEnv, startOAuthServer, tokenResponseToCredentials, unwrap, validateEnvAgainstProject };
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { A as generatePKCEChallenge, B as isTokenExpired, C as formatError, D as AUTH_ENVS, E as getConfig, F as setAuthEnv, H as saveCredentials, I as tokenResponseToCredentials, L as startOAuthServer, M as getUserInfo, N as refreshAccessToken, O as buildAuthorizationUrl, P as setAuthConfig, R as deleteCredentials, S as resolveAppUrl, T as DEFAULT_API_URL, U as ApiError, V as loadCredentials, a as formatInProjectSwitchWarning, b as createApiClient, c as isInsideProject, d as iac_exports, i as formatEnvMismatchError, j as getActiveAuthConfig, k as exchangeCodeForTokens, l as resolveProjectContext, o as formatProjectOrgFlagError, r as formatCredentialsMismatchWarning, s as renderProjectContextLine, t as InitService, u as validateEnvAgainstProject, w as sanitizeFileName, x as unwrap, z as getCredentialsPath } from "./core-B-IdeRNl.mjs";
2
- export { AUTH_ENVS, ApiError, DEFAULT_API_URL, InitService, buildAuthorizationUrl, createApiClient, deleteCredentials, exchangeCodeForTokens, formatCredentialsMismatchWarning, formatEnvMismatchError, formatError, formatInProjectSwitchWarning, formatProjectOrgFlagError, generatePKCEChallenge, getActiveAuthConfig, getConfig, getCredentialsPath, getUserInfo, iac_exports as iac, isInsideProject, isTokenExpired, loadCredentials, refreshAccessToken, renderProjectContextLine, resolveAppUrl, resolveProjectContext, sanitizeFileName, saveCredentials, setAuthConfig, setAuthEnv, startOAuthServer, tokenResponseToCredentials, unwrap, validateEnvAgainstProject };
1
+ import { A as buildAuthorizationUrl, B as deleteCredentials, C as formatError, D as resolveApiUrl, E as getConfig, F as refreshAccessToken, G as ApiError, H as isTokenExpired, I as setAuthConfig, L as setAuthEnv, M as generatePKCEChallenge, N as getActiveAuthConfig, O as performOAuthLogin, P as getUserInfo, R as tokenResponseToCredentials, S as resolveAppUrl, T as DEFAULT_API_URL, U as loadCredentials, V as getCredentialsPath, W as saveCredentials, a as formatInProjectSwitchWarning, b as createApiClient, c as isInsideProject, d as iac_exports, i as formatEnvMismatchError, j as exchangeCodeForTokens, k as AUTH_ENVS, l as resolveProjectContext, o as formatProjectOrgFlagError, r as formatCredentialsMismatchWarning, s as renderProjectContextLine, t as InitService, u as validateEnvAgainstProject, w as sanitizeFileName, x as unwrap, z as startOAuthServer } from "./core-CY9pC37x.mjs";
2
+ export { AUTH_ENVS, ApiError, DEFAULT_API_URL, InitService, buildAuthorizationUrl, createApiClient, deleteCredentials, exchangeCodeForTokens, formatCredentialsMismatchWarning, formatEnvMismatchError, formatError, formatInProjectSwitchWarning, formatProjectOrgFlagError, generatePKCEChallenge, getActiveAuthConfig, getConfig, getCredentialsPath, getUserInfo, iac_exports as iac, isInsideProject, isTokenExpired, loadCredentials, performOAuthLogin, refreshAccessToken, renderProjectContextLine, resolveApiUrl, resolveAppUrl, resolveProjectContext, sanitizeFileName, saveCredentials, setAuthConfig, setAuthEnv, startOAuthServer, tokenResponseToCredentials, unwrap, validateEnvAgainstProject };
@@ -1,5 +1,5 @@
1
- import { x as unwrap } from "./core-B-IdeRNl.mjs";
2
- import { n as createListRender, r as defineApiCommand, t as bodyFlag } from "./factory-CCcimDhl.mjs";
1
+ import { x as unwrap } from "./core-CY9pC37x.mjs";
2
+ import { n as createListRender, r as defineApiCommand, t as bodyFlag } from "./factory-DTqayaCF.mjs";
3
3
  import { Args, Flags } from "@oclif/core";
4
4
  //#region src/adapters/oclif/presets.ts
5
5
  function camelToKebab(s) {
@@ -1,5 +1,13 @@
1
1
  FROM mcr.microsoft.com/devcontainers/python:3.13
2
2
 
3
+ # jq is used by .devcontainer/welcome.sh + post-start.sh to parse
4
+ # `revos auth status --json`.
5
+ # It usually ships in the base image via common-debian.sh, but install
6
+ # explicitly so this gate doesn't silently break on a future base bump.
7
+ RUN apt-get update -q \
8
+ && apt-get install -y --no-install-recommends jq \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
3
11
  # Pre-install dbt so it's available before VS Code extensions activate
4
12
  # (cryptography<47 avoids Illegal instruction on ARM)
5
13
  RUN pip install --quiet dbt-bigquery "cryptography<47"
@@ -14,25 +14,26 @@
14
14
  },
15
15
  "containerEnv": {
16
16
  "DBT_PROJECT_DIR": "${containerWorkspaceFolder}/dbt",
17
- "GOOGLE_APPLICATION_CREDENTIALS": "/home/vscode/.revos/gsa-creds.json",
17
+ "GOOGLE_APPLICATION_CREDENTIALS": "/home/vscode/.revos/<%=projectSlug%>-gsa-creds.json",
18
18
  "GOOGLE_CLOUD_PROJECT": "<%=bqProjectId%>",
19
19
  "REVOS_BQ_DATASET": "<%=bqDataset%>",
20
20
  "REVOS_ORG_ID": "<%=organizationId%>"
21
21
  },
22
- "postCreateCommand": "bash .devcontainer/setup.sh",
22
+ "postCreateCommand": "bash .devcontainer/post-create.sh",
23
+ "postStartCommand": "bash .devcontainer/post-start.sh",
23
24
  "mounts": [
24
25
  {
25
- "source": "${localEnv:HOME}${localEnv:USERPROFILE}/.revos/<%=projectSlug%>-gsa-creds.json",
26
- "target": "/tmp/.revos-gsa-creds.json",
27
- "type": "bind"
26
+ "source": "revos-<%=projectSlug%>-credentials",
27
+ "target": "/home/vscode/.revos",
28
+ "type": "volume"
28
29
  },
29
30
  {
30
- "source": "${localEnv:HOME}${localEnv:USERPROFILE}/.revos/credentials.json",
31
- "target": "/tmp/.revos-credentials.json",
32
- "type": "bind"
31
+ "source": "revos-<%=projectSlug%>-gcloud",
32
+ "target": "/home/vscode/.config/gcloud",
33
+ "type": "volume"
33
34
  },
34
35
  {
35
- "source": "claude-code-config",
36
+ "source": "revos-<%=projectSlug%>-claude",
36
37
  "target": "/home/vscode/.claude",
37
38
  "type": "volume"
38
39
  }
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Named volumes mount as root-owned by default. We use three per-project
5
+ # volumes (~/.revos, ~/.config/gcloud, ~/.claude) instead of one whole-home
6
+ # volume because VS Code's server install writes to ~/.vscode-server before
7
+ # postCreateCommand runs, and there's no clean lifecycle hook to fix
8
+ # ownership early enough for a whole-home mount.
9
+ sudo chown -R vscode:vscode /home/vscode/.revos 2>/dev/null || true
10
+ sudo chown -R vscode:vscode /home/vscode/.config/gcloud 2>/dev/null || true
11
+ sudo chown -R vscode:vscode /home/vscode/.claude 2>/dev/null || true
12
+ mkdir -p "$HOME/.revos" "$HOME/.config/gcloud"
13
+
14
+ # Install RevOS CLI
15
+ npm install -g @revos/cli
16
+
17
+ # Best-effort gcloud activation. Usually a no-op on first container create
18
+ # (user hasn't run `revos init` yet, no key file), but covers the case
19
+ # where the credentials volume was preserved across a recreate. After this,
20
+ # the gcloud auth state lives in the persisted ~/.config/gcloud volume, so
21
+ # subsequent rebuilds don't need re-activation. `revos init` itself also
22
+ # activates when it provisions a new key.
23
+ KEY="${GOOGLE_APPLICATION_CREDENTIALS:-}"
24
+ if [ -n "$KEY" ] && [ -s "$KEY" ]; then
25
+ gcloud auth activate-service-account --key-file="$KEY" >/dev/null 2>&1 || true
26
+ if [ -n "${GOOGLE_CLOUD_PROJECT:-}" ]; then
27
+ gcloud config set project "$GOOGLE_CLOUD_PROJECT" >/dev/null 2>&1 || true
28
+ fi
29
+ fi
30
+
31
+ # Symlink dbt profiles so `dbt run` works without --profiles-dir
32
+ mkdir -p "$HOME/.dbt"
33
+ ln -sf "$(pwd)/dbt/profiles.yml" "$HOME/.dbt/profiles.yml"
34
+
35
+ # Install the onboarding-banner welcome check. We copy it into ~/.revos so
36
+ # it survives outside the workspace mount, and source it from ~/.bashrc so
37
+ # it prints at the top of every interactive terminal — instead of being
38
+ # buried under postStartCommand logs in the "Dev Containers" output panel.
39
+ # The script self-clears once auth + key exist.
40
+ cp .devcontainer/welcome.sh "$HOME/.revos/welcome.sh"
41
+
42
+ if ! grep -qF 'source ~/.revos/welcome.sh' "$HOME/.bashrc" 2>/dev/null; then
43
+ echo '' >> "$HOME/.bashrc"
44
+ echo '# RevOS dev-container onboarding banner (auto-clears once set up)' >> "$HOME/.bashrc"
45
+ echo 'source ~/.revos/welcome.sh' >> "$HOME/.bashrc"
46
+ fi
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Runs on every container start (postStartCommand). Pure information —
5
+ # either SETUP REQUIRED (with next steps) or READY (with environment debug
6
+ # info). Important for users who open Claude Code directly and never touch
7
+ # a terminal where welcome.sh would otherwise print the gate.
8
+ #
9
+ # gcloud activation lives in post-create.sh (one-time) and inside `revos
10
+ # init` (when a new key is provisioned). The persisted ~/.config/gcloud
11
+ # named volume keeps the activation state across rebuilds, so this script
12
+ # doesn't need to re-activate on every start.
13
+
14
+ need_setup=false
15
+
16
+ if command -v revos >/dev/null 2>&1; then
17
+ if ! revos auth status --json 2>/dev/null | jq -e '.authenticated' >/dev/null 2>&1; then
18
+ need_setup=true
19
+ fi
20
+ if [ ! -s "$HOME/.revos/<%=projectSlug%>-gsa-creds.json" ]; then
21
+ need_setup=true
22
+ fi
23
+ fi
24
+
25
+ if $need_setup; then
26
+ echo ""
27
+ echo "████████████████████████████████████████████████████████████████████████"
28
+ echo "█ █"
29
+ echo "█ ⚠ REVOS DEV CONTAINER — SETUP REQUIRED █"
30
+ echo "█ █"
31
+ echo "█ Open a terminal and run: █"
32
+ echo "█ █"
33
+ echo "█ revos init █"
34
+ echo "█ █"
35
+ echo "████████████████████████████████████████████████████████████████████████"
36
+ echo ""
37
+ else
38
+ # Setup is complete — print a confirmation banner with environment debug
39
+ # info. Useful for users who never open a terminal, and as a quick
40
+ # reference when troubleshooting "is my container looking at the right
41
+ # project / dataset / org?".
42
+ user_email=$(revos auth status --json 2>/dev/null | jq -r '.email // "(unknown)"')
43
+ gcloud_account=$(gcloud config get-value account 2>/dev/null || true)
44
+ gcloud_account=${gcloud_account:-(none)}
45
+ gcloud_project=$(gcloud config get-value project 2>/dev/null || true)
46
+ gcloud_project=${gcloud_project:-${GOOGLE_CLOUD_PROJECT:-(none)}}
47
+
48
+ echo ""
49
+ echo "████████████████████████████████████████████████████████████████████████"
50
+ echo "█ █"
51
+ echo "█ ✓ REVOS DEV CONTAINER — READY █"
52
+ echo "█ █"
53
+ printf "█ RevOS user: %-51s █\n" "${user_email:0:51}"
54
+ printf "█ GCP account: %-51s █\n" "${gcloud_account:0:51}"
55
+ printf "█ GCP project: %-51s █\n" "${gcloud_project:0:51}"
56
+ printf "█ BQ dataset: %-51s █\n" "${REVOS_BQ_DATASET:-(unset)}"
57
+ printf "█ Org ID: %-51s █\n" "${REVOS_ORG_ID:-(unset)}"
58
+ echo "█ █"
59
+ echo "████████████████████████████████████████████████████████████████████████"
60
+ echo ""
61
+ fi
@@ -0,0 +1,26 @@
1
+ # RevOS dev-container welcome check. Sourced from ~/.bashrc on every
2
+ # interactive shell. Silent once `revos auth status` is authenticated and
3
+ # the GSA key file is present. `revos init` handles both — it signs you in
4
+ # via the browser if needed, then provisions the GSA key.
5
+ __revos_need_setup=false
6
+
7
+ if ! command -v revos >/dev/null 2>&1; then
8
+ return 0
9
+ fi
10
+ if ! revos auth status --json 2>/dev/null | jq -e '.authenticated' >/dev/null 2>&1; then
11
+ __revos_need_setup=true
12
+ fi
13
+ if [ ! -s "$HOME/.revos/<%=projectSlug%>-gsa-creds.json" ]; then
14
+ __revos_need_setup=true
15
+ fi
16
+
17
+ if $__revos_need_setup; then
18
+ echo ""
19
+ echo "============================================================"
20
+ echo " Welcome to <%=projectName%> dev container!"
21
+ echo " To finish setup, run:"
22
+ echo " revos init"
23
+ echo "============================================================"
24
+ echo ""
25
+ fi
26
+ unset __revos_need_setup
@@ -1,23 +1,91 @@
1
1
  # <%=projectName%>
2
2
 
3
- RevOS data engineering project for **<%=orgName%>** organization.
3
+ RevOS data engineering project for **<%=orgName%>**.
4
+
5
+ This project is designed to be opened in a Dev Container. All tooling — Python, Node, dbt, the Google Cloud CLI, the RevOS CLI, GitHub CLI, and Claude Code — comes pre-installed. The container is the supported development environment; you should rarely need to install anything on your host.
4
6
 
5
7
  ## Getting started
6
8
 
7
- 1. Open this folder in VS Code and click **Reopen in Container** the Dev Container installs all tools automatically.
8
- 2. Inside the container, verify your setup:
9
+ 1. **Open in VS Code** and click **Reopen in Container** when prompted. First open builds the image (~1–2 min); subsequent opens are instant.
10
+
11
+ 2. **One-time setup inside the container.** Open a terminal and run:
12
+
13
+ ```bash
14
+ revos init # signs you in via browser (if needed), then provisions the BigQuery service account key
15
+ ```
16
+
17
+ `revos init` detects it's running inside an existing project, skips the org prompt and scaffolding, and just fills in the missing GCP key. If you aren't authenticated yet, it opens the browser for sign-in first — the org is taken from `revos.yaml`.
18
+
19
+ **You won't need to repeat this.** Credentials persist in per-project Docker volumes, so every future `Rebuild Container`, restart, or VS Code reopen lands in a fully-authenticated state — the container will print `REVOS DEV CONTAINER — READY` on every start.
20
+
21
+ 3. **Verify everything is wired up.** Either look at the banner the container prints on every start (`REVOS DEV CONTAINER — READY` with your auth + GCP details), or run:
22
+
9
23
  ```bash
10
- dbt --version
11
- bq version
24
+ bq ls $REVOS_BQ_DATASET # list tables in your BigQuery dataset
25
+ dbt debug # confirm dbt connection
26
+ revos status # list local Connections/Cubes vs. the API
12
27
  ```
13
28
 
14
- ## Project structure
29
+ ## Project layout
15
30
 
16
31
  ```
17
- dbt/models/
18
- bronze/ # raw ingested data
19
- silver/ # cleaned & conformed
20
- gold/ # business-ready marts
21
- semantic/
22
- cubes/ # Cube.dev cube definitions
32
+ .
33
+ ├── revos.yaml # binds this project to your RevOS org (do not edit)
34
+ ├── connections/ # sync pipelines (RevOS-managed; one YAML per Connection)
35
+ ├── cubes/ # Cube.dev semantic model definitions (one YAML per Cube)
36
+ ├── dbt/
37
+ │ ├── dbt_project.yml
38
+ │ ├── profiles.yml # pre-configured for BigQuery via $GOOGLE_APPLICATION_CREDENTIALS
39
+ │ └── models/
40
+ │ ├── bronze/ # raw ingested data — declared as dbt sources in schema.yml
41
+ │ ├── silver/ # cleaned & conformed
42
+ │ └── gold/ # business-ready marts
43
+ ├── .claude/ # AI companion config + pre-installed skills
44
+ ├── .devcontainer/ # Dev Container definition
45
+ ├── AGENTS.md # context for AI coding agents
46
+ └── CLAUDE.md # imports AGENTS.md
23
47
  ```
48
+
49
+ ## Common workflows
50
+
51
+ | Task | Command |
52
+ | --------------------------------------------- | ------------------------------------ |
53
+ | List data sources available on RevOS | `revos sources list` |
54
+ | Add a new data source (opens RevOS UI) | `revos sources create` |
55
+ | Pull current Connections & Cubes from the API | `revos pull` |
56
+ | Push local YAML changes back to the API | `revos apply` |
57
+ | Preview drift before applying | `revos diff` |
58
+ | Run all dbt models | `dbt run` |
59
+ | Run dbt tests | `dbt test` |
60
+ | Inspect a BigQuery table | `bq head -n 5 $REVOS_BQ_DATASET.<t>` |
61
+ | Show all `revos` commands | `revos --help` |
62
+
63
+ ## Working with Claude Code
64
+
65
+ This project ships pre-installed Claude skills under `.claude/skills/` for the common tasks:
66
+
67
+ - **`explore-lakehouse`** — survey your BigQuery datasets and tables.
68
+ - **`create-connections`** — author a Connection YAML from a Source's available streams.
69
+ - **`create-cubes`** — build Cube.dev semantic models from gold-layer tables.
70
+ - **`create-dbt-transformations`** — write bronze→silver→gold dbt models.
71
+ - **`load-sample-data`** — seed BigQuery with example data when the warehouse is empty.
72
+ - **`visualize-semantic-model`** — render the cube graph as an image.
73
+
74
+ Inside the container, ask Claude things like _"create a Connection for our Stripe source"_ or _"build a silver model for the orders table"_ and it will use the matching skill.
75
+
76
+ ## Troubleshooting
77
+
78
+ - **Container shows `SETUP REQUIRED` banner.** Run `revos init` in the container terminal — it handles login automatically.
79
+ - **`bq` or `dbt` fails with auth errors.** Container's gcloud is not activated. Rebuild the container, or run `bash .devcontainer/post-start.sh` to re-activate.
80
+ - **Start from a clean slate.** Wipe the per-project Docker volumes from your host:
81
+ ```bash
82
+ docker volume rm revos-<%=projectSlug%>-credentials \
83
+ revos-<%=projectSlug%>-gcloud \
84
+ revos-<%=projectSlug%>-claude
85
+ ```
86
+ Then `Rebuild Container` and rerun step 2.
87
+
88
+ ## Further reading
89
+
90
+ - RevOS CLI reference: <https://cli.revos.dev>
91
+ - This project's AI guidance: [`AGENTS.md`](./AGENTS.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revos/cli",
3
- "version": "0.2.3",
3
+ "version": "0.3.1",
4
4
  "description": "RevOS CLI for managing RevOS platform resources",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- # Copy mounted GCP service account key to vscode user's home
5
- if [ -f /tmp/.revos-gsa-creds.json ]; then
6
- mkdir -p "$HOME/.revos"
7
- cp /tmp/.revos-gsa-creds.json "$HOME/.revos/gsa-creds.json"
8
- chmod 600 "$HOME/.revos/gsa-creds.json"
9
- fi
10
-
11
- # Copy mounted RevOS CLI credentials so revos commands work without re-login
12
- if [ -f /tmp/.revos-credentials.json ]; then
13
- mkdir -p "$HOME/.revos"
14
- cp /tmp/.revos-credentials.json "$HOME/.revos/credentials.json"
15
- chmod 600 "$HOME/.revos/credentials.json"
16
- fi
17
-
18
- # Configure gcloud with service account and project
19
- GCP_KEY="$HOME/.revos/gsa-creds.json"
20
- if [ -f "$GCP_KEY" ]; then
21
- gcloud auth activate-service-account --key-file="$GCP_KEY"
22
- fi
23
- if [ -n "${GOOGLE_CLOUD_PROJECT:-}" ]; then
24
- gcloud config set project "$GOOGLE_CLOUD_PROJECT"
25
- fi
26
-
27
- # Fix Claude Code credentials permissions (volume is created as root)
28
- sudo chown -R vscode:vscode /home/vscode/.claude 2>/dev/null || true
29
-
30
- # Install RevOS CLI
31
- npm install -g @revos/cli
32
-
33
- # Symlink dbt profiles so `dbt run` works without --profiles-dir
34
- mkdir -p "$HOME/.dbt"
35
- ln -sf "$(pwd)/dbt/profiles.yml" "$HOME/.dbt/profiles.yml"