@stardeck-customer-apps/data-store-sdk 0.2.1 → 0.3.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.
package/SKILL.md CHANGED
@@ -38,7 +38,12 @@ Server Code
38
38
  Data Store Neon Database (direct connection)
39
39
  ```
40
40
 
41
- `DATA_STORE_{NAME}_URL` is automatically injected in all environments (production, preview, sandbox).
41
+ Connection info is injected in all environments (production, preview, sandbox) via the
42
+ `STARDECK_DATA_STORES` manifest (a JSON array of `{ id, name, slug, url, accessLevel }`,
43
+ one entry per connected store). The SDK resolves a store against this manifest by **stable
44
+ slug or id**, so a binding keeps working even after the store is renamed. The legacy
45
+ per-store `DATA_STORE_{NAME}_URL` / `DATA_STORE_{NAME}_ID` keys are still injected for
46
+ backward compatibility — prefer resolving by `storeName`/`storeId` through the SDK.
42
47
 
43
48
  **Schema Management (via Platform API):**
44
49
 
@@ -80,6 +85,12 @@ DEPLOYMENT_SECRET=your-secret-key # HMAC signing (NEVER expose to cli
80
85
  ORGANIZATION_ID=org_123
81
86
  PROJECT_ID=proj_456
82
87
  DEPLOYMENT_ID=deploy_789
88
+
89
+ # Canonical: one JSON entry per connected store. Resolve through the SDK by
90
+ # storeName/storeId — don't parse this by hand.
91
+ STARDECK_DATA_STORES=[{"id":"ds-abc123","name":"My Store","slug":"mystore","url":"postgres://...","accessLevel":"write"}]
92
+
93
+ # Legacy per-store keys (still injected for back-compat with older SDKs):
83
94
  DATA_STORE_MYSTORE_URL=postgres://... # Per-store connection string (for Kysely)
84
95
  DATA_STORE_MYSTORE_ID=ds-abc123 # Per-store ID (for DataStoreClient)
85
96
  ```
@@ -95,8 +106,9 @@ Use this for schema operations, agent-driven data access, or when you don't have
95
106
  import { DataStoreClient } from "@stardeck-customer-apps/data-store-sdk/server";
96
107
 
97
108
  export const dataStore = new DataStoreClient({
98
- storeId: process.env.DATA_STORE_MYSTORE_ID!,
99
- // Other config read from env vars automatically
109
+ // Resolve the store id from its name/slug via the injected manifest (survives
110
+ // renames). Or pass storeId directly. Other config is read from env vars.
111
+ storeName: "mystore",
100
112
  });
101
113
  ```
102
114
 
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { C as ColumnDefinition, D as DataStoreClientConfig, F as FilterOperator, L as ListObjectsResult, Q as QueryFilter, b as QueryOptions, c as QueryResult, S as StorageObject, T as TableColumn, a as TableSchema } from './types-CqVD-TLQ.mjs';
1
+ export { C as ColumnDefinition, D as DataStoreClientConfig, F as FilterOperator, L as ListObjectsResult, Q as QueryFilter, b as QueryOptions, c as QueryResult, S as StorageObject, T as TableColumn, a as TableSchema } from './types-D2D9kZNF.mjs';
2
2
 
3
3
  declare class DataStoreError extends Error {
4
4
  code: string;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { C as ColumnDefinition, D as DataStoreClientConfig, F as FilterOperator, L as ListObjectsResult, Q as QueryFilter, b as QueryOptions, c as QueryResult, S as StorageObject, T as TableColumn, a as TableSchema } from './types-CqVD-TLQ.js';
1
+ export { C as ColumnDefinition, D as DataStoreClientConfig, F as FilterOperator, L as ListObjectsResult, Q as QueryFilter, b as QueryOptions, c as QueryResult, S as StorageObject, T as TableColumn, a as TableSchema } from './types-D2D9kZNF.js';
2
2
 
3
3
  declare class DataStoreError extends Error {
4
4
  code: string;
@@ -1,4 +1,4 @@
1
- import { D as DataStoreClientConfig, a as TableSchema, C as ColumnDefinition, b as QueryOptions, c as QueryResult, L as ListObjectsResult } from '../types-CqVD-TLQ.mjs';
1
+ import { D as DataStoreClientConfig, a as TableSchema, C as ColumnDefinition, b as QueryOptions, c as QueryResult, L as ListObjectsResult } from '../types-D2D9kZNF.mjs';
2
2
  import { KyselyConfig, Kysely } from 'kysely';
3
3
 
4
4
  /**
@@ -91,13 +91,17 @@ declare function signDeploymentRequest(deploymentSecret: string, payload: {
91
91
  * import { createDataStore } from "@stardeck-customer-apps/data-store-sdk/server";
92
92
  * import type { DB } from "./generated/data-store-types";
93
93
  *
94
- * // Option 1: Use storeName to auto-read DATA_STORE_MYSTORE_URL from env
94
+ * // Option 1: Resolve by store name (matched against the stable slug in the
95
+ * // injected manifest, so it survives store renames)
95
96
  * const db = await createDataStore<DB>({ storeName: "mystore" });
96
97
  *
97
- * // Option 2: Pass connection string directly
98
+ * // Option 2: Resolve by immutable store id
99
+ * const db = await createDataStore<DB>({ storeId: process.env.DATA_STORE_MYSTORE_ID });
100
+ *
101
+ * // Option 3: Pass connection string directly
98
102
  * const db = await createDataStore<DB>({ connectionString: process.env.DATA_STORE_MYSTORE_URL });
99
103
  *
100
- * // Option 3: Falls back to DATA_STORE_URL env var
104
+ * // Option 4: Falls back to DATA_STORE_URL env var
101
105
  * const db = await createDataStore<DB>();
102
106
  *
103
107
  * const users = await db
@@ -110,7 +114,46 @@ declare function signDeploymentRequest(deploymentSecret: string, payload: {
110
114
  declare function createDataStore<DB>(options?: {
111
115
  connectionString?: string;
112
116
  storeName?: string;
117
+ storeId?: string;
113
118
  kyselyConfig?: Partial<KyselyConfig>;
114
119
  }): Promise<Kysely<DB>>;
115
120
 
116
- export { DataStoreClient, createDataStore, signDeploymentRequest };
121
+ /**
122
+ * Reads and resolves the data store manifest the platform injects into a
123
+ * deployed app.
124
+ *
125
+ * The platform injects a single env var, `STARDECK_DATA_STORES`, holding a JSON
126
+ * array of one entry per connected store: a stable `slug`, the store `id`, the
127
+ * current `name`, the connection `url`, and the `accessLevel`. Resolving against
128
+ * this manifest replaces the old `DATA_STORE_{NAME}_URL` key reconstruction — no
129
+ * fragile, must-match-the-injector key derivation on this side.
130
+ *
131
+ * This file intentionally mirrors `packages/lib/src/shared/data-store-manifest.ts`
132
+ * in the platform monorepo. The SDK is published and installed inside customer
133
+ * sandboxes, so it cannot import the workspace; the slug normalization here MUST
134
+ * stay in sync with the producer's `dataStoreSlug`.
135
+ *
136
+ * Everything degrades gracefully: a missing or malformed manifest resolves to an
137
+ * empty list, and callers fall back to the legacy per-store env keys.
138
+ */
139
+ interface DataStoreManifestEntry {
140
+ id: string;
141
+ name: string;
142
+ slug: string;
143
+ url: string;
144
+ accessLevel: "read" | "write" | "admin";
145
+ }
146
+ /**
147
+ * Resolves a store from the manifest by id, slug, or name. Exact id/slug/name
148
+ * matches win; a normalized slug match is the forgiving fallback so app code
149
+ * that passes a human store name (`storeName: "My Store"`) still resolves to the
150
+ * entry whose slug is `my_store`. Returns `undefined` if nothing matches.
151
+ */
152
+ declare function resolveDataStore(ref: {
153
+ storeId?: string;
154
+ storeName?: string;
155
+ }): DataStoreManifestEntry | undefined;
156
+ /** Returns every connected store in the manifest (for enumeration/discovery). */
157
+ declare function listDataStores(): DataStoreManifestEntry[];
158
+
159
+ export { DataStoreClient, type DataStoreManifestEntry, createDataStore, listDataStores, resolveDataStore, signDeploymentRequest };
@@ -1,4 +1,4 @@
1
- import { D as DataStoreClientConfig, a as TableSchema, C as ColumnDefinition, b as QueryOptions, c as QueryResult, L as ListObjectsResult } from '../types-CqVD-TLQ.js';
1
+ import { D as DataStoreClientConfig, a as TableSchema, C as ColumnDefinition, b as QueryOptions, c as QueryResult, L as ListObjectsResult } from '../types-D2D9kZNF.js';
2
2
  import { KyselyConfig, Kysely } from 'kysely';
3
3
 
4
4
  /**
@@ -91,13 +91,17 @@ declare function signDeploymentRequest(deploymentSecret: string, payload: {
91
91
  * import { createDataStore } from "@stardeck-customer-apps/data-store-sdk/server";
92
92
  * import type { DB } from "./generated/data-store-types";
93
93
  *
94
- * // Option 1: Use storeName to auto-read DATA_STORE_MYSTORE_URL from env
94
+ * // Option 1: Resolve by store name (matched against the stable slug in the
95
+ * // injected manifest, so it survives store renames)
95
96
  * const db = await createDataStore<DB>({ storeName: "mystore" });
96
97
  *
97
- * // Option 2: Pass connection string directly
98
+ * // Option 2: Resolve by immutable store id
99
+ * const db = await createDataStore<DB>({ storeId: process.env.DATA_STORE_MYSTORE_ID });
100
+ *
101
+ * // Option 3: Pass connection string directly
98
102
  * const db = await createDataStore<DB>({ connectionString: process.env.DATA_STORE_MYSTORE_URL });
99
103
  *
100
- * // Option 3: Falls back to DATA_STORE_URL env var
104
+ * // Option 4: Falls back to DATA_STORE_URL env var
101
105
  * const db = await createDataStore<DB>();
102
106
  *
103
107
  * const users = await db
@@ -110,7 +114,46 @@ declare function signDeploymentRequest(deploymentSecret: string, payload: {
110
114
  declare function createDataStore<DB>(options?: {
111
115
  connectionString?: string;
112
116
  storeName?: string;
117
+ storeId?: string;
113
118
  kyselyConfig?: Partial<KyselyConfig>;
114
119
  }): Promise<Kysely<DB>>;
115
120
 
116
- export { DataStoreClient, createDataStore, signDeploymentRequest };
121
+ /**
122
+ * Reads and resolves the data store manifest the platform injects into a
123
+ * deployed app.
124
+ *
125
+ * The platform injects a single env var, `STARDECK_DATA_STORES`, holding a JSON
126
+ * array of one entry per connected store: a stable `slug`, the store `id`, the
127
+ * current `name`, the connection `url`, and the `accessLevel`. Resolving against
128
+ * this manifest replaces the old `DATA_STORE_{NAME}_URL` key reconstruction — no
129
+ * fragile, must-match-the-injector key derivation on this side.
130
+ *
131
+ * This file intentionally mirrors `packages/lib/src/shared/data-store-manifest.ts`
132
+ * in the platform monorepo. The SDK is published and installed inside customer
133
+ * sandboxes, so it cannot import the workspace; the slug normalization here MUST
134
+ * stay in sync with the producer's `dataStoreSlug`.
135
+ *
136
+ * Everything degrades gracefully: a missing or malformed manifest resolves to an
137
+ * empty list, and callers fall back to the legacy per-store env keys.
138
+ */
139
+ interface DataStoreManifestEntry {
140
+ id: string;
141
+ name: string;
142
+ slug: string;
143
+ url: string;
144
+ accessLevel: "read" | "write" | "admin";
145
+ }
146
+ /**
147
+ * Resolves a store from the manifest by id, slug, or name. Exact id/slug/name
148
+ * matches win; a normalized slug match is the forgiving fallback so app code
149
+ * that passes a human store name (`storeName: "My Store"`) still resolves to the
150
+ * entry whose slug is `my_store`. Returns `undefined` if nothing matches.
151
+ */
152
+ declare function resolveDataStore(ref: {
153
+ storeId?: string;
154
+ storeName?: string;
155
+ }): DataStoreManifestEntry | undefined;
156
+ /** Returns every connected store in the manifest (for enumeration/discovery). */
157
+ declare function listDataStores(): DataStoreManifestEntry[];
158
+
159
+ export { DataStoreClient, type DataStoreManifestEntry, createDataStore, listDataStores, resolveDataStore, signDeploymentRequest };
@@ -32,6 +32,8 @@ var server_exports = {};
32
32
  __export(server_exports, {
33
33
  DataStoreClient: () => DataStoreClient,
34
34
  createDataStore: () => createDataStore,
35
+ listDataStores: () => listDataStores,
36
+ resolveDataStore: () => resolveDataStore,
35
37
  signDeploymentRequest: () => signDeploymentRequest
36
38
  });
37
39
  module.exports = __toCommonJS(server_exports);
@@ -71,6 +73,57 @@ function signDeploymentRequest(deploymentSecret, payload) {
71
73
  return `${payloadB64}.${signature}`;
72
74
  }
73
75
 
76
+ // src/server/manifest.ts
77
+ var STARDECK_DATA_STORES_ENV = "STARDECK_DATA_STORES";
78
+ function readEnv(key) {
79
+ if (typeof process !== "undefined" && process.env?.[key]) {
80
+ return process.env[key];
81
+ }
82
+ return void 0;
83
+ }
84
+ function dataStoreSlug(name) {
85
+ const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
86
+ return slug || "store";
87
+ }
88
+ function legacyDataStoreEnvName(name) {
89
+ return name.toUpperCase().replace(/[^A-Z0-9]/g, "_");
90
+ }
91
+ function readDataStoreManifest() {
92
+ const raw = readEnv(STARDECK_DATA_STORES_ENV);
93
+ if (!raw) return [];
94
+ try {
95
+ const parsed = JSON.parse(raw);
96
+ if (!Array.isArray(parsed)) return [];
97
+ return parsed.filter(
98
+ (e) => typeof e === "object" && e !== null && typeof e.id === "string" && typeof e.name === "string" && typeof e.slug === "string" && typeof e.url === "string"
99
+ );
100
+ } catch {
101
+ return [];
102
+ }
103
+ }
104
+ function resolveDataStore(ref) {
105
+ return resolveManifestEntry(readDataStoreManifest(), ref);
106
+ }
107
+ function resolveManifestEntry(entries, ref) {
108
+ if (ref.storeId) {
109
+ const byId = entries.find((e) => e.id === ref.storeId);
110
+ if (byId) return byId;
111
+ }
112
+ if (ref.storeName) {
113
+ const target = ref.storeName;
114
+ const exact = entries.find((e) => e.slug === target || e.id === target || e.name === target);
115
+ if (exact) return exact;
116
+ const norm = dataStoreSlug(target);
117
+ return entries.find(
118
+ (e) => e.slug === norm || typeof e.name === "string" && dataStoreSlug(e.name) === norm
119
+ );
120
+ }
121
+ return void 0;
122
+ }
123
+ function listDataStores() {
124
+ return readDataStoreManifest();
125
+ }
126
+
74
127
  // src/server/client.ts
75
128
  var DataStoreClient = class {
76
129
  baseUrl;
@@ -82,7 +135,7 @@ var DataStoreClient = class {
82
135
  maxRetries;
83
136
  debug;
84
137
  constructor(config) {
85
- this.storeId = config.storeId;
138
+ this.storeId = config.storeId || (config.storeName ? resolveDataStore({ storeName: config.storeName })?.id : void 0) || "";
86
139
  this.baseUrl = config.baseUrl || this.getEnv("CONTROL_PLANE_URL") || "";
87
140
  this.deploymentSecret = config.deploymentSecret || this.getEnv("DEPLOYMENT_SECRET") || "";
88
141
  this.organizationId = config.organizationId || this.getEnv("ORGANIZATION_ID") || "";
@@ -91,6 +144,7 @@ var DataStoreClient = class {
91
144
  this.maxRetries = config.maxRetries ?? 3;
92
145
  this.debug = config.debug ?? false;
93
146
  const missing = [
147
+ !this.storeId && "storeId (pass storeId/storeName, or connect the store so it appears in STARDECK_DATA_STORES)",
94
148
  !this.baseUrl && "CONTROL_PLANE_URL",
95
149
  !this.deploymentSecret && "DEPLOYMENT_SECRET",
96
150
  !this.organizationId && "ORGANIZATION_ID",
@@ -246,12 +300,32 @@ var DataStoreClient = class {
246
300
 
247
301
  // src/server/kysely.ts
248
302
  var import_kysely = require("kysely");
303
+ function readEnv2(key) {
304
+ if (typeof process !== "undefined" && process.env?.[key]) {
305
+ return process.env[key];
306
+ }
307
+ return void 0;
308
+ }
309
+ function resolveConnectionString(options) {
310
+ if (options?.connectionString) return options.connectionString;
311
+ const fromManifest = resolveDataStore({
312
+ storeId: options?.storeId,
313
+ storeName: options?.storeName
314
+ })?.url;
315
+ if (fromManifest) return fromManifest;
316
+ if (options?.storeName) {
317
+ const legacy = readEnv2(`DATA_STORE_${legacyDataStoreEnvName(options.storeName)}_URL`);
318
+ if (legacy) return legacy;
319
+ }
320
+ return readEnv2("DATA_STORE_URL");
321
+ }
249
322
  async function createDataStore(options) {
250
- const connectionString = options?.connectionString ?? (typeof process !== "undefined" && options?.storeName ? process.env?.[`DATA_STORE_${options.storeName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_URL`] : void 0) ?? (typeof process !== "undefined" ? process.env?.DATA_STORE_URL : void 0);
323
+ const connectionString = resolveConnectionString(options);
251
324
  if (!connectionString) {
252
- const envHint = options?.storeName ? `DATA_STORE_${options.storeName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_URL` : "DATA_STORE_URL";
325
+ const name = options?.storeName ?? options?.storeId;
326
+ const ref = name ? `data store "${name}"` : "a data store";
253
327
  throw new Error(
254
- `${envHint} environment variable is required, or pass connectionString in options`
328
+ `Could not resolve a connection string for ${ref}. Checked the STARDECK_DATA_STORES manifest, the legacy DATA_STORE_*_URL env var, and DATA_STORE_URL. Confirm the store is connected to this project, or pass connectionString in options.`
255
329
  );
256
330
  }
257
331
  const { Kysely: KyselyClass } = await import("kysely");
@@ -269,5 +343,7 @@ async function createDataStore(options) {
269
343
  0 && (module.exports = {
270
344
  DataStoreClient,
271
345
  createDataStore,
346
+ listDataStores,
347
+ resolveDataStore,
272
348
  signDeploymentRequest
273
349
  });
@@ -20,6 +20,57 @@ function signDeploymentRequest(deploymentSecret, payload) {
20
20
  return `${payloadB64}.${signature}`;
21
21
  }
22
22
 
23
+ // src/server/manifest.ts
24
+ var STARDECK_DATA_STORES_ENV = "STARDECK_DATA_STORES";
25
+ function readEnv(key) {
26
+ if (typeof process !== "undefined" && process.env?.[key]) {
27
+ return process.env[key];
28
+ }
29
+ return void 0;
30
+ }
31
+ function dataStoreSlug(name) {
32
+ const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
33
+ return slug || "store";
34
+ }
35
+ function legacyDataStoreEnvName(name) {
36
+ return name.toUpperCase().replace(/[^A-Z0-9]/g, "_");
37
+ }
38
+ function readDataStoreManifest() {
39
+ const raw = readEnv(STARDECK_DATA_STORES_ENV);
40
+ if (!raw) return [];
41
+ try {
42
+ const parsed = JSON.parse(raw);
43
+ if (!Array.isArray(parsed)) return [];
44
+ return parsed.filter(
45
+ (e) => typeof e === "object" && e !== null && typeof e.id === "string" && typeof e.name === "string" && typeof e.slug === "string" && typeof e.url === "string"
46
+ );
47
+ } catch {
48
+ return [];
49
+ }
50
+ }
51
+ function resolveDataStore(ref) {
52
+ return resolveManifestEntry(readDataStoreManifest(), ref);
53
+ }
54
+ function resolveManifestEntry(entries, ref) {
55
+ if (ref.storeId) {
56
+ const byId = entries.find((e) => e.id === ref.storeId);
57
+ if (byId) return byId;
58
+ }
59
+ if (ref.storeName) {
60
+ const target = ref.storeName;
61
+ const exact = entries.find((e) => e.slug === target || e.id === target || e.name === target);
62
+ if (exact) return exact;
63
+ const norm = dataStoreSlug(target);
64
+ return entries.find(
65
+ (e) => e.slug === norm || typeof e.name === "string" && dataStoreSlug(e.name) === norm
66
+ );
67
+ }
68
+ return void 0;
69
+ }
70
+ function listDataStores() {
71
+ return readDataStoreManifest();
72
+ }
73
+
23
74
  // src/server/client.ts
24
75
  var DataStoreClient = class {
25
76
  baseUrl;
@@ -31,7 +82,7 @@ var DataStoreClient = class {
31
82
  maxRetries;
32
83
  debug;
33
84
  constructor(config) {
34
- this.storeId = config.storeId;
85
+ this.storeId = config.storeId || (config.storeName ? resolveDataStore({ storeName: config.storeName })?.id : void 0) || "";
35
86
  this.baseUrl = config.baseUrl || this.getEnv("CONTROL_PLANE_URL") || "";
36
87
  this.deploymentSecret = config.deploymentSecret || this.getEnv("DEPLOYMENT_SECRET") || "";
37
88
  this.organizationId = config.organizationId || this.getEnv("ORGANIZATION_ID") || "";
@@ -40,6 +91,7 @@ var DataStoreClient = class {
40
91
  this.maxRetries = config.maxRetries ?? 3;
41
92
  this.debug = config.debug ?? false;
42
93
  const missing = [
94
+ !this.storeId && "storeId (pass storeId/storeName, or connect the store so it appears in STARDECK_DATA_STORES)",
43
95
  !this.baseUrl && "CONTROL_PLANE_URL",
44
96
  !this.deploymentSecret && "DEPLOYMENT_SECRET",
45
97
  !this.organizationId && "ORGANIZATION_ID",
@@ -195,12 +247,32 @@ var DataStoreClient = class {
195
247
 
196
248
  // src/server/kysely.ts
197
249
  import "kysely";
250
+ function readEnv2(key) {
251
+ if (typeof process !== "undefined" && process.env?.[key]) {
252
+ return process.env[key];
253
+ }
254
+ return void 0;
255
+ }
256
+ function resolveConnectionString(options) {
257
+ if (options?.connectionString) return options.connectionString;
258
+ const fromManifest = resolveDataStore({
259
+ storeId: options?.storeId,
260
+ storeName: options?.storeName
261
+ })?.url;
262
+ if (fromManifest) return fromManifest;
263
+ if (options?.storeName) {
264
+ const legacy = readEnv2(`DATA_STORE_${legacyDataStoreEnvName(options.storeName)}_URL`);
265
+ if (legacy) return legacy;
266
+ }
267
+ return readEnv2("DATA_STORE_URL");
268
+ }
198
269
  async function createDataStore(options) {
199
- const connectionString = options?.connectionString ?? (typeof process !== "undefined" && options?.storeName ? process.env?.[`DATA_STORE_${options.storeName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_URL`] : void 0) ?? (typeof process !== "undefined" ? process.env?.DATA_STORE_URL : void 0);
270
+ const connectionString = resolveConnectionString(options);
200
271
  if (!connectionString) {
201
- const envHint = options?.storeName ? `DATA_STORE_${options.storeName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_URL` : "DATA_STORE_URL";
272
+ const name = options?.storeName ?? options?.storeId;
273
+ const ref = name ? `data store "${name}"` : "a data store";
202
274
  throw new Error(
203
- `${envHint} environment variable is required, or pass connectionString in options`
275
+ `Could not resolve a connection string for ${ref}. Checked the STARDECK_DATA_STORES manifest, the legacy DATA_STORE_*_URL env var, and DATA_STORE_URL. Confirm the store is connected to this project, or pass connectionString in options.`
204
276
  );
205
277
  }
206
278
  const { Kysely: KyselyClass } = await import("kysely");
@@ -217,5 +289,7 @@ async function createDataStore(options) {
217
289
  export {
218
290
  DataStoreClient,
219
291
  createDataStore,
292
+ listDataStores,
293
+ resolveDataStore,
220
294
  signDeploymentRequest
221
295
  };
@@ -1,7 +1,24 @@
1
- interface DataStoreClientConfig {
1
+ /**
2
+ * Identifies the store to operate on. Exactly one of `storeId` / `storeName` is
3
+ * required at compile time (both-optional would let `new DataStoreClient({})`
4
+ * type-check and then throw at runtime).
5
+ */
6
+ type DataStoreRef = {
7
+ /** Immutable store id. */
8
+ storeId: string;
9
+ storeName?: string;
10
+ } | {
11
+ /**
12
+ * Store name or slug. Resolved to a store id via the injected
13
+ * `STARDECK_DATA_STORES` manifest (matched against the store's stable slug,
14
+ * so it survives renames).
15
+ */
16
+ storeName: string;
17
+ storeId?: string;
18
+ };
19
+ type DataStoreClientConfig = DataStoreRef & {
2
20
  /** Stardeck platform API base URL (default: CONTROL_PLANE_URL env var) */
3
21
  baseUrl?: string;
4
- storeId: string;
5
22
  /** HMAC signing secret (default: DEPLOYMENT_SECRET env var) */
6
23
  deploymentSecret?: string;
7
24
  organizationId?: string;
@@ -9,7 +26,7 @@ interface DataStoreClientConfig {
9
26
  deploymentId?: string;
10
27
  maxRetries?: number;
11
28
  debug?: boolean;
12
- }
29
+ };
13
30
  interface ColumnDefinition {
14
31
  name: string;
15
32
  fieldType: string;
@@ -1,7 +1,24 @@
1
- interface DataStoreClientConfig {
1
+ /**
2
+ * Identifies the store to operate on. Exactly one of `storeId` / `storeName` is
3
+ * required at compile time (both-optional would let `new DataStoreClient({})`
4
+ * type-check and then throw at runtime).
5
+ */
6
+ type DataStoreRef = {
7
+ /** Immutable store id. */
8
+ storeId: string;
9
+ storeName?: string;
10
+ } | {
11
+ /**
12
+ * Store name or slug. Resolved to a store id via the injected
13
+ * `STARDECK_DATA_STORES` manifest (matched against the store's stable slug,
14
+ * so it survives renames).
15
+ */
16
+ storeName: string;
17
+ storeId?: string;
18
+ };
19
+ type DataStoreClientConfig = DataStoreRef & {
2
20
  /** Stardeck platform API base URL (default: CONTROL_PLANE_URL env var) */
3
21
  baseUrl?: string;
4
- storeId: string;
5
22
  /** HMAC signing secret (default: DEPLOYMENT_SECRET env var) */
6
23
  deploymentSecret?: string;
7
24
  organizationId?: string;
@@ -9,7 +26,7 @@ interface DataStoreClientConfig {
9
26
  deploymentId?: string;
10
27
  maxRetries?: number;
11
28
  debug?: boolean;
12
- }
29
+ };
13
30
  interface ColumnDefinition {
14
31
  name: string;
15
32
  fieldType: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stardeck-customer-apps/data-store-sdk",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "SDK for accessing Stardeck data stores from deployed projects",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",