@clidey/whodb-sdk 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +81 -0
  2. package/dist/auth.d.ts +26 -0
  3. package/dist/auth.js +65 -0
  4. package/dist/client.d.ts +51 -0
  5. package/dist/client.js +157 -0
  6. package/dist/config.d.ts +37 -0
  7. package/dist/config.js +39 -0
  8. package/dist/dataset.d.ts +26 -0
  9. package/dist/dataset.js +45 -0
  10. package/dist/errors.d.ts +43 -0
  11. package/dist/errors.js +59 -0
  12. package/dist/files.d.ts +25 -0
  13. package/dist/files.js +53 -0
  14. package/dist/generated/hydration.d.ts +3 -0
  15. package/dist/generated/hydration.js +32 -0
  16. package/dist/generated/manifest.d.ts +12 -0
  17. package/dist/generated/manifest.js +80 -0
  18. package/dist/generated/operations.d.ts +196 -0
  19. package/dist/generated/operations.js +145 -0
  20. package/dist/generated/surface.d.ts +190 -0
  21. package/dist/generated/surface.js +191 -0
  22. package/dist/generated/types.d.ts +302 -0
  23. package/dist/generated/types.js +2 -0
  24. package/dist/hydrate.d.ts +18 -0
  25. package/dist/hydrate.js +83 -0
  26. package/dist/index.d.ts +14 -0
  27. package/dist/index.js +9 -0
  28. package/dist/manifest-check.d.ts +15 -0
  29. package/dist/manifest-check.js +43 -0
  30. package/dist/ontology.d.ts +73 -0
  31. package/dist/ontology.js +240 -0
  32. package/dist/pagination.d.ts +21 -0
  33. package/dist/pagination.js +33 -0
  34. package/dist/source.d.ts +31 -0
  35. package/dist/source.js +63 -0
  36. package/dist/transport-http.d.ts +22 -0
  37. package/dist/transport-http.js +60 -0
  38. package/dist/transport-ipc.d.ts +31 -0
  39. package/dist/transport-ipc.js +183 -0
  40. package/dist/transport.d.ts +9 -0
  41. package/dist/transport.js +1 -0
  42. package/dist/version.d.ts +5 -0
  43. package/dist/version.js +5 -0
  44. package/package.json +34 -0
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # @clidey/whodb-sdk
2
+
3
+ Official TypeScript/JavaScript SDK for the [WhoDB](https://whodb.com) hosted
4
+ platform — your ontology, datasets, and sources as in-code function APIs.
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npm install @clidey/whodb-sdk
10
+ ```
11
+
12
+ Requires Node.js ≥ 20.
13
+
14
+ ## Quickstart
15
+
16
+ ```ts
17
+ import { WhoDB } from '@clidey/whodb-sdk';
18
+
19
+ // Production: API key (create one in org settings → API keys).
20
+ // The key carries its org; the project auto-resolves when the key
21
+ // has access to exactly one project.
22
+ const whodb = new WhoDB({ apiKey: process.env.WHODB_API_KEY });
23
+
24
+ // Local development: zero config — reuses your `whodb login` session.
25
+ // const whodb = new WhoDB();
26
+
27
+ const users = whodb.ontology('User');
28
+
29
+ const user = await users.get('u_123');
30
+ const active = await users.list({ where: { status: { eq: 'active' } }, pageSize: 100 });
31
+ await users.create({ email: 'a@b.co' });
32
+ await users.createMany(rows, { idempotencyKey: 'import-42' });
33
+ await users.update('u_123', { plan: 'pro' });
34
+ const orders = await users.followLink('u_123', 'orders');
35
+
36
+ // Iterate everything, page by page:
37
+ for await (const page of users.list({ pageSize: 500 }).pages()) {
38
+ console.log(page.rows.length);
39
+ }
40
+
41
+ // Datasets and sources:
42
+ const kpis = await whodb.dataset('weekly_kpis').rows();
43
+ const raw = await whodb.source('src_...').rows({ Kind: 'Table', Locator: 'events' });
44
+ ```
45
+
46
+ ## Authentication
47
+
48
+ Credential precedence:
49
+
50
+ 1. `new WhoDB({ apiKey })` / `{ token }` / `{ credentials }` constructor options
51
+ 2. `WHODB_API_KEY` environment variable
52
+ 3. The `whodb` CLI's stored login (`whodb login`), gcloud-ADC-style — ideal
53
+ for local development
54
+
55
+ Workspace (`org` / `project`) is optional with an API key; pass `{ project }`
56
+ or set `WHODB_PROJECT` when the key has access to more than one project.
57
+
58
+ ## Typed clients
59
+
60
+ Generate typed entity classes from your project's ontology:
61
+
62
+ ```bash
63
+ whodb sdk generate --language ts --out src/whodb-gen/
64
+ ```
65
+
66
+ ```ts
67
+ import { createClient } from './whodb-gen/whodb.generated.js';
68
+
69
+ const { ontology } = createClient({ apiKey: process.env.WHODB_API_KEY });
70
+ const user = await ontology.User.get('u_123'); // fully typed
71
+ ```
72
+
73
+ ## Versioning
74
+
75
+ Each SDK release is generated against one WhoDB platform release. Deprecated
76
+ operations warn once per process with their removal date; operations removed
77
+ from the platform raise `WhoDBVersionError` — upgrade the package to resolve.
78
+
79
+ ## License
80
+
81
+ Apache-2.0
package/dist/auth.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * CredentialProvider yields a bearer credential for platform requests.
3
+ * refresh() is invoked once after a 401 before the request is retried.
4
+ */
5
+ export interface CredentialProvider {
6
+ token(): Promise<string>;
7
+ refresh?(): Promise<void>;
8
+ /** Workspace defaults carried by the credential source, if any. */
9
+ defaults?(): Promise<WorkspaceDefaults>;
10
+ }
11
+ /** Workspace defaults resolved from a credential source (CLI helper). */
12
+ export interface WorkspaceDefaults {
13
+ host?: string;
14
+ orgId?: string;
15
+ projectId?: string;
16
+ }
17
+ /** Static API-key credentials (production/headless usage). */
18
+ export declare function apiKeyProvider(apiKey: string): CredentialProvider;
19
+ /** Static OIDC token or caller-managed token callback. */
20
+ export declare function tokenProvider(source: string | (() => Promise<string>)): CredentialProvider;
21
+ /**
22
+ * CLI credentials: exec `whodb auth print-token --format json` and cache the
23
+ * token until shortly before its expiry — the gcloud-ADC pattern for local
24
+ * development. Requires the whodb CLI on PATH and a prior `whodb login`.
25
+ */
26
+ export declare function cliProvider(command?: string): CredentialProvider;
package/dist/auth.js ADDED
@@ -0,0 +1,65 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { AuthError, CliCredentialsError } from './errors.js';
3
+ /** Static API-key credentials (production/headless usage). */
4
+ export function apiKeyProvider(apiKey) {
5
+ return {
6
+ token: async () => apiKey,
7
+ };
8
+ }
9
+ /** Static OIDC token or caller-managed token callback. */
10
+ export function tokenProvider(source) {
11
+ if (typeof source === 'string') {
12
+ return { token: async () => source };
13
+ }
14
+ return { token: source };
15
+ }
16
+ const CLI_REFRESH_SKEW_MS = 60_000;
17
+ /**
18
+ * CLI credentials: exec `whodb auth print-token --format json` and cache the
19
+ * token until shortly before its expiry — the gcloud-ADC pattern for local
20
+ * development. Requires the whodb CLI on PATH and a prior `whodb login`.
21
+ */
22
+ export function cliProvider(command = 'whodb') {
23
+ let cached = null;
24
+ const exec = () => new Promise((resolvePromise, rejectPromise) => {
25
+ execFile(command, ['auth', 'print-token', '--format', 'json'], { timeout: 15_000 }, (error, stdout, stderr) => {
26
+ if (error) {
27
+ if (error.code === 'ENOENT') {
28
+ rejectPromise(new CliCredentialsError(`whodb CLI not found — install it or set WHODB_API_KEY`));
29
+ return;
30
+ }
31
+ rejectPromise(new CliCredentialsError(`whodb auth print-token failed: ${stderr.trim() || error.message}`));
32
+ return;
33
+ }
34
+ try {
35
+ resolvePromise(JSON.parse(stdout));
36
+ }
37
+ catch {
38
+ rejectPromise(new CliCredentialsError('whodb auth print-token returned invalid JSON'));
39
+ }
40
+ });
41
+ });
42
+ const isFresh = (entry) => {
43
+ if (!entry.expires_at)
44
+ return false; // no expiry info — re-exec every call
45
+ return new Date(entry.expires_at).getTime() - Date.now() > CLI_REFRESH_SKEW_MS;
46
+ };
47
+ return {
48
+ async token() {
49
+ if (cached && isFresh(cached))
50
+ return cached.access_token;
51
+ cached = await exec();
52
+ if (!cached.access_token)
53
+ throw new AuthError('whodb CLI returned an empty access token');
54
+ return cached.access_token;
55
+ },
56
+ async refresh() {
57
+ cached = null;
58
+ },
59
+ async defaults() {
60
+ if (!cached)
61
+ cached = await exec();
62
+ return { host: cached.host, orgId: cached.org_id, projectId: cached.project_id };
63
+ },
64
+ };
65
+ }
@@ -0,0 +1,51 @@
1
+ import type { Transport } from './transport.js';
2
+ import { type WhoDBConfig } from './config.js';
3
+ import { OntologyHandle } from './ontology.js';
4
+ import { DatasetHandle } from './dataset.js';
5
+ import { SourceHandle } from './source.js';
6
+ import { FilesHandle } from './files.js';
7
+ import type { OntologyObjectType, PlatformSource } from './generated/types.js';
8
+ /**
9
+ * WhoDB is the platform client. Configure with an API key (headless), a raw
10
+ * token, or nothing at all — local development falls back to `whodb login`
11
+ * credentials via the CLI helper.
12
+ *
13
+ * ```ts
14
+ * const whodb = new WhoDB({ apiKey: process.env.WHODB_API_KEY, org: "acme", project: "growth" });
15
+ * const user = await whodb.ontology("User").get("u_123");
16
+ * ```
17
+ */
18
+ export declare class WhoDB {
19
+ /** SHA-256 of the platform manifest this SDK release was generated from. */
20
+ static readonly manifestHash = "4b84678f5fe7d777fbd4c4b2a93dff64f4c8951978ce68006ddc3a0e25c6942f";
21
+ /** This SDK package's version. */
22
+ static readonly version = "0.0.0";
23
+ private readonly transport;
24
+ private readonly httpTransport;
25
+ private readonly filesHandle;
26
+ private readonly orgInput?;
27
+ private readonly projectInput?;
28
+ private workspacePromise;
29
+ constructor(config?: WhoDBConfig, transportOverride?: Transport);
30
+ private cliDefaults;
31
+ private skipWorkspaceResolution;
32
+ private usingApiKey;
33
+ /**
34
+ * Resolves org/project slugs or IDs to IDs, once, and stamps the workspace
35
+ * headers onto the transport. IDs pass through without a lookup.
36
+ */
37
+ private workspace;
38
+ private projectId;
39
+ /** Returns a handle for one ontology entity, addressed by apiName. */
40
+ ontology(name: string): OntologyHandle;
41
+ /** Lists all ontology entities in the project. */
42
+ ontologyEntities(): Promise<OntologyObjectType[]>;
43
+ /** Returns a handle for one dataset, addressed by name. */
44
+ dataset(name: string): DatasetHandle;
45
+ /** Returns a handle for one connected source, addressed by ID. */
46
+ source(id: string): SourceHandle;
47
+ /** Lists the project's connected sources. */
48
+ sources(): Promise<PlatformSource[]>;
49
+ /** File upload/download over the platform's bulk HTTP endpoints. */
50
+ get files(): FilesHandle;
51
+ }
package/dist/client.js ADDED
@@ -0,0 +1,157 @@
1
+ import { HttpTransport } from './transport-http.js';
2
+ import { IpcTransport } from './transport-ipc.js';
3
+ import { resolveConfig, DEFAULT_HOST } from './config.js';
4
+ import { OntologyHandle } from './ontology.js';
5
+ import { DatasetHandle } from './dataset.js';
6
+ import { SourceHandle, listSources } from './source.js';
7
+ import { FilesHandle } from './files.js';
8
+ import * as ops from './generated/operations.js';
9
+ import { manifestHash } from './generated/manifest.js';
10
+ import { ValidationError } from './errors.js';
11
+ import { SDK_VERSION } from './version.js';
12
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13
+ /**
14
+ * WhoDB is the platform client. Configure with an API key (headless), a raw
15
+ * token, or nothing at all — local development falls back to `whodb login`
16
+ * credentials via the CLI helper.
17
+ *
18
+ * ```ts
19
+ * const whodb = new WhoDB({ apiKey: process.env.WHODB_API_KEY, org: "acme", project: "growth" });
20
+ * const user = await whodb.ontology("User").get("u_123");
21
+ * ```
22
+ */
23
+ export class WhoDB {
24
+ /** SHA-256 of the platform manifest this SDK release was generated from. */
25
+ static manifestHash = manifestHash;
26
+ /** This SDK package's version. */
27
+ static version = SDK_VERSION;
28
+ transport;
29
+ httpTransport;
30
+ filesHandle;
31
+ orgInput;
32
+ projectInput;
33
+ workspacePromise = null;
34
+ constructor(config = {}, transportOverride) {
35
+ // Functions runtime autodetect: no explicit transport/credentials and the
36
+ // IPC env vars are present → route through the in-container IPC server.
37
+ if (!transportOverride &&
38
+ !config.credentials && !config.apiKey && !config.token &&
39
+ !process.env.WHODB_API_KEY && process.env.WHODB_IPC_TOKEN) {
40
+ transportOverride = new IpcTransport();
41
+ }
42
+ const resolved = resolveConfig(config);
43
+ this.orgInput = resolved.org;
44
+ this.projectInput = resolved.project;
45
+ this.usingApiKey = resolved.usingApiKey;
46
+ if (transportOverride) {
47
+ // Custom transports (IPC in the functions runtime, mocks in tests) skip
48
+ // slug resolution: org/project inputs are taken as IDs verbatim.
49
+ this.transport = transportOverride;
50
+ this.httpTransport = null;
51
+ this.filesHandle = null;
52
+ this.skipWorkspaceResolution = true;
53
+ return;
54
+ }
55
+ const host = resolved.host ?? DEFAULT_HOST;
56
+ const httpTransport = new HttpTransport({ host, credentials: resolved.credentials });
57
+ this.transport = httpTransport;
58
+ this.httpTransport = httpTransport;
59
+ this.filesHandle = new FilesHandle({
60
+ host,
61
+ credentials: resolved.credentials,
62
+ orgId: async () => (await this.workspace()).orgId,
63
+ projectId: async () => (await this.workspace()).projectId,
64
+ });
65
+ // Workspace headers must be present before the first scoped call; resolve
66
+ // lazily but wire the transport update into the resolution.
67
+ if (resolved.usingCliCredentials) {
68
+ this.cliDefaults = async () => {
69
+ const defaults = await resolved.credentials.defaults?.();
70
+ return { orgId: defaults?.orgId, projectId: defaults?.projectId };
71
+ };
72
+ }
73
+ }
74
+ cliDefaults = null;
75
+ skipWorkspaceResolution = false;
76
+ usingApiKey = false;
77
+ /**
78
+ * Resolves org/project slugs or IDs to IDs, once, and stamps the workspace
79
+ * headers onto the transport. IDs pass through without a lookup.
80
+ */
81
+ workspace() {
82
+ this.workspacePromise ??= (async () => {
83
+ let orgInput = this.orgInput;
84
+ let projectInput = this.projectInput;
85
+ if ((!orgInput || !projectInput) && this.cliDefaults) {
86
+ const defaults = await this.cliDefaults();
87
+ orgInput ??= defaults.orgId;
88
+ projectInput ??= defaults.projectId;
89
+ }
90
+ if ((!orgInput || !projectInput) && this.usingApiKey) {
91
+ // API keys carry their org, and the platform auto-resolves the
92
+ // project when the key has exactly one grant — discover both.
93
+ const mine = await ops.myWorkspace(this.transport, {});
94
+ orgInput ??= mine.orgId ?? undefined;
95
+ projectInput ??= mine.projectId ?? undefined;
96
+ if (!projectInput) {
97
+ throw new ValidationError('this API key has access to multiple (or zero) projects — pass { project } to the WhoDB constructor or set WHODB_PROJECT');
98
+ }
99
+ }
100
+ if (!orgInput || !projectInput) {
101
+ throw new ValidationError('org and project are required — pass { org, project } to the WhoDB constructor, set WHODB_ORG/WHODB_PROJECT, or run: whodb use');
102
+ }
103
+ if (this.skipWorkspaceResolution) {
104
+ return { orgId: orgInput, projectId: projectInput };
105
+ }
106
+ let orgId = orgInput;
107
+ if (!UUID_PATTERN.test(orgInput)) {
108
+ const orgs = await ops.myOrganizations(this.transport, {});
109
+ const match = orgs.find(o => o.slug === orgInput || o.name === orgInput);
110
+ if (!match)
111
+ throw new ValidationError(`organization "${orgInput}" not found for this account`);
112
+ orgId = match.id;
113
+ }
114
+ // Project resolution needs the org header in place.
115
+ this.httpTransport?.setWorkspace(orgId, undefined);
116
+ let projectId = projectInput;
117
+ if (!UUID_PATTERN.test(projectInput)) {
118
+ const projects = await ops.projects(this.transport, { orgId });
119
+ const match = projects.find(p => p.slug === projectInput || p.name === projectInput);
120
+ if (!match)
121
+ throw new ValidationError(`project "${projectInput}" not found in this organization`);
122
+ projectId = match.id;
123
+ }
124
+ this.httpTransport?.setWorkspace(orgId, projectId);
125
+ return { orgId, projectId };
126
+ })();
127
+ return this.workspacePromise;
128
+ }
129
+ projectId = async () => (await this.workspace()).projectId;
130
+ /** Returns a handle for one ontology entity, addressed by apiName. */
131
+ ontology(name) {
132
+ return new OntologyHandle(this.transport, this.projectId, name);
133
+ }
134
+ /** Lists all ontology entities in the project. */
135
+ async ontologyEntities() {
136
+ return ops.ontologyEntities(this.transport, { projectId: await this.projectId() });
137
+ }
138
+ /** Returns a handle for one dataset, addressed by name. */
139
+ dataset(name) {
140
+ return new DatasetHandle(this.transport, this.projectId, name);
141
+ }
142
+ /** Returns a handle for one connected source, addressed by ID. */
143
+ source(id) {
144
+ return new SourceHandle(this.transport, this.projectId, id);
145
+ }
146
+ /** Lists the project's connected sources. */
147
+ async sources() {
148
+ return listSources(this.transport, await this.projectId());
149
+ }
150
+ /** File upload/download over the platform's bulk HTTP endpoints. */
151
+ get files() {
152
+ if (!this.filesHandle) {
153
+ throw new ValidationError('files are not available over a custom transport');
154
+ }
155
+ return this.filesHandle;
156
+ }
157
+ }
@@ -0,0 +1,37 @@
1
+ import { type CredentialProvider } from './auth.js';
2
+ /** Constructor options for the WhoDB client. */
3
+ export interface WhoDBConfig {
4
+ /** Platform API key (whodb_sk_...). Highest-precedence credential. */
5
+ apiKey?: string;
6
+ /** Raw OIDC access token or an async token callback. */
7
+ token?: string | (() => Promise<string>);
8
+ /** Fully custom credential provider. */
9
+ credentials?: CredentialProvider;
10
+ /** Organization slug or ID. */
11
+ org?: string;
12
+ /** Project slug or ID. */
13
+ project?: string;
14
+ /** Platform host. Defaults to https://app.whodb.com. */
15
+ host?: string;
16
+ }
17
+ export declare const DEFAULT_HOST = "https://app.whodb.com";
18
+ /** Resolved client configuration after applying the precedence rules. */
19
+ export interface ResolvedConfig {
20
+ credentials: CredentialProvider;
21
+ /** True when credentials came from the CLI helper (workspace defaults apply). */
22
+ usingCliCredentials: boolean;
23
+ /** True for API keys: the key carries its org, and the platform
24
+ * auto-resolves the project when the key has exactly one grant — so
25
+ * org/project config is optional. */
26
+ usingApiKey: boolean;
27
+ host?: string;
28
+ org?: string;
29
+ project?: string;
30
+ }
31
+ /**
32
+ * Applies the credential precedence from SDK_DESIGN.md §5.3:
33
+ * constructor args → WHODB_API_KEY env → CLI helper (local-dev default).
34
+ * Workspace/host: explicit args → WHODB_ORG/WHODB_PROJECT/WHODB_HOST env →
35
+ * CLI helper's saved defaults (only when using CLI credentials).
36
+ */
37
+ export declare function resolveConfig(config: WhoDBConfig, env?: NodeJS.ProcessEnv): ResolvedConfig;
package/dist/config.js ADDED
@@ -0,0 +1,39 @@
1
+ import { apiKeyProvider, cliProvider, tokenProvider } from './auth.js';
2
+ export const DEFAULT_HOST = 'https://app.whodb.com';
3
+ /**
4
+ * Applies the credential precedence from SDK_DESIGN.md §5.3:
5
+ * constructor args → WHODB_API_KEY env → CLI helper (local-dev default).
6
+ * Workspace/host: explicit args → WHODB_ORG/WHODB_PROJECT/WHODB_HOST env →
7
+ * CLI helper's saved defaults (only when using CLI credentials).
8
+ */
9
+ export function resolveConfig(config, env = process.env) {
10
+ let credentials;
11
+ let usingCliCredentials = false;
12
+ let usingApiKey = false;
13
+ if (config.credentials) {
14
+ credentials = config.credentials;
15
+ }
16
+ else if (config.apiKey) {
17
+ credentials = apiKeyProvider(config.apiKey);
18
+ usingApiKey = true;
19
+ }
20
+ else if (config.token) {
21
+ credentials = tokenProvider(config.token);
22
+ }
23
+ else if (env.WHODB_API_KEY) {
24
+ credentials = apiKeyProvider(env.WHODB_API_KEY);
25
+ usingApiKey = true;
26
+ }
27
+ else {
28
+ credentials = cliProvider();
29
+ usingCliCredentials = true;
30
+ }
31
+ return {
32
+ credentials,
33
+ usingCliCredentials,
34
+ usingApiKey,
35
+ host: config.host ?? env.WHODB_HOST,
36
+ org: config.org ?? env.WHODB_ORG,
37
+ project: config.project ?? env.WHODB_PROJECT,
38
+ };
39
+ }
@@ -0,0 +1,26 @@
1
+ import type { Transport } from './transport.js';
2
+ import type { Dataset } from './generated/types.js';
3
+ import { type Row } from './hydrate.js';
4
+ /** Options for dataset row reads. */
5
+ export interface DatasetRowsOptions {
6
+ pageSize?: number;
7
+ pageOffset?: number;
8
+ }
9
+ /**
10
+ * DatasetHandle is the `whodb.dataset("weekly_kpis")` facade, addressed by
11
+ * dataset name.
12
+ */
13
+ export declare class DatasetHandle {
14
+ private readonly transport;
15
+ private readonly projectId;
16
+ private readonly name;
17
+ private datasetCache;
18
+ constructor(transport: Transport, projectId: () => Promise<string>, name: string);
19
+ /** Resolves and caches the dataset metadata backing this handle. */
20
+ meta(): Promise<Dataset>;
21
+ /** Queries dataset rows with optional filter/sort/paging. */
22
+ rows(options?: DatasetRowsOptions): Promise<{
23
+ rows: Row[];
24
+ totalCount: number | null;
25
+ }>;
26
+ }
@@ -0,0 +1,45 @@
1
+ import * as ops from './generated/operations.js';
2
+ import { hydrateRows } from './hydrate.js';
3
+ import { warnIfFlagged } from './manifest-check.js';
4
+ import { NotFoundError } from './errors.js';
5
+ /**
6
+ * DatasetHandle is the `whodb.dataset("weekly_kpis")` facade, addressed by
7
+ * dataset name.
8
+ */
9
+ export class DatasetHandle {
10
+ transport;
11
+ projectId;
12
+ name;
13
+ datasetCache = null;
14
+ constructor(transport, projectId, name) {
15
+ this.transport = transport;
16
+ this.projectId = projectId;
17
+ this.name = name;
18
+ }
19
+ /** Resolves and caches the dataset metadata backing this handle. */
20
+ async meta() {
21
+ if (this.datasetCache)
22
+ return this.datasetCache;
23
+ warnIfFlagged('ProjectDatasets');
24
+ const datasets = await ops.projectDatasets(this.transport, { projectId: await this.projectId() });
25
+ const dataset = datasets.find(d => d.name === this.name);
26
+ if (!dataset)
27
+ throw new NotFoundError(`dataset "${this.name}" not found in this project`);
28
+ this.datasetCache = dataset;
29
+ return dataset;
30
+ }
31
+ /** Queries dataset rows with optional filter/sort/paging. */
32
+ async rows(options = {}) {
33
+ const dataset = await this.meta();
34
+ warnIfFlagged('QueryDataset');
35
+ const result = await ops.queryDataset(this.transport, {
36
+ input: {
37
+ projectId: await this.projectId(),
38
+ datasetId: dataset.id,
39
+ pageSize: options.pageSize ?? 100,
40
+ pageOffset: options.pageOffset ?? 0,
41
+ },
42
+ });
43
+ return hydrateRows(result);
44
+ }
45
+ }
@@ -0,0 +1,43 @@
1
+ /** Base class for all errors thrown by the WhoDB SDK. */
2
+ export declare class WhoDBError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /** Authentication failed: missing, invalid, expired, or revoked credentials. */
6
+ export declare class AuthError extends WhoDBError {
7
+ }
8
+ /** The requested resource does not exist or the caller cannot see it. */
9
+ export declare class NotFoundError extends WhoDBError {
10
+ }
11
+ /** The request was rejected as invalid before execution. */
12
+ export declare class ValidationError extends WhoDBError {
13
+ }
14
+ /**
15
+ * This SDK release was generated against an older platform API and the
16
+ * operation no longer exists. The only fix is upgrading the package.
17
+ */
18
+ export declare class WhoDBVersionError extends WhoDBError {
19
+ }
20
+ /** The whodb CLI credential helper is unavailable or not logged in. */
21
+ export declare class CliCredentialsError extends WhoDBError {
22
+ }
23
+ /** An operation is not available over the current transport (e.g. IPC). */
24
+ export declare class TransportCapabilityError extends WhoDBError {
25
+ }
26
+ /** Any other platform-reported error, carrying the GraphQL error code. */
27
+ export declare class PlatformError extends WhoDBError {
28
+ readonly code: string;
29
+ constructor(message: string, code: string);
30
+ }
31
+ interface GraphQLErrorShape {
32
+ message: string;
33
+ extensions?: {
34
+ code?: string;
35
+ };
36
+ }
37
+ /**
38
+ * Maps a GraphQL errors array to the SDK error taxonomy. The first error
39
+ * decides the type; its code is preserved on PlatformError for callers that
40
+ * need to branch on specifics.
41
+ */
42
+ export declare function mapGraphQLErrors(errors: GraphQLErrorShape[]): WhoDBError;
43
+ export {};
package/dist/errors.js ADDED
@@ -0,0 +1,59 @@
1
+ /** Base class for all errors thrown by the WhoDB SDK. */
2
+ export class WhoDBError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = new.target.name;
6
+ }
7
+ }
8
+ /** Authentication failed: missing, invalid, expired, or revoked credentials. */
9
+ export class AuthError extends WhoDBError {
10
+ }
11
+ /** The requested resource does not exist or the caller cannot see it. */
12
+ export class NotFoundError extends WhoDBError {
13
+ }
14
+ /** The request was rejected as invalid before execution. */
15
+ export class ValidationError extends WhoDBError {
16
+ }
17
+ /**
18
+ * This SDK release was generated against an older platform API and the
19
+ * operation no longer exists. The only fix is upgrading the package.
20
+ */
21
+ export class WhoDBVersionError extends WhoDBError {
22
+ }
23
+ /** The whodb CLI credential helper is unavailable or not logged in. */
24
+ export class CliCredentialsError extends WhoDBError {
25
+ }
26
+ /** An operation is not available over the current transport (e.g. IPC). */
27
+ export class TransportCapabilityError extends WhoDBError {
28
+ }
29
+ /** Any other platform-reported error, carrying the GraphQL error code. */
30
+ export class PlatformError extends WhoDBError {
31
+ code;
32
+ constructor(message, code) {
33
+ super(message);
34
+ this.code = code;
35
+ }
36
+ }
37
+ /**
38
+ * Maps a GraphQL errors array to the SDK error taxonomy. The first error
39
+ * decides the type; its code is preserved on PlatformError for callers that
40
+ * need to branch on specifics.
41
+ */
42
+ export function mapGraphQLErrors(errors) {
43
+ const first = errors[0] ?? { message: 'unknown platform error' };
44
+ const code = first.extensions?.code ?? '';
45
+ const message = first.message;
46
+ switch (code) {
47
+ case 'UNAUTHENTICATED':
48
+ return new AuthError(message);
49
+ case 'FORBIDDEN':
50
+ return new AuthError(message);
51
+ case 'NOT_FOUND':
52
+ return new NotFoundError(message);
53
+ case 'BAD_USER_INPUT':
54
+ case 'GRAPHQL_VALIDATION_FAILED':
55
+ return new ValidationError(message);
56
+ default:
57
+ return new PlatformError(message, code);
58
+ }
59
+ }
@@ -0,0 +1,25 @@
1
+ import type { CredentialProvider } from './auth.js';
2
+ /** Options for the files facade. */
3
+ export interface FilesOptions {
4
+ host: string;
5
+ credentials: CredentialProvider;
6
+ orgId: () => Promise<string>;
7
+ projectId: () => Promise<string>;
8
+ }
9
+ /** Metadata returned after uploading a file. */
10
+ export interface UploadedFile {
11
+ id: string;
12
+ name: string;
13
+ }
14
+ /**
15
+ * FilesHandle wraps the platform's file HTTP endpoints — bulk payloads are
16
+ * deliberately not squeezed through GraphQL (SDK_DESIGN.md §4).
17
+ */
18
+ export declare class FilesHandle {
19
+ private readonly options;
20
+ constructor(options: FilesOptions);
21
+ /** Uploads a file (multipart) into the project's file storage. */
22
+ upload(name: string, content: Blob | Uint8Array | string, folderId?: string): Promise<UploadedFile>;
23
+ /** Downloads a project file's raw bytes. */
24
+ download(fileId: string): Promise<Uint8Array>;
25
+ }