@stardeck-customer-apps/testing 0.9.0 → 0.10.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 +67 -1
- package/dist/config.d.mts +6 -2
- package/dist/config.d.ts +6 -2
- package/dist/config.js +75 -1
- package/dist/config.mjs +73 -1
- package/dist/data-store-manifest-Zwgcv0DJ.d.mts +25 -0
- package/dist/data-store-manifest-Zwgcv0DJ.d.ts +25 -0
- package/dist/index.d.mts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +88 -3
- package/dist/index.mjs +85 -3
- package/dist/next/headers-shim.js +1 -0
- package/dist/next/headers-shim.mjs +1 -0
- package/dist/setup.js +2 -1
- package/dist/setup.mjs +2 -1
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -29,6 +29,65 @@ This writes `src/generated/data-store-types.ts` and
|
|
|
29
29
|
`src/generated/data-store-schema.sql`. The harness applies the SQL snapshot to
|
|
30
30
|
PGlite at test boot. **Commit both files.**
|
|
31
31
|
|
|
32
|
+
### Data store bindings
|
|
33
|
+
|
|
34
|
+
Configure each app-local data store binding once in `vitest.config.ts`. The
|
|
35
|
+
harness injects the same `STARDECK_DATA_STORES` manifest shape as production, so
|
|
36
|
+
application code resolves the binding without test-only branches:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { defineStardeckTestConfig } from "@stardeck-customer-apps/testing/config";
|
|
40
|
+
|
|
41
|
+
export default defineStardeckTestConfig(
|
|
42
|
+
{},
|
|
43
|
+
{
|
|
44
|
+
dataStores: [{ bindingKey: "development" }],
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { createDataStore } from "@stardeck-customer-apps/data-store-sdk/server";
|
|
51
|
+
|
|
52
|
+
const db = await createDataStore({ storeName: "development" });
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Do not branch on `DATA_STORE_URL?.includes(".stardeck.test")` or otherwise
|
|
56
|
+
sniff test hosts. Configure the binding and use `createDataStore({ storeName })`
|
|
57
|
+
the same way in tests and production.
|
|
58
|
+
|
|
59
|
+
For one test file that needs a different manifest, pass the same entries to the
|
|
60
|
+
app instead. This overrides the config-level manifest for that file:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
app = await createTestApp({
|
|
64
|
+
dataStores: [
|
|
65
|
+
{ bindingKey: "development" },
|
|
66
|
+
{ bindingKey: "uploads", name: "Customer Files", storeType: "storage" },
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
An app setup file may also set `STARDECK_DATA_STORES` directly. The harness
|
|
72
|
+
adopts a non-empty raw env value when `createTestApp()` has no `dataStores`
|
|
73
|
+
option; a per-app `dataStores` option still overrides it. An empty env value is
|
|
74
|
+
treated as unset, matching the SDK manifest parser.
|
|
75
|
+
|
|
76
|
+
Strictness follows adoption:
|
|
77
|
+
|
|
78
|
+
- With no manifest configuration, `createTestApp()` injects a `main` database
|
|
79
|
+
entry and keeps `DATA_STORE_URL` for older bare `createDataStore()` calls.
|
|
80
|
+
- Configuring `dataStores` through either channel removes `DATA_STORE_URL` by
|
|
81
|
+
default. A misspelled `storeName` then fails instead of silently connecting to
|
|
82
|
+
the default database.
|
|
83
|
+
- Passing `dataStores: []` explicitly creates a strict zero-store test world:
|
|
84
|
+
the manifest is `[]`, `DATA_STORE_URL` is absent, and every
|
|
85
|
+
`createDataStore(...)` call fails until a store is configured.
|
|
86
|
+
- Empty-string `bindingKey`, `slug`, or `name` values throw during test app
|
|
87
|
+
setup so typos cannot silently change manifest resolution.
|
|
88
|
+
- Set `legacyDataStoreUrl: true` per file only while migrating legacy code. Set
|
|
89
|
+
it to `false` to test strict manifest-only resolution even with zero config.
|
|
90
|
+
|
|
32
91
|
## Writing tests
|
|
33
92
|
|
|
34
93
|
```ts
|
|
@@ -186,7 +245,14 @@ expect(app.edge.latestDisplay()?.action).toBe("show");
|
|
|
186
245
|
|
|
187
246
|
- `createTestApp(options)` — boots PGlite + the control-plane simulator and
|
|
188
247
|
sets all Stardeck env vars (`CONTROL_PLANE_URL`, `DEPLOYMENT_SECRET`,
|
|
189
|
-
`
|
|
248
|
+
`STARDECK_DATA_STORES`, ids, and the legacy `DATA_STORE_URL` when enabled).
|
|
249
|
+
One per test file, in `beforeAll`.
|
|
250
|
+
- `dataStores` — per-file production-shaped data store manifest entries. The
|
|
251
|
+
first entry defaults to slug `main`; later entries need a `slug` or `name`.
|
|
252
|
+
Pass `[]` for strict zero-store mode. Empty `bindingKey`, `slug`, and `name`
|
|
253
|
+
values are rejected.
|
|
254
|
+
- `legacyDataStoreUrl` — force the legacy single-store URL on or off. When
|
|
255
|
+
omitted, it is on only for zero-config tests and off after manifest adoption.
|
|
190
256
|
- `schema` — path to the DDL snapshot (default
|
|
191
257
|
`./src/generated/data-store-schema.sql`); `null` for apps without a store.
|
|
192
258
|
- `schemaSql` — inline DDL instead of a file.
|
package/dist/config.d.mts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { ViteUserConfig } from 'vitest/config';
|
|
2
|
+
import { T as TestDataStoreInput } from './data-store-manifest-Zwgcv0DJ.mjs';
|
|
2
3
|
|
|
4
|
+
interface StardeckTestConfigOptions {
|
|
5
|
+
dataStores?: TestDataStoreInput[];
|
|
6
|
+
}
|
|
3
7
|
/**
|
|
4
8
|
* Vitest config for Stardeck customer apps. Aliases `next/headers` (and
|
|
5
9
|
* `server-only`) to harness shims so server code runs outside a Next request
|
|
@@ -11,6 +15,6 @@ import { ViteUserConfig } from 'vitest/config';
|
|
|
11
15
|
* export default defineStardeckTestConfig();
|
|
12
16
|
* ```
|
|
13
17
|
*/
|
|
14
|
-
declare function defineStardeckTestConfig(overrides?: ViteUserConfig): ViteUserConfig;
|
|
18
|
+
declare function defineStardeckTestConfig(overrides?: ViteUserConfig, stardeck?: StardeckTestConfigOptions): ViteUserConfig;
|
|
15
19
|
|
|
16
|
-
export { defineStardeckTestConfig };
|
|
20
|
+
export { type StardeckTestConfigOptions, defineStardeckTestConfig };
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { ViteUserConfig } from 'vitest/config';
|
|
2
|
+
import { T as TestDataStoreInput } from './data-store-manifest-Zwgcv0DJ.js';
|
|
2
3
|
|
|
4
|
+
interface StardeckTestConfigOptions {
|
|
5
|
+
dataStores?: TestDataStoreInput[];
|
|
6
|
+
}
|
|
3
7
|
/**
|
|
4
8
|
* Vitest config for Stardeck customer apps. Aliases `next/headers` (and
|
|
5
9
|
* `server-only`) to harness shims so server code runs outside a Next request
|
|
@@ -11,6 +15,6 @@ import { ViteUserConfig } from 'vitest/config';
|
|
|
11
15
|
* export default defineStardeckTestConfig();
|
|
12
16
|
* ```
|
|
13
17
|
*/
|
|
14
|
-
declare function defineStardeckTestConfig(overrides?: ViteUserConfig): ViteUserConfig;
|
|
18
|
+
declare function defineStardeckTestConfig(overrides?: ViteUserConfig, stardeck?: StardeckTestConfigOptions): ViteUserConfig;
|
|
15
19
|
|
|
16
|
-
export { defineStardeckTestConfig };
|
|
20
|
+
export { type StardeckTestConfigOptions, defineStardeckTestConfig };
|
package/dist/config.js
CHANGED
|
@@ -23,7 +23,77 @@ __export(config_exports, {
|
|
|
23
23
|
defineStardeckTestConfig: () => defineStardeckTestConfig
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(config_exports);
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
// src/constants.ts
|
|
28
|
+
var DATA_STORE_TEST_HOST = "db.stardeck.test";
|
|
29
|
+
var DATA_STORE_TEST_URL = `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`;
|
|
30
|
+
|
|
31
|
+
// src/data-store-manifest.ts
|
|
32
|
+
var STARDECK_DATA_STORES_ENV = "STARDECK_DATA_STORES";
|
|
33
|
+
function dataStoreSlug(name) {
|
|
34
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
35
|
+
return slug || "store";
|
|
36
|
+
}
|
|
37
|
+
function buildTestDataStoreManifest(inputs = [{}]) {
|
|
38
|
+
const takenSlugs = /* @__PURE__ */ new Set();
|
|
39
|
+
const takenBindingKeys = /* @__PURE__ */ new Set();
|
|
40
|
+
const takenIds = /* @__PURE__ */ new Set();
|
|
41
|
+
return inputs.map((input, index) => {
|
|
42
|
+
for (const field of ["bindingKey", "slug", "name"]) {
|
|
43
|
+
if (input[field] === "") {
|
|
44
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].${field} cannot be empty.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
let slug;
|
|
48
|
+
if (input.slug !== void 0) {
|
|
49
|
+
slug = input.slug;
|
|
50
|
+
if (takenSlugs.has(slug)) {
|
|
51
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].slug must be unique.`);
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
const base = input.name !== void 0 ? dataStoreSlug(input.name) : index === 0 ? "main" : null;
|
|
55
|
+
if (base === null) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`[stardeck-testing] dataStores[${index}] requires a slug or name. Only the first entry defaults to the "main" slug.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
slug = base;
|
|
61
|
+
let suffix = 2;
|
|
62
|
+
while (takenSlugs.has(slug)) {
|
|
63
|
+
slug = `${base}_${suffix}`;
|
|
64
|
+
suffix++;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const id = input.id ?? `00000000-0000-4000-8000-${String(index + 1).padStart(12, "0")}`;
|
|
68
|
+
if (takenIds.has(id)) {
|
|
69
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].id must be unique.`);
|
|
70
|
+
}
|
|
71
|
+
if (input.bindingKey !== void 0 && takenBindingKeys.has(input.bindingKey)) {
|
|
72
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].bindingKey must be unique.`);
|
|
73
|
+
}
|
|
74
|
+
takenSlugs.add(slug);
|
|
75
|
+
takenIds.add(id);
|
|
76
|
+
if (input.bindingKey !== void 0) takenBindingKeys.add(input.bindingKey);
|
|
77
|
+
const storeType = input.storeType ?? "database";
|
|
78
|
+
return {
|
|
79
|
+
id,
|
|
80
|
+
name: input.name ?? slug,
|
|
81
|
+
slug,
|
|
82
|
+
storeType,
|
|
83
|
+
accessLevel: input.accessLevel ?? "admin",
|
|
84
|
+
...storeType === "database" ? { url: input.url ?? DATA_STORE_TEST_URL } : {},
|
|
85
|
+
...input.bindingKey ? { bindingKey: input.bindingKey } : {}
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/config.ts
|
|
91
|
+
function defineStardeckTestConfig(overrides = {}, stardeck = {}) {
|
|
92
|
+
const dataStoreEnv = stardeck.dataStores !== void 0 ? {
|
|
93
|
+
[STARDECK_DATA_STORES_ENV]: JSON.stringify(
|
|
94
|
+
buildTestDataStoreManifest(stardeck.dataStores)
|
|
95
|
+
)
|
|
96
|
+
} : {};
|
|
27
97
|
return {
|
|
28
98
|
...overrides,
|
|
29
99
|
resolve: {
|
|
@@ -44,6 +114,10 @@ function defineStardeckTestConfig(overrides = {}) {
|
|
|
44
114
|
pool: "forks",
|
|
45
115
|
isolate: true,
|
|
46
116
|
...overrides.test,
|
|
117
|
+
env: {
|
|
118
|
+
...dataStoreEnv,
|
|
119
|
+
...overrides.test?.env
|
|
120
|
+
},
|
|
47
121
|
setupFiles: [
|
|
48
122
|
"@stardeck-customer-apps/testing/setup",
|
|
49
123
|
...overrides.test?.setupFiles ? Array.isArray(overrides.test.setupFiles) ? overrides.test.setupFiles : [overrides.test.setupFiles] : []
|
package/dist/config.mjs
CHANGED
|
@@ -1,5 +1,73 @@
|
|
|
1
|
+
// src/constants.ts
|
|
2
|
+
var DATA_STORE_TEST_HOST = "db.stardeck.test";
|
|
3
|
+
var DATA_STORE_TEST_URL = `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`;
|
|
4
|
+
|
|
5
|
+
// src/data-store-manifest.ts
|
|
6
|
+
var STARDECK_DATA_STORES_ENV = "STARDECK_DATA_STORES";
|
|
7
|
+
function dataStoreSlug(name) {
|
|
8
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
9
|
+
return slug || "store";
|
|
10
|
+
}
|
|
11
|
+
function buildTestDataStoreManifest(inputs = [{}]) {
|
|
12
|
+
const takenSlugs = /* @__PURE__ */ new Set();
|
|
13
|
+
const takenBindingKeys = /* @__PURE__ */ new Set();
|
|
14
|
+
const takenIds = /* @__PURE__ */ new Set();
|
|
15
|
+
return inputs.map((input, index) => {
|
|
16
|
+
for (const field of ["bindingKey", "slug", "name"]) {
|
|
17
|
+
if (input[field] === "") {
|
|
18
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].${field} cannot be empty.`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
let slug;
|
|
22
|
+
if (input.slug !== void 0) {
|
|
23
|
+
slug = input.slug;
|
|
24
|
+
if (takenSlugs.has(slug)) {
|
|
25
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].slug must be unique.`);
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
const base = input.name !== void 0 ? dataStoreSlug(input.name) : index === 0 ? "main" : null;
|
|
29
|
+
if (base === null) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`[stardeck-testing] dataStores[${index}] requires a slug or name. Only the first entry defaults to the "main" slug.`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
slug = base;
|
|
35
|
+
let suffix = 2;
|
|
36
|
+
while (takenSlugs.has(slug)) {
|
|
37
|
+
slug = `${base}_${suffix}`;
|
|
38
|
+
suffix++;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const id = input.id ?? `00000000-0000-4000-8000-${String(index + 1).padStart(12, "0")}`;
|
|
42
|
+
if (takenIds.has(id)) {
|
|
43
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].id must be unique.`);
|
|
44
|
+
}
|
|
45
|
+
if (input.bindingKey !== void 0 && takenBindingKeys.has(input.bindingKey)) {
|
|
46
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].bindingKey must be unique.`);
|
|
47
|
+
}
|
|
48
|
+
takenSlugs.add(slug);
|
|
49
|
+
takenIds.add(id);
|
|
50
|
+
if (input.bindingKey !== void 0) takenBindingKeys.add(input.bindingKey);
|
|
51
|
+
const storeType = input.storeType ?? "database";
|
|
52
|
+
return {
|
|
53
|
+
id,
|
|
54
|
+
name: input.name ?? slug,
|
|
55
|
+
slug,
|
|
56
|
+
storeType,
|
|
57
|
+
accessLevel: input.accessLevel ?? "admin",
|
|
58
|
+
...storeType === "database" ? { url: input.url ?? DATA_STORE_TEST_URL } : {},
|
|
59
|
+
...input.bindingKey ? { bindingKey: input.bindingKey } : {}
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
1
64
|
// src/config.ts
|
|
2
|
-
function defineStardeckTestConfig(overrides = {}) {
|
|
65
|
+
function defineStardeckTestConfig(overrides = {}, stardeck = {}) {
|
|
66
|
+
const dataStoreEnv = stardeck.dataStores !== void 0 ? {
|
|
67
|
+
[STARDECK_DATA_STORES_ENV]: JSON.stringify(
|
|
68
|
+
buildTestDataStoreManifest(stardeck.dataStores)
|
|
69
|
+
)
|
|
70
|
+
} : {};
|
|
3
71
|
return {
|
|
4
72
|
...overrides,
|
|
5
73
|
resolve: {
|
|
@@ -20,6 +88,10 @@ function defineStardeckTestConfig(overrides = {}) {
|
|
|
20
88
|
pool: "forks",
|
|
21
89
|
isolate: true,
|
|
22
90
|
...overrides.test,
|
|
91
|
+
env: {
|
|
92
|
+
...dataStoreEnv,
|
|
93
|
+
...overrides.test?.env
|
|
94
|
+
},
|
|
23
95
|
setupFiles: [
|
|
24
96
|
"@stardeck-customer-apps/testing/setup",
|
|
25
97
|
...overrides.test?.setupFiles ? Array.isArray(overrides.test.setupFiles) ? overrides.test.setupFiles : [overrides.test.setupFiles] : []
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare const STARDECK_DATA_STORES_ENV = "STARDECK_DATA_STORES";
|
|
2
|
+
interface TestDataStoreInput {
|
|
3
|
+
bindingKey?: string;
|
|
4
|
+
/** Stable snake_case handle for the store. */
|
|
5
|
+
slug?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
id?: string;
|
|
8
|
+
accessLevel?: "read" | "write" | "admin";
|
|
9
|
+
storeType?: "database" | "storage";
|
|
10
|
+
/** Defaults to the PGlite simulator URL for database stores. */
|
|
11
|
+
url?: string;
|
|
12
|
+
}
|
|
13
|
+
interface TestDataStoreManifestEntry {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
slug: string;
|
|
17
|
+
storeType: "database" | "storage";
|
|
18
|
+
accessLevel: "read" | "write" | "admin";
|
|
19
|
+
url?: string;
|
|
20
|
+
bindingKey?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Builds the production-shaped manifest injected into a test app. */
|
|
23
|
+
declare function buildTestDataStoreManifest(inputs?: TestDataStoreInput[]): TestDataStoreManifestEntry[];
|
|
24
|
+
|
|
25
|
+
export { STARDECK_DATA_STORES_ENV as S, type TestDataStoreInput as T, type TestDataStoreManifestEntry as a, buildTestDataStoreManifest as b };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare const STARDECK_DATA_STORES_ENV = "STARDECK_DATA_STORES";
|
|
2
|
+
interface TestDataStoreInput {
|
|
3
|
+
bindingKey?: string;
|
|
4
|
+
/** Stable snake_case handle for the store. */
|
|
5
|
+
slug?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
id?: string;
|
|
8
|
+
accessLevel?: "read" | "write" | "admin";
|
|
9
|
+
storeType?: "database" | "storage";
|
|
10
|
+
/** Defaults to the PGlite simulator URL for database stores. */
|
|
11
|
+
url?: string;
|
|
12
|
+
}
|
|
13
|
+
interface TestDataStoreManifestEntry {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
slug: string;
|
|
17
|
+
storeType: "database" | "storage";
|
|
18
|
+
accessLevel: "read" | "write" | "admin";
|
|
19
|
+
url?: string;
|
|
20
|
+
bindingKey?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Builds the production-shaped manifest injected into a test app. */
|
|
23
|
+
declare function buildTestDataStoreManifest(inputs?: TestDataStoreInput[]): TestDataStoreManifestEntry[];
|
|
24
|
+
|
|
25
|
+
export { STARDECK_DATA_STORES_ENV as S, type TestDataStoreInput as T, type TestDataStoreManifestEntry as a, buildTestDataStoreManifest as b };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as _stardeck_customer_apps_payments_sdk from '@stardeck-customer-apps/payments-sdk';
|
|
2
2
|
import * as next_server from 'next/server';
|
|
3
3
|
import { PGlite } from '@electric-sql/pglite';
|
|
4
|
+
import { T as TestDataStoreInput } from './data-store-manifest-Zwgcv0DJ.mjs';
|
|
5
|
+
export { S as STARDECK_DATA_STORES_ENV, a as TestDataStoreManifestEntry, b as buildTestDataStoreManifest } from './data-store-manifest-Zwgcv0DJ.mjs';
|
|
4
6
|
|
|
5
7
|
type RouteHandler<Req extends Request = Request, P = Record<string, string | string[]>> = (request: Req, context: {
|
|
6
8
|
params: Promise<P>;
|
|
@@ -437,6 +439,13 @@ interface TestEdge {
|
|
|
437
439
|
get count(): number;
|
|
438
440
|
}
|
|
439
441
|
interface TestAppOptions {
|
|
442
|
+
/** Data stores exposed through the production-shaped STARDECK_DATA_STORES manifest. */
|
|
443
|
+
dataStores?: TestDataStoreInput[];
|
|
444
|
+
/**
|
|
445
|
+
* Force the legacy single-store DATA_STORE_URL on or off. By default it is
|
|
446
|
+
* present only for the zero-config manifest, and omitted once a manifest is configured.
|
|
447
|
+
*/
|
|
448
|
+
legacyDataStoreUrl?: boolean;
|
|
440
449
|
/**
|
|
441
450
|
* Path to the schema.sql snapshot generated by
|
|
442
451
|
* `npx stardeck-data-store generate-types` (relative to the project root).
|
|
@@ -517,6 +526,7 @@ declare function parseWorkflowName(describeTitle: string): string | null;
|
|
|
517
526
|
|
|
518
527
|
declare const CONTROL_PLANE_TEST_URL = "https://control-plane.stardeck.test";
|
|
519
528
|
declare const DATA_STORE_TEST_HOST = "db.stardeck.test";
|
|
529
|
+
declare const DATA_STORE_TEST_URL = "postgresql://test:test@db.stardeck.test/main";
|
|
520
530
|
declare const STORAGE_TEST_URL = "https://storage.stardeck.test";
|
|
521
531
|
declare const STORAGE_TEST_HOST = "storage.stardeck.test";
|
|
522
532
|
declare const TEST_ENV_DEFAULTS: {
|
|
@@ -525,10 +535,9 @@ declare const TEST_ENV_DEFAULTS: {
|
|
|
525
535
|
readonly ORGANIZATION_ID: "00000000-0000-4000-8000-00000000000a";
|
|
526
536
|
readonly PROJECT_ID: "00000000-0000-4000-8000-00000000000b";
|
|
527
537
|
readonly DEPLOYMENT_ID: "00000000-0000-4000-8000-00000000000c";
|
|
528
|
-
readonly DATA_STORE_URL: "postgresql://test:test@db.stardeck.test/main";
|
|
529
538
|
readonly STORAGE_URL: "https://storage.stardeck.test";
|
|
530
539
|
};
|
|
531
540
|
/** Default location of the DDL snapshot written by `generate-types`. */
|
|
532
541
|
declare const DEFAULT_SCHEMA_PATH = "./src/generated/data-store-schema.sql";
|
|
533
542
|
|
|
534
|
-
export { type BindingInfo, CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedCheckout, type CapturedDisplay, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CapturedMessage, type CapturedPrint, type CapturedTestPrint, type CapturedUpload, DATA_STORE_TEST_HOST, DEFAULT_SCHEMA_PATH, type DeviceInfo, type PeripheralInfo, STORAGE_TEST_HOST, STORAGE_TEST_URL, type SessionTokens, type SimBoltCharge, type SimBoltConnection, type SimBoltIntentRecord, type SimBoltIntentStatus, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, type TestDirectory, type TestEdge, type TestInbox, type TestMessages, type TestPayments, type TestStorage, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
|
543
|
+
export { type BindingInfo, CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedCheckout, type CapturedDisplay, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CapturedMessage, type CapturedPrint, type CapturedTestPrint, type CapturedUpload, DATA_STORE_TEST_HOST, DATA_STORE_TEST_URL, DEFAULT_SCHEMA_PATH, type DeviceInfo, type PeripheralInfo, STORAGE_TEST_HOST, STORAGE_TEST_URL, type SessionTokens, type SimBoltCharge, type SimBoltConnection, type SimBoltIntentRecord, type SimBoltIntentStatus, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, TestDataStoreInput, type TestDirectory, type TestEdge, type TestInbox, type TestMessages, type TestPayments, type TestStorage, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as _stardeck_customer_apps_payments_sdk from '@stardeck-customer-apps/payments-sdk';
|
|
2
2
|
import * as next_server from 'next/server';
|
|
3
3
|
import { PGlite } from '@electric-sql/pglite';
|
|
4
|
+
import { T as TestDataStoreInput } from './data-store-manifest-Zwgcv0DJ.js';
|
|
5
|
+
export { S as STARDECK_DATA_STORES_ENV, a as TestDataStoreManifestEntry, b as buildTestDataStoreManifest } from './data-store-manifest-Zwgcv0DJ.js';
|
|
4
6
|
|
|
5
7
|
type RouteHandler<Req extends Request = Request, P = Record<string, string | string[]>> = (request: Req, context: {
|
|
6
8
|
params: Promise<P>;
|
|
@@ -437,6 +439,13 @@ interface TestEdge {
|
|
|
437
439
|
get count(): number;
|
|
438
440
|
}
|
|
439
441
|
interface TestAppOptions {
|
|
442
|
+
/** Data stores exposed through the production-shaped STARDECK_DATA_STORES manifest. */
|
|
443
|
+
dataStores?: TestDataStoreInput[];
|
|
444
|
+
/**
|
|
445
|
+
* Force the legacy single-store DATA_STORE_URL on or off. By default it is
|
|
446
|
+
* present only for the zero-config manifest, and omitted once a manifest is configured.
|
|
447
|
+
*/
|
|
448
|
+
legacyDataStoreUrl?: boolean;
|
|
440
449
|
/**
|
|
441
450
|
* Path to the schema.sql snapshot generated by
|
|
442
451
|
* `npx stardeck-data-store generate-types` (relative to the project root).
|
|
@@ -517,6 +526,7 @@ declare function parseWorkflowName(describeTitle: string): string | null;
|
|
|
517
526
|
|
|
518
527
|
declare const CONTROL_PLANE_TEST_URL = "https://control-plane.stardeck.test";
|
|
519
528
|
declare const DATA_STORE_TEST_HOST = "db.stardeck.test";
|
|
529
|
+
declare const DATA_STORE_TEST_URL = "postgresql://test:test@db.stardeck.test/main";
|
|
520
530
|
declare const STORAGE_TEST_URL = "https://storage.stardeck.test";
|
|
521
531
|
declare const STORAGE_TEST_HOST = "storage.stardeck.test";
|
|
522
532
|
declare const TEST_ENV_DEFAULTS: {
|
|
@@ -525,10 +535,9 @@ declare const TEST_ENV_DEFAULTS: {
|
|
|
525
535
|
readonly ORGANIZATION_ID: "00000000-0000-4000-8000-00000000000a";
|
|
526
536
|
readonly PROJECT_ID: "00000000-0000-4000-8000-00000000000b";
|
|
527
537
|
readonly DEPLOYMENT_ID: "00000000-0000-4000-8000-00000000000c";
|
|
528
|
-
readonly DATA_STORE_URL: "postgresql://test:test@db.stardeck.test/main";
|
|
529
538
|
readonly STORAGE_URL: "https://storage.stardeck.test";
|
|
530
539
|
};
|
|
531
540
|
/** Default location of the DDL snapshot written by `generate-types`. */
|
|
532
541
|
declare const DEFAULT_SCHEMA_PATH = "./src/generated/data-store-schema.sql";
|
|
533
542
|
|
|
534
|
-
export { type BindingInfo, CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedCheckout, type CapturedDisplay, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CapturedMessage, type CapturedPrint, type CapturedTestPrint, type CapturedUpload, DATA_STORE_TEST_HOST, DEFAULT_SCHEMA_PATH, type DeviceInfo, type PeripheralInfo, STORAGE_TEST_HOST, STORAGE_TEST_URL, type SessionTokens, type SimBoltCharge, type SimBoltConnection, type SimBoltIntentRecord, type SimBoltIntentStatus, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, type TestDirectory, type TestEdge, type TestInbox, type TestMessages, type TestPayments, type TestStorage, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
|
543
|
+
export { type BindingInfo, CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedCheckout, type CapturedDisplay, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CapturedMessage, type CapturedPrint, type CapturedTestPrint, type CapturedUpload, DATA_STORE_TEST_HOST, DATA_STORE_TEST_URL, DEFAULT_SCHEMA_PATH, type DeviceInfo, type PeripheralInfo, STORAGE_TEST_HOST, STORAGE_TEST_URL, type SessionTokens, type SimBoltCharge, type SimBoltConnection, type SimBoltIntentRecord, type SimBoltIntentStatus, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, TestDataStoreInput, type TestDirectory, type TestEdge, type TestInbox, type TestMessages, type TestPayments, type TestStorage, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
package/dist/index.js
CHANGED
|
@@ -32,11 +32,14 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
CONTROL_PLANE_TEST_URL: () => CONTROL_PLANE_TEST_URL,
|
|
34
34
|
DATA_STORE_TEST_HOST: () => DATA_STORE_TEST_HOST,
|
|
35
|
+
DATA_STORE_TEST_URL: () => DATA_STORE_TEST_URL,
|
|
35
36
|
DEFAULT_SCHEMA_PATH: () => DEFAULT_SCHEMA_PATH,
|
|
37
|
+
STARDECK_DATA_STORES_ENV: () => STARDECK_DATA_STORES_ENV,
|
|
36
38
|
STORAGE_TEST_HOST: () => STORAGE_TEST_HOST,
|
|
37
39
|
STORAGE_TEST_URL: () => STORAGE_TEST_URL,
|
|
38
40
|
TEST_ENV_DEFAULTS: () => TEST_ENV_DEFAULTS,
|
|
39
41
|
WORKFLOW_NAME_PREFIX: () => WORKFLOW_NAME_PREFIX,
|
|
42
|
+
buildTestDataStoreManifest: () => buildTestDataStoreManifest,
|
|
40
43
|
callRoute: () => callRoute,
|
|
41
44
|
createTestApp: () => createTestApp,
|
|
42
45
|
describeWorkflow: () => describeWorkflow,
|
|
@@ -93,6 +96,7 @@ function globalSingleton(key, create) {
|
|
|
93
96
|
// src/state.ts
|
|
94
97
|
var state = globalSingleton("state", () => ({
|
|
95
98
|
db: null,
|
|
99
|
+
lastHarnessDataStoreManifest: null,
|
|
96
100
|
currentUser: null,
|
|
97
101
|
sessions: /* @__PURE__ */ new Map(),
|
|
98
102
|
refreshSessions: /* @__PURE__ */ new Map(),
|
|
@@ -141,6 +145,7 @@ function requireDb() {
|
|
|
141
145
|
var TEST_DOMAIN_SUFFIX = ".stardeck.test";
|
|
142
146
|
var CONTROL_PLANE_TEST_URL = "https://control-plane.stardeck.test";
|
|
143
147
|
var DATA_STORE_TEST_HOST = "db.stardeck.test";
|
|
148
|
+
var DATA_STORE_TEST_URL = `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`;
|
|
144
149
|
var STORAGE_TEST_URL = "https://storage.stardeck.test";
|
|
145
150
|
var STORAGE_TEST_HOST = "storage.stardeck.test";
|
|
146
151
|
var TEST_ENV_DEFAULTS = {
|
|
@@ -149,7 +154,6 @@ var TEST_ENV_DEFAULTS = {
|
|
|
149
154
|
ORGANIZATION_ID: "00000000-0000-4000-8000-00000000000a",
|
|
150
155
|
PROJECT_ID: "00000000-0000-4000-8000-00000000000b",
|
|
151
156
|
DEPLOYMENT_ID: "00000000-0000-4000-8000-00000000000c",
|
|
152
|
-
DATA_STORE_URL: `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`,
|
|
153
157
|
STORAGE_URL: STORAGE_TEST_URL
|
|
154
158
|
};
|
|
155
159
|
var DEFAULT_TEST_USER = {
|
|
@@ -2603,11 +2607,89 @@ function uninstallFetchRouter() {
|
|
|
2603
2607
|
}
|
|
2604
2608
|
}
|
|
2605
2609
|
|
|
2610
|
+
// src/data-store-manifest.ts
|
|
2611
|
+
var STARDECK_DATA_STORES_ENV = "STARDECK_DATA_STORES";
|
|
2612
|
+
function dataStoreSlug(name) {
|
|
2613
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
2614
|
+
return slug || "store";
|
|
2615
|
+
}
|
|
2616
|
+
function buildTestDataStoreManifest(inputs = [{}]) {
|
|
2617
|
+
const takenSlugs = /* @__PURE__ */ new Set();
|
|
2618
|
+
const takenBindingKeys = /* @__PURE__ */ new Set();
|
|
2619
|
+
const takenIds = /* @__PURE__ */ new Set();
|
|
2620
|
+
return inputs.map((input, index) => {
|
|
2621
|
+
for (const field of ["bindingKey", "slug", "name"]) {
|
|
2622
|
+
if (input[field] === "") {
|
|
2623
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].${field} cannot be empty.`);
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
let slug;
|
|
2627
|
+
if (input.slug !== void 0) {
|
|
2628
|
+
slug = input.slug;
|
|
2629
|
+
if (takenSlugs.has(slug)) {
|
|
2630
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].slug must be unique.`);
|
|
2631
|
+
}
|
|
2632
|
+
} else {
|
|
2633
|
+
const base = input.name !== void 0 ? dataStoreSlug(input.name) : index === 0 ? "main" : null;
|
|
2634
|
+
if (base === null) {
|
|
2635
|
+
throw new Error(
|
|
2636
|
+
`[stardeck-testing] dataStores[${index}] requires a slug or name. Only the first entry defaults to the "main" slug.`
|
|
2637
|
+
);
|
|
2638
|
+
}
|
|
2639
|
+
slug = base;
|
|
2640
|
+
let suffix = 2;
|
|
2641
|
+
while (takenSlugs.has(slug)) {
|
|
2642
|
+
slug = `${base}_${suffix}`;
|
|
2643
|
+
suffix++;
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
const id = input.id ?? `00000000-0000-4000-8000-${String(index + 1).padStart(12, "0")}`;
|
|
2647
|
+
if (takenIds.has(id)) {
|
|
2648
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].id must be unique.`);
|
|
2649
|
+
}
|
|
2650
|
+
if (input.bindingKey !== void 0 && takenBindingKeys.has(input.bindingKey)) {
|
|
2651
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].bindingKey must be unique.`);
|
|
2652
|
+
}
|
|
2653
|
+
takenSlugs.add(slug);
|
|
2654
|
+
takenIds.add(id);
|
|
2655
|
+
if (input.bindingKey !== void 0) takenBindingKeys.add(input.bindingKey);
|
|
2656
|
+
const storeType = input.storeType ?? "database";
|
|
2657
|
+
return {
|
|
2658
|
+
id,
|
|
2659
|
+
name: input.name ?? slug,
|
|
2660
|
+
slug,
|
|
2661
|
+
storeType,
|
|
2662
|
+
accessLevel: input.accessLevel ?? "admin",
|
|
2663
|
+
...storeType === "database" ? { url: input.url ?? DATA_STORE_TEST_URL } : {},
|
|
2664
|
+
...input.bindingKey ? { bindingKey: input.bindingKey } : {}
|
|
2665
|
+
};
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2606
2669
|
// src/test-app.ts
|
|
2607
|
-
function applyTestEnv() {
|
|
2670
|
+
function applyTestEnv(options) {
|
|
2608
2671
|
for (const [key, value] of Object.entries(TEST_ENV_DEFAULTS)) {
|
|
2609
2672
|
process.env[key] = value;
|
|
2610
2673
|
}
|
|
2674
|
+
let manifestAdopted = true;
|
|
2675
|
+
if (options.dataStores !== void 0) {
|
|
2676
|
+
const manifest = JSON.stringify(buildTestDataStoreManifest(options.dataStores));
|
|
2677
|
+
process.env[STARDECK_DATA_STORES_ENV] = manifest;
|
|
2678
|
+
state.lastHarnessDataStoreManifest = manifest;
|
|
2679
|
+
} else {
|
|
2680
|
+
const currentManifest = process.env[STARDECK_DATA_STORES_ENV];
|
|
2681
|
+
if (!currentManifest || currentManifest === state.lastHarnessDataStoreManifest) {
|
|
2682
|
+
const manifest = JSON.stringify(buildTestDataStoreManifest());
|
|
2683
|
+
process.env[STARDECK_DATA_STORES_ENV] = manifest;
|
|
2684
|
+
state.lastHarnessDataStoreManifest = manifest;
|
|
2685
|
+
manifestAdopted = false;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
if (options.legacyDataStoreUrl === true || !manifestAdopted && options.legacyDataStoreUrl === void 0) {
|
|
2689
|
+
process.env.DATA_STORE_URL = DATA_STORE_TEST_URL;
|
|
2690
|
+
} else {
|
|
2691
|
+
delete process.env.DATA_STORE_URL;
|
|
2692
|
+
}
|
|
2611
2693
|
delete process.env.DISABLE_AUTH;
|
|
2612
2694
|
delete process.env.NEXT_PUBLIC_DISABLE_AUTH;
|
|
2613
2695
|
delete process.env.SANDBOX_MODE;
|
|
@@ -2640,7 +2722,7 @@ async function createTestApp(options = {}) {
|
|
|
2640
2722
|
"[stardeck-testing] A test app is already active in this test file. Call `app.close()` first, or share one app per file."
|
|
2641
2723
|
);
|
|
2642
2724
|
}
|
|
2643
|
-
applyTestEnv();
|
|
2725
|
+
applyTestEnv(options);
|
|
2644
2726
|
state.allowNetwork = options.allowNetwork ?? false;
|
|
2645
2727
|
installFetchRouter();
|
|
2646
2728
|
const db = await createPgliteDatabase();
|
|
@@ -2742,11 +2824,14 @@ function parseWorkflowName(describeTitle) {
|
|
|
2742
2824
|
0 && (module.exports = {
|
|
2743
2825
|
CONTROL_PLANE_TEST_URL,
|
|
2744
2826
|
DATA_STORE_TEST_HOST,
|
|
2827
|
+
DATA_STORE_TEST_URL,
|
|
2745
2828
|
DEFAULT_SCHEMA_PATH,
|
|
2829
|
+
STARDECK_DATA_STORES_ENV,
|
|
2746
2830
|
STORAGE_TEST_HOST,
|
|
2747
2831
|
STORAGE_TEST_URL,
|
|
2748
2832
|
TEST_ENV_DEFAULTS,
|
|
2749
2833
|
WORKFLOW_NAME_PREFIX,
|
|
2834
|
+
buildTestDataStoreManifest,
|
|
2750
2835
|
callRoute,
|
|
2751
2836
|
createTestApp,
|
|
2752
2837
|
describeWorkflow,
|
package/dist/index.mjs
CHANGED
|
@@ -47,6 +47,7 @@ function globalSingleton(key, create) {
|
|
|
47
47
|
// src/state.ts
|
|
48
48
|
var state = globalSingleton("state", () => ({
|
|
49
49
|
db: null,
|
|
50
|
+
lastHarnessDataStoreManifest: null,
|
|
50
51
|
currentUser: null,
|
|
51
52
|
sessions: /* @__PURE__ */ new Map(),
|
|
52
53
|
refreshSessions: /* @__PURE__ */ new Map(),
|
|
@@ -95,6 +96,7 @@ function requireDb() {
|
|
|
95
96
|
var TEST_DOMAIN_SUFFIX = ".stardeck.test";
|
|
96
97
|
var CONTROL_PLANE_TEST_URL = "https://control-plane.stardeck.test";
|
|
97
98
|
var DATA_STORE_TEST_HOST = "db.stardeck.test";
|
|
99
|
+
var DATA_STORE_TEST_URL = `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`;
|
|
98
100
|
var STORAGE_TEST_URL = "https://storage.stardeck.test";
|
|
99
101
|
var STORAGE_TEST_HOST = "storage.stardeck.test";
|
|
100
102
|
var TEST_ENV_DEFAULTS = {
|
|
@@ -103,7 +105,6 @@ var TEST_ENV_DEFAULTS = {
|
|
|
103
105
|
ORGANIZATION_ID: "00000000-0000-4000-8000-00000000000a",
|
|
104
106
|
PROJECT_ID: "00000000-0000-4000-8000-00000000000b",
|
|
105
107
|
DEPLOYMENT_ID: "00000000-0000-4000-8000-00000000000c",
|
|
106
|
-
DATA_STORE_URL: `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`,
|
|
107
108
|
STORAGE_URL: STORAGE_TEST_URL
|
|
108
109
|
};
|
|
109
110
|
var DEFAULT_TEST_USER = {
|
|
@@ -2557,11 +2558,89 @@ function uninstallFetchRouter() {
|
|
|
2557
2558
|
}
|
|
2558
2559
|
}
|
|
2559
2560
|
|
|
2561
|
+
// src/data-store-manifest.ts
|
|
2562
|
+
var STARDECK_DATA_STORES_ENV = "STARDECK_DATA_STORES";
|
|
2563
|
+
function dataStoreSlug(name) {
|
|
2564
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
2565
|
+
return slug || "store";
|
|
2566
|
+
}
|
|
2567
|
+
function buildTestDataStoreManifest(inputs = [{}]) {
|
|
2568
|
+
const takenSlugs = /* @__PURE__ */ new Set();
|
|
2569
|
+
const takenBindingKeys = /* @__PURE__ */ new Set();
|
|
2570
|
+
const takenIds = /* @__PURE__ */ new Set();
|
|
2571
|
+
return inputs.map((input, index) => {
|
|
2572
|
+
for (const field of ["bindingKey", "slug", "name"]) {
|
|
2573
|
+
if (input[field] === "") {
|
|
2574
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].${field} cannot be empty.`);
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
let slug;
|
|
2578
|
+
if (input.slug !== void 0) {
|
|
2579
|
+
slug = input.slug;
|
|
2580
|
+
if (takenSlugs.has(slug)) {
|
|
2581
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].slug must be unique.`);
|
|
2582
|
+
}
|
|
2583
|
+
} else {
|
|
2584
|
+
const base = input.name !== void 0 ? dataStoreSlug(input.name) : index === 0 ? "main" : null;
|
|
2585
|
+
if (base === null) {
|
|
2586
|
+
throw new Error(
|
|
2587
|
+
`[stardeck-testing] dataStores[${index}] requires a slug or name. Only the first entry defaults to the "main" slug.`
|
|
2588
|
+
);
|
|
2589
|
+
}
|
|
2590
|
+
slug = base;
|
|
2591
|
+
let suffix = 2;
|
|
2592
|
+
while (takenSlugs.has(slug)) {
|
|
2593
|
+
slug = `${base}_${suffix}`;
|
|
2594
|
+
suffix++;
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
const id = input.id ?? `00000000-0000-4000-8000-${String(index + 1).padStart(12, "0")}`;
|
|
2598
|
+
if (takenIds.has(id)) {
|
|
2599
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].id must be unique.`);
|
|
2600
|
+
}
|
|
2601
|
+
if (input.bindingKey !== void 0 && takenBindingKeys.has(input.bindingKey)) {
|
|
2602
|
+
throw new Error(`[stardeck-testing] dataStores[${index}].bindingKey must be unique.`);
|
|
2603
|
+
}
|
|
2604
|
+
takenSlugs.add(slug);
|
|
2605
|
+
takenIds.add(id);
|
|
2606
|
+
if (input.bindingKey !== void 0) takenBindingKeys.add(input.bindingKey);
|
|
2607
|
+
const storeType = input.storeType ?? "database";
|
|
2608
|
+
return {
|
|
2609
|
+
id,
|
|
2610
|
+
name: input.name ?? slug,
|
|
2611
|
+
slug,
|
|
2612
|
+
storeType,
|
|
2613
|
+
accessLevel: input.accessLevel ?? "admin",
|
|
2614
|
+
...storeType === "database" ? { url: input.url ?? DATA_STORE_TEST_URL } : {},
|
|
2615
|
+
...input.bindingKey ? { bindingKey: input.bindingKey } : {}
|
|
2616
|
+
};
|
|
2617
|
+
});
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2560
2620
|
// src/test-app.ts
|
|
2561
|
-
function applyTestEnv() {
|
|
2621
|
+
function applyTestEnv(options) {
|
|
2562
2622
|
for (const [key, value] of Object.entries(TEST_ENV_DEFAULTS)) {
|
|
2563
2623
|
process.env[key] = value;
|
|
2564
2624
|
}
|
|
2625
|
+
let manifestAdopted = true;
|
|
2626
|
+
if (options.dataStores !== void 0) {
|
|
2627
|
+
const manifest = JSON.stringify(buildTestDataStoreManifest(options.dataStores));
|
|
2628
|
+
process.env[STARDECK_DATA_STORES_ENV] = manifest;
|
|
2629
|
+
state.lastHarnessDataStoreManifest = manifest;
|
|
2630
|
+
} else {
|
|
2631
|
+
const currentManifest = process.env[STARDECK_DATA_STORES_ENV];
|
|
2632
|
+
if (!currentManifest || currentManifest === state.lastHarnessDataStoreManifest) {
|
|
2633
|
+
const manifest = JSON.stringify(buildTestDataStoreManifest());
|
|
2634
|
+
process.env[STARDECK_DATA_STORES_ENV] = manifest;
|
|
2635
|
+
state.lastHarnessDataStoreManifest = manifest;
|
|
2636
|
+
manifestAdopted = false;
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
if (options.legacyDataStoreUrl === true || !manifestAdopted && options.legacyDataStoreUrl === void 0) {
|
|
2640
|
+
process.env.DATA_STORE_URL = DATA_STORE_TEST_URL;
|
|
2641
|
+
} else {
|
|
2642
|
+
delete process.env.DATA_STORE_URL;
|
|
2643
|
+
}
|
|
2565
2644
|
delete process.env.DISABLE_AUTH;
|
|
2566
2645
|
delete process.env.NEXT_PUBLIC_DISABLE_AUTH;
|
|
2567
2646
|
delete process.env.SANDBOX_MODE;
|
|
@@ -2594,7 +2673,7 @@ async function createTestApp(options = {}) {
|
|
|
2594
2673
|
"[stardeck-testing] A test app is already active in this test file. Call `app.close()` first, or share one app per file."
|
|
2595
2674
|
);
|
|
2596
2675
|
}
|
|
2597
|
-
applyTestEnv();
|
|
2676
|
+
applyTestEnv(options);
|
|
2598
2677
|
state.allowNetwork = options.allowNetwork ?? false;
|
|
2599
2678
|
installFetchRouter();
|
|
2600
2679
|
const db = await createPgliteDatabase();
|
|
@@ -2695,11 +2774,14 @@ function parseWorkflowName(describeTitle) {
|
|
|
2695
2774
|
export {
|
|
2696
2775
|
CONTROL_PLANE_TEST_URL,
|
|
2697
2776
|
DATA_STORE_TEST_HOST,
|
|
2777
|
+
DATA_STORE_TEST_URL,
|
|
2698
2778
|
DEFAULT_SCHEMA_PATH,
|
|
2779
|
+
STARDECK_DATA_STORES_ENV,
|
|
2699
2780
|
STORAGE_TEST_HOST,
|
|
2700
2781
|
STORAGE_TEST_URL,
|
|
2701
2782
|
TEST_ENV_DEFAULTS,
|
|
2702
2783
|
WORKFLOW_NAME_PREFIX,
|
|
2784
|
+
buildTestDataStoreManifest,
|
|
2703
2785
|
callRoute,
|
|
2704
2786
|
createTestApp,
|
|
2705
2787
|
describeWorkflow,
|
|
@@ -39,6 +39,7 @@ function globalSingleton(key, create) {
|
|
|
39
39
|
// src/state.ts
|
|
40
40
|
var state = globalSingleton("state", () => ({
|
|
41
41
|
db: null,
|
|
42
|
+
lastHarnessDataStoreManifest: null,
|
|
42
43
|
currentUser: null,
|
|
43
44
|
sessions: /* @__PURE__ */ new Map(),
|
|
44
45
|
refreshSessions: /* @__PURE__ */ new Map(),
|
|
@@ -12,6 +12,7 @@ function globalSingleton(key, create) {
|
|
|
12
12
|
// src/state.ts
|
|
13
13
|
var state = globalSingleton("state", () => ({
|
|
14
14
|
db: null,
|
|
15
|
+
lastHarnessDataStoreManifest: null,
|
|
15
16
|
currentUser: null,
|
|
16
17
|
sessions: /* @__PURE__ */ new Map(),
|
|
17
18
|
refreshSessions: /* @__PURE__ */ new Map(),
|
package/dist/setup.js
CHANGED
|
@@ -33,6 +33,7 @@ function globalSingleton(key, create) {
|
|
|
33
33
|
// src/state.ts
|
|
34
34
|
var state = globalSingleton("state", () => ({
|
|
35
35
|
db: null,
|
|
36
|
+
lastHarnessDataStoreManifest: null,
|
|
36
37
|
currentUser: null,
|
|
37
38
|
sessions: /* @__PURE__ */ new Map(),
|
|
38
39
|
refreshSessions: /* @__PURE__ */ new Map(),
|
|
@@ -81,6 +82,7 @@ function requireDb() {
|
|
|
81
82
|
var TEST_DOMAIN_SUFFIX = ".stardeck.test";
|
|
82
83
|
var CONTROL_PLANE_TEST_URL = "https://control-plane.stardeck.test";
|
|
83
84
|
var DATA_STORE_TEST_HOST = "db.stardeck.test";
|
|
85
|
+
var DATA_STORE_TEST_URL = `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`;
|
|
84
86
|
var STORAGE_TEST_URL = "https://storage.stardeck.test";
|
|
85
87
|
var STORAGE_TEST_HOST = "storage.stardeck.test";
|
|
86
88
|
var TEST_ENV_DEFAULTS = {
|
|
@@ -89,7 +91,6 @@ var TEST_ENV_DEFAULTS = {
|
|
|
89
91
|
ORGANIZATION_ID: "00000000-0000-4000-8000-00000000000a",
|
|
90
92
|
PROJECT_ID: "00000000-0000-4000-8000-00000000000b",
|
|
91
93
|
DEPLOYMENT_ID: "00000000-0000-4000-8000-00000000000c",
|
|
92
|
-
DATA_STORE_URL: `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`,
|
|
93
94
|
STORAGE_URL: STORAGE_TEST_URL
|
|
94
95
|
};
|
|
95
96
|
|
package/dist/setup.mjs
CHANGED
|
@@ -9,6 +9,7 @@ function globalSingleton(key, create) {
|
|
|
9
9
|
// src/state.ts
|
|
10
10
|
var state = globalSingleton("state", () => ({
|
|
11
11
|
db: null,
|
|
12
|
+
lastHarnessDataStoreManifest: null,
|
|
12
13
|
currentUser: null,
|
|
13
14
|
sessions: /* @__PURE__ */ new Map(),
|
|
14
15
|
refreshSessions: /* @__PURE__ */ new Map(),
|
|
@@ -57,6 +58,7 @@ function requireDb() {
|
|
|
57
58
|
var TEST_DOMAIN_SUFFIX = ".stardeck.test";
|
|
58
59
|
var CONTROL_PLANE_TEST_URL = "https://control-plane.stardeck.test";
|
|
59
60
|
var DATA_STORE_TEST_HOST = "db.stardeck.test";
|
|
61
|
+
var DATA_STORE_TEST_URL = `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`;
|
|
60
62
|
var STORAGE_TEST_URL = "https://storage.stardeck.test";
|
|
61
63
|
var STORAGE_TEST_HOST = "storage.stardeck.test";
|
|
62
64
|
var TEST_ENV_DEFAULTS = {
|
|
@@ -65,7 +67,6 @@ var TEST_ENV_DEFAULTS = {
|
|
|
65
67
|
ORGANIZATION_ID: "00000000-0000-4000-8000-00000000000a",
|
|
66
68
|
PROJECT_ID: "00000000-0000-4000-8000-00000000000b",
|
|
67
69
|
DEPLOYMENT_ID: "00000000-0000-4000-8000-00000000000c",
|
|
68
|
-
DATA_STORE_URL: `postgresql://test:test@${DATA_STORE_TEST_HOST}/main`,
|
|
69
70
|
STORAGE_URL: STORAGE_TEST_URL
|
|
70
71
|
};
|
|
71
72
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stardeck-customer-apps/testing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Vitest test harness for Stardeck customer apps — in-process Postgres (PGlite) plus a control-plane simulator so the real Stardeck SDKs run unmodified in tests",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|