@ishibashi0112/webview2-bridge-test 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/bridge.d.ts +34 -0
  4. package/dist/bridge.d.ts.map +1 -0
  5. package/dist/bridge.js +72 -0
  6. package/dist/bridge.js.map +1 -0
  7. package/dist/cli.d.ts +4 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +166 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/clipboard.d.ts +2 -0
  12. package/dist/clipboard.d.ts.map +1 -0
  13. package/dist/clipboard.js +39 -0
  14. package/dist/clipboard.js.map +1 -0
  15. package/dist/config.d.ts +106 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +65 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/db/diff.d.ts +29 -0
  20. package/dist/db/diff.d.ts.map +1 -0
  21. package/dist/db/diff.js +76 -0
  22. package/dist/db/diff.js.map +1 -0
  23. package/dist/db/env.d.ts +19 -0
  24. package/dist/db/env.d.ts.map +1 -0
  25. package/dist/db/env.js +119 -0
  26. package/dist/db/env.js.map +1 -0
  27. package/dist/db/guard.d.ts +28 -0
  28. package/dist/db/guard.d.ts.map +1 -0
  29. package/dist/db/guard.js +68 -0
  30. package/dist/db/guard.js.map +1 -0
  31. package/dist/db/index.d.ts +72 -0
  32. package/dist/db/index.d.ts.map +1 -0
  33. package/dist/db/index.js +120 -0
  34. package/dist/db/index.js.map +1 -0
  35. package/dist/fixtures.d.ts +25 -0
  36. package/dist/fixtures.d.ts.map +1 -0
  37. package/dist/fixtures.js +167 -0
  38. package/dist/fixtures.js.map +1 -0
  39. package/dist/host.d.ts +41 -0
  40. package/dist/host.d.ts.map +1 -0
  41. package/dist/host.js +154 -0
  42. package/dist/host.js.map +1 -0
  43. package/dist/index.d.ts +9 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +9 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/reporter.d.ts +42 -0
  48. package/dist/reporter.d.ts.map +1 -0
  49. package/dist/reporter.js +221 -0
  50. package/dist/reporter.js.map +1 -0
  51. package/package.json +82 -0
@@ -0,0 +1,29 @@
1
+ /**
2
+ * テーブル行の「前後差分」を取る純粋関数。DB を知らない(Knex から取った行配列だけを扱う)。
3
+ * キー列で行を同定し、inserted / updated / deleted に分ける。updated は変わった列だけを before / after で返す。
4
+ */
5
+ export type Row = Record<string, unknown>;
6
+ export interface UpdatedRow {
7
+ key: Row;
8
+ before: Row;
9
+ after: Row;
10
+ /** 変わった列だけ */
11
+ changed: Record<string, {
12
+ before: unknown;
13
+ after: unknown;
14
+ }>;
15
+ }
16
+ export interface TableDiff {
17
+ inserted: Row[];
18
+ updated: UpdatedRow[];
19
+ deleted: Row[];
20
+ }
21
+ /** 値を比較可能な形に正規化する(Date → ISO 文字列、Buffer → base64、bigint → 文字列) */
22
+ export declare function normalizeValue(value: unknown): unknown;
23
+ /** キー列の値を連結した文字列(Map のキーに使う) */
24
+ export declare function keyOf(row: Row, key: readonly string[]): string;
25
+ export declare function pickKey(row: Row, key: readonly string[]): Row;
26
+ export declare function diffRows(before: readonly Row[], after: readonly Row[], key: readonly string[]): TableDiff;
27
+ /** レポート向けの 1 行要約 */
28
+ export declare function summarizeDiff(diff: TableDiff): string;
29
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/db/diff.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,GAAG,CAAC;IACZ,KAAK,EAAE,GAAG,CAAC;IACX,cAAc;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,GAAG,EAAE,CAAC;CAChB;AAED,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOtD;AAED,gCAAgC;AAChC,wBAAgB,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAE9D;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAI7D;AAYD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAyBzG;AAED,oBAAoB;AACpB,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAErD"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * テーブル行の「前後差分」を取る純粋関数。DB を知らない(Knex から取った行配列だけを扱う)。
3
+ * キー列で行を同定し、inserted / updated / deleted に分ける。updated は変わった列だけを before / after で返す。
4
+ */
5
+ /** 値を比較可能な形に正規化する(Date → ISO 文字列、Buffer → base64、bigint → 文字列) */
6
+ export function normalizeValue(value) {
7
+ if (value === undefined)
8
+ return null;
9
+ if (value instanceof Date)
10
+ return Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
11
+ if (typeof value === "bigint")
12
+ return value.toString();
13
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(value))
14
+ return `base64:${value.toString("base64")}`;
15
+ if (value instanceof Uint8Array)
16
+ return `base64:${Buffer.from(value).toString("base64")}`;
17
+ return value;
18
+ }
19
+ /** キー列の値を連結した文字列(Map のキーに使う) */
20
+ export function keyOf(row, key) {
21
+ return JSON.stringify(key.map((k) => normalizeValue(row[k])));
22
+ }
23
+ export function pickKey(row, key) {
24
+ const out = {};
25
+ for (const k of key)
26
+ out[k] = row[k];
27
+ return out;
28
+ }
29
+ function sameValue(a, b) {
30
+ const na = normalizeValue(a);
31
+ const nb = normalizeValue(b);
32
+ if (na === nb)
33
+ return true;
34
+ // 数値と数値文字列(Oracle の NUMBER など)は同じとみなす
35
+ if (typeof na === "number" && typeof nb === "string" && nb.trim() !== "" && Number(nb) === na)
36
+ return true;
37
+ if (typeof nb === "number" && typeof na === "string" && na.trim() !== "" && Number(na) === nb)
38
+ return true;
39
+ return JSON.stringify(na) === JSON.stringify(nb);
40
+ }
41
+ export function diffRows(before, after, key) {
42
+ if (key.length === 0)
43
+ throw new Error("diffRows: key columns are required");
44
+ const beforeMap = new Map();
45
+ for (const row of before)
46
+ beforeMap.set(keyOf(row, key), row);
47
+ const result = { inserted: [], updated: [], deleted: [] };
48
+ const seen = new Set();
49
+ for (const row of after) {
50
+ const k = keyOf(row, key);
51
+ seen.add(k);
52
+ const prev = beforeMap.get(k);
53
+ if (prev === undefined) {
54
+ result.inserted.push(row);
55
+ continue;
56
+ }
57
+ const changed = {};
58
+ const columns = new Set([...Object.keys(prev), ...Object.keys(row)]);
59
+ for (const col of columns) {
60
+ if (!sameValue(prev[col], row[col]))
61
+ changed[col] = { before: prev[col], after: row[col] };
62
+ }
63
+ if (Object.keys(changed).length > 0)
64
+ result.updated.push({ key: pickKey(row, key), before: prev, after: row, changed });
65
+ }
66
+ for (const [k, row] of beforeMap) {
67
+ if (!seen.has(k))
68
+ result.deleted.push(row);
69
+ }
70
+ return result;
71
+ }
72
+ /** レポート向けの 1 行要約 */
73
+ export function summarizeDiff(diff) {
74
+ return `inserted ${diff.inserted.length} / updated ${diff.updated.length} / deleted ${diff.deleted.length}`;
75
+ }
76
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/db/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type DbClient } from "./guard.js";
2
+ export interface KnexLikeConfig {
3
+ client: DbClient;
4
+ connection: Record<string, unknown>;
5
+ useNullAsDefault?: boolean;
6
+ pool?: {
7
+ min: number;
8
+ max: number;
9
+ };
10
+ }
11
+ export declare const DEFAULT_ENV_FILES: readonly [".env.e2e.local", ".env.e2e"];
12
+ /** env ファイルを読み、未設定の変数だけ target に入れる。読んだファイルのパスを返す */
13
+ export declare function loadEnvFiles(baseDir: string, files?: readonly string[], target?: NodeJS.ProcessEnv): string[];
14
+ export declare class DbEnvError extends Error {
15
+ name: string;
16
+ }
17
+ /** 環境変数から Knex の設定を作る。E2E_DB_CLIENT が無ければ undefined(DB なしで動く) */
18
+ export declare function knexConfigFromEnv(env?: NodeJS.ProcessEnv): KnexLikeConfig | undefined;
19
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/db/env.ts"],"names":[],"mappings":"AAaA,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,QAAQ,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC;AAED,eAAO,MAAM,iBAAiB,yCAA0C,CAAC;AAEzE,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,SAAS,MAAM,EAAsB,EAAE,MAAM,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,EAAE,CAY7I;AAeD,qBAAa,UAAW,SAAQ,KAAK;IAC1B,IAAI,SAAgB;CAC9B;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,cAAc,GAAG,SAAS,CAmElG"}
package/dist/db/env.js ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * `.env.e2e.local` / `.env.e2e` と環境変数から Knex の接続設定を組み立てる。
3
+ * 依存を増やさないため Node 標準の util.parseEnv を使う。既にある環境変数は上書きしない(dotenv と同じ)。
4
+ *
5
+ * E2E_DB_CLIENT mssql | oracledb | pg | mysql2 | better-sqlite3
6
+ * E2E_DB_HOST / E2E_DB_PORT / E2E_DB_USER / E2E_DB_PASSWORD / E2E_DB_DATABASE
7
+ * E2E_DB_CONNECT_STRING Oracle 用(省略時は host:port/database から組み立てる)
8
+ * E2E_DB_FILENAME sqlite 用
9
+ * E2E_DB_OPTIONS JSON。接続オブジェクトに深くマージする(例: {"options":{"encrypt":false}})
10
+ */
11
+ import { existsSync, readFileSync } from "node:fs";
12
+ import path from "node:path";
13
+ import { parseEnv } from "node:util";
14
+ import { isDbClient } from "./guard.js";
15
+ export const DEFAULT_ENV_FILES = [".env.e2e.local", ".env.e2e"];
16
+ /** env ファイルを読み、未設定の変数だけ target に入れる。読んだファイルのパスを返す */
17
+ export function loadEnvFiles(baseDir, files = DEFAULT_ENV_FILES, target = process.env) {
18
+ const loaded = [];
19
+ for (const file of files) {
20
+ const full = path.resolve(baseDir, file);
21
+ if (!existsSync(full))
22
+ continue;
23
+ const parsed = parseEnv(readFileSync(full, "utf8"));
24
+ for (const [k, v] of Object.entries(parsed)) {
25
+ if (target[k] === undefined)
26
+ target[k] = v;
27
+ }
28
+ loaded.push(full);
29
+ }
30
+ return loaded;
31
+ }
32
+ function isRecord(value) {
33
+ return typeof value === "object" && value !== null && !Array.isArray(value);
34
+ }
35
+ function deepMerge(base, extra) {
36
+ const out = { ...base };
37
+ for (const [k, v] of Object.entries(extra)) {
38
+ const cur = out[k];
39
+ out[k] = isRecord(cur) && isRecord(v) ? deepMerge(cur, v) : v;
40
+ }
41
+ return out;
42
+ }
43
+ export class DbEnvError extends Error {
44
+ name = "DbEnvError";
45
+ }
46
+ /** 環境変数から Knex の設定を作る。E2E_DB_CLIENT が無ければ undefined(DB なしで動く) */
47
+ export function knexConfigFromEnv(env = process.env) {
48
+ const client = env["E2E_DB_CLIENT"]?.trim();
49
+ if (client === undefined || client === "")
50
+ return undefined;
51
+ if (!isDbClient(client)) {
52
+ throw new DbEnvError(`E2E_DB_CLIENT=${client} は未対応です(mssql | oracledb | pg | mysql2 | better-sqlite3)`);
53
+ }
54
+ const host = env["E2E_DB_HOST"];
55
+ const port = env["E2E_DB_PORT"] !== undefined && env["E2E_DB_PORT"] !== "" ? Number(env["E2E_DB_PORT"]) : undefined;
56
+ if (port !== undefined && !Number.isInteger(port))
57
+ throw new DbEnvError(`E2E_DB_PORT=${env["E2E_DB_PORT"]} は整数ではありません`);
58
+ const user = env["E2E_DB_USER"];
59
+ const password = env["E2E_DB_PASSWORD"];
60
+ const database = env["E2E_DB_DATABASE"];
61
+ let options = {};
62
+ if (env["E2E_DB_OPTIONS"] !== undefined && env["E2E_DB_OPTIONS"].trim() !== "") {
63
+ let parsed;
64
+ try {
65
+ parsed = JSON.parse(env["E2E_DB_OPTIONS"]);
66
+ }
67
+ catch (e) {
68
+ throw new DbEnvError(`E2E_DB_OPTIONS が JSON として読めません: ${e instanceof Error ? e.message : String(e)}`);
69
+ }
70
+ if (!isRecord(parsed))
71
+ throw new DbEnvError("E2E_DB_OPTIONS は JSON オブジェクトで指定してください");
72
+ options = parsed;
73
+ }
74
+ const required = (name, value) => {
75
+ if (value === undefined || value === "")
76
+ throw new DbEnvError(`${name} が設定されていません(.env.e2e.local を確認してください)`);
77
+ return value;
78
+ };
79
+ let connection;
80
+ const config = { client, connection: {}, pool: { min: 0, max: 2 } };
81
+ switch (client) {
82
+ case "mssql":
83
+ connection = {
84
+ server: required("E2E_DB_HOST", host),
85
+ ...(port !== undefined && { port }),
86
+ user: required("E2E_DB_USER", user),
87
+ password: password ?? "",
88
+ database: required("E2E_DB_DATABASE", database),
89
+ // 社内の SQL Server は自己署名証明書が多い。encrypt は E2E_DB_OPTIONS で明示できる
90
+ options: { trustServerCertificate: true },
91
+ };
92
+ break;
93
+ case "oracledb": {
94
+ const connectString = env["E2E_DB_CONNECT_STRING"] !== undefined && env["E2E_DB_CONNECT_STRING"] !== ""
95
+ ? env["E2E_DB_CONNECT_STRING"]
96
+ : `${required("E2E_DB_HOST", host)}:${port ?? 1521}/${required("E2E_DB_DATABASE", database)}`;
97
+ connection = { user: required("E2E_DB_USER", user), password: password ?? "", connectString };
98
+ break;
99
+ }
100
+ case "pg":
101
+ case "mysql2":
102
+ connection = {
103
+ host: required("E2E_DB_HOST", host),
104
+ ...(port !== undefined && { port }),
105
+ user: required("E2E_DB_USER", user),
106
+ password: password ?? "",
107
+ database: required("E2E_DB_DATABASE", database),
108
+ };
109
+ break;
110
+ case "better-sqlite3":
111
+ connection = { filename: required("E2E_DB_FILENAME", env["E2E_DB_FILENAME"]) };
112
+ config.useNullAsDefault = true;
113
+ delete config.pool;
114
+ break;
115
+ }
116
+ config.connection = deepMerge(connection, options);
117
+ return config;
118
+ }
119
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/db/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 本番 DB に向けてテストが走らないためのガード。
3
+ * 接続設定から「どの DB か」を 1 つの文字列に要約し、許可リスト(allowedDatabases)と照合する。
4
+ * 許可リストの各項目は、DB 名(大文字小文字を区別しない)か `host/DB名` のどちらかに一致すればよい。
5
+ */
6
+ export type DbClient = "mssql" | "oracledb" | "pg" | "mysql2" | "better-sqlite3";
7
+ export interface ConnectionDescription {
8
+ client: DbClient;
9
+ /** DB 名(sqlite はファイル名、Oracle はサービス名) */
10
+ database: string;
11
+ host?: string | undefined;
12
+ /** 人が読む用: client host/database */
13
+ label: string;
14
+ }
15
+ export declare function isDbClient(value: unknown): value is DbClient;
16
+ /** Oracle の connectString(`host:port/service` や `host/service`、tnsnames の別名)からサービス名を取り出す */
17
+ export declare function oracleServiceName(connectString: string): {
18
+ host?: string | undefined;
19
+ service: string;
20
+ };
21
+ export declare function describeConnection(client: DbClient, connection: Record<string, unknown>): ConnectionDescription;
22
+ export interface GuardResult {
23
+ ok: boolean;
24
+ description: ConnectionDescription;
25
+ reason?: string;
26
+ }
27
+ export declare function checkAllowed(description: ConnectionDescription, allowedDatabases: readonly string[]): GuardResult;
28
+ //# sourceMappingURL=guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/db/guard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,IAAI,GAAG,QAAQ,GAAG,gBAAgB,CAAC;AAEjF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,QAAQ,CAAC;IACjB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAMD,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAMvG;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,qBAAqB,CAuB/G;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,qBAAqB,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,WAAW,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CAoBjH"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * 本番 DB に向けてテストが走らないためのガード。
3
+ * 接続設定から「どの DB か」を 1 つの文字列に要約し、許可リスト(allowedDatabases)と照合する。
4
+ * 許可リストの各項目は、DB 名(大文字小文字を区別しない)か `host/DB名` のどちらかに一致すればよい。
5
+ */
6
+ export function isDbClient(value) {
7
+ return value === "mssql" || value === "oracledb" || value === "pg" || value === "mysql2" || value === "better-sqlite3";
8
+ }
9
+ function str(value) {
10
+ return typeof value === "string" && value !== "" ? value : undefined;
11
+ }
12
+ /** Oracle の connectString(`host:port/service` や `host/service`、tnsnames の別名)からサービス名を取り出す */
13
+ export function oracleServiceName(connectString) {
14
+ const slash = connectString.lastIndexOf("/");
15
+ if (slash < 0)
16
+ return { service: connectString };
17
+ const hostPort = connectString.slice(0, slash);
18
+ const colon = hostPort.indexOf(":");
19
+ return { host: colon >= 0 ? hostPort.slice(0, colon) : hostPort, service: connectString.slice(slash + 1) };
20
+ }
21
+ export function describeConnection(client, connection) {
22
+ switch (client) {
23
+ case "mssql": {
24
+ const host = str(connection["server"]) ?? str(connection["host"]);
25
+ const database = str(connection["database"]) ?? "";
26
+ return { client, database, host, label: `${client} ${host ?? "?"}/${database || "?"}` };
27
+ }
28
+ case "oracledb": {
29
+ const cs = str(connection["connectString"]) ?? "";
30
+ const { host, service } = oracleServiceName(cs);
31
+ return { client, database: service, host, label: `${client} ${cs || "?"}` };
32
+ }
33
+ case "pg":
34
+ case "mysql2": {
35
+ const host = str(connection["host"]);
36
+ const database = str(connection["database"]) ?? "";
37
+ return { client, database, host, label: `${client} ${host ?? "?"}/${database || "?"}` };
38
+ }
39
+ case "better-sqlite3": {
40
+ const database = str(connection["filename"]) ?? "";
41
+ return { client, database, label: `${client} ${database || "?"}` };
42
+ }
43
+ }
44
+ }
45
+ export function checkAllowed(description, allowedDatabases) {
46
+ if (allowedDatabases.length === 0) {
47
+ return { ok: false, description, reason: "allowedDatabases が空です。テスト DB の名前を e2e.config.ts の db.allowedDatabases に書いてください(本番 DB に向けて走らせないためのガードです)" };
48
+ }
49
+ const db = description.database.toLowerCase();
50
+ const hostDb = description.host !== undefined ? `${description.host.toLowerCase()}/${db}` : undefined;
51
+ for (const entry of allowedDatabases) {
52
+ const e = entry.trim().toLowerCase();
53
+ if (e === "")
54
+ continue;
55
+ if (e === db || (hostDb !== undefined && e === hostDb))
56
+ return { ok: true, description };
57
+ // sqlite はファイル名の末尾一致も許す(相対 / 絶対の差を吸収)
58
+ if (description.client === "better-sqlite3" && (db.endsWith(e) || db.endsWith(`/${e}`) || db.endsWith(`\\${e}`))) {
59
+ return { ok: true, description };
60
+ }
61
+ }
62
+ return {
63
+ ok: false,
64
+ description,
65
+ reason: `接続先 ${description.label} は allowedDatabases [${allowedDatabases.join(", ")}] に含まれていません。テスト DB ではない可能性があるため停止します`,
66
+ };
67
+ }
68
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/db/guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * テスト本文に `db` として渡る DB ヘルパ。Knex を薄く包み、方言は Knex に任せる。
3
+ * - insert で入れた行と、diff で「増えた」と判定した行を記録し、cleanup() で逆順に削除する(後片付け)
4
+ * - snapshot / diff はテーブル行の前後比較(db/diff.ts の純粋関数)
5
+ */
6
+ import type { Knex } from "knex";
7
+ import { diffRows, summarizeDiff, type Row, type TableDiff } from "./diff.js";
8
+ export interface SnapshotSpec {
9
+ table: string;
10
+ /** 行を同定するキー列 */
11
+ key: string[];
12
+ /** 絞り込み(通常は testId 接頭辞)。省略すると全行(maxRows で打ち切り) */
13
+ where?: Row | ((qb: Knex.QueryBuilder) => Knex.QueryBuilder) | undefined;
14
+ }
15
+ export interface TableSnapshot {
16
+ spec: SnapshotSpec;
17
+ rows: Row[];
18
+ /** maxRows を超えて打ち切った(diff は信頼できない) */
19
+ truncated: boolean;
20
+ }
21
+ export interface DbSnapshot {
22
+ takenAt: string;
23
+ tables: Record<string, TableSnapshot>;
24
+ }
25
+ export type DbDiff = Record<string, TableDiff>;
26
+ export interface CleanupEntry {
27
+ table: string;
28
+ where: Row;
29
+ /** 何によって記録されたか */
30
+ source: "insert" | "diff";
31
+ }
32
+ export interface CleanupFailure extends CleanupEntry {
33
+ error: string;
34
+ }
35
+ export interface CleanupResult {
36
+ deleted: number;
37
+ failures: CleanupFailure[];
38
+ }
39
+ export interface DbOptions {
40
+ /** snapshot で where を省略したときに読む最大行数(既定 5000) */
41
+ maxRows?: number | undefined;
42
+ /** diff を取ったときに呼ばれる(レポート添付用) */
43
+ onDiff?: ((diff: DbDiff, snapshot: DbSnapshot) => void | Promise<void>) | undefined;
44
+ /** snapshot の where 省略など、注意事項を受け取る */
45
+ onWarning?: ((message: string) => void) | undefined;
46
+ }
47
+ export interface Db {
48
+ /** 生の Knex。ヘルパに無いことをするとき用 */
49
+ readonly knex: Knex;
50
+ /** 生 SQL(読み取り用)。バインドは `?` */
51
+ query<T extends Row = Row>(sql: string, params?: readonly unknown[]): Promise<T[]>;
52
+ /** 前提行を入れる。後片付けの対象に記録する(行の全列を where にして削除する) */
53
+ insert(table: string, row: Row): Promise<void>;
54
+ insertMany(table: string, rows: readonly Row[]): Promise<void>;
55
+ /** 条件に合う行を取る */
56
+ rows<T extends Row = Row>(table: string, where?: Row): Promise<T[]>;
57
+ /** 現在の行を控える */
58
+ snapshot(specs: readonly SnapshotSpec[]): Promise<DbSnapshot>;
59
+ /** 控えと現在を比べる。増えた行は後片付けの対象に記録する */
60
+ diff(snapshot: DbSnapshot): Promise<DbDiff>;
61
+ /** 1 行取って部分一致を確かめる。無い / 複数 / 不一致は例外 */
62
+ expectRow(table: string, where: Row, expected: Row): Promise<Row>;
63
+ /** 記録した行を逆順に削除する(フィクスチャが自動で呼ぶ) */
64
+ cleanup(): Promise<CleanupResult>;
65
+ /** 後片付けの対象を手で足す(アプリが作った行を diff 以外で知っているとき) */
66
+ trackForCleanup(table: string, where: Row): void;
67
+ }
68
+ export declare function createDb(knex: Knex, options?: DbOptions): Db;
69
+ /** knex.raw の戻り値は方言ごとに形が違う。行配列に揃える */
70
+ export declare function normalizeRawResult(knex: Knex, result: unknown): Row[];
71
+ export { diffRows, summarizeDiff, type Row, type TableDiff };
72
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ import { diffRows, pickKey, summarizeDiff } from "./diff.js";
2
+ function fmt(value) {
3
+ return typeof value === "string" ? JSON.stringify(value) : String(value);
4
+ }
5
+ export function createDb(knex, options = {}) {
6
+ const maxRows = options.maxRows ?? 5000;
7
+ const cleanupEntries = [];
8
+ const applyWhere = (qb, where) => {
9
+ if (where === undefined)
10
+ return qb;
11
+ if (typeof where === "function")
12
+ return where(qb);
13
+ return qb.where(where);
14
+ };
15
+ const db = {
16
+ knex,
17
+ async query(sql, params = []) {
18
+ const result = await knex.raw(sql, [...params]);
19
+ return normalizeRawResult(knex, result);
20
+ },
21
+ async insert(table, row) {
22
+ await knex(table).insert(row);
23
+ cleanupEntries.push({ table, where: { ...row }, source: "insert" });
24
+ },
25
+ async insertMany(table, rows) {
26
+ for (const row of rows)
27
+ await db.insert(table, row);
28
+ },
29
+ async rows(table, where = {}) {
30
+ return (await knex(table).where(where).select("*"));
31
+ },
32
+ async snapshot(specs) {
33
+ const tables = {};
34
+ for (const spec of specs) {
35
+ if (spec.key.length === 0)
36
+ throw new Error(`snapshot: ${spec.table} の key が空です`);
37
+ if (spec.where === undefined) {
38
+ options.onWarning?.(`snapshot(${spec.table}): where が無いので全行(最大 ${maxRows} 行)を読みます。testId で絞ることを勧めます`);
39
+ }
40
+ const rows = (await applyWhere(knex(spec.table), spec.where).select("*").limit(maxRows + 1));
41
+ const truncated = rows.length > maxRows;
42
+ if (truncated) {
43
+ rows.length = maxRows;
44
+ options.onWarning?.(`snapshot(${spec.table}): ${maxRows} 行を超えたため打ち切りました。diff は信頼できません`);
45
+ }
46
+ tables[spec.table] = { spec, rows, truncated };
47
+ }
48
+ return { takenAt: new Date().toISOString(), tables };
49
+ },
50
+ async diff(snapshot) {
51
+ const result = {};
52
+ for (const [table, snap] of Object.entries(snapshot.tables)) {
53
+ const rows = (await applyWhere(knex(table), snap.spec.where).select("*").limit(maxRows + 1));
54
+ if (rows.length > maxRows)
55
+ rows.length = maxRows;
56
+ const d = diffRows(snap.rows, rows, snap.spec.key);
57
+ result[table] = d;
58
+ for (const inserted of d.inserted) {
59
+ cleanupEntries.push({ table, where: pickKey(inserted, snap.spec.key), source: "diff" });
60
+ }
61
+ }
62
+ await options.onDiff?.(result, snapshot);
63
+ return result;
64
+ },
65
+ async expectRow(table, where, expected) {
66
+ const rows = await db.rows(table, where);
67
+ if (rows.length !== 1) {
68
+ throw new Error(`expectRow(${table} where ${JSON.stringify(where)}): ${rows.length} 行でした(1 行を期待)`);
69
+ }
70
+ const row = rows[0];
71
+ const mismatches = [];
72
+ const d = diffRows([{ ...row, ...expected }], [row], Object.keys(where).length > 0 ? Object.keys(where) : Object.keys(row));
73
+ for (const u of d.updated) {
74
+ for (const [col, c] of Object.entries(u.changed))
75
+ mismatches.push(`${col}: 期待 ${fmt(c.before)} / 実際 ${fmt(c.after)}`);
76
+ }
77
+ if (mismatches.length > 0)
78
+ throw new Error(`expectRow(${table}): 不一致\n ${mismatches.join("\n ")}`);
79
+ return row;
80
+ },
81
+ trackForCleanup(table, where) {
82
+ cleanupEntries.push({ table, where: { ...where }, source: "diff" });
83
+ },
84
+ async cleanup() {
85
+ const failures = [];
86
+ let deleted = 0;
87
+ // 逆順(外部キー: 子 → 親)。同じ行を二重に記録していても 2 回目は 0 件削除で済む
88
+ for (const entry of [...cleanupEntries].reverse()) {
89
+ try {
90
+ deleted += await knex(entry.table).where(entry.where).delete();
91
+ }
92
+ catch (e) {
93
+ failures.push({ ...entry, error: e instanceof Error ? e.message : String(e) });
94
+ }
95
+ }
96
+ cleanupEntries.length = 0;
97
+ return { deleted, failures };
98
+ },
99
+ };
100
+ return db;
101
+ }
102
+ /** knex.raw の戻り値は方言ごとに形が違う。行配列に揃える */
103
+ export function normalizeRawResult(knex, result) {
104
+ const client = knex.client.config?.client;
105
+ if (client === "pg") {
106
+ const r = result;
107
+ return r.rows ?? [];
108
+ }
109
+ if (client === "mysql2") {
110
+ const r = result;
111
+ return Array.isArray(r) && Array.isArray(r[0]) ? r[0] : [];
112
+ }
113
+ if (client === "oracledb") {
114
+ return Array.isArray(result) ? result : [];
115
+ }
116
+ // mssql / better-sqlite3 は行配列
117
+ return Array.isArray(result) ? result : [];
118
+ }
119
+ export { diffRows, summarizeDiff };
120
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { expect } from "@playwright/test";
2
+ import type { Knex } from "knex";
3
+ import { type Bridge } from "./bridge.js";
4
+ import type { E2EWorkerOptions, TrackWhere } from "./config.js";
5
+ import { type Db, type SnapshotSpec } from "./db/index.js";
6
+ import { type HostApp } from "./host.js";
7
+ export interface E2ETestFixtures {
8
+ testId: string;
9
+ db: Db;
10
+ bridge: Bridge;
11
+ }
12
+ export interface E2EWorkerFixtures extends E2EWorkerOptions {
13
+ /** api / host で起動したホスト exe(screen では null) */
14
+ hostApp: HostApp | null;
15
+ /** DB 接続(設定が無ければ null) */
16
+ dbConnection: Knex | null;
17
+ /** playwright.config.ts のあるディレクトリ(パスの基準) */
18
+ appRoot: string;
19
+ }
20
+ export declare function makeTestId(now?: Date, random?: string): string;
21
+ /** TrackSpec の where を snapshot 用に解決する("{testId}" の置換 / 関数への testId 注入) */
22
+ export declare function resolveTrackWhere(where: TrackWhere | undefined, testId: string): SnapshotSpec["where"];
23
+ export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & E2ETestFixtures, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions & E2EWorkerFixtures>;
24
+ export { expect };
25
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../src/fixtures.ts"],"names":[],"mappings":"AAWA,OAAO,EAAgB,MAAM,EAAa,MAAM,kBAAkB,CAAC;AACnE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAuC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,KAAK,EAAa,gBAAgB,EAAoB,UAAU,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,EAAY,KAAK,EAAE,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,EAAc,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,EAAE,CAAC;IACP,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,8CAA8C;IAC9C,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,0BAA0B;IAC1B,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,GAAG,GAAE,IAAiB,EAAE,MAAM,GAAE,MAA+C,GAAG,MAAM,CAGlH;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAMtG;AAmBD,eAAO,MAAM,IAAI,mRA0Hf,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,CAAC"}