@jterrazz/test 16.1.0 → 17.0.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 (304) hide show
  1. package/README.md +45 -171
  2. package/dist/browser/index.js +2 -2867
  3. package/dist/browser/services.js +2 -0
  4. package/dist/browser/stubs.js +2 -0
  5. package/dist/checker.d.ts +6 -1
  6. package/dist/checker.js +4551 -2612
  7. package/dist/config.d.ts +40 -0
  8. package/dist/config.js +309 -0
  9. package/dist/in-place.global-setup.d.ts +11 -0
  10. package/dist/in-place.global-setup.js +21 -0
  11. package/dist/index.d.ts +1653 -3002
  12. package/dist/index.js +5226 -3845
  13. package/dist/mobile-session.global-setup.d.ts +14 -0
  14. package/dist/mobile-session.global-setup.js +31 -0
  15. package/dist/oxlint.cjs +6073 -5616
  16. package/dist/oxlint.d.cts +43 -7212
  17. package/dist/oxlint.d.ts +43 -7212
  18. package/dist/oxlint.js +6065 -5609
  19. package/dist/route-coverage.global-setup.d.ts +42 -0
  20. package/dist/route-coverage.global-setup.js +2 -0
  21. package/dist/services.d.ts +3 -0
  22. package/dist/services.global-setup.d.ts +43 -0
  23. package/dist/services.global-setup.js +2 -0
  24. package/dist/services.js +597 -0
  25. package/dist/shared-appium.adapter.js +428 -0
  26. package/dist/shared-artifacts.js +32 -0
  27. package/dist/shared-chapter.js +7 -0
  28. package/dist/shared-container.port.d.ts +31 -0
  29. package/dist/shared-derived-projects.js +58 -0
  30. package/dist/shared-device.port.d.ts +189 -0
  31. package/dist/shared-exchange.js +447 -0
  32. package/dist/shared-in-place.js +172 -0
  33. package/dist/shared-index.browser.js +3191 -0
  34. package/dist/shared-index.services.d.ts +346 -0
  35. package/dist/shared-index.stubs.d.ts +287 -0
  36. package/dist/shared-json-shape.js +17 -0
  37. package/dist/shared-landmarks.js +71 -0
  38. package/dist/shared-ledger.js +68 -0
  39. package/dist/shared-literate-plugin.js +183 -0
  40. package/dist/shared-manifest.js +1321 -0
  41. package/dist/shared-pause.js +11 -0
  42. package/dist/shared-peer.js +88 -0
  43. package/dist/shared-playwright.adapter.js +330 -0
  44. package/dist/shared-process.adapter.js +74 -0
  45. package/dist/shared-refusal.js +35 -0
  46. package/dist/shared-resolve.js +24 -0
  47. package/dist/shared-route-coverage.global-setup.js +187 -0
  48. package/dist/shared-scenario-failure.js +198 -0
  49. package/dist/shared-serve.js +365 -0
  50. package/dist/shared-service-images.js +10 -0
  51. package/dist/shared-services.global-setup.js +179 -0
  52. package/dist/shared-session-ledger.js +301 -0
  53. package/dist/shared-setup-entry.js +12 -0
  54. package/dist/shared-source-scan.js +133 -0
  55. package/dist/shared-spec-document.js +365 -0
  56. package/dist/shared-specifications.js +26 -0
  57. package/dist/shared-stream-body.js +130 -0
  58. package/dist/shared-stub-server.js +190 -0
  59. package/dist/shared-temp-root.global-setup.js +80 -0
  60. package/dist/shared-test-baseline.js +26 -0
  61. package/dist/shared-test-section.js +58 -0
  62. package/dist/shared-testcontainers.adapter.js +203 -0
  63. package/dist/shared-tokens.js +55 -0
  64. package/dist/shared-yaml-document.js +119 -0
  65. package/dist/stubs.d.ts +2 -0
  66. package/dist/stubs.js +657 -0
  67. package/dist/temp-root.global-setup.d.ts +7 -0
  68. package/dist/temp-root.global-setup.js +2 -0
  69. package/dist/vitest.d.ts +97 -163
  70. package/dist/vitest.js +374 -507
  71. package/docs/README.md +82 -36
  72. package/docs/concepts/architecture.md +118 -0
  73. package/docs/concepts/conventions.md +333 -0
  74. package/docs/guides/api-specs.md +374 -0
  75. package/docs/guides/cli-specs.md +564 -0
  76. package/docs/guides/component-specs.md +252 -0
  77. package/docs/guides/develop.md +94 -0
  78. package/docs/guides/integration-specs.md +181 -0
  79. package/docs/guides/job-specs.md +180 -0
  80. package/docs/guides/lint-specs.md +174 -0
  81. package/docs/guides/mobile-specs.md +319 -0
  82. package/docs/guides/module-tests.md +149 -0
  83. package/docs/guides/release.md +43 -0
  84. package/docs/guides/spec-documents.md +189 -0
  85. package/docs/guides/website-specs.md +413 -0
  86. package/docs/reference/assertions.md +345 -0
  87. package/docs/reference/glossary.md +20 -0
  88. package/docs/reference/linting.md +483 -0
  89. package/docs/reference/services.md +236 -0
  90. package/docs/reference/stubs.md +498 -0
  91. package/docs/reference/time-and-doubles.md +137 -0
  92. package/docs/reference/tokens.md +258 -0
  93. package/docs/reference/visitor.md +221 -0
  94. package/docs/start/getting-started.md +187 -0
  95. package/docs/start/set-up-a-project.md +214 -0
  96. package/package.json +50 -30
  97. package/schema/spec.schema.json +43 -17
  98. package/dist/appium.adapter.js +0 -489
  99. package/dist/artifacts.js +0 -32
  100. package/dist/fixtures.js +0 -110
  101. package/dist/literate.js +0 -1747
  102. package/dist/match.js +0 -804
  103. package/dist/playwright.adapter.js +0 -349
  104. package/dist/server.js +0 -160
  105. package/dist/stream.js +0 -321
  106. package/dist/substring-warning.js +0 -244
  107. package/docs/01-architecture.md +0 -95
  108. package/docs/02-developing.md +0 -351
  109. package/docs/03-testing.md +0 -495
  110. package/docs/04-operating.md +0 -101
  111. package/docs/05-module-tests.md +0 -152
  112. package/docs/06-integration.md +0 -180
  113. package/docs/07-component.md +0 -246
  114. package/docs/08-website.md +0 -404
  115. package/docs/09-mobile.md +0 -270
  116. package/docs/10-api.md +0 -264
  117. package/docs/11-jobs.md +0 -157
  118. package/docs/12-cli.md +0 -677
  119. package/docs/13-elements.md +0 -242
  120. package/docs/14-assertions.md +0 -314
  121. package/docs/15-tokens.md +0 -253
  122. package/docs/16-contracts.md +0 -438
  123. package/docs/17-services.md +0 -188
  124. package/docs/18-conventions.md +0 -305
  125. package/docs/19-linting.md +0 -510
  126. package/docs/decisions/001-v9-conventions-on-three-channels.md +0 -50
  127. package/docs/decisions/002-the-statique-channel-holds-only-what-upstream-does-not.md +0 -49
  128. package/docs/decisions/003-a-rendered-component-is-a-facet-on-vitest-browser-mode.md +0 -84
  129. package/docs/decisions/004-a-module-against-real-services-or-a-golden-is-the-integration-facet.md +0 -81
  130. package/docs/decisions/005-the-doubles-ladder-is-closed.md +0 -86
  131. package/docs/decisions/006-the-catalogue-reaches-a-file-by-its-role.md +0 -245
  132. package/docs/decisions/007-compose-mode-leaves-the-package.md +0 -53
  133. package/docs/decisions/008-vitest-5-node-24-and-the-native-seams-as-optional-peers.md +0 -75
  134. package/docs/decisions/_template.md +0 -22
  135. package/docs/reference/classes/Matcher.md +0 -120
  136. package/docs/reference/classes/ProcessHandle.md +0 -368
  137. package/docs/reference/functions/defineContract.md +0 -39
  138. package/docs/reference/functions/defineContracts.md +0 -36
  139. package/docs/reference/functions/disabled.md +0 -28
  140. package/docs/reference/functions/enabled.md +0 -20
  141. package/docs/reference/functions/focused.md +0 -26
  142. package/docs/reference/functions/mockOf.md +0 -79
  143. package/docs/reference/functions/postgres.md +0 -31
  144. package/docs/reference/functions/process.md +0 -33
  145. package/docs/reference/functions/redis.md +0 -28
  146. package/docs/reference/functions/required.md +0 -41
  147. package/docs/reference/functions/selected.md +0 -26
  148. package/docs/reference/functions/sqlite.md +0 -33
  149. package/docs/reference/functions/testId.md +0 -20
  150. package/docs/reference/functions/text.md +0 -40
  151. package/docs/reference/functions/valued.md +0 -28
  152. package/docs/reference/functions/waitUntil.md +0 -46
  153. package/docs/reference/functions/within.md +0 -29
  154. package/docs/reference/index.md +0 -196
  155. package/docs/reference/interfaces/BaseResult.md +0 -87
  156. package/docs/reference/interfaces/CallResult.md +0 -160
  157. package/docs/reference/interfaces/CaptureScope.md +0 -82
  158. package/docs/reference/interfaces/CliResult.md +0 -253
  159. package/docs/reference/interfaces/ContainerAccessor.md +0 -166
  160. package/docs/reference/interfaces/DirectoryAccessor.md +0 -33
  161. package/docs/reference/interfaces/FetchResult.md +0 -180
  162. package/docs/reference/interfaces/FilesystemAccessor.md +0 -46
  163. package/docs/reference/interfaces/HttpResult.md +0 -126
  164. package/docs/reference/interfaces/JsonAccessor.md +0 -46
  165. package/docs/reference/interfaces/PageResult.md +0 -356
  166. package/docs/reference/interfaces/RenderResult.md +0 -72
  167. package/docs/reference/interfaces/RenderedText.md +0 -110
  168. package/docs/reference/interfaces/ResponseAccessor.md +0 -47
  169. package/docs/reference/interfaces/ScreenResult.md +0 -128
  170. package/docs/reference/interfaces/TableAccessor.md +0 -26
  171. package/docs/reference/interfaces/TextAccessor.md +0 -96
  172. package/docs/reference/type-aliases/ApiHandle.md +0 -68
  173. package/docs/reference/type-aliases/ApiSpecification.md +0 -213
  174. package/docs/reference/type-aliases/ApiSpecificationOptions.md +0 -68
  175. package/docs/reference/type-aliases/BrowserConsoleMessage.md +0 -30
  176. package/docs/reference/type-aliases/BrowserLinkElement.md +0 -50
  177. package/docs/reference/type-aliases/BrowserMetaElement.md +0 -40
  178. package/docs/reference/type-aliases/BrowserOpenOptions.md +0 -87
  179. package/docs/reference/type-aliases/BrowserPage.md +0 -132
  180. package/docs/reference/type-aliases/BrowserPort.md +0 -51
  181. package/docs/reference/type-aliases/CliEnv.md +0 -11
  182. package/docs/reference/type-aliases/CliHandle.md +0 -80
  183. package/docs/reference/type-aliases/CliInput.md +0 -36
  184. package/docs/reference/type-aliases/CliOutput.md +0 -46
  185. package/docs/reference/type-aliases/CliPort.md +0 -58
  186. package/docs/reference/type-aliases/CliSpecification.md +0 -144
  187. package/docs/reference/type-aliases/CliSpecificationOptions.md +0 -134
  188. package/docs/reference/type-aliases/ComponentChain.md +0 -156
  189. package/docs/reference/type-aliases/ComponentScenario.md +0 -20
  190. package/docs/reference/type-aliases/ComponentUi.md +0 -47
  191. package/docs/reference/type-aliases/ComponentVisitor.md +0 -10
  192. package/docs/reference/type-aliases/ContainerPort.md +0 -113
  193. package/docs/reference/type-aliases/Contract.md +0 -68
  194. package/docs/reference/type-aliases/ContractInput.md +0 -13
  195. package/docs/reference/type-aliases/ContractRequest.md +0 -95
  196. package/docs/reference/type-aliases/ContractResponder.md +0 -23
  197. package/docs/reference/type-aliases/ContractResponse.md +0 -78
  198. package/docs/reference/type-aliases/ContractResponseValue.md +0 -13
  199. package/docs/reference/type-aliases/Contracts.md +0 -48
  200. package/docs/reference/type-aliases/DatabaseKeys.md +0 -16
  201. package/docs/reference/type-aliases/DatabasePort.md +0 -72
  202. package/docs/reference/type-aliases/DeviceOpenOptions.md +0 -46
  203. package/docs/reference/type-aliases/DevicePort.md +0 -51
  204. package/docs/reference/type-aliases/DeviceScreen.md +0 -32
  205. package/docs/reference/type-aliases/DeviceTimeouts.md +0 -39
  206. package/docs/reference/type-aliases/DockerSpecConfig.md +0 -43
  207. package/docs/reference/type-aliases/DomMount.md +0 -21
  208. package/docs/reference/type-aliases/ElementKind.md +0 -27
  209. package/docs/reference/type-aliases/ElementMatch.md +0 -74
  210. package/docs/reference/type-aliases/ElementOptions.md +0 -29
  211. package/docs/reference/type-aliases/ElementRef.md +0 -128
  212. package/docs/reference/type-aliases/ExecOptions.md +0 -37
  213. package/docs/reference/type-aliases/FileAccessor.md +0 -54
  214. package/docs/reference/type-aliases/HonoApp.md +0 -31
  215. package/docs/reference/type-aliases/HttpContractFilter.md +0 -49
  216. package/docs/reference/type-aliases/HttpResponseInit.md +0 -46
  217. package/docs/reference/type-aliases/HttpStreamInit.md +0 -58
  218. package/docs/reference/type-aliases/IntegrationHandle.md +0 -46
  219. package/docs/reference/type-aliases/IntegrationSpecification.md +0 -111
  220. package/docs/reference/type-aliases/IntegrationSpecificationOptions.md +0 -42
  221. package/docs/reference/type-aliases/Intercept.md +0 -19
  222. package/docs/reference/type-aliases/InterceptOptions.md +0 -28
  223. package/docs/reference/type-aliases/InterceptScope.md +0 -11
  224. package/docs/reference/type-aliases/IsolationStrategy.md +0 -75
  225. package/docs/reference/type-aliases/JobHandle.md +0 -34
  226. package/docs/reference/type-aliases/JobsHandle.md +0 -57
  227. package/docs/reference/type-aliases/JobsResult.md +0 -16
  228. package/docs/reference/type-aliases/JobsSpecification.md +0 -94
  229. package/docs/reference/type-aliases/JobsSpecificationOptions.md +0 -56
  230. package/docs/reference/type-aliases/LandmarkKind.md +0 -20
  231. package/docs/reference/type-aliases/LiterateRunFlags.md +0 -27
  232. package/docs/reference/type-aliases/LiterateServeRegistration.md +0 -70
  233. package/docs/reference/type-aliases/MatchFixtureOptions.md +0 -27
  234. package/docs/reference/type-aliases/MatchableRequest.md +0 -61
  235. package/docs/reference/type-aliases/MatcherKind.md +0 -34
  236. package/docs/reference/type-aliases/MobileBackendOptions.md +0 -28
  237. package/docs/reference/type-aliases/MobileElementKind.md +0 -14
  238. package/docs/reference/type-aliases/MobileElementMatch.md +0 -60
  239. package/docs/reference/type-aliases/MobileElementRef.md +0 -20
  240. package/docs/reference/type-aliases/MobileHandle.md +0 -65
  241. package/docs/reference/type-aliases/MobileScenario.md +0 -20
  242. package/docs/reference/type-aliases/MobileSpecification.md +0 -51
  243. package/docs/reference/type-aliases/MobileSpecificationOptions.md +0 -126
  244. package/docs/reference/type-aliases/MobileVisitor.md +0 -81
  245. package/docs/reference/type-aliases/MockOfOptions.md +0 -26
  246. package/docs/reference/type-aliases/MockPort.md +0 -10
  247. package/docs/reference/type-aliases/PinnedClock.md +0 -10
  248. package/docs/reference/type-aliases/PostgresOptions.md +0 -32
  249. package/docs/reference/type-aliases/ProcessOptions.md +0 -112
  250. package/docs/reference/type-aliases/RedisOptions.md +0 -20
  251. package/docs/reference/type-aliases/RenderSubject.md +0 -12
  252. package/docs/reference/type-aliases/ScreenNode.md +0 -67
  253. package/docs/reference/type-aliases/ServerPort.md +0 -36
  254. package/docs/reference/type-aliases/ServerResponse.md +0 -46
  255. package/docs/reference/type-aliases/ServerSpec.md +0 -21
  256. package/docs/reference/type-aliases/ServiceHandle.md +0 -216
  257. package/docs/reference/type-aliases/ServiceRecord.md +0 -12
  258. package/docs/reference/type-aliases/SpecDocument.md +0 -84
  259. package/docs/reference/type-aliases/SpecEnvToken.md +0 -21
  260. package/docs/reference/type-aliases/SpecFileAssertion.md +0 -27
  261. package/docs/reference/type-aliases/SpecFixture.md +0 -30
  262. package/docs/reference/type-aliases/SpecKind.md +0 -8
  263. package/docs/reference/type-aliases/SpecRun.md +0 -108
  264. package/docs/reference/type-aliases/SpecServeEntry.md +0 -40
  265. package/docs/reference/type-aliases/SpecStream.md +0 -32
  266. package/docs/reference/type-aliases/SpecificationConfig.md +0 -290
  267. package/docs/reference/type-aliases/SqliteOptions.md +0 -36
  268. package/docs/reference/type-aliases/SseEvent.md +0 -58
  269. package/docs/reference/type-aliases/StreamBody.md +0 -61
  270. package/docs/reference/type-aliases/TextFilter.md +0 -22
  271. package/docs/reference/type-aliases/VisitScenario.md +0 -20
  272. package/docs/reference/type-aliases/Visitor.md +0 -215
  273. package/docs/reference/type-aliases/WaitUntilOptions.md +0 -46
  274. package/docs/reference/type-aliases/WebsiteBackendOptions.md +0 -37
  275. package/docs/reference/type-aliases/WebsiteHandle.md +0 -51
  276. package/docs/reference/type-aliases/WebsiteSpecification.md +0 -118
  277. package/docs/reference/type-aliases/WebsiteSpecificationOptions.md +0 -40
  278. package/docs/reference/variables/anthropic.md +0 -19
  279. package/docs/reference/variables/banner.md +0 -10
  280. package/docs/reference/variables/button.md +0 -10
  281. package/docs/reference/variables/clock.md +0 -16
  282. package/docs/reference/variables/complementary.md +0 -10
  283. package/docs/reference/variables/component.md +0 -10
  284. package/docs/reference/variables/content.md +0 -10
  285. package/docs/reference/variables/contentinfo.md +0 -10
  286. package/docs/reference/variables/dialog.md +0 -10
  287. package/docs/reference/variables/field.md +0 -10
  288. package/docs/reference/variables/form.md +0 -10
  289. package/docs/reference/variables/heading.md +0 -10
  290. package/docs/reference/variables/http.md +0 -40
  291. package/docs/reference/variables/intercept.md +0 -11
  292. package/docs/reference/variables/link.md +0 -10
  293. package/docs/reference/variables/listitem.md +0 -10
  294. package/docs/reference/variables/main.md +0 -10
  295. package/docs/reference/variables/match.md +0 -8
  296. package/docs/reference/variables/navigation.md +0 -10
  297. package/docs/reference/variables/openai.md +0 -21
  298. package/docs/reference/variables/option.md +0 -17
  299. package/docs/reference/variables/region.md +0 -10
  300. package/docs/reference/variables/row.md +0 -10
  301. package/docs/reference/variables/search.md +0 -10
  302. package/docs/reference/variables/specification.md +0 -8
  303. package/docs/reference/variables/status.md +0 -10
  304. package/docs/reference/variables/table.md +0 -10
@@ -0,0 +1,42 @@
1
+ import { TestProject } from "vitest/node";
2
+ //#region src/specifications/api/routes/ledger.d.ts
3
+ type Shard = {
4
+ count: number;
5
+ index: number;
6
+ };
7
+ declare module 'vitest' {
8
+ interface ProvidedContext {
9
+ routesLedger?: string;
10
+ }
11
+ }
12
+ //#endregion
13
+ //#region src/specifications/api/routes/route-coverage.global-setup.d.ts
14
+ /** Judged only on a whole green run: a shard, a `-t` filter, `--changed` or a failed file is no count. The ratchet is exact both ways; an app with no known route table fails the run. */
15
+ export type RouteProject = {
16
+ config: {
17
+ root: string;
18
+ };
19
+ globTestFiles: () => Promise<{
20
+ testFiles: string[];
21
+ }>;
22
+ name: string;
23
+ provide: (key: 'routesLedger', value: string) => void;
24
+ vitest: {
25
+ config: {
26
+ shard?: Shard | undefined;
27
+ testNamePattern?: RegExp | undefined;
28
+ };
29
+ state: {
30
+ getFailedFilepaths: () => string[];
31
+ getFiles: () => readonly {
32
+ filepath: string;
33
+ projectName?: string | undefined;
34
+ }[];
35
+ };
36
+ };
37
+ };
38
+ export declare function routeCoverageSetup(): string;
39
+ export declare function setupRoutes(project: RouteProject): () => Promise<void>;
40
+ export default function setup(project: TestProject): () => Promise<void>;
41
+ //#endregion
42
+ //# sourceMappingURL=route-coverage.global-setup.d.ts.map
@@ -0,0 +1,2 @@
1
+ import { n as setup, r as setupRoutes, t as routeCoverageSetup } from "./shared-route-coverage.global-setup.js";
2
+ export { setup as default, routeCoverageSetup, setupRoutes };
@@ -0,0 +1,3 @@
1
+ import { C as IsolationStrategy, S as ServiceHandle, a as processService, b as ServiceRecord, c as RedisOptions, d as postgres, i as ProcessOptions, l as redis, n as SeedSource, o as sqlite, r as ProcessHandle, s as SqliteOptions, u as PostgresOptions, w as DatabasePort, y as DatabaseKeys } from "./shared-index.services.js";
2
+ import { n as ContainerPort, t as ContainerOptions } from "./shared-container.port.js";
3
+ export { type ContainerOptions, type ContainerPort, type DatabaseKeys, type DatabasePort, type IsolationStrategy, type PostgresOptions, ProcessHandle, type ProcessOptions, type RedisOptions, type SeedSource, type ServiceHandle, type ServiceRecord, type SqliteOptions, postgres, processService as process, redis, sqlite };
@@ -0,0 +1,43 @@
1
+ import { n as ContainerPort, r as ContainerRequest } from "./shared-container.port.js";
2
+ import { ContainerRuntimeClient } from "testcontainers";
3
+ //#region src/services/containers/run-containers.d.ts
4
+ /** Two requests alike (image, port, environment, options) share one container; the run stops them all at teardown. */
5
+ type RunAddress = {
6
+ host: string;
7
+ key: string;
8
+ port: number;
9
+ };
10
+ declare class RunContainers {
11
+ private readonly started;
12
+ private readonly create;
13
+ private readonly ready;
14
+ /** `ready`'s rejection is the one answer every request gets, and no container is created. */
15
+ constructor(create: (request: ContainerRequest) => ContainerPort, ready?: () => Promise<void>);
16
+ acquire(request: ContainerRequest): Promise<RunAddress>;
17
+ logs(key: string, since?: Date): Promise<string>;
18
+ stop(): Promise<void>;
19
+ private start;
20
+ }
21
+ type ServedContainers = {
22
+ close: () => Promise<void>;
23
+ url: string;
24
+ };
25
+ declare function serveContainers(containers: RunContainers): Promise<ServedContainers>;
26
+ //#endregion
27
+ //#region src/services/containers/services.global-setup.d.ts
28
+ /** Every project's setup joins the one run's containers. Default images are pulled in the background, so the first file waits on a pull at most once; a project declaring no service needs no Docker. */
29
+ export declare const DOCKER_ABSENT = "no Docker daemon answered";
30
+ /** `connect` stands in for the runtime's own client lookup, so the refusal is reachable without a daemon to stop. */
31
+ export declare function prepareDocker(connect?: () => Promise<ContainerRuntimeClient>): Promise<void>;
32
+ export declare function servicesSetup(): string;
33
+ type RunProject = {
34
+ provide: (key: 'serviceContainers', value: string) => void;
35
+ };
36
+ type RunSeams = {
37
+ create: (request: ContainerRequest) => ContainerPort;
38
+ prepare: () => Promise<void>;
39
+ serve: typeof serveContainers;
40
+ };
41
+ export default function setup(project: RunProject, seams?: Partial<RunSeams>): Promise<() => Promise<void>>;
42
+ //#endregion
43
+ //# sourceMappingURL=services.global-setup.d.ts.map
@@ -0,0 +1,2 @@
1
+ import { i as setup, n as prepareDocker, r as servicesSetup, t as DOCKER_ABSENT } from "./shared-services.global-setup.js";
2
+ export { DOCKER_ABSENT, setup as default, prepareDocker, servicesSetup };
@@ -0,0 +1,597 @@
1
+ import { t as discoverRoot } from "./shared-resolve.js";
2
+ import { n as refusal, t as invariant } from "./shared-refusal.js";
3
+ import { t as pause } from "./shared-pause.js";
4
+ import { n as processService, t as ProcessHandle } from "./shared-process.adapter.js";
5
+ import { n as requireBuiltPeer, t as loadPeer } from "./shared-peer.js";
6
+ import { c as SQLITE_TEMPLATE_DIR } from "./shared-artifacts.js";
7
+ import { t as SERVICE_IMAGES } from "./shared-service-images.js";
8
+ import { closeSync, copyFileSync, existsSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
9
+ import { join, resolve } from "node:path";
10
+ import { createHash } from "node:crypto";
11
+ import { tmpdir } from "node:os";
12
+ //#region src/services/driver-reason.ts
13
+ /** What a database driver says went wrong: its message, else its code; a refused connection is an `AggregateError` with an empty message and `ECONNREFUSED`. */
14
+ function driverReason(error) {
15
+ if (error instanceof Error && error.message !== "") return error.message;
16
+ const code = Reflect.get(new Object(error), "code");
17
+ return typeof code === "string" && code !== "" ? code : String(error);
18
+ }
19
+ //#endregion
20
+ //#region src/services/postgres/template.ts
21
+ /** An optional peer: a repository that never connects never pays for the import. */
22
+ async function clientConstructor() {
23
+ return await loadPeer("pg", "postgres()", async () => {
24
+ return (await import("pg")).Client;
25
+ });
26
+ }
27
+ async function endQuietly(client) {
28
+ try {
29
+ await client?.end();
30
+ } catch {}
31
+ }
32
+ function withDatabase$1(connectionString, database) {
33
+ const url = new URL(connectionString);
34
+ url.pathname = `/${database}`;
35
+ return url.toString();
36
+ }
37
+ /** Unique among one container's clones and the same on every run, so a clone a crashed run left is dropped by the next worker of that name. */
38
+ function cloneName(base, service, workerId) {
39
+ return `${base}_${service}_${workerId}`.toLowerCase().replaceAll(/[^a-z0-9_]/gu, "_");
40
+ }
41
+ async function withClient(connectionString, work) {
42
+ const client = new (await (clientConstructor()))({ connectionString });
43
+ client.on("error", () => {});
44
+ await client.connect();
45
+ try {
46
+ return await work(client);
47
+ } finally {
48
+ await endQuietly(client);
49
+ }
50
+ }
51
+ /** Named by the script's digest; built under an advisory lock, marked `IS_TEMPLATE` only once the script ran whole, a crash's unmarked one rebuilt. */
52
+ async function buildTemplate(connectionString, sql, initPath) {
53
+ const template = `template_${createHash("sha256").update(sql).digest("hex").slice(0, 16)}`;
54
+ return await withClient(connectionString, async (admin) => {
55
+ await admin.query("SELECT pg_advisory_lock(hashtext($1))", [template]);
56
+ try {
57
+ if ((await admin.query("SELECT datistemplate FROM pg_database WHERE datname = $1", [template])).rows[0]?.datistemplate === true) return template;
58
+ await admin.query(`DROP DATABASE IF EXISTS "${template}" WITH (FORCE)`);
59
+ await admin.query(`CREATE DATABASE "${template}"`);
60
+ try {
61
+ await withClient(withDatabase$1(connectionString, template), async (builder) => {
62
+ await builder.query(sql);
63
+ });
64
+ } catch (error) {
65
+ await admin.query(`DROP DATABASE IF EXISTS "${template}" WITH (FORCE)`);
66
+ throw new Error(refusal({
67
+ fix: `correct ${initPath}: the SQL fails as written`,
68
+ found: `the postgres init script ${initPath} failed: ${error instanceof Error ? error.message : String(error)}`,
69
+ read: "docs/reference/services.md#dockerserviceinitsql",
70
+ why: "A postgres service's template database is built by its init script, run whole."
71
+ }), { cause: error });
72
+ }
73
+ await admin.query(`ALTER DATABASE "${template}" IS_TEMPLATE true`);
74
+ return template;
75
+ } finally {
76
+ await admin.query("SELECT pg_advisory_unlock(hashtext($1))", [template]);
77
+ }
78
+ });
79
+ }
80
+ //#endregion
81
+ //#region src/services/postgres/postgres.adapter.ts
82
+ const DISPOSABLE = {
83
+ command: [
84
+ "postgres",
85
+ "-c",
86
+ "fsync=off",
87
+ "-c",
88
+ "synchronous_commit=off",
89
+ "-c",
90
+ "full_page_writes=off",
91
+ "-c",
92
+ "log_checkpoints=off"
93
+ ],
94
+ tmpfs: { "/var/lib/postgresql/data": "rw" }
95
+ };
96
+ var PostgresHandle = class {
97
+ type = "postgres";
98
+ serviceName = null;
99
+ defaultPort = 5432;
100
+ defaultImage;
101
+ environment;
102
+ containerOptions = DISPOSABLE;
103
+ connectionString = "";
104
+ client = null;
105
+ template = null;
106
+ clone = null;
107
+ constructor(options = {}) {
108
+ this.defaultImage = options.image ?? SERVICE_IMAGES.postgres;
109
+ this.environment = {
110
+ POSTGRES_DB: "test",
111
+ POSTGRES_PASSWORD: "test",
112
+ POSTGRES_USER: "test",
113
+ ...options.env
114
+ };
115
+ }
116
+ buildConnectionString(host, port) {
117
+ return `postgresql://${this.environment.POSTGRES_USER ?? "test"}:${this.environment.POSTGRES_PASSWORD ?? "test"}@${host}:${port}/${this.environment.POSTGRES_DB ?? "test"}`;
118
+ }
119
+ createDatabaseAdapter() {
120
+ return this;
121
+ }
122
+ async healthcheck() {
123
+ if (!this.connectionString) throw invariant("postgres() was healthchecked before it had a connection string");
124
+ try {
125
+ const client = new (await (clientConstructor()))({ connectionString: this.connectionString });
126
+ await client.connect();
127
+ await client.query("SELECT 1");
128
+ await client.end();
129
+ } catch (error) {
130
+ throw new Error(refusal({
131
+ fix: "check the container is running and reachable (`docker ps`), and run again",
132
+ found: `postgres() did not answer its healthcheck: ${driverReason(error)}`,
133
+ read: "docs/reference/services.md#service-factories",
134
+ why: "A declared service is handed to the chain once it answers its healthcheck."
135
+ }), { cause: error });
136
+ }
137
+ }
138
+ async initialize(dockerDir) {
139
+ const initPaths = [...this.serviceName === null ? [] : [resolve(dockerDir, `${this.serviceName}/init.sql`)], resolve(dockerDir, "postgres/init.sql")];
140
+ for (const initPath of initPaths) if (existsSync(initPath)) {
141
+ this.template = await buildTemplate(this.connectionString, readFileSync(initPath, "utf8"), initPath);
142
+ return;
143
+ }
144
+ }
145
+ async getClient() {
146
+ if (this.client) return this.client;
147
+ const client = new (await (clientConstructor()))({ connectionString: this.connectionString });
148
+ client.on("error", () => {
149
+ this.client = null;
150
+ });
151
+ await client.connect();
152
+ this.client = client;
153
+ return client;
154
+ }
155
+ async seed(sql) {
156
+ await (await this.getClient()).query(sql);
157
+ }
158
+ async reset() {
159
+ const client = await this.getClient();
160
+ const tables = (await client.query(`
161
+ SELECT tablename FROM pg_tables
162
+ WHERE schemaname = 'public'
163
+ AND tablename NOT LIKE '_prisma%'
164
+ `)).rows.map(({ tablename }) => `"public"."${tablename}"`);
165
+ if (tables.length > 0) await client.query(`TRUNCATE ${tables.join(", ")} RESTART IDENTITY CASCADE`);
166
+ }
167
+ async query(table, columns) {
168
+ const client = await this.getClient();
169
+ const columnList = columns.join(", ");
170
+ return (await client.query(`SELECT ${columnList} FROM "public"."${table}" ORDER BY 1`)).rows.map((row) => columns.map((col) => row[col]));
171
+ }
172
+ async columns(table) {
173
+ return (await (await this.getClient()).query("SELECT column_name FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 ORDER BY ordinal_position", ["public", table])).rows.map((row) => row.column_name);
174
+ }
175
+ isolation() {
176
+ return {
177
+ acquire: async (workerId) => {
178
+ const database = cloneName(this.environment.POSTGRES_DB ?? "test", this.serviceName ?? this.type, workerId);
179
+ await withClient(this.connectionString, async (admin) => {
180
+ await admin.query(`DROP DATABASE IF EXISTS "${database}" WITH (FORCE)`);
181
+ await admin.query(`CREATE DATABASE "${database}" TEMPLATE "${this.template ?? "template1"}"`);
182
+ });
183
+ await this.closeClient();
184
+ this.clone = {
185
+ container: this.connectionString,
186
+ database
187
+ };
188
+ this.connectionString = withDatabase$1(this.connectionString, database);
189
+ },
190
+ reset: async () => {
191
+ await this.reset();
192
+ },
193
+ release: async () => {
194
+ await this.closeClient();
195
+ const { clone } = this;
196
+ if (clone === null) return;
197
+ this.connectionString = clone.container;
198
+ this.clone = null;
199
+ await withClient(this.connectionString, async (admin) => {
200
+ await admin.query(`DROP DATABASE IF EXISTS "${clone.database}" WITH (FORCE)`);
201
+ });
202
+ }
203
+ };
204
+ }
205
+ async closeClient() {
206
+ const { client } = this;
207
+ this.client = null;
208
+ await endQuietly(client);
209
+ }
210
+ };
211
+ /** Create a PostgreSQL service handle; its record key names the init script folder (`docker/<key>/init.sql`). */
212
+ function postgres(options = {}) {
213
+ return new PostgresHandle(options);
214
+ }
215
+ //#endregion
216
+ //#region src/services/redis/redis.adapter.ts
217
+ const DATABASES = 256;
218
+ const SERVICES_PER_WORKER = 4;
219
+ const WORKERS = Math.floor(255 / SERVICES_PER_WORKER);
220
+ const PAIR_INDEXES = { command: [
221
+ "redis-server",
222
+ "--databases",
223
+ String(DATABASES)
224
+ ] };
225
+ const slots = /* @__PURE__ */ new Map();
226
+ function slotsOf(worker) {
227
+ const held = slots.get(worker) ?? /* @__PURE__ */ new Map();
228
+ slots.set(worker, held);
229
+ return held;
230
+ }
231
+ function takeSlot(held, service) {
232
+ const pair = held.get(service) ?? {
233
+ holders: 0,
234
+ slot: lowestFree(held)
235
+ };
236
+ pair.holders += 1;
237
+ held.set(service, pair);
238
+ return {
239
+ free: () => {
240
+ pair.holders -= 1;
241
+ if (pair.holders === 0) held.delete(service);
242
+ },
243
+ slot: pair.slot
244
+ };
245
+ }
246
+ function lowestFree(held) {
247
+ const taken = new Set([...held.values()].map((pair) => pair.slot));
248
+ let slot = 0;
249
+ while (taken.has(slot)) slot += 1;
250
+ return slot;
251
+ }
252
+ async function redisDriver() {
253
+ return await loadPeer("redis", "redis()", async () => await import("redis"));
254
+ }
255
+ var RedisHandle = class {
256
+ type = "redis";
257
+ serviceName = null;
258
+ defaultPort = 6379;
259
+ defaultImage;
260
+ environment = {};
261
+ containerOptions = PAIR_INDEXES;
262
+ connectionString = "";
263
+ dbIndex = 0;
264
+ /** What this handle holds: its slot's release, and the container's own string it extended. */
265
+ pair = null;
266
+ constructor(options = {}) {
267
+ this.defaultImage = options.image ?? SERVICE_IMAGES.redis;
268
+ }
269
+ buildConnectionString(host, port) {
270
+ return `redis://${host}:${port}`;
271
+ }
272
+ createDatabaseAdapter() {
273
+ return null;
274
+ }
275
+ async healthcheck() {
276
+ if (!this.connectionString) throw invariant("redis() was healthchecked before it had a connection string");
277
+ try {
278
+ const { createClient } = await redisDriver();
279
+ const client = createClient({ url: this.connectionString });
280
+ await client.connect();
281
+ await client.ping();
282
+ client.destroy();
283
+ } catch (error) {
284
+ throw new Error(refusal({
285
+ fix: "check the container is running and reachable (`docker ps`), and run again",
286
+ found: `redis() did not answer its healthcheck: ${driverReason(error)}`,
287
+ read: "docs/reference/services.md#service-factories",
288
+ why: "A declared service is handed to the chain once it answers its healthcheck."
289
+ }), { cause: error });
290
+ }
291
+ }
292
+ async initialize() {}
293
+ async reset() {
294
+ const { createClient } = await redisDriver();
295
+ const client = createClient({
296
+ url: this.connectionString,
297
+ database: this.dbIndex
298
+ });
299
+ await client.connect();
300
+ try {
301
+ await client.flushDb();
302
+ } finally {
303
+ client.destroy();
304
+ }
305
+ }
306
+ isolation() {
307
+ return {
308
+ acquire: async (workerId) => {
309
+ this.letGo();
310
+ const worker = Number.parseInt(workerId, 10) || 0;
311
+ const service = this.serviceName ?? this.type;
312
+ const { free, slot } = takeSlot(slotsOf(workerId), service);
313
+ if (slot >= SERVICES_PER_WORKER || worker > WORKERS) {
314
+ free();
315
+ throw new Error(refusal({
316
+ fix: slot >= SERVICES_PER_WORKER ? `declare fewer redis services: a worker holds ${SERVICES_PER_WORKER} at once` : `run with fewer workers (--maxWorkers): a container serves ${WORKERS}`,
317
+ found: `redis: worker ${workerId} has no database index for "${service}"`,
318
+ read: "docs/reference/services.md#per-worker-isolation",
319
+ why: "A redis container's indexes are shared out four per worker, so its workers and their services are counted."
320
+ }));
321
+ }
322
+ this.pair = {
323
+ free,
324
+ shared: this.connectionString
325
+ };
326
+ this.dbIndex = 1 + SERVICES_PER_WORKER * (Math.max(worker, 1) - 1) + slot;
327
+ this.connectionString = `${this.connectionString}/${this.dbIndex}`;
328
+ await this.reset();
329
+ },
330
+ reset: async () => {
331
+ await this.reset();
332
+ },
333
+ release: async () => {
334
+ try {
335
+ await this.reset();
336
+ } finally {
337
+ this.letGo();
338
+ }
339
+ }
340
+ };
341
+ }
342
+ letGo() {
343
+ if (this.pair === null) return;
344
+ this.pair.free();
345
+ this.connectionString = this.pair.shared;
346
+ this.pair = null;
347
+ this.dbIndex = 0;
348
+ }
349
+ };
350
+ /** Create a Redis service handle, reported under its record key. */
351
+ function redis(options = {}) {
352
+ return new RedisHandle(options);
353
+ }
354
+ //#endregion
355
+ //#region src/services/sqlite/sqlite-template.ts
356
+ const SQLITE_FILE_HEADER = Buffer.from("SQLite format 3\0");
357
+ function withDescriptor(path, flags, use) {
358
+ const fd = openSync(path, flags);
359
+ try {
360
+ return use(fd);
361
+ } finally {
362
+ closeSync(fd);
363
+ }
364
+ }
365
+ /** Checks the header only: enough to reject a 0-byte or truncated leftover. */
366
+ function isValidSqliteTemplate(path) {
367
+ try {
368
+ return withDescriptor(path, "r", (fd) => {
369
+ const header = Buffer.alloc(SQLITE_FILE_HEADER.length);
370
+ return readSync(fd, header, 0, header.length, 0) === SQLITE_FILE_HEADER.length && header.equals(SQLITE_FILE_HEADER);
371
+ });
372
+ } catch {
373
+ return false;
374
+ }
375
+ }
376
+ const PRISMA_PUSH = "npx prisma db push --force-reset";
377
+ /** `--schema` is required: without it Prisma's own discovery ignores the option, and only a machine without a cached template fails. */
378
+ function prismaPushCommand(prismaSchema) {
379
+ if (prismaSchema === null) return PRISMA_PUSH;
380
+ return `${PRISMA_PUSH} --schema ${JSON.stringify(resolve(prismaSchema))}`;
381
+ }
382
+ const TEMPLATE_PREFIX = "template";
383
+ const LOCK_STALE_MS = 12e4;
384
+ function schemaBytes(path) {
385
+ try {
386
+ if (statSync(path).isDirectory()) return readdirSync(path).toSorted().map((entry) => schemaBytes(join(path, entry))).join("\0");
387
+ return `${path}\0${readFileSync(path, "utf8")}`;
388
+ } catch {
389
+ return `${path}\0<unreadable>`;
390
+ }
391
+ }
392
+ /** Editing a schema builds a new template: the stale file is header-valid and would never be rebuilt. */
393
+ function sqliteTemplateName(options = {}) {
394
+ const [source, path] = options.prismaSchema === void 0 ? ["init", options.init] : ["prisma", options.prismaSchema];
395
+ const fingerprint = path === void 0 ? "empty" : `${source}\0${resolve(path)}\0${schemaBytes(resolve(path))}`;
396
+ const key = createHash("sha256").update(fingerprint).digest("hex").slice(0, 8);
397
+ return `${TEMPLATE_PREFIX}-${key}.sqlite`;
398
+ }
399
+ /** Per project, never the OS tmpdir: two checkouts sharing one template inherit each other's schema. */
400
+ function sqliteTemplateDir(root) {
401
+ const dir = resolve(root, SQLITE_TEMPLATE_DIR);
402
+ mkdirSync(dir, { recursive: true });
403
+ return dir;
404
+ }
405
+ /** `wx` creates and claims the file in one syscall: two workers cannot both win and run `prisma db push` on one file. */
406
+ function acquireTemplateLock(lockPath) {
407
+ try {
408
+ withDescriptor(lockPath, "wx", (fd) => writeSync(fd, process.pid.toString()));
409
+ } catch (error) {
410
+ if (error instanceof Error && "code" in error && error.code === "EEXIST") return false;
411
+ throw error;
412
+ }
413
+ return true;
414
+ }
415
+ function releaseTemplateLock(lockPath) {
416
+ try {
417
+ unlinkSync(lockPath);
418
+ } catch {}
419
+ }
420
+ /** A lock that no longer exists is not stale: the waiter retries. */
421
+ function isStaleTemplateLock(lockPath, now = Date.now()) {
422
+ try {
423
+ return now - statSync(lockPath).mtimeMs > LOCK_STALE_MS;
424
+ } catch {
425
+ return false;
426
+ }
427
+ }
428
+ //#endregion
429
+ //#region src/services/sqlite/sqlite.adapter.ts
430
+ let databaseConstructor = null;
431
+ async function loadDatabase() {
432
+ if (databaseConstructor === null) {
433
+ const constructor = await loadPeer("better-sqlite3", "sqlite()", async () => {
434
+ return (await import("better-sqlite3")).default;
435
+ });
436
+ requireBuiltPeer("better-sqlite3", "sqlite()", () => {
437
+ new constructor(":memory:").close();
438
+ });
439
+ databaseConstructor = constructor;
440
+ }
441
+ return databaseConstructor;
442
+ }
443
+ function database() {
444
+ if (databaseConstructor === null) throw invariant("sqlite() was read before `initialize()` loaded its driver");
445
+ return databaseConstructor;
446
+ }
447
+ function openInWal(path) {
448
+ const db = new (database())(path);
449
+ db.pragma("journal_mode = WAL");
450
+ return db;
451
+ }
452
+ const LOCK_POLL_MS = 50;
453
+ const SIDECARS = [
454
+ "",
455
+ "-wal",
456
+ "-shm"
457
+ ];
458
+ function removeDatabaseFiles(path) {
459
+ for (const suffix of SIDECARS) rmSync(`${path}${suffix}`, { force: true });
460
+ }
461
+ function withDatabase(path, use) {
462
+ const db = new (database())(path);
463
+ try {
464
+ use(db);
465
+ } finally {
466
+ db.close();
467
+ }
468
+ }
469
+ var SqliteHandle = class {
470
+ type = "sqlite";
471
+ serviceName = null;
472
+ defaultPort = 0;
473
+ defaultImage = "";
474
+ environment = {};
475
+ connectionString = "";
476
+ db = null;
477
+ templatePath = "";
478
+ workerDbPath = "";
479
+ initSql;
480
+ prismaSchema;
481
+ options;
482
+ constructor(options = {}) {
483
+ this.options = options;
484
+ this.initSql = options.init ?? null;
485
+ this.prismaSchema = options.prismaSchema ?? null;
486
+ }
487
+ buildConnectionString() {
488
+ return `file:${this.workerDbPath || this.templatePath}`;
489
+ }
490
+ createDatabaseAdapter() {
491
+ return this;
492
+ }
493
+ async healthcheck() {}
494
+ /** One worker builds under an exclusive lock, the others wait: two concurrent `prisma db push` on one file is `database is locked`. */
495
+ async initialize(_dockerDir, root) {
496
+ await loadDatabase();
497
+ const projectRoot = root ?? discoverRoot(process.cwd());
498
+ this.templatePath = resolve(sqliteTemplateDir(projectRoot), sqliteTemplateName(this.options));
499
+ const lockPath = `${this.templatePath}.lock`;
500
+ for (;;) {
501
+ if (isValidSqliteTemplate(this.templatePath)) break;
502
+ if (!acquireTemplateLock(lockPath)) {
503
+ if (isStaleTemplateLock(lockPath)) releaseTemplateLock(lockPath);
504
+ else await pause(LOCK_POLL_MS);
505
+ continue;
506
+ }
507
+ try {
508
+ await this.buildTemplate();
509
+ } finally {
510
+ releaseTemplateLock(lockPath);
511
+ }
512
+ break;
513
+ }
514
+ this.connectionString = `file:${this.templatePath}`;
515
+ }
516
+ /** Built on a private path, then renamed into place: `prisma db push` writes the header long before the tables exist. */
517
+ async buildTemplate() {
518
+ const buildPath = `${this.templatePath}.${process.pid}.building`;
519
+ removeDatabaseFiles(buildPath);
520
+ try {
521
+ await this.writeTemplate(buildPath);
522
+ renameSync(buildPath, this.templatePath);
523
+ } finally {
524
+ removeDatabaseFiles(buildPath);
525
+ }
526
+ }
527
+ async writeTemplate(buildPath) {
528
+ if (this.prismaSchema !== null) {
529
+ const { runToCompletion } = await import("./shared-serve.js").then((n) => n.n);
530
+ runToCompletion(prismaPushCommand(this.prismaSchema), {
531
+ ...process.env,
532
+ DATABASE_URL: `file:${buildPath}`,
533
+ PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION: "yes"
534
+ });
535
+ withDatabase(buildPath, (db) => {
536
+ db.pragma("wal_checkpoint(TRUNCATE)");
537
+ });
538
+ return;
539
+ }
540
+ const { initSql } = this;
541
+ withDatabase(buildPath, (db) => {
542
+ if (initSql !== null) db.exec(readFileSync(initSql, "utf8"));
543
+ db.exec("VACUUM");
544
+ });
545
+ }
546
+ getDb() {
547
+ this.db ??= openInWal(this.workerDbPath || this.templatePath);
548
+ return this.db;
549
+ }
550
+ closeDb() {
551
+ this.db?.close();
552
+ this.db = null;
553
+ }
554
+ async seed(sql) {
555
+ this.getDb().exec(sql);
556
+ }
557
+ async query(table, columns) {
558
+ const columnList = columns.join(", ");
559
+ return this.getDb().prepare(`SELECT ${columnList} FROM "${table}" ORDER BY 1`).all().map((row) => columns.map((col) => row[col]));
560
+ }
561
+ async columns(table) {
562
+ return this.getDb().prepare(`PRAGMA table_info("${table}")`).all().map((row) => row.name);
563
+ }
564
+ async reset() {
565
+ const db = this.getDb();
566
+ const tables = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE '_prisma%' AND name != 'sqlite_sequence'`).all();
567
+ for (const { name } of tables) db.exec(`DELETE FROM "${name}"`);
568
+ if (db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name = 'sqlite_sequence'`).get() !== void 0) db.exec("DELETE FROM sqlite_sequence");
569
+ }
570
+ isolation() {
571
+ return {
572
+ acquire: async (workerId) => {
573
+ this.closeDb();
574
+ this.workerDbPath = resolve(tmpdir(), `test-worker-${workerId}-${process.pid}-${Date.now()}.sqlite`);
575
+ copyFileSync(this.templatePath, this.workerDbPath);
576
+ this.connectionString = `file:${this.workerDbPath}`;
577
+ },
578
+ reset: async () => {
579
+ await this.reset();
580
+ },
581
+ release: async () => {
582
+ this.closeDb();
583
+ removeDatabaseFiles(this.workerDbPath);
584
+ this.workerDbPath = "";
585
+ this.connectionString = `file:${this.templatePath}`;
586
+ }
587
+ };
588
+ }
589
+ };
590
+ /** Create a SQLite service handle, isolated per test by file copy. */
591
+ function sqlite(options = {}) {
592
+ return new SqliteHandle(options);
593
+ }
594
+ //#endregion
595
+ export { ProcessHandle, postgres, processService as process, redis, sqlite };
596
+
597
+ //# sourceMappingURL=services.js.map