@stardeck-customer-apps/testing 0.2.0 → 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/dist/index.d.mts +48 -1
- package/dist/index.d.ts +48 -1
- package/dist/index.js +35 -0
- package/dist/index.mjs +37 -0
- package/package.json +7 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PGlite } from '@electric-sql/pglite';
|
|
2
|
+
import { ModuleSchemaOp, ModuleDataPort, IdentityClient } from '@stardeck-customer-apps/core';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* The user shape returned by project-auth's `getSession()`. Mirrors the
|
|
@@ -140,6 +141,52 @@ interface TestApp {
|
|
|
140
141
|
*/
|
|
141
142
|
declare function createTestApp(options?: TestAppOptions): Promise<TestApp>;
|
|
142
143
|
|
|
144
|
+
/** The minimal slice of a module definition the harness needs to stand it up. */
|
|
145
|
+
interface MountableModule {
|
|
146
|
+
schema: ModuleSchemaOp[];
|
|
147
|
+
}
|
|
148
|
+
interface ModuleSeedDeps {
|
|
149
|
+
/** Raw-SQL data port over the harness PGlite — what the module engine reads/writes through. */
|
|
150
|
+
data: ModuleDataPort;
|
|
151
|
+
/** Identity client backed by the simulated platform identity directory. */
|
|
152
|
+
identities: IdentityClient;
|
|
153
|
+
}
|
|
154
|
+
interface CreateModuleAppOptions {
|
|
155
|
+
/** Modules whose install schema is rendered to DDL and applied to the test DB. */
|
|
156
|
+
modules: MountableModule[];
|
|
157
|
+
/**
|
|
158
|
+
* Seed run once after the schema is applied, and again on every `reset()`.
|
|
159
|
+
* Receives the same data port + identity client the module engine uses, so a
|
|
160
|
+
* module's own `seed*` function drops straight in.
|
|
161
|
+
*/
|
|
162
|
+
seed?: (deps: ModuleSeedDeps) => Promise<void>;
|
|
163
|
+
/** Allow real outbound network (default false). */
|
|
164
|
+
allowNetwork?: boolean;
|
|
165
|
+
}
|
|
166
|
+
interface ModuleApp extends ModuleSeedDeps {
|
|
167
|
+
/** The underlying harness app (db, identities inspector, callRoute, asUser, …). */
|
|
168
|
+
app: TestApp;
|
|
169
|
+
/** Reset to a clean slate: drop + re-apply the module schema, clear the sim, re-run the seed. */
|
|
170
|
+
reset(): Promise<void>;
|
|
171
|
+
/** Tear down (restore global fetch, close the db). */
|
|
172
|
+
close(): Promise<void>;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Stand a capability module up on the in-process platform simulator — the **L2**
|
|
176
|
+
* harness. It renders the module's install schema to real DDL (the SAME renderer
|
|
177
|
+
* the control plane uses, drift-tested in apps/web), applies it to PGlite, wires a
|
|
178
|
+
* raw-SQL data port over it, and a real `integrations-sdk` identity client talking
|
|
179
|
+
* to the simulated identity directory (so scoping + governance behave as in prod).
|
|
180
|
+
*
|
|
181
|
+
* That's a near-end-to-end test of a module's runtime — schema + data port +
|
|
182
|
+
* identity integration + engine — minus the HTTP/RSC shell (those belong to a
|
|
183
|
+
* real-deploy smoke). The same seams back the local dev playground.
|
|
184
|
+
*
|
|
185
|
+
* Adding a module costs one co-located test file calling this with its own
|
|
186
|
+
* definition + seed; there is no per-module harness to maintain.
|
|
187
|
+
*/
|
|
188
|
+
declare function createModuleApp(options: CreateModuleAppOptions): Promise<ModuleApp>;
|
|
189
|
+
|
|
143
190
|
type RouteHandler<Req extends Request, P> = (request: Req, context: {
|
|
144
191
|
params: Promise<P>;
|
|
145
192
|
}) => Promise<Response> | Response;
|
|
@@ -183,4 +230,4 @@ declare const TEST_ENV_DEFAULTS: {
|
|
|
183
230
|
/** Default location of the DDL snapshot written by `generate-types`. */
|
|
184
231
|
declare const DEFAULT_SCHEMA_PATH = "./src/generated/data-store-schema.sql";
|
|
185
232
|
|
|
186
|
-
export { CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, DATA_STORE_TEST_HOST, DEFAULT_SCHEMA_PATH, type SessionTokens, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, type TestDirectory, type TestInbox, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
|
233
|
+
export { CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CreateModuleAppOptions, DATA_STORE_TEST_HOST, DEFAULT_SCHEMA_PATH, type ModuleApp, type ModuleSeedDeps, type MountableModule, type SessionTokens, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, type TestDirectory, type TestInbox, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createModuleApp, createTestApp, describeWorkflow, parseWorkflowName };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PGlite } from '@electric-sql/pglite';
|
|
2
|
+
import { ModuleSchemaOp, ModuleDataPort, IdentityClient } from '@stardeck-customer-apps/core';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* The user shape returned by project-auth's `getSession()`. Mirrors the
|
|
@@ -140,6 +141,52 @@ interface TestApp {
|
|
|
140
141
|
*/
|
|
141
142
|
declare function createTestApp(options?: TestAppOptions): Promise<TestApp>;
|
|
142
143
|
|
|
144
|
+
/** The minimal slice of a module definition the harness needs to stand it up. */
|
|
145
|
+
interface MountableModule {
|
|
146
|
+
schema: ModuleSchemaOp[];
|
|
147
|
+
}
|
|
148
|
+
interface ModuleSeedDeps {
|
|
149
|
+
/** Raw-SQL data port over the harness PGlite — what the module engine reads/writes through. */
|
|
150
|
+
data: ModuleDataPort;
|
|
151
|
+
/** Identity client backed by the simulated platform identity directory. */
|
|
152
|
+
identities: IdentityClient;
|
|
153
|
+
}
|
|
154
|
+
interface CreateModuleAppOptions {
|
|
155
|
+
/** Modules whose install schema is rendered to DDL and applied to the test DB. */
|
|
156
|
+
modules: MountableModule[];
|
|
157
|
+
/**
|
|
158
|
+
* Seed run once after the schema is applied, and again on every `reset()`.
|
|
159
|
+
* Receives the same data port + identity client the module engine uses, so a
|
|
160
|
+
* module's own `seed*` function drops straight in.
|
|
161
|
+
*/
|
|
162
|
+
seed?: (deps: ModuleSeedDeps) => Promise<void>;
|
|
163
|
+
/** Allow real outbound network (default false). */
|
|
164
|
+
allowNetwork?: boolean;
|
|
165
|
+
}
|
|
166
|
+
interface ModuleApp extends ModuleSeedDeps {
|
|
167
|
+
/** The underlying harness app (db, identities inspector, callRoute, asUser, …). */
|
|
168
|
+
app: TestApp;
|
|
169
|
+
/** Reset to a clean slate: drop + re-apply the module schema, clear the sim, re-run the seed. */
|
|
170
|
+
reset(): Promise<void>;
|
|
171
|
+
/** Tear down (restore global fetch, close the db). */
|
|
172
|
+
close(): Promise<void>;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Stand a capability module up on the in-process platform simulator — the **L2**
|
|
176
|
+
* harness. It renders the module's install schema to real DDL (the SAME renderer
|
|
177
|
+
* the control plane uses, drift-tested in apps/web), applies it to PGlite, wires a
|
|
178
|
+
* raw-SQL data port over it, and a real `integrations-sdk` identity client talking
|
|
179
|
+
* to the simulated identity directory (so scoping + governance behave as in prod).
|
|
180
|
+
*
|
|
181
|
+
* That's a near-end-to-end test of a module's runtime — schema + data port +
|
|
182
|
+
* identity integration + engine — minus the HTTP/RSC shell (those belong to a
|
|
183
|
+
* real-deploy smoke). The same seams back the local dev playground.
|
|
184
|
+
*
|
|
185
|
+
* Adding a module costs one co-located test file calling this with its own
|
|
186
|
+
* definition + seed; there is no per-module harness to maintain.
|
|
187
|
+
*/
|
|
188
|
+
declare function createModuleApp(options: CreateModuleAppOptions): Promise<ModuleApp>;
|
|
189
|
+
|
|
143
190
|
type RouteHandler<Req extends Request, P> = (request: Req, context: {
|
|
144
191
|
params: Promise<P>;
|
|
145
192
|
}) => Promise<Response> | Response;
|
|
@@ -183,4 +230,4 @@ declare const TEST_ENV_DEFAULTS: {
|
|
|
183
230
|
/** Default location of the DDL snapshot written by `generate-types`. */
|
|
184
231
|
declare const DEFAULT_SCHEMA_PATH = "./src/generated/data-store-schema.sql";
|
|
185
232
|
|
|
186
|
-
export { CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, DATA_STORE_TEST_HOST, DEFAULT_SCHEMA_PATH, type SessionTokens, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, type TestDirectory, type TestInbox, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
|
233
|
+
export { CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CreateModuleAppOptions, DATA_STORE_TEST_HOST, DEFAULT_SCHEMA_PATH, type ModuleApp, type ModuleSeedDeps, type MountableModule, type SessionTokens, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, type TestDirectory, type TestInbox, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createModuleApp, createTestApp, describeWorkflow, parseWorkflowName };
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
TEST_ENV_DEFAULTS: () => TEST_ENV_DEFAULTS,
|
|
37
37
|
WORKFLOW_NAME_PREFIX: () => WORKFLOW_NAME_PREFIX,
|
|
38
38
|
callRoute: () => callRoute,
|
|
39
|
+
createModuleApp: () => createModuleApp,
|
|
39
40
|
createTestApp: () => createTestApp,
|
|
40
41
|
describeWorkflow: () => describeWorkflow,
|
|
41
42
|
parseWorkflowName: () => parseWorkflowName
|
|
@@ -980,6 +981,39 @@ async function createTestApp(options = {}) {
|
|
|
980
981
|
return app;
|
|
981
982
|
}
|
|
982
983
|
|
|
984
|
+
// src/module-app.ts
|
|
985
|
+
var import_core = require("@stardeck-customer-apps/core");
|
|
986
|
+
async function createModuleApp(options) {
|
|
987
|
+
const schemaSql = options.modules.map((m) => (0, import_core.renderSchemaOpsToSql)(m.schema)).join("\n\n");
|
|
988
|
+
const app = await createTestApp({ schemaSql, allowNetwork: options.allowNetwork });
|
|
989
|
+
const sql = { query: (text, params) => app.db.query(text, params ?? []) };
|
|
990
|
+
const data = (0, import_core.makeSqlPort)(sql);
|
|
991
|
+
const { createIntegrationsClient } = await import("@stardeck-customer-apps/integrations-sdk");
|
|
992
|
+
const identities = createIntegrationsClient({
|
|
993
|
+
controlPlaneUrl: TEST_ENV_DEFAULTS.CONTROL_PLANE_URL,
|
|
994
|
+
organizationId: TEST_ENV_DEFAULTS.ORGANIZATION_ID,
|
|
995
|
+
projectId: TEST_ENV_DEFAULTS.PROJECT_ID,
|
|
996
|
+
deploymentId: TEST_ENV_DEFAULTS.DEPLOYMENT_ID,
|
|
997
|
+
deploymentSecret: TEST_ENV_DEFAULTS.DEPLOYMENT_SECRET
|
|
998
|
+
}).identities;
|
|
999
|
+
const runSeed = async () => {
|
|
1000
|
+
if (options.seed) await options.seed({ data, identities });
|
|
1001
|
+
};
|
|
1002
|
+
await runSeed();
|
|
1003
|
+
return {
|
|
1004
|
+
app,
|
|
1005
|
+
data,
|
|
1006
|
+
identities,
|
|
1007
|
+
async reset() {
|
|
1008
|
+
await app.reset();
|
|
1009
|
+
await runSeed();
|
|
1010
|
+
},
|
|
1011
|
+
async close() {
|
|
1012
|
+
await app.close();
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
|
|
983
1017
|
// src/next/headers-shim.ts
|
|
984
1018
|
var import_node_async_hooks = require("async_hooks");
|
|
985
1019
|
var requestScopeStorage = globalSingleton(
|
|
@@ -1077,6 +1111,7 @@ function parseWorkflowName(describeTitle) {
|
|
|
1077
1111
|
TEST_ENV_DEFAULTS,
|
|
1078
1112
|
WORKFLOW_NAME_PREFIX,
|
|
1079
1113
|
callRoute,
|
|
1114
|
+
createModuleApp,
|
|
1080
1115
|
createTestApp,
|
|
1081
1116
|
describeWorkflow,
|
|
1082
1117
|
parseWorkflowName
|
package/dist/index.mjs
CHANGED
|
@@ -936,6 +936,42 @@ async function createTestApp(options = {}) {
|
|
|
936
936
|
return app;
|
|
937
937
|
}
|
|
938
938
|
|
|
939
|
+
// src/module-app.ts
|
|
940
|
+
import {
|
|
941
|
+
makeSqlPort,
|
|
942
|
+
renderSchemaOpsToSql
|
|
943
|
+
} from "@stardeck-customer-apps/core";
|
|
944
|
+
async function createModuleApp(options) {
|
|
945
|
+
const schemaSql = options.modules.map((m) => renderSchemaOpsToSql(m.schema)).join("\n\n");
|
|
946
|
+
const app = await createTestApp({ schemaSql, allowNetwork: options.allowNetwork });
|
|
947
|
+
const sql = { query: (text, params) => app.db.query(text, params ?? []) };
|
|
948
|
+
const data = makeSqlPort(sql);
|
|
949
|
+
const { createIntegrationsClient } = await import("@stardeck-customer-apps/integrations-sdk");
|
|
950
|
+
const identities = createIntegrationsClient({
|
|
951
|
+
controlPlaneUrl: TEST_ENV_DEFAULTS.CONTROL_PLANE_URL,
|
|
952
|
+
organizationId: TEST_ENV_DEFAULTS.ORGANIZATION_ID,
|
|
953
|
+
projectId: TEST_ENV_DEFAULTS.PROJECT_ID,
|
|
954
|
+
deploymentId: TEST_ENV_DEFAULTS.DEPLOYMENT_ID,
|
|
955
|
+
deploymentSecret: TEST_ENV_DEFAULTS.DEPLOYMENT_SECRET
|
|
956
|
+
}).identities;
|
|
957
|
+
const runSeed = async () => {
|
|
958
|
+
if (options.seed) await options.seed({ data, identities });
|
|
959
|
+
};
|
|
960
|
+
await runSeed();
|
|
961
|
+
return {
|
|
962
|
+
app,
|
|
963
|
+
data,
|
|
964
|
+
identities,
|
|
965
|
+
async reset() {
|
|
966
|
+
await app.reset();
|
|
967
|
+
await runSeed();
|
|
968
|
+
},
|
|
969
|
+
async close() {
|
|
970
|
+
await app.close();
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
|
|
939
975
|
// src/next/headers-shim.ts
|
|
940
976
|
import { AsyncLocalStorage } from "async_hooks";
|
|
941
977
|
var requestScopeStorage = globalSingleton(
|
|
@@ -1032,6 +1068,7 @@ export {
|
|
|
1032
1068
|
TEST_ENV_DEFAULTS,
|
|
1033
1069
|
WORKFLOW_NAME_PREFIX,
|
|
1034
1070
|
callRoute,
|
|
1071
|
+
createModuleApp,
|
|
1035
1072
|
createTestApp,
|
|
1036
1073
|
describeWorkflow,
|
|
1037
1074
|
parseWorkflowName
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stardeck-customer-apps/testing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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",
|
|
@@ -62,13 +62,18 @@
|
|
|
62
62
|
"author": "Stardeck",
|
|
63
63
|
"license": "MIT",
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@electric-sql/pglite": "^0.3.0"
|
|
65
|
+
"@electric-sql/pglite": "^0.3.0",
|
|
66
|
+
"@stardeck-customer-apps/core": "*"
|
|
66
67
|
},
|
|
67
68
|
"peerDependencies": {
|
|
69
|
+
"@stardeck-customer-apps/integrations-sdk": ">=1.6.0",
|
|
68
70
|
"next": "^14.0.0 || ^15.0.0 || ^16.0.0",
|
|
69
71
|
"vitest": ">=2.0.0"
|
|
70
72
|
},
|
|
71
73
|
"peerDependenciesMeta": {
|
|
74
|
+
"@stardeck-customer-apps/integrations-sdk": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
72
77
|
"next": {
|
|
73
78
|
"optional": true
|
|
74
79
|
}
|