@plan2net/typo3-playwright-toolkit 0.1.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 (164) hide show
  1. package/LICENSE +338 -0
  2. package/README.md +404 -0
  3. package/dist/builders/content-builder.d.ts +30 -0
  4. package/dist/builders/content-builder.d.ts.map +1 -0
  5. package/dist/builders/content-builder.js +67 -0
  6. package/dist/builders/content-builder.js.map +1 -0
  7. package/dist/builders/content-factory.d.ts +10 -0
  8. package/dist/builders/content-factory.d.ts.map +1 -0
  9. package/dist/builders/content-factory.js +23 -0
  10. package/dist/builders/content-factory.js.map +1 -0
  11. package/dist/builders/core-content.d.ts +127 -0
  12. package/dist/builders/core-content.d.ts.map +1 -0
  13. package/dist/builders/core-content.js +223 -0
  14. package/dist/builders/core-content.js.map +1 -0
  15. package/dist/builders/fields.d.ts +7 -0
  16. package/dist/builders/fields.d.ts.map +1 -0
  17. package/dist/builders/fields.js +20 -0
  18. package/dist/builders/fields.js.map +1 -0
  19. package/dist/builders/identifier.d.ts +2 -0
  20. package/dist/builders/identifier.d.ts.map +1 -0
  21. package/dist/builders/identifier.js +11 -0
  22. package/dist/builders/identifier.js.map +1 -0
  23. package/dist/builders/page-builder.d.ts +40 -0
  24. package/dist/builders/page-builder.d.ts.map +1 -0
  25. package/dist/builders/page-builder.js +119 -0
  26. package/dist/builders/page-builder.js.map +1 -0
  27. package/dist/builders/request-context.d.ts +23 -0
  28. package/dist/builders/request-context.d.ts.map +1 -0
  29. package/dist/builders/request-context.js +32 -0
  30. package/dist/builders/request-context.js.map +1 -0
  31. package/dist/checks/accessibility.d.ts +34 -0
  32. package/dist/checks/accessibility.d.ts.map +1 -0
  33. package/dist/checks/accessibility.js +90 -0
  34. package/dist/checks/accessibility.js.map +1 -0
  35. package/dist/checks/csp.d.ts +39 -0
  36. package/dist/checks/csp.d.ts.map +1 -0
  37. package/dist/checks/csp.js +179 -0
  38. package/dist/checks/csp.js.map +1 -0
  39. package/dist/checks/screenshot.d.ts +18 -0
  40. package/dist/checks/screenshot.d.ts.map +1 -0
  41. package/dist/checks/screenshot.js +125 -0
  42. package/dist/checks/screenshot.js.map +1 -0
  43. package/dist/config.d.ts +100 -0
  44. package/dist/config.d.ts.map +1 -0
  45. package/dist/config.js +68 -0
  46. package/dist/config.js.map +1 -0
  47. package/dist/contract.d.ts +9 -0
  48. package/dist/contract.d.ts.map +1 -0
  49. package/dist/contract.js +25 -0
  50. package/dist/contract.js.map +1 -0
  51. package/dist/global-setup.d.ts +20 -0
  52. package/dist/global-setup.d.ts.map +1 -0
  53. package/dist/global-setup.js +103 -0
  54. package/dist/global-setup.js.map +1 -0
  55. package/dist/global-teardown.d.ts +34 -0
  56. package/dist/global-teardown.d.ts.map +1 -0
  57. package/dist/global-teardown.js +269 -0
  58. package/dist/global-teardown.js.map +1 -0
  59. package/dist/http/api-secret.d.ts +11 -0
  60. package/dist/http/api-secret.d.ts.map +1 -0
  61. package/dist/http/api-secret.js +27 -0
  62. package/dist/http/api-secret.js.map +1 -0
  63. package/dist/http/cleanup-client.d.ts +26 -0
  64. package/dist/http/cleanup-client.d.ts.map +1 -0
  65. package/dist/http/cleanup-client.js +91 -0
  66. package/dist/http/cleanup-client.js.map +1 -0
  67. package/dist/http/off-site-headers.d.ts +13 -0
  68. package/dist/http/off-site-headers.d.ts.map +1 -0
  69. package/dist/http/off-site-headers.js +27 -0
  70. package/dist/http/off-site-headers.js.map +1 -0
  71. package/dist/http/prepare-context.d.ts +4 -0
  72. package/dist/http/prepare-context.d.ts.map +1 -0
  73. package/dist/http/prepare-context.js +6 -0
  74. package/dist/http/prepare-context.js.map +1 -0
  75. package/dist/http/record-edit.d.ts +37 -0
  76. package/dist/http/record-edit.d.ts.map +1 -0
  77. package/dist/http/record-edit.js +86 -0
  78. package/dist/http/record-edit.js.map +1 -0
  79. package/dist/http/toolkit-request.d.ts +8 -0
  80. package/dist/http/toolkit-request.d.ts.map +1 -0
  81. package/dist/http/toolkit-request.js +45 -0
  82. package/dist/http/toolkit-request.js.map +1 -0
  83. package/dist/index.d.ts +18 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +14 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/inspect/cli.d.ts +3 -0
  88. package/dist/inspect/cli.d.ts.map +1 -0
  89. package/dist/inspect/cli.js +36 -0
  90. package/dist/inspect/cli.js.map +1 -0
  91. package/dist/inspect/links.d.ts +10 -0
  92. package/dist/inspect/links.d.ts.map +1 -0
  93. package/dist/inspect/links.js +51 -0
  94. package/dist/inspect/links.js.map +1 -0
  95. package/dist/inspect/token.d.ts +5 -0
  96. package/dist/inspect/token.d.ts.map +1 -0
  97. package/dist/inspect/token.js +15 -0
  98. package/dist/inspect/token.js.map +1 -0
  99. package/dist/playwright/base-config.d.ts +4 -0
  100. package/dist/playwright/base-config.d.ts.map +1 -0
  101. package/dist/playwright/base-config.js +34 -0
  102. package/dist/playwright/base-config.js.map +1 -0
  103. package/dist/playwright/index.d.ts +3 -0
  104. package/dist/playwright/index.d.ts.map +1 -0
  105. package/dist/playwright/index.js +3 -0
  106. package/dist/playwright/index.js.map +1 -0
  107. package/dist/scenario.d.ts +46 -0
  108. package/dist/scenario.d.ts.map +1 -0
  109. package/dist/scenario.js +139 -0
  110. package/dist/scenario.js.map +1 -0
  111. package/dist/state/attempt-claim.d.ts +8 -0
  112. package/dist/state/attempt-claim.d.ts.map +1 -0
  113. package/dist/state/attempt-claim.js +47 -0
  114. package/dist/state/attempt-claim.js.map +1 -0
  115. package/dist/state/attempt-registry.d.ts +36 -0
  116. package/dist/state/attempt-registry.d.ts.map +1 -0
  117. package/dist/state/attempt-registry.js +68 -0
  118. package/dist/state/attempt-registry.js.map +1 -0
  119. package/dist/state/ensure-state.d.ts +42 -0
  120. package/dist/state/ensure-state.d.ts.map +1 -0
  121. package/dist/state/ensure-state.js +169 -0
  122. package/dist/state/ensure-state.js.map +1 -0
  123. package/dist/state/json-safe.d.ts +9 -0
  124. package/dist/state/json-safe.d.ts.map +1 -0
  125. package/dist/state/json-safe.js +18 -0
  126. package/dist/state/json-safe.js.map +1 -0
  127. package/dist/state/run-id.d.ts +6 -0
  128. package/dist/state/run-id.d.ts.map +1 -0
  129. package/dist/state/run-id.js +28 -0
  130. package/dist/state/run-id.js.map +1 -0
  131. package/dist/state/run-namespace.d.ts +33 -0
  132. package/dist/state/run-namespace.d.ts.map +1 -0
  133. package/dist/state/run-namespace.js +136 -0
  134. package/dist/state/run-namespace.js.map +1 -0
  135. package/dist/state/safe-paths.d.ts +10 -0
  136. package/dist/state/safe-paths.d.ts.map +1 -0
  137. package/dist/state/safe-paths.js +56 -0
  138. package/dist/state/safe-paths.js.map +1 -0
  139. package/dist/state/scenario-outcome.d.ts +9 -0
  140. package/dist/state/scenario-outcome.d.ts.map +1 -0
  141. package/dist/state/scenario-outcome.js +23 -0
  142. package/dist/state/scenario-outcome.js.map +1 -0
  143. package/dist/state/scenario-state.d.ts +41 -0
  144. package/dist/state/scenario-state.d.ts.map +1 -0
  145. package/dist/state/scenario-state.js +50 -0
  146. package/dist/state/scenario-state.js.map +1 -0
  147. package/dist/state/setup-lock.d.ts +22 -0
  148. package/dist/state/setup-lock.d.ts.map +1 -0
  149. package/dist/state/setup-lock.js +90 -0
  150. package/dist/state/setup-lock.js.map +1 -0
  151. package/dist/types/common.d.ts +17 -0
  152. package/dist/types/common.d.ts.map +1 -0
  153. package/dist/types/common.js +2 -0
  154. package/dist/types/common.js.map +1 -0
  155. package/dist/types/content-builder.d.ts +16 -0
  156. package/dist/types/content-builder.d.ts.map +1 -0
  157. package/dist/types/content-builder.js +2 -0
  158. package/dist/types/content-builder.js.map +1 -0
  159. package/dist/types/playwright-extensions.d.ts +8 -0
  160. package/dist/types/playwright-extensions.d.ts.map +1 -0
  161. package/dist/types/playwright-extensions.js +2 -0
  162. package/dist/types/playwright-extensions.js.map +1 -0
  163. package/package.json +88 -0
  164. package/tsconfig.base.json +13 -0
@@ -0,0 +1,269 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { getToolkitConfig } from './config.js';
4
+ import { httpCleanup } from './http/cleanup-client.js';
5
+ import { readAttemptsFrom, readRegisteredTestIds } from './state/attempt-registry.js';
6
+ import { listRunIds, runLastActiveMs, runPaths, runsRoot } from './state/run-namespace.js';
7
+ import { assertDeletableDirectory, safeJoin } from './state/safe-paths.js';
8
+ import { inspectUrl } from './inspect/token.js';
9
+ import { resolveApiSecret } from './http/api-secret.js';
10
+ export const DEFAULT_ORPHAN_AGE_MS = 86_400_000;
11
+ /** Age at which a TYPO3 session directory is no longer any run's. */
12
+ const STALE_SESSION_AGE_MS = 60 * 60 * 1000;
13
+ const ALL_SCENARIOS = '*';
14
+ export function failedScenarioKeys(config) {
15
+ const directory = runPaths(config).failuresDir;
16
+ if (!fs.existsSync(directory)) {
17
+ return [];
18
+ }
19
+ const keys = new Set();
20
+ for (const entry of fs.readdirSync(directory)) {
21
+ if (!entry.endsWith('.json')) {
22
+ continue;
23
+ }
24
+ try {
25
+ const record = JSON.parse(fs.readFileSync(path.join(directory, entry), 'utf-8'));
26
+ keys.add('string' === typeof record.scenarioKey ? record.scenarioKey : ALL_SCENARIOS);
27
+ }
28
+ catch {
29
+ // The run we cannot read is the one most likely to need its databases.
30
+ console.error(`[teardown] Unreadable failure record ${entry}: keeping every database.`);
31
+ keys.add(ALL_SCENARIOS);
32
+ }
33
+ }
34
+ return [...keys];
35
+ }
36
+ export function preservedTestIds(config) {
37
+ const failed = new Set(failedScenarioKeys(config));
38
+ if (failed.size === 0) {
39
+ return [];
40
+ }
41
+ const attempts = readAttemptsFrom(runPaths(config).attemptsFile);
42
+ const keepAll = failed.has(ALL_SCENARIOS);
43
+ return [
44
+ ...new Set(attempts
45
+ .filter((attempt) => keepAll || failed.has(attempt.key))
46
+ .map((attempt) => attempt.testId)),
47
+ ];
48
+ }
49
+ export function resolvePreservePlan(config, cleanupSwitchedOff) {
50
+ if (cleanupSwitchedOff) {
51
+ return { mode: 'all', reason: 'NO_DATABASE_CLEANUP=1' };
52
+ }
53
+ const failed = failedScenarioKeys(config);
54
+ if (failed.length === 0) {
55
+ return { mode: 'none' };
56
+ }
57
+ const reason = `${failed.length} failed scenario${failed.length === 1 ? '' : 's'}`;
58
+ switch (config.cleanup?.preserveOnFailure ?? 'failed') {
59
+ case 'none':
60
+ return { mode: 'none' };
61
+ case 'all':
62
+ return { mode: 'all', reason };
63
+ default:
64
+ return { mode: 'some', testIds: preservedTestIds(config), reason };
65
+ }
66
+ }
67
+ function preserveList(plan) {
68
+ return 'some' === plan.mode ? plan.testIds : [];
69
+ }
70
+ /** Only live runs go in `keepTestIds`; an abandoned run's databases are dropped. */
71
+ export async function sweepOrphans(config, cleanup, now = Date.now()) {
72
+ const { stateDir } = config.paths;
73
+ const orphanAgeMs = config.cleanup?.orphanAgeMs ?? DEFAULT_ORPHAN_AGE_MS;
74
+ const cutoff = now - orphanAgeMs;
75
+ const currentRunId = runPaths(config).runId;
76
+ let reclaimed = 0;
77
+ const liveTestIds = new Set();
78
+ const abandonedRunIds = [];
79
+ for (const runId of listRunIds(stateDir)) {
80
+ const runDir = path.join(runsRoot(stateDir), runId);
81
+ const lastActiveMs = runLastActiveMs(runDir);
82
+ if (lastActiveMs === 0) {
83
+ continue;
84
+ }
85
+ if (runId !== currentRunId && lastActiveMs < cutoff) {
86
+ abandonedRunIds.push(runId);
87
+ continue;
88
+ }
89
+ for (const attempt of readAttemptsFrom(path.join(runDir, 'attempts.jsonl'))) {
90
+ liveTestIds.add(attempt.testId);
91
+ }
92
+ }
93
+ for (const runId of abandonedRunIds) {
94
+ const runDir = path.join(runsRoot(stateDir), runId);
95
+ // Re-check: another sweeper may have taken it, or it may have woken up.
96
+ const stillAbandoned = runLastActiveMs(runDir);
97
+ if (stillAbandoned === 0 || stillAbandoned >= cutoff) {
98
+ // A run that woke up is live now, and its ids were left out of the
99
+ // keep set during the first pass — so without this the sweep below
100
+ // would reclaim the databases it has just started using again.
101
+ for (const attempt of readAttemptsFrom(path.join(runDir, 'attempts.jsonl'))) {
102
+ liveTestIds.add(attempt.testId);
103
+ }
104
+ continue;
105
+ }
106
+ const testIds = readAttemptsFrom(path.join(runDir, 'attempts.jsonl')).map((attempt) => attempt.testId);
107
+ const results = await cleanup.drop(testIds);
108
+ reclaimed += results.filter((result) => 'dropped' === result.outcome).length;
109
+ // Only a failure is worth retrying, so the directory survives just that.
110
+ if (results.some((result) => 'failed' === result.outcome)) {
111
+ console.error(`[teardown] Keeping abandoned run ${runId}: some databases could not be dropped.`);
112
+ continue;
113
+ }
114
+ fs.rmSync(runDir, { recursive: true, force: true });
115
+ }
116
+ const sweep = await cleanup.sweep([...liveTestIds], orphanAgeMs);
117
+ reclaimed += sweep.results.filter((result) => 'dropped' === result.outcome).length;
118
+ return reclaimed;
119
+ }
120
+ export function describePreservedRun(config, keptTestIds, secret = '', now = Date.now()) {
121
+ const paths = runPaths(config);
122
+ const attempts = readAttemptsFrom(paths.attemptsFile);
123
+ const kept = undefined === keptTestIds ? attempts : attempts.filter((a) => keptTestIds.includes(a.testId));
124
+ if (kept.length === 0) {
125
+ return `[teardown] Run ${paths.runId} preserved (no databases recorded).`;
126
+ }
127
+ const lines = kept.map((attempt) => {
128
+ const line = ` ${attempt.name ?? attempt.key} → db${attempt.testId}`;
129
+ if ('' === secret) {
130
+ return line;
131
+ }
132
+ return `${line}\n ${inspectUrl(config.testingURL, secret, attempt.testId, now)}`;
133
+ });
134
+ const dropped = attempts.length - kept.length;
135
+ const alsoDropped = dropped > 0 ? `, ${dropped} passing one(s) dropped` : '';
136
+ return [
137
+ `[teardown] Run ${paths.runId} kept ${kept.length} database(s)${alsoDropped}:`,
138
+ ...lines,
139
+ ].join('\n');
140
+ }
141
+ export async function runTeardown(config, options) {
142
+ const { stateDir, sessionDir } = config.paths;
143
+ const { cleanup, preserve } = options;
144
+ // setToolkitConfig bypasses defineToolkitConfig, so re-check here: everything
145
+ // below this line deletes recursively.
146
+ assertDeletableDirectory('stateDir', stateDir, config.paths.consumerRoot);
147
+ assertDeletableDirectory('sessionDir', sessionDir, config.paths.consumerRoot);
148
+ const kept = 'all' === preserve.mode ? readRegisteredTestIds(config) : preserveList(preserve);
149
+ const drop = 'all' === preserve.mode
150
+ ? { dropped: 0, leaked: [], incomplete: false }
151
+ : await dropRegisteredDatabases(config, cleanup, kept);
152
+ // A partial preserve still sweeps: the kept ids reach keepTestIds through
153
+ // this run's attempts.jsonl.
154
+ if ('all' !== preserve.mode) {
155
+ await sweepOrphans(config, cleanup);
156
+ }
157
+ const cleanedSessions = pruneStaleSessions(sessionDir, Date.now() - STALE_SESSION_AGE_MS);
158
+ if ('none' === preserve.mode) {
159
+ removeRunState(config, drop.incomplete);
160
+ report(drop.dropped, cleanedSessions);
161
+ }
162
+ return { dropped: drop.dropped, leaked: drop.leaked, preserved: kept };
163
+ }
164
+ async function dropRegisteredDatabases(config, cleanup, keep) {
165
+ const report = { dropped: 0, leaked: [], incomplete: false };
166
+ const kept = new Set(keep);
167
+ const targets = readRegisteredTestIds(config).filter((testId) => !kept.has(testId));
168
+ if (targets.length === 0) {
169
+ return report;
170
+ }
171
+ for (const result of await cleanup.drop(targets)) {
172
+ if ('dropped' === result.outcome) {
173
+ report.dropped++;
174
+ continue;
175
+ }
176
+ // Only a failure can change on a retry, so only it keeps the registry.
177
+ if ('failed' === result.outcome) {
178
+ report.incomplete = true;
179
+ report.leaked.push(result.testId);
180
+ continue;
181
+ }
182
+ // Terminal but worth saying out loud: something else owns a name this
183
+ // run recorded, or the id was never contract-shaped.
184
+ if ('absent' !== result.outcome) {
185
+ console.error(`[teardown] db${result.testId}: ${result.outcome}`);
186
+ report.leaked.push(result.testId);
187
+ }
188
+ }
189
+ return report;
190
+ }
191
+ function pruneStaleSessions(sessionDir, cutoffMs) {
192
+ if (!fs.existsSync(sessionDir)) {
193
+ return 0;
194
+ }
195
+ let cleaned = 0;
196
+ for (const dir of fs.readdirSync(sessionDir)) {
197
+ const sessionPath = safeJoin(sessionDir, dir);
198
+ // sessionDir is shared, so another teardown may have taken it since the listing.
199
+ const stats = fs.statSync(sessionPath, { throwIfNoEntry: false });
200
+ if (stats?.isDirectory() && stats.mtimeMs < cutoffMs) {
201
+ fs.rmSync(sessionPath, { recursive: true, force: true });
202
+ cleaned++;
203
+ }
204
+ }
205
+ return cleaned;
206
+ }
207
+ function removeRunState(config, keepRegistry) {
208
+ const paths = runPaths(config);
209
+ // Keep the registry when anything was left behind: it is the only record of
210
+ // the leak. Only this run's directory either way — other runs live in stateDir too.
211
+ if (keepRegistry) {
212
+ console.error(`[teardown] Keeping ${paths.runDir}: some databases could not be dropped. ` +
213
+ 'Their ids are in attempts.jsonl.');
214
+ return;
215
+ }
216
+ fs.rmSync(paths.runDir, { recursive: true, force: true });
217
+ }
218
+ function report(droppedDatabases, cleanedSessions) {
219
+ const parts = [];
220
+ if (droppedDatabases > 0) {
221
+ parts.push(`${droppedDatabases} DBs`);
222
+ }
223
+ if (cleanedSessions > 0) {
224
+ parts.push(`${cleanedSessions} session dirs`);
225
+ }
226
+ if (parts.length > 0) {
227
+ console.log(`[teardown] Cleaned ${parts.join(', ')}.`);
228
+ }
229
+ }
230
+ async function globalTeardown() {
231
+ const config = getToolkitConfig();
232
+ const preserve = resolvePreservePlan(config, process.env.NO_DATABASE_CLEANUP === '1');
233
+ let summary;
234
+ try {
235
+ summary = await runTeardown(config, { cleanup: httpCleanup(config), preserve });
236
+ if ('none' !== preserve.mode) {
237
+ console.log(`[teardown] Kept for debugging (${preserve.reason}).`);
238
+ console.log(describePreservedRun(config, 'some' === preserve.mode ? preserve.testIds : undefined, inspectSecret(config)));
239
+ }
240
+ }
241
+ catch (error) {
242
+ console.error('[teardown] Error during cleanup:', error);
243
+ if (failOnLeak(config)) {
244
+ throw error;
245
+ }
246
+ return;
247
+ }
248
+ if (summary.leaked.length > 0 && failOnLeak(config)) {
249
+ // Swallowing this is how a suite stays green while it fills the disk.
250
+ throw new Error(`[teardown] ${summary.leaked.length} test database(s) could not be dropped: ` +
251
+ `${summary.leaked.map((testId) => `db${testId}`).join(', ')}. ` +
252
+ 'Set cleanup.failOnLeak to false to downgrade this to a warning.');
253
+ }
254
+ }
255
+ /** No secret means no link; the databases are still named, which is the important part. */
256
+ function inspectSecret(config) {
257
+ try {
258
+ return resolveApiSecret(config);
259
+ }
260
+ catch {
261
+ return '';
262
+ }
263
+ }
264
+ /** Defaults to failing in CI, where a leak has no one watching the output. */
265
+ function failOnLeak(config) {
266
+ return config.cleanup?.failOnLeak ?? !!process.env.CI;
267
+ }
268
+ export default globalTeardown;
269
+ //# sourceMappingURL=global-teardown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-teardown.js","sourceRoot":"","sources":["../src/global-teardown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,gBAAgB,EAAsB,MAAM,aAAa,CAAA;AAClE,OAAO,EAAE,WAAW,EAAsB,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AACrF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAC1F,OAAO,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAA;AAE/C,qEAAqE;AACrE,MAAM,oBAAoB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAE3C,MAAM,aAAa,GAAG,GAAG,CAAA;AAEzB,MAAM,UAAU,kBAAkB,CAAC,MAAqB;IACpD,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,WAAW,CAAA;IAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAA;IACb,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,SAAQ;QACZ,CAAC;QACD,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,CAE9E,CAAA;YACD,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAA;QACzF,CAAC;QAAC,MAAM,CAAC;YACL,uEAAuE;YACvE,OAAO,CAAC,KAAK,CAAC,wCAAwC,KAAK,2BAA2B,CAAC,CAAA;YACvF,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;QAC3B,CAAC;IACL,CAAC;IAED,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;AACpB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IAClD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAA;IAClD,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,CAAA;IACb,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAA;IAChE,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;IAEzC,OAAO;QACH,GAAG,IAAI,GAAG,CACN,QAAQ;aACH,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;aACvD,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CACxC;KACJ,CAAA;AACL,CAAC;AAOD,MAAM,UAAU,mBAAmB,CAAC,MAAqB,EAAE,kBAA2B;IAClF,IAAI,kBAAkB,EAAE,CAAC;QACrB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAA;IAC3D,CAAC;IAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;IACzC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IAC3B,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,mBAAmB,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAA;IAElF,QAAQ,MAAM,CAAC,OAAO,EAAE,iBAAiB,IAAI,QAAQ,EAAE,CAAC;QACpD,KAAK,MAAM;YACP,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;QAC3B,KAAK,KAAK;YACN,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;QAClC;YACI,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1E,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,IAAkB;IACpC,OAAO,MAAM,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;AACnD,CAAC;AAeD,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,YAAY,CAC9B,MAAqB,EACrB,OAAsB,EACtB,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,KAAK,CAAA;IACjC,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,EAAE,WAAW,IAAI,qBAAqB,CAAA;IACxE,MAAM,MAAM,GAAG,GAAG,GAAG,WAAW,CAAA;IAChC,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAA;IAC3C,IAAI,SAAS,GAAG,CAAC,CAAA;IAEjB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IACrC,MAAM,eAAe,GAAa,EAAE,CAAA;IAEpC,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAA;QACnD,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;QAE5C,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;YACrB,SAAQ;QACZ,CAAC;QACD,IAAI,KAAK,KAAK,YAAY,IAAI,YAAY,GAAG,MAAM,EAAE,CAAC;YAClD,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAC3B,SAAQ;QACZ,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC;YAC1E,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACnC,CAAC;IACL,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAA;QAEnD,wEAAwE;QACxE,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;QAC9C,IAAI,cAAc,KAAK,CAAC,IAAI,cAAc,IAAI,MAAM,EAAE,CAAC;YACnD,mEAAmE;YACnE,mEAAmE;YACnE,+DAA+D;YAC/D,KAAK,MAAM,OAAO,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC;gBAC1E,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;YACnC,CAAC;YACD,SAAQ;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,CACrE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAC9B,CAAA;QACD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC3C,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAA;QAE5E,yEAAyE;QACzE,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,KAAK,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,KAAK,CAAC,oCAAoC,KAAK,wCAAwC,CAAC,CAAA;YAChG,SAAQ;QACZ,CAAC;QACD,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACvD,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,WAAW,CAAC,EAAE,WAAW,CAAC,CAAA;IAChE,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAA;IAElF,OAAO,SAAS,CAAA;AACpB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAChC,MAAqB,EACrB,WAAsB,EACtB,MAAM,GAAG,EAAE,EACX,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC9B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IACrD,MAAM,IAAI,GAAG,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAE1G,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,kBAAkB,KAAK,CAAC,KAAK,qCAAqC,CAAA;IAC7E,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,KAAK,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAA;QACrE,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;YAChB,OAAO,IAAI,CAAA;QACf,CAAC;QAED,OAAO,GAAG,IAAI,SAAS,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAA;IACvF,CAAC,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAC7C,MAAM,WAAW,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,yBAAyB,CAAC,CAAC,CAAC,EAAE,CAAA;IAE5E,OAAO;QACH,kBAAkB,KAAK,CAAC,KAAK,SAAS,IAAI,CAAC,MAAM,eAAe,WAAW,GAAG;QAC9E,GAAG,KAAK;KACX,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAqB,EAAE,OAAwB;IAC7E,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,KAAK,CAAA;IAC7C,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IAErC,8EAA8E;IAC9E,uCAAuC;IACvC,wBAAwB,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IACzE,wBAAwB,CAAC,YAAY,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IAE7E,MAAM,IAAI,GAAG,KAAK,KAAK,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;IAE7F,MAAM,IAAI,GACN,KAAK,KAAK,QAAQ,CAAC,IAAI;QACnB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE;QAC/C,CAAC,CAAC,MAAM,uBAAuB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;IAE9D,0EAA0E;IAC1E,6BAA6B;IAC7B,IAAI,KAAK,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACvC,CAAC;IAED,MAAM,eAAe,GAAG,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,oBAAoB,CAAC,CAAA;IAEzF,IAAI,MAAM,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC3B,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;QACvC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IACzC,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;AAC1E,CAAC;AASD,KAAK,UAAU,uBAAuB,CAClC,MAAqB,EACrB,OAAsB,EACtB,IAAc;IAEd,MAAM,MAAM,GAAe,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;IACxE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;IAC1B,MAAM,OAAO,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;IAEnF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,MAAM,CAAA;IACjB,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/C,IAAI,SAAS,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,SAAQ;QACZ,CAAC;QACD,uEAAuE;QACvE,IAAI,QAAQ,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,CAAC,UAAU,GAAG,IAAI,CAAA;YACxB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YACjC,SAAQ;QACZ,CAAC;QACD,sEAAsE;QACtE,qDAAqD;QACrD,IAAI,QAAQ,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,gBAAgB,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;YACjE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACrC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAA;AACjB,CAAC;AAED,SAAS,kBAAkB,CAAC,UAAkB,EAAE,QAAgB;IAC5D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,CAAA;IACZ,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,KAAK,MAAM,GAAG,IAAI,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3C,MAAM,WAAW,GAAG,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;QAC7C,iFAAiF;QACjF,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAA;QACjE,IAAI,KAAK,EAAE,WAAW,EAAE,IAAI,KAAK,CAAC,OAAO,GAAG,QAAQ,EAAE,CAAC;YACnD,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YACxD,OAAO,EAAE,CAAA;QACb,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAA;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,MAAqB,EAAE,YAAqB;IAChE,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IAE9B,4EAA4E;IAC5E,oFAAoF;IACpF,IAAI,YAAY,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACT,sBAAsB,KAAK,CAAC,MAAM,yCAAyC;YACvE,kCAAkC,CACzC,CAAA;QAED,OAAM;IACV,CAAC;IAED,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAC7D,CAAC;AAED,SAAS,MAAM,CAAC,gBAAwB,EAAE,eAAuB;IAC7D,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,gBAAgB,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,GAAG,gBAAgB,MAAM,CAAC,CAAA;IACzC,CAAC;IACD,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,GAAG,eAAe,eAAe,CAAC,CAAA;IACjD,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC1D,CAAC;AACL,CAAC;AAED,KAAK,UAAU,cAAc;IACzB,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAA;IACjC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,GAAG,CAAC,CAAA;IAErF,IAAI,OAAwB,CAAA;IAC5B,IAAI,CAAC;QACD,OAAO,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;QAE/E,IAAI,MAAM,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,kCAAkC,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAA;YAClE,OAAO,CAAC,GAAG,CACP,oBAAoB,CAChB,MAAM,EACN,MAAM,KAAK,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EACvD,aAAa,CAAC,MAAM,CAAC,CACxB,CACJ,CAAA;QACL,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAA;QAExD,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,MAAM,KAAK,CAAA;QACf,CAAC;QACD,OAAM;IACV,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,sEAAsE;QACtE,MAAM,IAAI,KAAK,CACX,cAAc,OAAO,CAAC,MAAM,CAAC,MAAM,0CAA0C;YACzE,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAC/D,iEAAiE,CACxE,CAAA;IACL,CAAC;AACL,CAAC;AAED,2FAA2F;AAC3F,SAAS,aAAa,CAAC,MAAqB;IACxC,IAAI,CAAC;QACD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACnC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAA;IACb,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,SAAS,UAAU,CAAC,MAAqB;IACrC,OAAO,MAAM,CAAC,OAAO,EAAE,UAAU,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;AACzD,CAAC;AAED,eAAe,cAAc,CAAA"}
@@ -0,0 +1,11 @@
1
+ import type { ToolkitConfig } from '../config.js';
2
+ export declare const SECRET_HEADER = "X-Playwright-Toolkit-Secret";
3
+ export declare const SECRET_ENV = "PLAYWRIGHT_TOOLKIT_SECRET";
4
+ /** Where `playwright:prepare` writes it, inside TYPO3's var path. */
5
+ export declare function secretFileFor(config: ToolkitConfig): string;
6
+ /**
7
+ * Every test endpoint requires this, so failing here is better than failing on
8
+ * each request with an unexplained 401.
9
+ */
10
+ export declare function resolveApiSecret(config: ToolkitConfig): string;
11
+ //# sourceMappingURL=api-secret.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-secret.d.ts","sourceRoot":"","sources":["../../src/http/api-secret.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,eAAO,MAAM,aAAa,gCAAgC,CAAA;AAC1D,eAAO,MAAM,UAAU,8BAA8B,CAAA;AAErD,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAE3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAiB9D"}
@@ -0,0 +1,27 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ export const SECRET_HEADER = 'X-Playwright-Toolkit-Secret';
4
+ export const SECRET_ENV = 'PLAYWRIGHT_TOOLKIT_SECRET';
5
+ /** Where `playwright:prepare` writes it, inside TYPO3's var path. */
6
+ export function secretFileFor(config) {
7
+ return path.join(config.paths.consumerRoot, 'var', 'playwright', 'api-secret');
8
+ }
9
+ /**
10
+ * Every test endpoint requires this, so failing here is better than failing on
11
+ * each request with an unexplained 401.
12
+ */
13
+ export function resolveApiSecret(config) {
14
+ const fromEnvironment = (process.env[SECRET_ENV] ?? '').trim();
15
+ if (fromEnvironment) {
16
+ return fromEnvironment;
17
+ }
18
+ const file = secretFileFor(config);
19
+ const fromFile = fs.existsSync(file) ? fs.readFileSync(file, 'utf-8').trim() : '';
20
+ if (fromFile) {
21
+ return fromFile;
22
+ }
23
+ throw new Error(`[typo3-playwright-toolkit] No test API secret. Run \`ddev playwright-prepare\` ` +
24
+ `(or \`typo3 playwright:prepare\`) to create ${file}, or set ${SECRET_ENV} ` +
25
+ 'to the same value when PHP and Node do not share a filesystem.');
26
+ }
27
+ //# sourceMappingURL=api-secret.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-secret.js","sourceRoot":"","sources":["../../src/http/api-secret.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAG5B,MAAM,CAAC,MAAM,aAAa,GAAG,6BAA6B,CAAA;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,2BAA2B,CAAA;AAErD,qEAAqE;AACrE,MAAM,UAAU,aAAa,CAAC,MAAqB;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,CAAC,CAAA;AAClF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IAClD,MAAM,eAAe,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC9D,IAAI,eAAe,EAAE,CAAC;QAClB,OAAO,eAAe,CAAA;IAC1B,CAAC;IAED,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACjF,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,QAAQ,CAAA;IACnB,CAAC;IAED,MAAM,IAAI,KAAK,CACX,iFAAiF;QAC7E,+CAA+C,IAAI,YAAY,UAAU,GAAG;QAC5E,gEAAgE,CACvE,CAAA;AACL,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ToolkitConfig } from '../config.js';
2
+ /** Mirrors the extension's CleanupOutcome. */
3
+ export type CleanupOutcome = 'dropped' | 'absent' | 'unclaimed' | 'refused' | 'failed';
4
+ export interface CleanupResult {
5
+ testId: string;
6
+ outcome: CleanupOutcome;
7
+ }
8
+ export interface SweepReport {
9
+ results: CleanupResult[];
10
+ kept: number;
11
+ cutoffMs: number;
12
+ /** True when the site could not be reached, which is not a run failure. */
13
+ unreachable: boolean;
14
+ }
15
+ /** The endpoint refuses a larger batch, so requests are chunked to this size. */
16
+ export declare const MAXIMUM_BATCH = 500;
17
+ export type DropDatabases = (testIds: string[]) => Promise<CleanupResult[]>;
18
+ export interface CleanupClient {
19
+ drop: DropDatabases;
20
+ sweep(keepTestIds: string[], minimumAgeMs: number): Promise<SweepReport>;
21
+ }
22
+ export declare function httpCleanup(config: ToolkitConfig, options?: {
23
+ fetchImpl?: typeof fetch;
24
+ timeoutMs?: number;
25
+ }): CleanupClient;
26
+ //# sourceMappingURL=cleanup-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup-client.d.ts","sourceRoot":"","sources":["../../src/http/cleanup-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAGjD,8CAA8C;AAC9C,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEtF,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,cAAc,CAAA;CAC1B;AAED,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,WAAW,EAAE,OAAO,CAAA;CACvB;AAED,iFAAiF;AACjF,eAAO,MAAM,aAAa,MAAM,CAAA;AAkChC,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;AAE3E,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,aAAa,CAAA;IACnB,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;CAC3E;AAED,wBAAgB,WAAW,CACvB,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/D,aAAa,CAuEf"}
@@ -0,0 +1,91 @@
1
+ import { SECRET_HEADER, resolveApiSecret } from './api-secret.js';
2
+ /** The endpoint refuses a larger batch, so requests are chunked to this size. */
3
+ export const MAXIMUM_BATCH = 500;
4
+ const OUTCOMES = ['dropped', 'absent', 'unclaimed', 'refused', 'failed'];
5
+ /**
6
+ * Accepts only these five results. Teardown forgets a database once its result is
7
+ * final, and those records are the only proof the database ever existed — so an
8
+ * answer we do not understand must never count as final.
9
+ */
10
+ function parseResults(body) {
11
+ if (!body || typeof body !== 'object' || !Array.isArray(body.results)) {
12
+ return [];
13
+ }
14
+ const parsed = [];
15
+ for (const entry of body.results) {
16
+ if (!entry || typeof entry !== 'object') {
17
+ continue;
18
+ }
19
+ const { testId, outcome } = entry;
20
+ if (typeof testId !== 'string') {
21
+ continue;
22
+ }
23
+ parsed.push({
24
+ testId,
25
+ outcome: OUTCOMES.includes(outcome)
26
+ ? outcome
27
+ : 'failed',
28
+ });
29
+ }
30
+ return parsed;
31
+ }
32
+ export function httpCleanup(config, options = {}) {
33
+ const doFetch = options.fetchImpl ?? fetch;
34
+ const timeoutMs = options.timeoutMs ?? (Number(process.env.PW_CLEANUP_TIMEOUT_MS) || 30000);
35
+ async function post(operation, payload) {
36
+ const url = `${config.testingURL}/typo3/test-api/databases/${operation}`;
37
+ // No test-ID header: one would make the extension provision a database
38
+ // on the way in, and this request exists to remove them.
39
+ const response = await doFetch(url, {
40
+ method: 'POST',
41
+ headers: {
42
+ 'Content-Type': 'application/json',
43
+ [SECRET_HEADER]: resolveApiSecret(config),
44
+ },
45
+ body: JSON.stringify(payload),
46
+ signal: AbortSignal.timeout(timeoutMs),
47
+ });
48
+ if (!response.ok) {
49
+ throw new Error(`${url} answered ${response.status}`);
50
+ }
51
+ return await response.json();
52
+ }
53
+ return {
54
+ async drop(testIds) {
55
+ const results = [];
56
+ for (let index = 0; index < testIds.length; index += MAXIMUM_BATCH) {
57
+ const batch = testIds.slice(index, index + MAXIMUM_BATCH);
58
+ let reported = [];
59
+ try {
60
+ reported = parseResults(await post('drop', { testIds: batch }));
61
+ }
62
+ catch (error) {
63
+ console.error(`[teardown] Cleanup request failed: ${error.message}`);
64
+ }
65
+ // An id the endpoint said nothing about is not known to be gone, so
66
+ // it counts as failed and keeps the run registry alive.
67
+ const byTestId = new Map(reported.map((result) => [result.testId, result]));
68
+ for (const testId of batch) {
69
+ results.push(byTestId.get(testId) ?? { testId, outcome: 'failed' });
70
+ }
71
+ }
72
+ return results;
73
+ },
74
+ async sweep(keepTestIds, minimumAgeMs) {
75
+ try {
76
+ const body = (await post('sweep', { keepTestIds, minimumAgeMs }));
77
+ return {
78
+ results: parseResults(body),
79
+ kept: typeof body.kept === 'number' ? body.kept : 0,
80
+ cutoffMs: typeof body.cutoffMs === 'number' ? body.cutoffMs : minimumAgeMs,
81
+ unreachable: false,
82
+ };
83
+ }
84
+ catch (error) {
85
+ console.error(`[teardown] Orphan sweep skipped: ${error.message}`);
86
+ return { results: [], kept: 0, cutoffMs: minimumAgeMs, unreachable: true };
87
+ }
88
+ },
89
+ };
90
+ }
91
+ //# sourceMappingURL=cleanup-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup-client.js","sourceRoot":"","sources":["../../src/http/cleanup-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { BrowserContext } from '@playwright/test';
2
+ import type { ToolkitConfig } from '../config.js';
3
+ /**
4
+ * Adds the test ID for the site under test, and takes both toolkit headers off
5
+ * anything else. Routing rather than extraHTTPHeaders: a context-wide header also
6
+ * rides on page.request, which context.route cannot reach.
7
+ *
8
+ * Register this last. Playwright runs the newest matching handler first, and
9
+ * `fallback` then passes the request down to the ones a consumer added earlier —
10
+ * `continue` would end the chain and silently disable them.
11
+ */
12
+ export declare function applyToolkitHeaders(context: BrowserContext, config: ToolkitConfig, testId: string): Promise<void>;
13
+ //# sourceMappingURL=off-site-headers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"off-site-headers.d.ts","sourceRoot":"","sources":["../../src/http/off-site-headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAGtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAIjD;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACrC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -0,0 +1,27 @@
1
+ import { SECRET_HEADER } from './api-secret.js';
2
+ import { TEST_ID_HEADER, browserHeaders } from '../contract.js';
3
+ const TOOLKIT_HEADERS = [TEST_ID_HEADER.toLowerCase(), SECRET_HEADER.toLowerCase()];
4
+ /**
5
+ * Adds the test ID for the site under test, and takes both toolkit headers off
6
+ * anything else. Routing rather than extraHTTPHeaders: a context-wide header also
7
+ * rides on page.request, which context.route cannot reach.
8
+ *
9
+ * Register this last. Playwright runs the newest matching handler first, and
10
+ * `fallback` then passes the request down to the ones a consumer added earlier —
11
+ * `continue` would end the chain and silently disable them.
12
+ */
13
+ export async function applyToolkitHeaders(context, config, testId) {
14
+ const site = new URL(config.testingURL).origin;
15
+ await context.route(() => true, async (route) => {
16
+ const headers = { ...route.request().headers() };
17
+ if (new URL(route.request().url()).origin === site) {
18
+ await route.fallback({ headers: { ...headers, ...browserHeaders(testId) } });
19
+ return;
20
+ }
21
+ for (const name of TOOLKIT_HEADERS) {
22
+ delete headers[name];
23
+ }
24
+ await route.fallback({ headers });
25
+ });
26
+ }
27
+ //# sourceMappingURL=off-site-headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"off-site-headers.js","sourceRoot":"","sources":["../../src/http/off-site-headers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/D,MAAM,eAAe,GAAG,CAAC,cAAc,CAAC,WAAW,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,CAAC,CAAA;AAEnF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACrC,OAAuB,EACvB,MAAqB,EACrB,MAAc;IAEd,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAA;IAE9C,MAAM,OAAO,CAAC,KAAK,CACf,GAAG,EAAE,CAAC,IAAI,EACV,KAAK,EAAE,KAAK,EAAE,EAAE;QACZ,MAAM,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAA;QAEhD,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACjD,MAAM,KAAK,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;YAE5E,OAAM;QACV,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACjC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAA;QACxB,CAAC;QAED,MAAM,KAAK,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;IACrC,CAAC,CACJ,CAAA;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { BrowserContext } from '@playwright/test';
2
+ import type { ToolkitConfig } from '../config.js';
3
+ export declare function prepareScenarioContext(context: BrowserContext, config: ToolkitConfig, testId: string): Promise<void>;
4
+ //# sourceMappingURL=prepare-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepare-context.d.ts","sourceRoot":"","sources":["../../src/http/prepare-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAGjD,wBAAsB,sBAAsB,CACxC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAGf"}
@@ -0,0 +1,6 @@
1
+ import { applyToolkitHeaders } from './off-site-headers.js';
2
+ export async function prepareScenarioContext(context, config, testId) {
3
+ await config.prepareContext?.(context);
4
+ await applyToolkitHeaders(context, config, testId);
5
+ }
6
+ //# sourceMappingURL=prepare-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepare-context.js","sourceRoot":"","sources":["../../src/http/prepare-context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAE3D,MAAM,CAAC,KAAK,UAAU,sBAAsB,CACxC,OAAuB,EACvB,MAAqB,EACrB,MAAc;IAEd,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,CAAA;IACtC,MAAM,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AACtD,CAAC"}
@@ -0,0 +1,37 @@
1
+ /** Relative to the backend entry point, which a project may have moved. */
2
+ export declare const RECORD_EDIT_ROUTE = "/record/edit";
3
+ /** Shaped like a DataHandler datamap: table → identifier → fields. */
4
+ export type RecordDataMap = Record<string, Record<string, Record<string, unknown>>>;
5
+ export interface FormResponse {
6
+ status(): number;
7
+ headers(): Record<string, string>;
8
+ text(): Promise<string>;
9
+ }
10
+ export interface FormPoster {
11
+ post(url: string, options: {
12
+ headers: Record<string, string>;
13
+ multipart: Record<string, string>;
14
+ maxRedirects: number;
15
+ }): Promise<FormResponse>;
16
+ }
17
+ export interface EditContext {
18
+ baseUrl: string;
19
+ backendPath: string;
20
+ testId: string;
21
+ routeToken: string;
22
+ }
23
+ export interface RecordToSave {
24
+ table: string;
25
+ /** A `NEW` prefix creates; anything else is a uid the form opens for editing. */
26
+ identifier: string;
27
+ /** `edit[table][target]` — the parent page when creating, the record itself when updating. */
28
+ target: number;
29
+ data: RecordDataMap;
30
+ }
31
+ /**
32
+ * The route the backend's own edit form posts to, so a TYPO3 release that changes
33
+ * it, its request-token rules or its field names fails the suite rather than
34
+ * passing quietly.
35
+ */
36
+ export declare function saveRecord(poster: FormPoster, context: EditContext, record: RecordToSave): Promise<number>;
37
+ //# sourceMappingURL=record-edit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-edit.d.ts","sourceRoot":"","sources":["../../src/http/record-edit.ts"],"names":[],"mappings":"AAGA,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB,iBAAiB,CAAA;AAE/C,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;AAEnF,MAAM,WAAW,YAAY;IACzB,MAAM,IAAI,MAAM,CAAA;IAChB,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAC1B;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,CACA,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GACtG,OAAO,CAAC,YAAY,CAAC,CAAA;CAC3B;AAED,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAA;IAClB,8FAA8F;IAC9F,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,aAAa,CAAA;CACtB;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAC5B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,YAAY,GACrB,OAAO,CAAC,MAAM,CAAC,CAwCjB"}