@revos/cli 0.2.0 → 0.2.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.
- package/LICENSE +9 -0
- package/README.md +45 -0
- package/dist/adapters/oclif/commands/action-runs/get.mjs +1 -1
- package/dist/adapters/oclif/commands/action-runs/list.mjs +1 -1
- package/dist/adapters/oclif/commands/actions/get-input-schema.mjs +2 -2
- package/dist/adapters/oclif/commands/actions/get-params-schema.mjs +2 -2
- package/dist/adapters/oclif/commands/actions/get.mjs +1 -1
- package/dist/adapters/oclif/commands/actions/list.mjs +2 -2
- package/dist/adapters/oclif/commands/ai-instructions/create.mjs +1 -1
- package/dist/adapters/oclif/commands/ai-instructions/delete.mjs +1 -1
- package/dist/adapters/oclif/commands/ai-instructions/get.mjs +1 -1
- package/dist/adapters/oclif/commands/ai-instructions/list.mjs +1 -1
- package/dist/adapters/oclif/commands/ai-instructions/update.mjs +1 -1
- package/dist/adapters/oclif/commands/auth/login.mjs +2 -2
- package/dist/adapters/oclif/commands/auth/logout.mjs +7 -3
- package/dist/adapters/oclif/commands/auth/status.mjs +2 -2
- package/dist/adapters/oclif/commands/gservice-account-keys/get.mjs +1 -1
- package/dist/adapters/oclif/commands/gservice-account-keys/reveal.mjs +2 -2
- package/dist/adapters/oclif/commands/gservice-accounts/create.mjs +1 -1
- package/dist/adapters/oclif/commands/gservice-accounts/delete.mjs +1 -1
- package/dist/adapters/oclif/commands/gservice-accounts/get.mjs +1 -1
- package/dist/adapters/oclif/commands/gservice-accounts/list.mjs +1 -1
- package/dist/adapters/oclif/commands/init.mjs +4 -3
- package/dist/adapters/oclif/commands/integrations/create.d.mts +11 -0
- package/dist/adapters/oclif/commands/integrations/create.mjs +16 -0
- package/dist/adapters/oclif/commands/integrations/get.d.mts +15 -0
- package/dist/adapters/oclif/commands/integrations/get.mjs +21 -0
- package/dist/adapters/oclif/commands/integrations/list.d.mts +11 -0
- package/dist/adapters/oclif/commands/integrations/list.mjs +16 -0
- package/dist/adapters/oclif/commands/integrations/update.d.mts +15 -0
- package/dist/adapters/oclif/commands/integrations/update.mjs +21 -0
- package/dist/adapters/oclif/commands/org/create.mjs +1 -1
- package/dist/adapters/oclif/commands/org/current.mjs +2 -2
- package/dist/adapters/oclif/commands/org/get.mjs +1 -1
- package/dist/adapters/oclif/commands/org/list.mjs +2 -2
- package/dist/adapters/oclif/commands/org/switch.mjs +5 -4
- package/dist/adapters/oclif/commands/overlays/diff.mjs +5 -5
- package/dist/adapters/oclif/commands/overlays/pull.mjs +4 -3
- package/dist/adapters/oclif/commands/overlays/push.mjs +2 -2
- package/dist/adapters/oclif/commands/overlays/status.mjs +2 -2
- package/dist/adapters/oclif/commands/score-groups/create.mjs +1 -1
- package/dist/adapters/oclif/commands/score-groups/delete.mjs +1 -1
- package/dist/adapters/oclif/commands/score-groups/get.mjs +1 -1
- package/dist/adapters/oclif/commands/score-groups/list.mjs +1 -1
- package/dist/adapters/oclif/commands/score-groups/update.mjs +1 -1
- package/dist/adapters/oclif/commands/scores/create.mjs +1 -1
- package/dist/adapters/oclif/commands/scores/delete.mjs +1 -1
- package/dist/adapters/oclif/commands/scores/list.mjs +1 -1
- package/dist/adapters/oclif/commands/scores/update.mjs +1 -1
- package/dist/adapters/oclif/commands/segments/create.mjs +1 -1
- package/dist/adapters/oclif/commands/segments/delete.mjs +1 -1
- package/dist/adapters/oclif/commands/segments/evaluate.mjs +2 -2
- package/dist/adapters/oclif/commands/segments/get-evaluation-history.mjs +2 -2
- package/dist/adapters/oclif/commands/segments/get-version.mjs +2 -2
- package/dist/adapters/oclif/commands/segments/get.mjs +1 -1
- package/dist/adapters/oclif/commands/segments/list-versions.mjs +2 -2
- package/dist/adapters/oclif/commands/segments/list.mjs +1 -1
- package/dist/adapters/oclif/commands/segments/restore-version.mjs +2 -2
- package/dist/adapters/oclif/commands/segments/update.mjs +1 -1
- package/dist/adapters/oclif/commands/table-views/create.mjs +1 -1
- package/dist/adapters/oclif/commands/table-views/delete.mjs +1 -1
- package/dist/adapters/oclif/commands/table-views/list.mjs +1 -1
- package/dist/adapters/oclif/commands/table-views/update.mjs +1 -1
- package/dist/adapters/oclif/commands/tables/create.mjs +1 -1
- package/dist/adapters/oclif/commands/tables/delete.mjs +1 -1
- package/dist/adapters/oclif/commands/tables/get.mjs +1 -1
- package/dist/adapters/oclif/commands/tables/list.mjs +1 -1
- package/dist/adapters/oclif/commands/tables/update.mjs +1 -1
- package/dist/{base.command-DlVQ9Cqa.mjs → base.command-YiwlGlKs.mjs} +1 -1
- package/dist/{core-gKJ_V-K5.mjs → core-jpFPylBb.mjs} +31 -7
- package/dist/{factory-D9sR_S_g.mjs → factory-BrFKT8t-.mjs} +2 -2
- package/dist/{index-KAzwt5vr.d.mts → index-DD2Vr-pu.d.mts} +4 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{presets-Cvazkjmu.mjs → presets-D9b6IWKy.mjs} +2 -2
- package/dist/templates/.devcontainer/devcontainer.json +2 -2
- package/dist/templates/AGENTS.md +19 -9
- package/dist/templates/skills/create-dbt-transformations/SKILL.md +21 -13
- package/dist/templates/skills/create-dbt-transformations/references/edge-cases.md +1 -1
- package/dist/templates/skills/create-semantic-model/SKILL.md +11 -11
- package/dist/templates/skills/create-semantic-model/references/cube-examples.md +83 -5
- package/dist/templates/skills/explore-lakehouse/SKILL.md +7 -3
- package/dist/templates/skills/load-sample-data/SKILL.md +119 -0
- package/package.json +7 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { m as unwrap } from "../../../../core-
|
|
2
|
-
import { n as defineApiCommand } from "../../../../factory-
|
|
1
|
+
import { m as unwrap } from "../../../../core-jpFPylBb.mjs";
|
|
2
|
+
import { n as defineApiCommand } from "../../../../factory-BrFKT8t-.mjs";
|
|
3
3
|
import { Args } from "@oclif/core";
|
|
4
4
|
//#region src/adapters/oclif/commands/segments/evaluate.ts
|
|
5
5
|
var evaluate_default = defineApiCommand({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { m as unwrap } from "../../../../core-
|
|
2
|
-
import { n as defineApiCommand } from "../../../../factory-
|
|
1
|
+
import { m as unwrap } from "../../../../core-jpFPylBb.mjs";
|
|
2
|
+
import { n as defineApiCommand } from "../../../../factory-BrFKT8t-.mjs";
|
|
3
3
|
import { Args } from "@oclif/core";
|
|
4
4
|
//#region src/adapters/oclif/commands/segments/get-evaluation-history.ts
|
|
5
5
|
var get_evaluation_history_default = defineApiCommand({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { m as unwrap } from "../../../../core-
|
|
2
|
-
import { n as defineApiCommand } from "../../../../factory-
|
|
1
|
+
import { m as unwrap } from "../../../../core-jpFPylBb.mjs";
|
|
2
|
+
import { n as defineApiCommand } from "../../../../factory-BrFKT8t-.mjs";
|
|
3
3
|
import { Args } from "@oclif/core";
|
|
4
4
|
//#region src/adapters/oclif/commands/segments/get-version.ts
|
|
5
5
|
var get_version_default = defineApiCommand({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { m as unwrap } from "../../../../core-
|
|
2
|
-
import { n as defineApiCommand } from "../../../../factory-
|
|
1
|
+
import { m as unwrap } from "../../../../core-jpFPylBb.mjs";
|
|
2
|
+
import { n as defineApiCommand } from "../../../../factory-BrFKT8t-.mjs";
|
|
3
3
|
import { Args, Flags } from "@oclif/core";
|
|
4
4
|
//#region src/adapters/oclif/commands/segments/list-versions.ts
|
|
5
5
|
var list_versions_default = defineApiCommand({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { m as unwrap } from "../../../../core-
|
|
2
|
-
import { n as defineApiCommand } from "../../../../factory-
|
|
1
|
+
import { m as unwrap } from "../../../../core-jpFPylBb.mjs";
|
|
2
|
+
import { n as defineApiCommand } from "../../../../factory-BrFKT8t-.mjs";
|
|
3
3
|
import { Args } from "@oclif/core";
|
|
4
4
|
//#region src/adapters/oclif/commands/segments/restore-version.ts
|
|
5
5
|
var restore_version_default = defineApiCommand({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as setClerkEnv, F as ApiError } from "./core-jpFPylBb.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
|
|
@@ -21,6 +21,7 @@ var ApiError = class extends Error {
|
|
|
21
21
|
//#region src/core/auth/credentials-store.ts
|
|
22
22
|
const REVOS_DIR = path.join(os.homedir(), ".revos");
|
|
23
23
|
const CREDENTIALS_FILE = path.join(REVOS_DIR, "credentials.json");
|
|
24
|
+
const isPosix = process.platform !== "win32";
|
|
24
25
|
function getCredentialsPath() {
|
|
25
26
|
return CREDENTIALS_FILE;
|
|
26
27
|
}
|
|
@@ -34,11 +35,11 @@ function loadCredentials() {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
function saveCredentials(credentials) {
|
|
37
|
-
if (!fs.existsSync(REVOS_DIR)) fs.mkdirSync(REVOS_DIR, { mode: 448 });
|
|
38
|
-
fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), {
|
|
38
|
+
if (!fs.existsSync(REVOS_DIR)) fs.mkdirSync(REVOS_DIR, isPosix ? { mode: 448 } : void 0);
|
|
39
|
+
fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), isPosix ? {
|
|
39
40
|
mode: 384,
|
|
40
41
|
encoding: "utf-8"
|
|
41
|
-
});
|
|
42
|
+
} : { encoding: "utf-8" });
|
|
42
43
|
}
|
|
43
44
|
function deleteCredentials() {
|
|
44
45
|
try {
|
|
@@ -391,6 +392,26 @@ function findRemoteOnlyOverlays(localOverlays, remoteOverlays) {
|
|
|
391
392
|
return remoteOverlays.filter((r) => !localNames.has(r.name));
|
|
392
393
|
}
|
|
393
394
|
//#endregion
|
|
395
|
+
//#region src/core/url.ts
|
|
396
|
+
const DEFAULT_APP_URL = "https://app.revos.dev";
|
|
397
|
+
/**
|
|
398
|
+
* Derive the RevOS app (frontend) URL from the API URL.
|
|
399
|
+
* `https://api.revos.ai` → `https://app.revos.ai`
|
|
400
|
+
* `https://api.revos.dev` → `https://app.revos.dev`
|
|
401
|
+
*/
|
|
402
|
+
function resolveAppUrl(apiUrl) {
|
|
403
|
+
try {
|
|
404
|
+
const parsed = new URL(apiUrl);
|
|
405
|
+
const host = parsed.hostname;
|
|
406
|
+
if (host.startsWith("api.")) {
|
|
407
|
+
parsed.hostname = host.replace(/^api\./, "app.");
|
|
408
|
+
parsed.pathname = "/";
|
|
409
|
+
return parsed.origin;
|
|
410
|
+
}
|
|
411
|
+
} catch {}
|
|
412
|
+
return DEFAULT_APP_URL;
|
|
413
|
+
}
|
|
414
|
+
//#endregion
|
|
394
415
|
//#region src/core/api/create-client.ts
|
|
395
416
|
function createApiClient(config) {
|
|
396
417
|
const headers = {};
|
|
@@ -817,6 +838,7 @@ var InitService = class InitService {
|
|
|
817
838
|
".claude/skills/create-semantic-model/references",
|
|
818
839
|
".claude/skills/create-dbt-transformations",
|
|
819
840
|
".claude/skills/create-dbt-transformations/references",
|
|
841
|
+
".claude/skills/load-sample-data",
|
|
820
842
|
"dbt/models/bronze",
|
|
821
843
|
"dbt/models/silver",
|
|
822
844
|
"dbt/models/gold",
|
|
@@ -841,6 +863,7 @@ var InitService = class InitService {
|
|
|
841
863
|
".claude/skills/create-dbt-transformations/references/sql-templates.md",
|
|
842
864
|
".claude/skills/create-dbt-transformations/references/schema-conventions.md",
|
|
843
865
|
".claude/skills/create-dbt-transformations/references/edge-cases.md",
|
|
866
|
+
".claude/skills/load-sample-data/SKILL.md",
|
|
844
867
|
"dbt/models/bronze/.gitkeep",
|
|
845
868
|
"dbt/models/silver/.gitkeep",
|
|
846
869
|
"dbt/models/gold/.gitkeep",
|
|
@@ -895,10 +918,10 @@ var InitService = class InitService {
|
|
|
895
918
|
if (!keyJson) throw new Error("Service account key is empty");
|
|
896
919
|
const gcpKeyPath = path.join(os.homedir(), ".revos", `${projectSlug}-gsa-creds.json`);
|
|
897
920
|
fs.mkdirSync(path.dirname(gcpKeyPath), { recursive: true });
|
|
898
|
-
fs.writeFileSync(gcpKeyPath, keyJson, {
|
|
921
|
+
fs.writeFileSync(gcpKeyPath, keyJson, process.platform !== "win32" ? {
|
|
899
922
|
encoding: "utf-8",
|
|
900
923
|
mode: 384
|
|
901
|
-
});
|
|
924
|
+
} : { encoding: "utf-8" });
|
|
902
925
|
return JSON.parse(keyJson).project_id ?? "";
|
|
903
926
|
}
|
|
904
927
|
dryRun(projectName, targetDir) {
|
|
@@ -948,6 +971,7 @@ var InitService = class InitService {
|
|
|
948
971
|
".claude/skills/create-dbt-transformations/references/sql-templates.md": this.renderTemplate("skills/create-dbt-transformations/references/sql-templates.md", {}),
|
|
949
972
|
".claude/skills/create-dbt-transformations/references/schema-conventions.md": this.renderTemplate("skills/create-dbt-transformations/references/schema-conventions.md", {}),
|
|
950
973
|
".claude/skills/create-dbt-transformations/references/edge-cases.md": this.renderTemplate("skills/create-dbt-transformations/references/edge-cases.md", {}),
|
|
974
|
+
".claude/skills/load-sample-data/SKILL.md": this.renderTemplate("skills/load-sample-data/SKILL.md", {}),
|
|
951
975
|
"dbt/models/bronze/.gitkeep": "",
|
|
952
976
|
"dbt/models/silver/.gitkeep": "",
|
|
953
977
|
"dbt/models/gold/.gitkeep": "",
|
|
@@ -956,7 +980,7 @@ var InitService = class InitService {
|
|
|
956
980
|
for (const [rel, content] of Object.entries(files)) {
|
|
957
981
|
const full = path.join(projectDir, rel);
|
|
958
982
|
fs.writeFileSync(full, content, "utf-8");
|
|
959
|
-
if (rel.endsWith(".sh")) fs.chmodSync(full, 493);
|
|
983
|
+
if (rel.endsWith(".sh") && process.platform !== "win32") fs.chmodSync(full, 493);
|
|
960
984
|
created.push(rel);
|
|
961
985
|
}
|
|
962
986
|
return created;
|
|
@@ -970,4 +994,4 @@ var InitService = class InitService {
|
|
|
970
994
|
}
|
|
971
995
|
};
|
|
972
996
|
//#endregion
|
|
973
|
-
export {
|
|
997
|
+
export { deleteCredentials as A, generatePKCEChallenge as C, setClerkEnv as D, setClerkConfig as E, ApiError as F, isTokenExpired as M, loadCredentials as N, tokenResponseToCredentials as O, saveCredentials as P, exchangeCodeForTokens as S, refreshAccessToken as T, formatError as _, PullService as a, getConfig as b, loadOverlayFile as c, loadOverlaysFromDir as d, saveOverlayToFile as f, findRemoteOnlyOverlays as g, resolveAppUrl as h, StatusService as i, getCredentialsPath as j, startOAuthServer as k, loadOverlays as l, unwrap as m, selectOrganization as n, PushService as o, createApiClient as p, DiffService as r, getLocalOverlayNames as s, InitService as t, loadOverlaysByNames as u, isContentEqual as v, getUserInfo as w, buildAuthorizationUrl as x, sanitizeFileName as y };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as BaseCommand } from "./base.command-
|
|
1
|
+
import { b as getConfig, p as createApiClient } from "./core-jpFPylBb.mjs";
|
|
2
|
+
import { t as BaseCommand } from "./base.command-YiwlGlKs.mjs";
|
|
3
3
|
import * as fs from "fs";
|
|
4
4
|
import * as path from "path";
|
|
5
5
|
import chalk from "chalk";
|
|
@@ -80,6 +80,9 @@ declare function sanitizeFileName(name: string): string;
|
|
|
80
80
|
declare function isContentEqual(local: OverlayFile, remote: CubeOverlay): boolean;
|
|
81
81
|
declare function findRemoteOnlyOverlays(localOverlays: LoadedOverlay[], remoteOverlays: CubeOverlay[]): CubeOverlay[];
|
|
82
82
|
//#endregion
|
|
83
|
+
//#region src/core/url.d.ts
|
|
84
|
+
declare function resolveAppUrl(apiUrl: string): string;
|
|
85
|
+
//#endregion
|
|
83
86
|
//#region src/core/api/create-client.d.ts
|
|
84
87
|
type ApiClient = Client;
|
|
85
88
|
declare function createApiClient(config: {
|
|
@@ -187,4 +190,4 @@ declare class InitService {
|
|
|
187
190
|
private renderTemplate;
|
|
188
191
|
}
|
|
189
192
|
//#endregion
|
|
190
|
-
export {
|
|
193
|
+
export { saveOverlayToFile as A, setClerkEnv as B, sanitizeFileName as C, loadOverlays as D, loadOverlayFile as E, exchangeCodeForTokens as F, getCredentialsPath as G, OAuthServerResult as H, generatePKCEChallenge as I, saveCredentials as J, isTokenExpired as K, getUserInfo as L, ClerkOAuthConfig as M, PKCEChallenge as N, loadOverlaysByNames as O, buildAuthorizationUrl as P, refreshAccessToken as R, isContentEqual as S, getLocalOverlayNames as T, startOAuthServer as U, tokenResponseToCredentials as V, deleteCredentials as W, ApiError as X, getConfig as Y, createApiClient as _, DiffOptions as a, findRemoteOnlyOverlays as b, StatusOptions as c, PullOptions as d, PullService as f, ApiClient as g, PushService as h, DiffContext as i, ClerkEnv as j, loadOverlaysFromDir as k, StatusService as l, PushOptions as m, InitResult as n, DiffService as o, PushContext as p, loadCredentials as q, InitService as r, StatusContext as s, InitOptions as t, PullContext as u, unwrap as v, LoadedOverlay as w, formatError as x, resolveAppUrl as y, setClerkConfig as z };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { a as DiffEntry, c as OverlayFileData, d as PushResult, f as StatusResult, i as DiffChange, l as OverlayStatusInfo, n as CubeDefinition, o as DiffResult, p as SyncStatus, r as CubeOverlay, s as OverlayFile, t as Config, u as PullResult } from "./types-C_p_6rkj.mjs";
|
|
2
|
-
import { A as
|
|
2
|
+
import { A as saveOverlayToFile, B as setClerkEnv, C as sanitizeFileName, D as loadOverlays, E as loadOverlayFile, F as exchangeCodeForTokens, G as getCredentialsPath, H as OAuthServerResult, I as generatePKCEChallenge, J as saveCredentials, K as isTokenExpired, L as getUserInfo, M as ClerkOAuthConfig, N as PKCEChallenge, O as loadOverlaysByNames, P as buildAuthorizationUrl, R as refreshAccessToken, S as isContentEqual, T as getLocalOverlayNames, U as startOAuthServer, V as tokenResponseToCredentials, W as deleteCredentials, X as ApiError, Y as getConfig, _ as createApiClient, a as DiffOptions, b as findRemoteOnlyOverlays, c as StatusOptions, d as PullOptions, f as PullService, g as ApiClient, h as PushService, i as DiffContext, j as ClerkEnv, k as loadOverlaysFromDir, l as StatusService, m as PushOptions, n as InitResult, o as DiffService, p as PushContext, q as loadCredentials, r as InitService, s as StatusContext, t as InitOptions, u as PullContext, v as unwrap, w as LoadedOverlay, x as formatError, y as resolveAppUrl, z as setClerkConfig } from "./index-DD2Vr-pu.mjs";
|
|
3
3
|
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-Y_ht_ja5.mjs";
|
|
4
|
-
export { ApiClient, ApiError, AuthResult, AuthStatusInfo, ClerkEnv, ClerkOAuthConfig, ClerkUserInfo, Config, CubeDefinition, CubeOverlay, DiffChange, DiffContext, DiffEntry, DiffOptions, DiffResult, DiffService, InitOptions, InitResult, InitService, LoadedOverlay, OAuthCallbackResult, OAuthServerResult, OrgListResult, OrgSwitchResult, OrganizationInfo, OverlayFile, OverlayFileData, OverlayStatusInfo, PKCEChallenge, PullContext, PullOptions, PullResult, PullService, PushContext, PushOptions, PushResult, PushService, StatusContext, StatusOptions, StatusResult, StatusService, StoredCredentials, SyncStatus, TokenResponse, buildAuthorizationUrl, createApiClient, deleteCredentials, exchangeCodeForTokens, findRemoteOnlyOverlays, formatError, generatePKCEChallenge, getConfig, getCredentialsPath, getLocalOverlayNames, getUserInfo, isContentEqual, isTokenExpired, loadCredentials, loadOverlayFile, loadOverlays, loadOverlaysByNames, loadOverlaysFromDir, refreshAccessToken, sanitizeFileName, saveCredentials, saveOverlayToFile, setClerkConfig, setClerkEnv, startOAuthServer, tokenResponseToCredentials, unwrap };
|
|
4
|
+
export { ApiClient, ApiError, AuthResult, AuthStatusInfo, ClerkEnv, ClerkOAuthConfig, ClerkUserInfo, Config, CubeDefinition, CubeOverlay, DiffChange, DiffContext, DiffEntry, DiffOptions, DiffResult, DiffService, InitOptions, InitResult, InitService, LoadedOverlay, OAuthCallbackResult, OAuthServerResult, OrgListResult, OrgSwitchResult, OrganizationInfo, OverlayFile, OverlayFileData, OverlayStatusInfo, PKCEChallenge, PullContext, PullOptions, PullResult, PullService, PushContext, PushOptions, PushResult, PushService, StatusContext, StatusOptions, StatusResult, StatusService, StoredCredentials, SyncStatus, TokenResponse, buildAuthorizationUrl, createApiClient, deleteCredentials, exchangeCodeForTokens, findRemoteOnlyOverlays, formatError, generatePKCEChallenge, getConfig, getCredentialsPath, getLocalOverlayNames, getUserInfo, isContentEqual, isTokenExpired, loadCredentials, loadOverlayFile, loadOverlays, loadOverlaysByNames, loadOverlaysFromDir, refreshAccessToken, resolveAppUrl, sanitizeFileName, saveCredentials, saveOverlayToFile, setClerkConfig, setClerkEnv, startOAuthServer, tokenResponseToCredentials, unwrap };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { ApiError, DiffService, InitService, PullService, PushService, StatusService, buildAuthorizationUrl, createApiClient, deleteCredentials, exchangeCodeForTokens, findRemoteOnlyOverlays, formatError, generatePKCEChallenge, getConfig, getCredentialsPath, getLocalOverlayNames, getUserInfo, isContentEqual, isTokenExpired, loadCredentials, loadOverlayFile, loadOverlays, loadOverlaysByNames, loadOverlaysFromDir, refreshAccessToken, sanitizeFileName, saveCredentials, saveOverlayToFile, setClerkConfig, setClerkEnv, startOAuthServer, tokenResponseToCredentials, unwrap };
|
|
1
|
+
import { A as deleteCredentials, C as generatePKCEChallenge, D as setClerkEnv, E as setClerkConfig, F as ApiError, M as isTokenExpired, N as loadCredentials, O as tokenResponseToCredentials, P as saveCredentials, S as exchangeCodeForTokens, T as refreshAccessToken, _ as formatError, a as PullService, b as getConfig, c as loadOverlayFile, d as loadOverlaysFromDir, f as saveOverlayToFile, g as findRemoteOnlyOverlays, h as resolveAppUrl, i as StatusService, j as getCredentialsPath, k as startOAuthServer, l as loadOverlays, m as unwrap, o as PushService, p as createApiClient, r as DiffService, s as getLocalOverlayNames, t as InitService, u as loadOverlaysByNames, v as isContentEqual, w as getUserInfo, x as buildAuthorizationUrl, y as sanitizeFileName } from "./core-jpFPylBb.mjs";
|
|
2
|
+
export { ApiError, DiffService, InitService, PullService, PushService, StatusService, buildAuthorizationUrl, createApiClient, deleteCredentials, exchangeCodeForTokens, findRemoteOnlyOverlays, formatError, generatePKCEChallenge, getConfig, getCredentialsPath, getLocalOverlayNames, getUserInfo, isContentEqual, isTokenExpired, loadCredentials, loadOverlayFile, loadOverlays, loadOverlaysByNames, loadOverlaysFromDir, refreshAccessToken, resolveAppUrl, sanitizeFileName, saveCredentials, saveOverlayToFile, setClerkConfig, setClerkEnv, startOAuthServer, tokenResponseToCredentials, unwrap };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { m as unwrap } from "./core-
|
|
2
|
-
import { n as defineApiCommand, t as bodyFlag } from "./factory-
|
|
1
|
+
import { m as unwrap } from "./core-jpFPylBb.mjs";
|
|
2
|
+
import { n as defineApiCommand, t as bodyFlag } from "./factory-BrFKT8t-.mjs";
|
|
3
3
|
import { Args, Flags } from "@oclif/core";
|
|
4
4
|
//#region src/adapters/oclif/presets.ts
|
|
5
5
|
const listFlags = {
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"postCreateCommand": "bash .devcontainer/setup.sh",
|
|
23
23
|
"mounts": [
|
|
24
24
|
{
|
|
25
|
-
"source": "${localEnv:HOME}/.revos/<%=projectSlug%>-gsa-creds.json",
|
|
25
|
+
"source": "${localEnv:HOME}${localEnv:USERPROFILE}/.revos/<%=projectSlug%>-gsa-creds.json",
|
|
26
26
|
"target": "/tmp/.revos-gsa-creds.json",
|
|
27
27
|
"type": "bind"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
|
-
"source": "${localEnv:HOME}/.revos/credentials.json",
|
|
30
|
+
"source": "${localEnv:HOME}${localEnv:USERPROFILE}/.revos/credentials.json",
|
|
31
31
|
"target": "/tmp/.revos-credentials.json",
|
|
32
32
|
"type": "bind"
|
|
33
33
|
},
|
package/dist/templates/AGENTS.md
CHANGED
|
@@ -11,12 +11,22 @@ This is a RevOS data engineering project for **<%=orgName%>** organization.
|
|
|
11
11
|
|
|
12
12
|
## Key Commands
|
|
13
13
|
|
|
14
|
-
| Command
|
|
15
|
-
|
|
|
16
|
-
| `revos auth login`
|
|
17
|
-
| `revos overlays push`
|
|
18
|
-
| `revos overlays pull`
|
|
19
|
-
| `revos overlays diff`
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
14
|
+
| Command | Description |
|
|
15
|
+
| -------------------------------- | ------------------------------------- |
|
|
16
|
+
| `revos auth login` | Authenticate with RevOS |
|
|
17
|
+
| `revos overlays push` | Push Cube overlays to RevOS |
|
|
18
|
+
| `revos overlays pull` | Pull Cube overlays from RevOS |
|
|
19
|
+
| `revos overlays diff` | Compare local vs remote overlays |
|
|
20
|
+
| `revos integrations list` | Open integrations page in RevOS UI |
|
|
21
|
+
| `revos integrations create` | Open RevOS UI to add a data source |
|
|
22
|
+
| `revos integrations update <id>` | Open RevOS UI to edit an integration |
|
|
23
|
+
| `dbt run` | Run dbt models |
|
|
24
|
+
| `dbt test` | Test dbt models |
|
|
25
|
+
| `bq ls` | List BigQuery datasets/tables |
|
|
26
|
+
|
|
27
|
+
## Data Sources
|
|
28
|
+
|
|
29
|
+
When the user wants to add or manage data sources (integrations):
|
|
30
|
+
- To add a new data source: suggest `revos integrations create`
|
|
31
|
+
- To view existing integrations: suggest `revos integrations list`
|
|
32
|
+
- If a BigQuery dataset is empty or has no tables, mention that integrations can be configured with `revos integrations create`, or sample data can be loaded if available
|
|
@@ -5,7 +5,7 @@ description: Create new dbt transformations (bronze/silver/gold models) in the R
|
|
|
5
5
|
|
|
6
6
|
# Create dbt Transformations
|
|
7
7
|
|
|
8
|
-
Use this skill to generate SQL models, declare sources, update `schema.yml`, and validate models with `
|
|
8
|
+
Use this skill to generate SQL models, declare sources, update `schema.yml`, and validate models with `dbt run` / `dbt test`.
|
|
9
9
|
|
|
10
10
|
For BigQuery exploration (listing datasets, inspecting raw tables, previewing rows, null rates), load the `explore-lakehouse` skill. If that skill is not installed, fall back to:
|
|
11
11
|
|
|
@@ -72,15 +72,13 @@ Always declare raw tables as sources before referencing them. Do not use bare fu
|
|
|
72
72
|
|
|
73
73
|
## Standard dbt Commands
|
|
74
74
|
|
|
75
|
-
Always use the `revos` wrapper:
|
|
76
|
-
|
|
77
75
|
```bash
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
dbt parse # validate syntax (no warehouse)
|
|
77
|
+
dbt compile --select <model> # resolve refs, produce compiled SQL
|
|
78
|
+
dbt run --select <model> # execute against warehouse
|
|
79
|
+
dbt test --select <model> # run tests
|
|
80
|
+
dbt build --select <model> # run + test
|
|
81
|
+
dbt build --select path:models/<layer> # entire layer
|
|
84
82
|
```
|
|
85
83
|
|
|
86
84
|
---
|
|
@@ -99,8 +97,8 @@ For each transformation (one at a time — do not batch):
|
|
|
99
97
|
6. Generate `dbt/models/<layer>/<model_name>.sql`.
|
|
100
98
|
7. Detect the primary key (Checkpoint 3 if ambiguous).
|
|
101
99
|
8. Add model entry to `dbt/models/<layer>/schema.yml` with PK and FK tests. See [schema-conventions.md](references/schema-conventions.md).
|
|
102
|
-
9. Run `
|
|
103
|
-
10. Run `
|
|
100
|
+
9. Run `dbt run --select <model_name>` and report result.
|
|
101
|
+
10. Run `dbt test --select <model_name>` and report result.
|
|
104
102
|
11. Summarize (see Final Response Format).
|
|
105
103
|
|
|
106
104
|
For multiple transformations in one request: repeat steps 1–11 per model in order.
|
|
@@ -169,6 +167,16 @@ If none produce a clear answer → Checkpoint 3.
|
|
|
169
167
|
|
|
170
168
|
A column is a FK candidate if it matches `<entity>_id` where `<entity>` ≠ model's own entity, is not part of the PK, and is not nullable by design. Add `not_null` test only (no `relationships` tests by default).
|
|
171
169
|
|
|
170
|
+
## Timestamp Column Propagation (Gold Models)
|
|
171
|
+
|
|
172
|
+
Every gold model **must** propagate at least one timestamp column so downstream Cube overlays can use SQL-based `refresh_key` (see `create-semantic-model` skill). Priority:
|
|
173
|
+
|
|
174
|
+
1. `_airbyte_extracted_at` — present on all Airbyte sources; always propagate if available in upstream.
|
|
175
|
+
2. `updated_at` / `modified_at` — CDC-friendly streams.
|
|
176
|
+
3. `created_at` — insert-only fact tables.
|
|
177
|
+
|
|
178
|
+
If the upstream source has none of these, document it in a SQL comment: `-- no timestamp column available from source`.
|
|
179
|
+
|
|
172
180
|
## SQL File Generation
|
|
173
181
|
|
|
174
182
|
See [sql-templates.md](references/sql-templates.md) for:
|
|
@@ -206,8 +214,8 @@ Tests:
|
|
|
206
214
|
- not_null on <fk>: added
|
|
207
215
|
|
|
208
216
|
Validation:
|
|
209
|
-
-
|
|
210
|
-
-
|
|
217
|
+
- dbt run: passed | failed
|
|
218
|
+
- dbt test: passed | failed
|
|
211
219
|
|
|
212
220
|
Physical table after run:
|
|
213
221
|
`<resolved_dataset>.<model_name>`
|
|
@@ -34,7 +34,7 @@ Declare it as a source in `dbt/models/bronze/schema.yml` first (see [schema-conv
|
|
|
34
34
|
|
|
35
35
|
1. Show the error verbatim — do not paraphrase warehouse errors.
|
|
36
36
|
2. Offer to fix the SQL based on the error message.
|
|
37
|
-
3. Do not proceed to `
|
|
37
|
+
3. Do not proceed to `dbt test` until run succeeds.
|
|
38
38
|
|
|
39
39
|
## test fails
|
|
40
40
|
|
|
@@ -15,8 +15,7 @@ project layout, finding gold models, resolving dbt model names to BigQuery table
|
|
|
15
15
|
creating bridge models from JSON arrays, and dbt validation commands.
|
|
16
16
|
|
|
17
17
|
If `create-dbt-transformations` is not installed: discover gold models directly via
|
|
18
|
-
`find dbt/models/gold -name "*.sql"
|
|
19
|
-
(`dbt parse`, `dbt run`, `dbt test`), and skip bridge model delegation.
|
|
18
|
+
`find dbt/models/gold -name "*.sql"` and skip bridge model delegation.
|
|
20
19
|
Warn the user: "The `create-dbt-transformations` skill is not installed — bridge model creation and dbt validation are limited."
|
|
21
20
|
|
|
22
21
|
If BigQuery exploration is needed (listing tables, inspecting schemas, previewing rows),
|
|
@@ -95,7 +94,7 @@ Follow these phases in order. Do not skip ahead.
|
|
|
95
94
|
|
|
96
95
|
1. Discover gold models via `find dbt/models/gold -name "*.sql"`.
|
|
97
96
|
2. If none exist, stop and tell the user to create gold models first via `create-dbt-transformations`.
|
|
98
|
-
3. Inspect 1-2 existing overlays in `semantic/` to detect conventions (
|
|
97
|
+
3. Inspect 1-2 existing overlays in `semantic/` to detect conventions (`extends:`, `public:`, `refresh_key` style). Apply detected conventions to new overlays. Always use flat single-cube YAML (never `cubes:` or `views:` root).
|
|
99
98
|
4. If the user named a specific model, find it. If not found, stop.
|
|
100
99
|
5. Otherwise list all discovered gold models and ask which should participate (Checkpoint 1).
|
|
101
100
|
6. Keep the full discovered list available for connector search in Phase 3.
|
|
@@ -238,13 +237,14 @@ Create Cube.dev YAML files in `semantic/`. Follow the existing style detected in
|
|
|
238
237
|
|
|
239
238
|
Key rules:
|
|
240
239
|
|
|
241
|
-
1.
|
|
242
|
-
2.
|
|
243
|
-
3.
|
|
244
|
-
4.
|
|
245
|
-
5.
|
|
246
|
-
6. `refresh_key.
|
|
247
|
-
7.
|
|
240
|
+
1. **One cube per file, flat YAML.** Each overlay file contains a single cube starting with `name:` at the root level. Never wrap with `cubes:` or `views:` at the root.
|
|
241
|
+
2. File name = cube `name` (no `gold_` prefix) + `.yml`.
|
|
242
|
+
3. `sql_table` uses fully qualified BigQuery reference with `gold_` prefix.
|
|
243
|
+
4. Every confirmed relationship gets joins in both directions.
|
|
244
|
+
5. Bridge/junction cubes use `public: false`.
|
|
245
|
+
6. Every overlay **must** include a SQL-based `refresh_key`. Use `SELECT MAX(<timestamp_col>)` with columns in this priority: `_airbyte_extracted_at` (present on all Airbyte sources), `updated_at`/`modified_at` (CDC streams), `created_at` (insert-only facts). Only use `every: <interval>` as absolute last resort when **no timestamp column exists in the table** — add a YAML comment explaining why (e.g. `# no timestamp column available`).
|
|
246
|
+
7. `refresh_key.sql` references the same table as `sql_table`.
|
|
247
|
+
8. Tag unvalidated joins with `# UNVALIDATED: <reason>`.
|
|
248
248
|
|
|
249
249
|
See [references/cube-examples.md](references/cube-examples.md) for canonical standard cube, bridge cube, join direction examples, and refresh key variants.
|
|
250
250
|
|
|
@@ -252,7 +252,7 @@ See [references/cube-examples.md](references/cube-examples.md) for canonical sta
|
|
|
252
252
|
|
|
253
253
|
## Phase 9: Validate Generated Files
|
|
254
254
|
|
|
255
|
-
1. If `create-dbt-transformations` was invoked (bridge model), it already validated dbt models. Otherwise run `
|
|
255
|
+
1. If `create-dbt-transformations` was invoked (bridge model), it already validated dbt models. Otherwise run `dbt parse`.
|
|
256
256
|
2. Verify physical tables exist in BigQuery: `bq show <dataset>.<table_name>`. If missing, document as pending.
|
|
257
257
|
3. Verify generated overlays match conventions: flat YAML, correct naming, correct `sql_table`, all dimensions present, `refresh_key` included, joins in both directions.
|
|
258
258
|
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
- [Refresh Key Variants](#refresh-key-variants)
|
|
10
10
|
- [Type Mapping](#type-mapping)
|
|
11
11
|
- [Measure Suggestions](#measure-suggestions)
|
|
12
|
+
- [Common Mistakes](#common-mistakes)
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
@@ -215,24 +216,68 @@ joins:
|
|
|
215
216
|
|
|
216
217
|
## Refresh Key Variants
|
|
217
218
|
|
|
218
|
-
|
|
219
|
+
SQL-based refresh keys are **required**. They ensure caches invalidate only when data actually changes, instead of on a fixed timer.
|
|
220
|
+
|
|
221
|
+
Priority — use the first available timestamp column:
|
|
219
222
|
|
|
220
223
|
```yaml
|
|
221
|
-
# 1. Airbyte timestamp (preferred)
|
|
224
|
+
# 1. Airbyte timestamp (preferred — present on all Airbyte sources)
|
|
222
225
|
refresh_key:
|
|
223
226
|
sql: "SELECT MAX(_airbyte_extracted_at) FROM `<dataset>.<gold_model>`"
|
|
224
227
|
|
|
225
|
-
# 2.
|
|
228
|
+
# 2. CDC / update timestamp
|
|
226
229
|
refresh_key:
|
|
227
230
|
sql: "SELECT MAX(updated_at) FROM `<dataset>.<gold_model>`"
|
|
228
231
|
|
|
229
|
-
# 3.
|
|
232
|
+
# 3. Insert-only fact table
|
|
230
233
|
refresh_key:
|
|
231
|
-
|
|
234
|
+
sql: "SELECT MAX(created_at) FROM `<dataset>.<gold_model>`"
|
|
235
|
+
|
|
236
|
+
# 4. Last resort — ONLY when the table has no timestamp column at all
|
|
237
|
+
# Add a comment explaining why:
|
|
238
|
+
refresh_key:
|
|
239
|
+
every: 1 hour # no timestamp column available in this table
|
|
232
240
|
```
|
|
233
241
|
|
|
234
242
|
`refresh_key.sql` must reference the same fully qualified table as the cube's `sql_table`.
|
|
235
243
|
|
|
244
|
+
### Common Mistakes
|
|
245
|
+
|
|
246
|
+
```yaml
|
|
247
|
+
# BAD — fixed cadence, ignores actual data changes.
|
|
248
|
+
# This forces cache rebuild every hour even when data hasn't changed.
|
|
249
|
+
refresh_key:
|
|
250
|
+
every: 1 hour
|
|
251
|
+
|
|
252
|
+
# GOOD — only invalidates when new rows arrive
|
|
253
|
+
refresh_key:
|
|
254
|
+
sql: "SELECT MAX(_airbyte_extracted_at) FROM `<dataset>.<gold_model>`"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```yaml
|
|
258
|
+
# BAD — omitting refresh_key entirely (cube uses default, which may be too aggressive)
|
|
259
|
+
name: my_cube
|
|
260
|
+
sql_table: ...
|
|
261
|
+
|
|
262
|
+
# GOOD — always include an explicit refresh_key
|
|
263
|
+
name: my_cube
|
|
264
|
+
sql_table: ...
|
|
265
|
+
refresh_key:
|
|
266
|
+
sql: "SELECT MAX(_airbyte_extracted_at) FROM `<dataset>.<gold_model>`"
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
```yaml
|
|
270
|
+
# BAD — refresh_key.sql references a different table than sql_table
|
|
271
|
+
sql_table: "`project.dataset.gold_orders`"
|
|
272
|
+
refresh_key:
|
|
273
|
+
sql: "SELECT MAX(_airbyte_extracted_at) FROM `project.dataset.gold_customers`"
|
|
274
|
+
|
|
275
|
+
# GOOD — same table in both
|
|
276
|
+
sql_table: "`project.dataset.gold_orders`"
|
|
277
|
+
refresh_key:
|
|
278
|
+
sql: "SELECT MAX(_airbyte_extracted_at) FROM `project.dataset.gold_orders`"
|
|
279
|
+
```
|
|
280
|
+
|
|
236
281
|
---
|
|
237
282
|
|
|
238
283
|
## Type Mapping
|
|
@@ -265,3 +310,36 @@ updated_at -> last_updated_at (max)
|
|
|
265
310
|
```
|
|
266
311
|
|
|
267
312
|
`count_distinct` on FK columns: define inside the cube that owns the FK, not the parent cube. Joins can produce row fan-out that distorts distinct counts.
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Common Mistakes
|
|
317
|
+
|
|
318
|
+
### Wrapping with `cubes:` or `views:` at the root
|
|
319
|
+
|
|
320
|
+
RevOS expects one cube per file with flat YAML — `name:` at the root level. The Cube.dev docs show a multi-cube `cubes:` list format, but RevOS does not use it.
|
|
321
|
+
|
|
322
|
+
```yaml
|
|
323
|
+
# BAD — multi-cube list format
|
|
324
|
+
cubes:
|
|
325
|
+
- name: hubspot_companies
|
|
326
|
+
sql_table: "`dataset.gold_hubspot_companies`"
|
|
327
|
+
dimensions:
|
|
328
|
+
id:
|
|
329
|
+
sql: "${CUBE}.id"
|
|
330
|
+
type: string
|
|
331
|
+
primary_key: true
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
```yaml
|
|
335
|
+
# GOOD — flat single-cube format
|
|
336
|
+
name: hubspot_companies
|
|
337
|
+
sql_table: "`dataset.gold_hubspot_companies`"
|
|
338
|
+
dimensions:
|
|
339
|
+
id:
|
|
340
|
+
sql: "${CUBE}.id"
|
|
341
|
+
type: string
|
|
342
|
+
primary_key: true
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Same applies to `views:` — never use it as a root key.
|