@stratal/testing 0.0.22 → 0.0.23
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/README.md +0 -16
- package/dist/database/index.d.mts +2 -0
- package/dist/database/index.mjs +2 -0
- package/dist/database-B02eYKhE.mjs +334 -0
- package/dist/database-B02eYKhE.mjs.map +1 -0
- package/dist/decorate-B7nr7eBl.mjs +9 -0
- package/dist/feature-flags/index.d.mts +2 -0
- package/dist/feature-flags/index.mjs +2 -0
- package/dist/feature-flags-BiLhfSGh.mjs +86 -0
- package/dist/feature-flags-BiLhfSGh.mjs.map +1 -0
- package/dist/index-BIr5nLof.d.mts +122 -0
- package/dist/index-BIr5nLof.d.mts.map +1 -0
- package/dist/{index-D-Q2cR2v.d.mts → index-CrHzUDKX.d.mts} +1 -1
- package/dist/index-CrHzUDKX.d.mts.map +1 -0
- package/dist/index-qgWNJRdC.d.mts +65 -0
- package/dist/index-qgWNJRdC.d.mts.map +1 -0
- package/dist/index.d.mts +29 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +95 -65
- package/dist/index.mjs.map +1 -1
- package/dist/mocks/zenstack-language.d.mts.map +1 -1
- package/dist/mocks/zenstack-language.mjs.map +1 -1
- package/dist/storage/index.d.mts +2 -2
- package/dist/storage/index.mjs +1 -1
- package/dist/{storage-BXOfzNKK.mjs → storage-DhoxWqyF.mjs} +4 -11
- package/dist/{storage-BXOfzNKK.mjs.map → storage-DhoxWqyF.mjs.map} +1 -1
- package/dist/vitest-plugin/index.d.mts +41 -5
- package/dist/vitest-plugin/index.d.mts.map +1 -1
- package/dist/vitest-plugin/index.mjs +29 -9
- package/dist/vitest-plugin/index.mjs.map +1 -1
- package/package.json +26 -16
- package/dist/index-D-Q2cR2v.d.mts.map +0 -1
- package/dist/mocks/nodemailer.d.mts +0 -12
- package/dist/mocks/nodemailer.d.mts.map +0 -1
- package/dist/mocks/nodemailer.mjs +0 -7
- package/dist/mocks/nodemailer.mjs.map +0 -1
|
@@ -1,8 +1,42 @@
|
|
|
1
|
+
import { r as DatabaseIsolation } from "../index-BIr5nLof.mjs";
|
|
2
|
+
import { StratalEnv } from "stratal";
|
|
1
3
|
import { cloudflareTest } from "@cloudflare/vitest-pool-workers";
|
|
2
4
|
import { Plugin } from "vite";
|
|
3
5
|
|
|
4
6
|
//#region src/vitest-plugin/stratal-test.d.ts
|
|
5
7
|
type CloudflareTestOptions = Parameters<typeof cloudflareTest>[0];
|
|
8
|
+
/** String keys of `StratalEnv` whose value is a Hyperdrive binding. */
|
|
9
|
+
type HyperdriveKeys = Extract<{ [K in keyof StratalEnv]-?: StratalEnv[K] extends Hyperdrive ? K : never }[keyof StratalEnv], string>;
|
|
10
|
+
/**
|
|
11
|
+
* Names of declared Hyperdrive bindings, drawn from the consumer's augmented
|
|
12
|
+
* `StratalEnv` (which extends `Cloudflare.Env`). Falls back to `string` only
|
|
13
|
+
* when no Hyperdrive binding is declared (nothing to constrain to).
|
|
14
|
+
*/
|
|
15
|
+
type HyperdriveBindingName = [HyperdriveKeys] extends [never] ? string : HyperdriveKeys;
|
|
16
|
+
/** Stratal-specific test database configuration for {@link stratalTest}. */
|
|
17
|
+
interface StratalTestDatabaseOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Database isolation mode for parallel runs. Defaults to `'shared'`.
|
|
20
|
+
*
|
|
21
|
+
* - `'shared'` — all test files share one database (serial; today's behaviour).
|
|
22
|
+
* - `'database'` — each test file gets its own database cloned from a migrated
|
|
23
|
+
* template (dropped on teardown), and file parallelism is enabled.
|
|
24
|
+
*
|
|
25
|
+
* Pair with `createTestDatabaseGlobalSetup({ isolation })` from
|
|
26
|
+
* `@stratal/testing/database` in your Vitest `globalSetup`.
|
|
27
|
+
*/
|
|
28
|
+
isolation?: DatabaseIsolation;
|
|
29
|
+
/**
|
|
30
|
+
* Name of the Hyperdrive binding to isolate per test file. Defaults to `'DB'`.
|
|
31
|
+
* Constrained to Hyperdrive binding names declared on `Cloudflare.Env` /
|
|
32
|
+
* `StratalEnv`.
|
|
33
|
+
*/
|
|
34
|
+
binding?: HyperdriveBindingName;
|
|
35
|
+
}
|
|
36
|
+
type WorkersPoolOptions = Exclude<CloudflareTestOptions, (...args: never[]) => unknown>;
|
|
37
|
+
type StratalTestOptions = WorkersPoolOptions & {
|
|
38
|
+
database?: StratalTestDatabaseOptions;
|
|
39
|
+
};
|
|
6
40
|
/**
|
|
7
41
|
* Returns a Vite plugin that forces CJS resolution for `pg` sub-dependencies.
|
|
8
42
|
*
|
|
@@ -66,15 +100,17 @@ declare const fixNobleHashesCjs: () => Plugin;
|
|
|
66
100
|
/**
|
|
67
101
|
* Returns Vite plugins for Stratal tests running in the Cloudflare Workers (workerd) environment.
|
|
68
102
|
*
|
|
69
|
-
* Includes the cloudflare pool plugin and Stratal alias plugin.
|
|
70
|
-
*
|
|
103
|
+
* Includes the cloudflare pool plugin and Stratal alias plugin. Pass
|
|
104
|
+
* `database: { isolation: 'database' }` to give each test file its own
|
|
105
|
+
* database (cloned from a migrated template, dropped on teardown) and enable
|
|
106
|
+
* file parallelism. Use inside a project-level `plugins` array.
|
|
71
107
|
*
|
|
72
108
|
* **Note:** `fixPgCjs()` must be registered separately at the root `defineConfig` level.
|
|
73
109
|
*
|
|
74
|
-
* @param options -
|
|
110
|
+
* @param options - `cloudflareTest()` options plus Stratal `database` options
|
|
75
111
|
* @returns An array of Vite plugins
|
|
76
112
|
*/
|
|
77
|
-
declare function stratalTest(options?:
|
|
113
|
+
declare function stratalTest(options?: StratalTestOptions): Plugin[];
|
|
78
114
|
//#endregion
|
|
79
|
-
export { fixNobleHashesCjs, fixPgCjs, stratalTest };
|
|
115
|
+
export { type StratalTestDatabaseOptions, fixNobleHashesCjs, fixPgCjs, stratalTest };
|
|
80
116
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/vitest-plugin/stratal-test.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/vitest-plugin/stratal-test.ts"],"mappings":";;;;;;KAWK,qBAAA,GAAwB,UAAU,QAAQ,cAAA;;KAG1C,cAAA,GAAiB,OAAA,eACN,UAAA,KAAe,UAAA,CAAW,CAAA,UAAW,UAAA,GAAa,CAAA,iBAAkB,UAAA;;AAJvB;AAAA;;;KAaxD,qBAAA,IAAyB,cAAA,6BAA2C,cAAc;;UAGtE,0BAAA;EAZoC;;;;;;;;;;EAuBnD,SAAA,GAAY,iBAAA;EAvBuC;;;;AAAyC;EA6B5F,OAAA,GAAU,qBAAqB;AAAA;AAAA,KAG5B,kBAAA,GAAqB,OAAO,CAAC,qBAAA,MAA2B,IAAA;AAAA,KACxD,kBAAA,GAAqB,kBAAA;EAAuB,QAAA,GAAW,0BAA0B;AAAA;;;;;;;;;AAJrD;AAChC;;;;;;;;AAEgE;AAAA;;;;;;;;AACqB;AAsCtF;;cAAa,QAAA,QAAe,MAY1B;;AAAA;AA+BF;;;;AA0BC;AA4CD;;;;;;;;AAAqE;;;;;;;;;;;;;;cAtExD,iBAAA,QAAwB,MA0BpC;;;;;;;;;;;;;;iBA4Ce,WAAA,CAAY,OAAA,GAAS,kBAAA,GAA0B,MAAM"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { f as normalizeIsolation, r as ISOLATION_ENV_VAR, t as BINDING_ENV_VAR } from "../database-B02eYKhE.mjs";
|
|
1
2
|
import { createRequire } from "node:module";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { cloudflareTest } from "@cloudflare/vitest-pool-workers";
|
|
@@ -102,34 +103,53 @@ const fixNobleHashesCjs = () => {
|
|
|
102
103
|
}
|
|
103
104
|
};
|
|
104
105
|
};
|
|
105
|
-
const
|
|
106
|
+
const createStratalPlugin = (isolation) => ({
|
|
106
107
|
name: "stratal-test",
|
|
107
108
|
config() {
|
|
108
|
-
|
|
109
|
+
const config = {
|
|
109
110
|
resolve: { alias: {
|
|
110
111
|
tslib: "tslib/tslib.es6.mjs",
|
|
111
112
|
"@zenstackhq/language/ast": "@stratal/testing/mocks/zenstack-language",
|
|
112
113
|
"@zenstackhq/language/utils": "@stratal/testing/mocks/zenstack-language",
|
|
113
|
-
"@zenstackhq/language": "@stratal/testing/mocks/zenstack-language"
|
|
114
|
-
nodemailer: "@stratal/testing/mocks/nodemailer"
|
|
114
|
+
"@zenstackhq/language": "@stratal/testing/mocks/zenstack-language"
|
|
115
115
|
} },
|
|
116
116
|
ssr: { noExternal: ["@zenstackhq/better-auth"] }
|
|
117
117
|
};
|
|
118
|
+
if (isolation === "database") config.test = {
|
|
119
|
+
fileParallelism: true,
|
|
120
|
+
isolate: true
|
|
121
|
+
};
|
|
122
|
+
return config;
|
|
118
123
|
}
|
|
119
|
-
};
|
|
124
|
+
});
|
|
120
125
|
/**
|
|
121
126
|
* Returns Vite plugins for Stratal tests running in the Cloudflare Workers (workerd) environment.
|
|
122
127
|
*
|
|
123
|
-
* Includes the cloudflare pool plugin and Stratal alias plugin.
|
|
124
|
-
*
|
|
128
|
+
* Includes the cloudflare pool plugin and Stratal alias plugin. Pass
|
|
129
|
+
* `database: { isolation: 'database' }` to give each test file its own
|
|
130
|
+
* database (cloned from a migrated template, dropped on teardown) and enable
|
|
131
|
+
* file parallelism. Use inside a project-level `plugins` array.
|
|
125
132
|
*
|
|
126
133
|
* **Note:** `fixPgCjs()` must be registered separately at the root `defineConfig` level.
|
|
127
134
|
*
|
|
128
|
-
* @param options -
|
|
135
|
+
* @param options - `cloudflareTest()` options plus Stratal `database` options
|
|
129
136
|
* @returns An array of Vite plugins
|
|
130
137
|
*/
|
|
131
138
|
function stratalTest(options = {}) {
|
|
132
|
-
|
|
139
|
+
const { database, ...cfOptions } = options;
|
|
140
|
+
const isolation = normalizeIsolation(database?.isolation);
|
|
141
|
+
const binding = database?.binding ?? "DB";
|
|
142
|
+
return [cloudflareTest({
|
|
143
|
+
...cfOptions,
|
|
144
|
+
miniflare: {
|
|
145
|
+
...cfOptions.miniflare,
|
|
146
|
+
bindings: {
|
|
147
|
+
...cfOptions.miniflare?.bindings,
|
|
148
|
+
[ISOLATION_ENV_VAR]: isolation,
|
|
149
|
+
[BINDING_ENV_VAR]: binding
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}), createStratalPlugin(isolation)];
|
|
133
153
|
}
|
|
134
154
|
//#endregion
|
|
135
155
|
export { fixNobleHashesCjs, fixPgCjs, stratalTest };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/vitest-plugin/stratal-test.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport path from 'node:path'\n\nimport { cloudflareTest } from '@cloudflare/vitest-pool-workers'\nimport type { Plugin, UserConfig } from 'vite'\n\nconst require = createRequire(import.meta.url)\n\ntype CloudflareTestOptions = Parameters<typeof cloudflareTest>[0]\n\nconst pgCjsResolvers = new Map<string, () => string>([\n ['pg-protocol', () => require.resolve('pg-protocol')],\n ['pg-connection-string', () => require.resolve('pg-connection-string')],\n ['pg-pool', () => require.resolve('pg-pool')],\n ['pg-cloudflare', () => path.join(path.dirname(require.resolve('pg-cloudflare')), 'index.js')],\n])\n\n/**\n * Returns a Vite plugin that forces CJS resolution for `pg` sub-dependencies.\n *\n * `pg` is CJS but its dependencies (`pg-protocol`, `pg-connection-string`, `pg-pool`) ship\n * dual CJS/ESM exports. In workerd, the module fallback resolver prefers the ESM condition,\n * causing `SyntaxError: Cannot use import statement outside a module` when CJS `pg` does\n * `require()`. Additionally, `pg-cloudflare` uses a `workerd` export condition that the\n * root Vite instance doesn't resolve.\n *\n * Must be used at the **root** `defineConfig` level so that the\n * `@cloudflare/vitest-pool-workers` module fallback resolver (which uses the root Vite\n * instance) resolves pg sub-deps correctly.\n *\n * @example\n * ```ts\n * import { fixPgCjs, stratalTest } from '@stratal/testing/vitest-plugin'\n * import { defineConfig } from 'vitest/config'\n *\n * export default defineConfig({\n * plugins: [fixPgCjs()],\n * test: {\n * projects: [{\n * plugins: [stratalTest({ wrangler: { configPath: './wrangler.jsonc' } })],\n * test: { name: 'e2e', include: ['test/e2e/**\\/*.spec.ts'] },\n * }],\n * },\n * })\n * ```\n */\nexport const fixPgCjs = (): Plugin => ({\n name: 'stratal-pg-cjs',\n enforce: 'pre',\n resolveId(id) {\n const resolver = pgCjsResolvers.get(id)\n if (!resolver) return\n try {\n return resolver()\n } catch {\n return\n }\n },\n})\n\n/**\n * Returns a Vite plugin that forces CJS resolution for `@noble/hashes` subpaths\n * used by `@paralleldrive/cuid2@2.x` (the version `@zenstackhq/orm` depends on).\n *\n * cuid2@2.x is CJS and does `require(\"@noble/hashes/sha3\")` without the `.js`\n * extension. In a workspace that also installs `@noble/hashes@2.x` (ESM-only),\n * the hoisted v2 package has no extensionless `./sha3` entry in its exports\n * map, so Vite/workerd resolution fails. This plugin routes the extensionless\n * subpaths through the consumer's nested `@noble/hashes@1.x` (a sibling of\n * cuid2 under `@zenstackhq/orm/node_modules`), which ships proper CJS exports.\n *\n * If the consumer doesn't depend on `@zenstackhq/orm`, the plugin is a no-op.\n * Otherwise it throws loudly at config-resolution time if the resolution chain\n * is unexpectedly broken — surfacing dependency drift instead of letting the\n * symptom resurface as an opaque test failure.\n *\n * Must be used at the **root** `defineConfig` level (same constraint as\n * `fixPgCjs`).\n *\n * @example\n * ```ts\n * import { fixNobleHashesCjs, fixPgCjs, stratalTest } from '@stratal/testing/vitest-plugin'\n *\n * export default defineConfig({\n * plugins: [fixPgCjs(), fixNobleHashesCjs()],\n * // ...\n * })\n * ```\n */\nexport const fixNobleHashesCjs = (): Plugin => {\n const ids = ['@noble/hashes/sha3', '@noble/hashes/crypto']\n let resolved: Map<string, string> | null = null\n\n return {\n name: 'stratal-noble-hashes-cjs',\n enforce: 'pre',\n configResolved(config) {\n const consumerRequire = createRequire(path.join(config.root, 'noop.js'))\n let zenstackPath: string\n try {\n zenstackPath = consumerRequire.resolve('@zenstackhq/orm')\n } catch {\n // Consumer doesn't use ZenStack — nothing to fix.\n return\n }\n const cuid2Path = createRequire(zenstackPath).resolve('@paralleldrive/cuid2')\n const cuid2Require = createRequire(cuid2Path)\n resolved = new Map<string, string>(\n ids.map((id) => [id, cuid2Require.resolve(id)]),\n )\n },\n resolveId(id) {\n return resolved?.get(id)\n },\n }\n}\n\nconst stratalPlugin: Plugin = {\n name: 'stratal-test',\n config() {\n return {\n resolve: {\n alias: {\n tslib: 'tslib/tslib.es6.mjs',\n '@zenstackhq/language/ast': '@stratal/testing/mocks/zenstack-language',\n '@zenstackhq/language/utils': '@stratal/testing/mocks/zenstack-language',\n '@zenstackhq/language': '@stratal/testing/mocks/zenstack-language',\n nodemailer: '@stratal/testing/mocks/nodemailer',\n },\n },\n ssr: {\n noExternal: ['@zenstackhq/better-auth'],\n },\n } satisfies UserConfig\n },\n}\n\n/**\n * Returns Vite plugins for Stratal tests running in the Cloudflare Workers (workerd) environment.\n *\n * Includes the cloudflare pool plugin and Stratal alias plugin.\n * Use inside a project-level `plugins` array.\n *\n * **Note:** `fixPgCjs()` must be registered separately at the root `defineConfig` level.\n *\n * @param options - Same options as `cloudflareTest()` from `@cloudflare/vitest-pool-workers`\n * @returns An array of Vite plugins\n */\nexport function stratalTest(options: CloudflareTestOptions = {}): Plugin[] {\n return [cloudflareTest(options) as unknown as Plugin, stratalPlugin]\n}\n"],"mappings":";;;;AAMA,MAAM,UAAU,cAAc,OAAO,KAAK,IAAI;AAI9C,MAAM,iBAAiB,IAAI,IAA0B;CACnD,CAAC,qBAAqB,QAAQ,QAAQ,cAAc,CAAC;CACrD,CAAC,8BAA8B,QAAQ,QAAQ,uBAAuB,CAAC;CACvE,CAAC,iBAAiB,QAAQ,QAAQ,UAAU,CAAC;CAC7C,CAAC,uBAAuB,KAAK,KAAK,KAAK,QAAQ,QAAQ,QAAQ,gBAAgB,CAAC,EAAE,WAAW,CAAC;CAC/F,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BF,MAAa,kBAA0B;CACrC,MAAM;CACN,SAAS;CACT,UAAU,IAAI;EACZ,MAAM,WAAW,eAAe,IAAI,GAAG;EACvC,IAAI,CAAC,UAAU;EACf,IAAI;GACF,OAAO,UAAU;UACX;GACN;;;CAGL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BD,MAAa,0BAAkC;CAC7C,MAAM,MAAM,CAAC,sBAAsB,uBAAuB;CAC1D,IAAI,WAAuC;CAE3C,OAAO;EACL,MAAM;EACN,SAAS;EACT,eAAe,QAAQ;GACrB,MAAM,kBAAkB,cAAc,KAAK,KAAK,OAAO,MAAM,UAAU,CAAC;GACxE,IAAI;GACJ,IAAI;IACF,eAAe,gBAAgB,QAAQ,kBAAkB;WACnD;IAEN;;GAGF,MAAM,eAAe,cADH,cAAc,aAAa,CAAC,QAAQ,uBACV,CAAC;GAC7C,WAAW,IAAI,IACb,IAAI,KAAK,OAAO,CAAC,IAAI,aAAa,QAAQ,GAAG,CAAC,CAAC,CAChD;;EAEH,UAAU,IAAI;GACZ,OAAO,UAAU,IAAI,GAAG;;EAE3B;;AAGH,MAAM,gBAAwB;CAC5B,MAAM;CACN,SAAS;EACP,OAAO;GACL,SAAS,EACP,OAAO;IACL,OAAO;IACP,4BAA4B;IAC5B,8BAA8B;IAC9B,wBAAwB;IACxB,YAAY;IACb,EACF;GACD,KAAK,EACH,YAAY,CAAC,0BAA0B,EACxC;GACF;;CAEJ;;;;;;;;;;;;AAaD,SAAgB,YAAY,UAAiC,EAAE,EAAY;CACzE,OAAO,CAAC,eAAe,QAAQ,EAAuB,cAAc"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/vitest-plugin/stratal-test.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport path from 'node:path'\n\nimport { cloudflareTest } from '@cloudflare/vitest-pool-workers'\nimport type { StratalEnv } from 'stratal'\nimport type { Plugin, UserConfig } from 'vite'\nimport type { TestUserConfig } from 'vitest/config'\nimport { BINDING_ENV_VAR, DEFAULT_DB_BINDING, ISOLATION_ENV_VAR, normalizeIsolation, type DatabaseIsolation } from '../database'\n\nconst require = createRequire(import.meta.url)\n\ntype CloudflareTestOptions = Parameters<typeof cloudflareTest>[0]\n\n/** String keys of `StratalEnv` whose value is a Hyperdrive binding. */\ntype HyperdriveKeys = Extract<\n { [K in keyof StratalEnv]-?: StratalEnv[K] extends Hyperdrive ? K : never }[keyof StratalEnv],\n string\n>\n\n/**\n * Names of declared Hyperdrive bindings, drawn from the consumer's augmented\n * `StratalEnv` (which extends `Cloudflare.Env`). Falls back to `string` only\n * when no Hyperdrive binding is declared (nothing to constrain to).\n */\ntype HyperdriveBindingName = [HyperdriveKeys] extends [never] ? string : HyperdriveKeys\n\n/** Stratal-specific test database configuration for {@link stratalTest}. */\nexport interface StratalTestDatabaseOptions {\n /**\n * Database isolation mode for parallel runs. Defaults to `'shared'`.\n *\n * - `'shared'` — all test files share one database (serial; today's behaviour).\n * - `'database'` — each test file gets its own database cloned from a migrated\n * template (dropped on teardown), and file parallelism is enabled.\n *\n * Pair with `createTestDatabaseGlobalSetup({ isolation })` from\n * `@stratal/testing/database` in your Vitest `globalSetup`.\n */\n isolation?: DatabaseIsolation\n /**\n * Name of the Hyperdrive binding to isolate per test file. Defaults to `'DB'`.\n * Constrained to Hyperdrive binding names declared on `Cloudflare.Env` /\n * `StratalEnv`.\n */\n binding?: HyperdriveBindingName\n}\n\ntype WorkersPoolOptions = Exclude<CloudflareTestOptions, (...args: never[]) => unknown>\ntype StratalTestOptions = WorkersPoolOptions & { database?: StratalTestDatabaseOptions }\n\nconst pgCjsResolvers = new Map<string, () => string>([\n ['pg-protocol', () => require.resolve('pg-protocol')],\n ['pg-connection-string', () => require.resolve('pg-connection-string')],\n ['pg-pool', () => require.resolve('pg-pool')],\n ['pg-cloudflare', () => path.join(path.dirname(require.resolve('pg-cloudflare')), 'index.js')],\n])\n\n/**\n * Returns a Vite plugin that forces CJS resolution for `pg` sub-dependencies.\n *\n * `pg` is CJS but its dependencies (`pg-protocol`, `pg-connection-string`, `pg-pool`) ship\n * dual CJS/ESM exports. In workerd, the module fallback resolver prefers the ESM condition,\n * causing `SyntaxError: Cannot use import statement outside a module` when CJS `pg` does\n * `require()`. Additionally, `pg-cloudflare` uses a `workerd` export condition that the\n * root Vite instance doesn't resolve.\n *\n * Must be used at the **root** `defineConfig` level so that the\n * `@cloudflare/vitest-pool-workers` module fallback resolver (which uses the root Vite\n * instance) resolves pg sub-deps correctly.\n *\n * @example\n * ```ts\n * import { fixPgCjs, stratalTest } from '@stratal/testing/vitest-plugin'\n * import { defineConfig } from 'vitest/config'\n *\n * export default defineConfig({\n * plugins: [fixPgCjs()],\n * test: {\n * projects: [{\n * plugins: [stratalTest({ wrangler: { configPath: './wrangler.jsonc' } })],\n * test: { name: 'e2e', include: ['test/e2e/**\\/*.spec.ts'] },\n * }],\n * },\n * })\n * ```\n */\nexport const fixPgCjs = (): Plugin => ({\n name: 'stratal-pg-cjs',\n enforce: 'pre',\n resolveId(id) {\n const resolver = pgCjsResolvers.get(id)\n if (!resolver) return\n try {\n return resolver()\n } catch {\n return\n }\n },\n})\n\n/**\n * Returns a Vite plugin that forces CJS resolution for `@noble/hashes` subpaths\n * used by `@paralleldrive/cuid2@2.x` (the version `@zenstackhq/orm` depends on).\n *\n * cuid2@2.x is CJS and does `require(\"@noble/hashes/sha3\")` without the `.js`\n * extension. In a workspace that also installs `@noble/hashes@2.x` (ESM-only),\n * the hoisted v2 package has no extensionless `./sha3` entry in its exports\n * map, so Vite/workerd resolution fails. This plugin routes the extensionless\n * subpaths through the consumer's nested `@noble/hashes@1.x` (a sibling of\n * cuid2 under `@zenstackhq/orm/node_modules`), which ships proper CJS exports.\n *\n * If the consumer doesn't depend on `@zenstackhq/orm`, the plugin is a no-op.\n * Otherwise it throws loudly at config-resolution time if the resolution chain\n * is unexpectedly broken — surfacing dependency drift instead of letting the\n * symptom resurface as an opaque test failure.\n *\n * Must be used at the **root** `defineConfig` level (same constraint as\n * `fixPgCjs`).\n *\n * @example\n * ```ts\n * import { fixNobleHashesCjs, fixPgCjs, stratalTest } from '@stratal/testing/vitest-plugin'\n *\n * export default defineConfig({\n * plugins: [fixPgCjs(), fixNobleHashesCjs()],\n * // ...\n * })\n * ```\n */\nexport const fixNobleHashesCjs = (): Plugin => {\n const ids = ['@noble/hashes/sha3', '@noble/hashes/crypto']\n let resolved: Map<string, string> | null = null\n\n return {\n name: 'stratal-noble-hashes-cjs',\n enforce: 'pre',\n configResolved(config) {\n const consumerRequire = createRequire(path.join(config.root, 'noop.js'))\n let zenstackPath: string\n try {\n zenstackPath = consumerRequire.resolve('@zenstackhq/orm')\n } catch {\n // Consumer doesn't use ZenStack — nothing to fix.\n return\n }\n const cuid2Path = createRequire(zenstackPath).resolve('@paralleldrive/cuid2')\n const cuid2Require = createRequire(cuid2Path)\n resolved = new Map<string, string>(\n ids.map((id) => [id, cuid2Require.resolve(id)]),\n )\n },\n resolveId(id) {\n return resolved?.get(id)\n },\n }\n}\n\nconst createStratalPlugin = (isolation: DatabaseIsolation): Plugin => ({\n name: 'stratal-test',\n config() {\n const config: UserConfig & { test?: TestUserConfig } = {\n resolve: {\n alias: {\n tslib: 'tslib/tslib.es6.mjs',\n '@zenstackhq/language/ast': '@stratal/testing/mocks/zenstack-language',\n '@zenstackhq/language/utils': '@stratal/testing/mocks/zenstack-language',\n '@zenstackhq/language': '@stratal/testing/mocks/zenstack-language',\n },\n },\n ssr: {\n noExternal: ['@zenstackhq/better-auth'],\n },\n }\n\n // In 'database' mode each test file owns its database, so enable file\n // parallelism + isolation. In 'shared' mode leave these untouched so the\n // project's own defaults stand (forcing them would alter maxWorkers and\n // can collide with sibling projects' sequence.groupOrder).\n if (isolation === 'database') {\n config.test = { fileParallelism: true, isolate: true }\n }\n\n return config\n },\n})\n\n/**\n * Returns Vite plugins for Stratal tests running in the Cloudflare Workers (workerd) environment.\n *\n * Includes the cloudflare pool plugin and Stratal alias plugin. Pass\n * `database: { isolation: 'database' }` to give each test file its own\n * database (cloned from a migrated template, dropped on teardown) and enable\n * file parallelism. Use inside a project-level `plugins` array.\n *\n * **Note:** `fixPgCjs()` must be registered separately at the root `defineConfig` level.\n *\n * @param options - `cloudflareTest()` options plus Stratal `database` options\n * @returns An array of Vite plugins\n */\nexport function stratalTest(options: StratalTestOptions = {}): Plugin[] {\n const { database, ...cfOptions } = options\n const isolation = normalizeIsolation(database?.isolation)\n const binding = database?.binding ?? DEFAULT_DB_BINDING\n\n // Expose the mode + binding name to the worker as env vars so\n // TestingModule.compile() can decide whether and what to provision.\n const merged = {\n ...cfOptions,\n miniflare: {\n ...cfOptions.miniflare,\n bindings: {\n ...(cfOptions.miniflare?.bindings as Record<string, unknown> | undefined),\n [ISOLATION_ENV_VAR]: isolation,\n [BINDING_ENV_VAR]: binding,\n },\n },\n }\n\n return [cloudflareTest(merged) as unknown as Plugin, createStratalPlugin(isolation)]\n}\n"],"mappings":";;;;;AASA,MAAM,UAAU,cAAc,OAAO,KAAK,GAAG;AAyC7C,MAAM,iBAAiB,IAAI,IAA0B;CACnD,CAAC,qBAAqB,QAAQ,QAAQ,aAAa,CAAC;CACpD,CAAC,8BAA8B,QAAQ,QAAQ,sBAAsB,CAAC;CACtE,CAAC,iBAAiB,QAAQ,QAAQ,SAAS,CAAC;CAC5C,CAAC,uBAAuB,KAAK,KAAK,KAAK,QAAQ,QAAQ,QAAQ,eAAe,CAAC,GAAG,UAAU,CAAC;AAC/F,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BD,MAAa,kBAA0B;CACrC,MAAM;CACN,SAAS;CACT,UAAU,IAAI;EACZ,MAAM,WAAW,eAAe,IAAI,EAAE;EACtC,IAAI,CAAC,UAAU;EACf,IAAI;GACF,OAAO,SAAS;EAClB,QAAQ;GACN;EACF;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,0BAAkC;CAC7C,MAAM,MAAM,CAAC,sBAAsB,sBAAsB;CACzD,IAAI,WAAuC;CAE3C,OAAO;EACL,MAAM;EACN,SAAS;EACT,eAAe,QAAQ;GACrB,MAAM,kBAAkB,cAAc,KAAK,KAAK,OAAO,MAAM,SAAS,CAAC;GACvE,IAAI;GACJ,IAAI;IACF,eAAe,gBAAgB,QAAQ,iBAAiB;GAC1D,QAAQ;IAEN;GACF;GAEA,MAAM,eAAe,cADH,cAAc,YAAY,EAAE,QAAQ,sBACX,CAAC;GAC5C,WAAW,IAAI,IACb,IAAI,KAAK,OAAO,CAAC,IAAI,aAAa,QAAQ,EAAE,CAAC,CAAC,CAChD;EACF;EACA,UAAU,IAAI;GACZ,OAAO,UAAU,IAAI,EAAE;EACzB;CACF;AACF;AAEA,MAAM,uBAAuB,eAA0C;CACrE,MAAM;CACN,SAAS;EACP,MAAM,SAAiD;GACrD,SAAS,EACP,OAAO;IACL,OAAO;IACP,4BAA4B;IAC5B,8BAA8B;IAC9B,wBAAwB;GAC1B,EACF;GACA,KAAK,EACH,YAAY,CAAC,yBAAyB,EACxC;EACF;EAMA,IAAI,cAAc,YAChB,OAAO,OAAO;GAAE,iBAAiB;GAAM,SAAS;EAAK;EAGvD,OAAO;CACT;AACF;;;;;;;;;;;;;;AAeA,SAAgB,YAAY,UAA8B,CAAC,GAAa;CACtE,MAAM,EAAE,UAAU,GAAG,cAAc;CACnC,MAAM,YAAY,mBAAmB,UAAU,SAAS;CACxD,MAAM,UAAU,UAAU,WAAA;CAgB1B,OAAO,CAAC,eAAe;EAXrB,GAAG;EACH,WAAW;GACT,GAAG,UAAU;GACb,UAAU;IACR,GAAI,UAAU,WAAW;KACxB,oBAAoB;KACpB,kBAAkB;GACrB;EACF;CAG0B,CAAC,GAAwB,oBAAoB,SAAS,CAAC;AACrF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratal/testing",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"description": "Testing utilities and mocks for Stratal framework applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,14 +37,18 @@
|
|
|
37
37
|
"types": "./dist/index.d.mts",
|
|
38
38
|
"import": "./dist/index.mjs"
|
|
39
39
|
},
|
|
40
|
+
"./database": {
|
|
41
|
+
"types": "./dist/database/index.d.mts",
|
|
42
|
+
"import": "./dist/database/index.mjs"
|
|
43
|
+
},
|
|
44
|
+
"./feature-flags": {
|
|
45
|
+
"types": "./dist/feature-flags/index.d.mts",
|
|
46
|
+
"import": "./dist/feature-flags/index.mjs"
|
|
47
|
+
},
|
|
40
48
|
"./mocks": {
|
|
41
49
|
"types": "./dist/mocks/index.d.mts",
|
|
42
50
|
"import": "./dist/mocks/index.mjs"
|
|
43
51
|
},
|
|
44
|
-
"./mocks/nodemailer": {
|
|
45
|
-
"types": "./dist/mocks/nodemailer.d.mts",
|
|
46
|
-
"import": "./dist/mocks/nodemailer.mjs"
|
|
47
|
-
},
|
|
48
52
|
"./mocks/zenstack-language": {
|
|
49
53
|
"types": "./dist/mocks/zenstack-language.d.mts",
|
|
50
54
|
"import": "./dist/mocks/zenstack-language.mjs"
|
|
@@ -66,14 +70,15 @@
|
|
|
66
70
|
"lint:fix": "npx oxlint --fix ."
|
|
67
71
|
},
|
|
68
72
|
"dependencies": {
|
|
69
|
-
"@cloudflare/vitest-pool-workers": "^0.16.
|
|
73
|
+
"@cloudflare/vitest-pool-workers": "^0.16.12",
|
|
70
74
|
"@golevelup/ts-vitest": "^4.0.0",
|
|
71
|
-
"msw": "^2.14.
|
|
75
|
+
"msw": "^2.14.6"
|
|
72
76
|
},
|
|
73
77
|
"peerDependencies": {
|
|
74
|
-
"@stratal/framework": ">=0.0.
|
|
78
|
+
"@stratal/framework": ">=0.0.23",
|
|
75
79
|
"better-auth": ">=1.4",
|
|
76
|
-
"
|
|
80
|
+
"pg": "^8.0.0",
|
|
81
|
+
"stratal": ">=0.0.23",
|
|
77
82
|
"vitest": "^4.1.0"
|
|
78
83
|
},
|
|
79
84
|
"peerDependenciesMeta": {
|
|
@@ -82,18 +87,23 @@
|
|
|
82
87
|
},
|
|
83
88
|
"better-auth": {
|
|
84
89
|
"optional": true
|
|
90
|
+
},
|
|
91
|
+
"pg": {
|
|
92
|
+
"optional": true
|
|
85
93
|
}
|
|
86
94
|
},
|
|
87
95
|
"devDependencies": {
|
|
88
|
-
"@cloudflare/workers-types": "4.
|
|
96
|
+
"@cloudflare/workers-types": "4.20260603.1",
|
|
89
97
|
"@stratal/framework": "workspace:*",
|
|
90
|
-
"@types/node": "^25.
|
|
91
|
-
"@
|
|
92
|
-
"@vitest/
|
|
93
|
-
"
|
|
98
|
+
"@types/node": "^25.9.1",
|
|
99
|
+
"@types/pg": "^8.20.0",
|
|
100
|
+
"@vitest/runner": "~4.1.8",
|
|
101
|
+
"@vitest/snapshot": "~4.1.8",
|
|
102
|
+
"better-auth": "^1.6.14",
|
|
103
|
+
"pg": "^8.21.0",
|
|
94
104
|
"stratal": "workspace:*",
|
|
95
|
-
"tsdown": "^0.22.
|
|
105
|
+
"tsdown": "^0.22.1",
|
|
96
106
|
"typescript": "^6.0.3",
|
|
97
|
-
"vitest": "~4.1.
|
|
107
|
+
"vitest": "~4.1.8"
|
|
98
108
|
}
|
|
99
109
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-D-Q2cR2v.d.mts","names":[],"sources":["../src/storage/fake-storage.service.ts"],"mappings":";;;;;AAkBA;UAAiB,UAAA;EACf,OAAA,EAAS,UAAA;EACT,QAAA;EACA,IAAA;EACA,QAAA,GAAW,MAAA;EACX,UAAA,EAAY,IAAA;AAAA;;;;;;;;;;;AAoBd;;;;;;;cACa,kBAAA,SAA2B,cAAA;EAAA,mBAKjB,cAAA,EAAgB,qBAAA;EAAA,mBAEhB,OAAA,EAAS,aAAA;EAAA,QANtB,KAAA;cAIa,cAAA,EAAgB,qBAAA,EAEhB,OAAA,EAAS,aAAA;EAsCN;;;EA9BlB,MAAA,CACJ,IAAA,EAAM,8BAAA,EACN,YAAA,UACA,OAAA,EAAS,aAAA,EACT,IAAA,YACC,OAAA,CAAQ,YAAA;EAoER;;;EA3CH,QAAA,CAAS,IAAA,WAAe,OAAA,CAAQ,cAAA;EA+D7B;;;EAtCH,MAAA,CAAO,IAAA,WAAe,OAAA;EAkDX;;;EA1CX,MAAA,CAAO,IAAA,WAAe,OAAA;EAyHC;;;EAlHvB,uBAAA,CACE,IAAA,UACA,SAAA,YACC,OAAA,CAAQ,kBAAA;EAxF2B;;;EA+FtC,qBAAA,CACE,IAAA,UACA,SAAA,YACC,OAAA,CAAQ,kBAAA;EA3FmB;;;EAkG9B,qBAAA,CACE,IAAA,UACA,SAAA,YACC,OAAA,CAAQ,kBAAA;EAvGU;;;EA8Gf,aAAA,CACJ,IAAA,EAAM,8BAAA,EACN,IAAA,UACA,OAAA,EAAS,IAAA,CAAK,aAAA;IAA2B,IAAA;EAAA,GACzC,IAAA,YACC,OAAA,CAAQ,YAAA;EAvGT;;;;;;EAwHF,YAAA,CAAa,IAAA;EA5FJ;;;;;;EAyGT,aAAA,CAAc,IAAA;EAxEP;;;;;EAoFP,WAAA,CAAA;EA1EW;;;;;;EAuFX,WAAA,CAAY,KAAA;EArEV;;;EA+EF,cAAA,CAAA,GAAkB,GAAA,SAAY,UAAA;EAtExB;;;EA6EN,cAAA,CAAA;EA1EW;;;EAiFX,OAAA,CAAQ,IAAA,WAAe,UAAA;EAhFrB;;;EAuFF,KAAA,CAAA;EAAA,QAQQ,kBAAA;EAAA,QAeM,gBAAA;AAAA"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
//#region src/mocks/nodemailer.d.ts
|
|
2
|
-
declare const _default: {
|
|
3
|
-
createTransport: () => {
|
|
4
|
-
sendMail: () => Promise<{}>;
|
|
5
|
-
};
|
|
6
|
-
};
|
|
7
|
-
declare const createTransport: () => {
|
|
8
|
-
sendMail: () => Promise<{}>;
|
|
9
|
-
};
|
|
10
|
-
//#endregion
|
|
11
|
-
export { createTransport, _default as default };
|
|
12
|
-
//# sourceMappingURL=nodemailer.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nodemailer.d.mts","names":[],"sources":["../../src/mocks/nodemailer.ts"],"mappings":";;;;;;cAMa,eAAA;kBAEX,OAAA;AAAA"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
//#region src/mocks/nodemailer.ts
|
|
2
|
-
var nodemailer_default = { createTransport: () => ({ sendMail: () => Promise.resolve({}) }) };
|
|
3
|
-
const createTransport = () => ({ sendMail: () => Promise.resolve({}) });
|
|
4
|
-
//#endregion
|
|
5
|
-
export { createTransport, nodemailer_default as default };
|
|
6
|
-
|
|
7
|
-
//# sourceMappingURL=nodemailer.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nodemailer.mjs","names":[],"sources":["../../src/mocks/nodemailer.ts"],"sourcesContent":["export default {\n createTransport: () => ({\n sendMail: () => Promise.resolve({}),\n }),\n}\n\nexport const createTransport = () => ({\n sendMail: () => Promise.resolve({}),\n})\n"],"mappings":";AAAA,IAAA,qBAAe,EACb,wBAAwB,EACtB,gBAAgB,QAAQ,QAAQ,EAAE,CAAC,EACpC,GACF;AAED,MAAa,yBAAyB,EACpC,gBAAgB,QAAQ,QAAQ,EAAE,CAAC,EACpC"}
|