@smthrs/kernel 0.0.0-stage → 1.0.0-rc.3

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 (267) hide show
  1. package/CHANGELOG.md +206 -0
  2. package/LICENSE +21 -0
  3. package/README.md +154 -2
  4. package/dist/cjs/CapabilitySet.d.ts +6 -0
  5. package/dist/cjs/CapabilitySet.d.ts.map +1 -0
  6. package/dist/cjs/CapabilitySet.js +19 -0
  7. package/dist/cjs/CapabilitySet.js.map +7 -0
  8. package/dist/cjs/ChildProcessEnvironment.d.ts +60 -0
  9. package/dist/cjs/ChildProcessEnvironment.d.ts.map +1 -0
  10. package/dist/cjs/ChildProcessEnvironment.js +61 -0
  11. package/dist/cjs/ChildProcessEnvironment.js.map +7 -0
  12. package/dist/cjs/ChildProcessSpawner.d.ts +100 -0
  13. package/dist/cjs/ChildProcessSpawner.d.ts.map +1 -0
  14. package/dist/cjs/ChildProcessSpawner.js +291 -0
  15. package/dist/cjs/ChildProcessSpawner.js.map +7 -0
  16. package/dist/cjs/CommandLine.d.ts +173 -0
  17. package/dist/cjs/CommandLine.d.ts.map +1 -0
  18. package/dist/cjs/CommandLine.js +54 -0
  19. package/dist/cjs/CommandLine.js.map +7 -0
  20. package/dist/cjs/ContainedSpawner.d.ts +135 -0
  21. package/dist/cjs/ContainedSpawner.d.ts.map +1 -0
  22. package/dist/cjs/ContainedSpawner.js +141 -0
  23. package/dist/cjs/ContainedSpawner.js.map +7 -0
  24. package/dist/cjs/FileSystem.d.ts +452 -0
  25. package/dist/cjs/FileSystem.d.ts.map +1 -0
  26. package/dist/cjs/FileSystem.js +890 -0
  27. package/dist/cjs/FileSystem.js.map +7 -0
  28. package/dist/cjs/FileSystemBatch.d.ts +94 -0
  29. package/dist/cjs/FileSystemBatch.d.ts.map +1 -0
  30. package/dist/cjs/FileSystemBatch.js +31 -0
  31. package/dist/cjs/FileSystemBatch.js.map +7 -0
  32. package/dist/cjs/GrantEvent.d.ts +240 -0
  33. package/dist/cjs/GrantEvent.d.ts.map +1 -0
  34. package/dist/cjs/GrantEvent.js +115 -0
  35. package/dist/cjs/GrantEvent.js.map +7 -0
  36. package/dist/cjs/GrantStore.d.ts +270 -0
  37. package/dist/cjs/GrantStore.d.ts.map +1 -0
  38. package/dist/cjs/GrantStore.js +857 -0
  39. package/dist/cjs/GrantStore.js.map +7 -0
  40. package/dist/cjs/HostError.d.ts +36 -0
  41. package/dist/cjs/HostError.d.ts.map +1 -0
  42. package/dist/cjs/HostError.js +17 -0
  43. package/dist/cjs/HostError.js.map +7 -0
  44. package/dist/cjs/HostServices.d.ts +101 -0
  45. package/dist/cjs/HostServices.d.ts.map +1 -0
  46. package/dist/cjs/HostServices.js +66 -0
  47. package/dist/cjs/HostServices.js.map +7 -0
  48. package/dist/cjs/HttpClient.d.ts +177 -0
  49. package/dist/cjs/HttpClient.d.ts.map +1 -0
  50. package/dist/cjs/HttpClient.js +217 -0
  51. package/dist/cjs/HttpClient.js.map +7 -0
  52. package/dist/cjs/Jj.d.ts +67 -0
  53. package/dist/cjs/Jj.d.ts.map +1 -0
  54. package/dist/cjs/Jj.js +118 -0
  55. package/dist/cjs/Jj.js.map +7 -0
  56. package/dist/cjs/JournalGrantStore.d.ts +65 -0
  57. package/dist/cjs/JournalGrantStore.d.ts.map +1 -0
  58. package/dist/cjs/JournalGrantStore.js +354 -0
  59. package/dist/cjs/JournalGrantStore.js.map +7 -0
  60. package/dist/cjs/Path.d.ts +37 -0
  61. package/dist/cjs/Path.d.ts.map +1 -0
  62. package/dist/cjs/Path.js +46 -0
  63. package/dist/cjs/Path.js.map +7 -0
  64. package/dist/cjs/ProcessConfinement.d.ts +55 -0
  65. package/dist/cjs/ProcessConfinement.d.ts.map +1 -0
  66. package/dist/cjs/ProcessConfinement.js +94 -0
  67. package/dist/cjs/ProcessConfinement.js.map +7 -0
  68. package/dist/cjs/ProcessLedger.d.ts +260 -0
  69. package/dist/cjs/ProcessLedger.d.ts.map +1 -0
  70. package/dist/cjs/ProcessLedger.js +190 -0
  71. package/dist/cjs/ProcessLedger.js.map +7 -0
  72. package/dist/cjs/Rooted.d.ts +53 -0
  73. package/dist/cjs/Rooted.d.ts.map +1 -0
  74. package/dist/cjs/Rooted.js +101 -0
  75. package/dist/cjs/Rooted.js.map +7 -0
  76. package/dist/cjs/Unreachable.d.ts +27 -0
  77. package/dist/cjs/Unreachable.d.ts.map +1 -0
  78. package/dist/cjs/Unreachable.js +43 -0
  79. package/dist/cjs/Unreachable.js.map +7 -0
  80. package/dist/cjs/Workspace.d.ts +62 -0
  81. package/dist/cjs/Workspace.d.ts.map +1 -0
  82. package/dist/cjs/Workspace.js +35 -0
  83. package/dist/cjs/Workspace.js.map +7 -0
  84. package/dist/cjs/index.d.ts +161 -0
  85. package/dist/cjs/index.d.ts.map +1 -0
  86. package/dist/cjs/index.js +73 -0
  87. package/dist/cjs/index.js.map +7 -0
  88. package/dist/cjs/internal/Containment.d.ts +24 -0
  89. package/dist/cjs/internal/Containment.d.ts.map +1 -0
  90. package/dist/cjs/internal/Containment.js +30 -0
  91. package/dist/cjs/internal/Containment.js.map +7 -0
  92. package/dist/cjs/internal/Pipeline.d.ts +18 -0
  93. package/dist/cjs/internal/Pipeline.d.ts.map +1 -0
  94. package/dist/cjs/internal/Pipeline.js +90 -0
  95. package/dist/cjs/internal/Pipeline.js.map +7 -0
  96. package/dist/cjs/internal/makeCapability.d.ts +16 -0
  97. package/dist/cjs/internal/makeCapability.d.ts.map +1 -0
  98. package/dist/cjs/internal/makeCapability.js +44 -0
  99. package/dist/cjs/internal/makeCapability.js.map +7 -0
  100. package/dist/cjs/package.json +1 -0
  101. package/dist/cjs/test/FileSystemBatchContract.d.ts +15 -0
  102. package/dist/cjs/test/FileSystemBatchContract.d.ts.map +1 -0
  103. package/dist/cjs/test/FileSystemBatchContract.js +76 -0
  104. package/dist/cjs/test/FileSystemBatchContract.js.map +7 -0
  105. package/dist/cjs/test/HostContract.d.ts +225 -0
  106. package/dist/cjs/test/HostContract.d.ts.map +1 -0
  107. package/dist/cjs/test/HostContract.js +489 -0
  108. package/dist/cjs/test/HostContract.js.map +7 -0
  109. package/dist/cjs/test/TestGrantStore.d.ts +31 -0
  110. package/dist/cjs/test/TestGrantStore.d.ts.map +1 -0
  111. package/dist/cjs/test/TestGrantStore.js +65 -0
  112. package/dist/cjs/test/TestGrantStore.js.map +7 -0
  113. package/dist/esm/CapabilitySet.d.ts +6 -0
  114. package/dist/esm/CapabilitySet.d.ts.map +1 -0
  115. package/dist/esm/CapabilitySet.js +6 -0
  116. package/dist/esm/CapabilitySet.js.map +1 -0
  117. package/dist/esm/ChildProcessEnvironment.d.ts +60 -0
  118. package/dist/esm/ChildProcessEnvironment.d.ts.map +1 -0
  119. package/dist/esm/ChildProcessEnvironment.js +91 -0
  120. package/dist/esm/ChildProcessEnvironment.js.map +1 -0
  121. package/dist/esm/ChildProcessSpawner.d.ts +100 -0
  122. package/dist/esm/ChildProcessSpawner.d.ts.map +1 -0
  123. package/dist/esm/ChildProcessSpawner.js +342 -0
  124. package/dist/esm/ChildProcessSpawner.js.map +1 -0
  125. package/dist/esm/CommandLine.d.ts +173 -0
  126. package/dist/esm/CommandLine.d.ts.map +1 -0
  127. package/dist/esm/CommandLine.js +195 -0
  128. package/dist/esm/CommandLine.js.map +1 -0
  129. package/dist/esm/ContainedSpawner.d.ts +135 -0
  130. package/dist/esm/ContainedSpawner.d.ts.map +1 -0
  131. package/dist/esm/ContainedSpawner.js +180 -0
  132. package/dist/esm/ContainedSpawner.js.map +1 -0
  133. package/dist/esm/FileSystem.d.ts +452 -0
  134. package/dist/esm/FileSystem.d.ts.map +1 -0
  135. package/dist/esm/FileSystem.js +989 -0
  136. package/dist/esm/FileSystem.js.map +1 -0
  137. package/dist/esm/FileSystemBatch.d.ts +94 -0
  138. package/dist/esm/FileSystemBatch.d.ts.map +1 -0
  139. package/dist/esm/FileSystemBatch.js +26 -0
  140. package/dist/esm/FileSystemBatch.js.map +1 -0
  141. package/dist/esm/GrantEvent.d.ts +240 -0
  142. package/dist/esm/GrantEvent.d.ts.map +1 -0
  143. package/dist/esm/GrantEvent.js +155 -0
  144. package/dist/esm/GrantEvent.js.map +1 -0
  145. package/dist/esm/GrantStore.d.ts +270 -0
  146. package/dist/esm/GrantStore.d.ts.map +1 -0
  147. package/dist/esm/GrantStore.js +951 -0
  148. package/dist/esm/GrantStore.js.map +1 -0
  149. package/dist/esm/HostError.d.ts +36 -0
  150. package/dist/esm/HostError.d.ts.map +1 -0
  151. package/dist/esm/HostError.js +20 -0
  152. package/dist/esm/HostError.js.map +1 -0
  153. package/dist/esm/HostServices.d.ts +101 -0
  154. package/dist/esm/HostServices.d.ts.map +1 -0
  155. package/dist/esm/HostServices.js +76 -0
  156. package/dist/esm/HostServices.js.map +1 -0
  157. package/dist/esm/HttpClient.d.ts +177 -0
  158. package/dist/esm/HttpClient.d.ts.map +1 -0
  159. package/dist/esm/HttpClient.js +299 -0
  160. package/dist/esm/HttpClient.js.map +1 -0
  161. package/dist/esm/Jj.d.ts +67 -0
  162. package/dist/esm/Jj.d.ts.map +1 -0
  163. package/dist/esm/Jj.js +111 -0
  164. package/dist/esm/Jj.js.map +1 -0
  165. package/dist/esm/JournalGrantStore.d.ts +65 -0
  166. package/dist/esm/JournalGrantStore.d.ts.map +1 -0
  167. package/dist/esm/JournalGrantStore.js +350 -0
  168. package/dist/esm/JournalGrantStore.js.map +1 -0
  169. package/dist/esm/Path.d.ts +37 -0
  170. package/dist/esm/Path.d.ts.map +1 -0
  171. package/dist/esm/Path.js +34 -0
  172. package/dist/esm/Path.js.map +1 -0
  173. package/dist/esm/ProcessConfinement.d.ts +55 -0
  174. package/dist/esm/ProcessConfinement.d.ts.map +1 -0
  175. package/dist/esm/ProcessConfinement.js +106 -0
  176. package/dist/esm/ProcessConfinement.js.map +1 -0
  177. package/dist/esm/ProcessLedger.d.ts +260 -0
  178. package/dist/esm/ProcessLedger.d.ts.map +1 -0
  179. package/dist/esm/ProcessLedger.js +283 -0
  180. package/dist/esm/ProcessLedger.js.map +1 -0
  181. package/dist/esm/Rooted.d.ts +53 -0
  182. package/dist/esm/Rooted.d.ts.map +1 -0
  183. package/dist/esm/Rooted.js +104 -0
  184. package/dist/esm/Rooted.js.map +1 -0
  185. package/dist/esm/Unreachable.d.ts +27 -0
  186. package/dist/esm/Unreachable.d.ts.map +1 -0
  187. package/dist/esm/Unreachable.js +26 -0
  188. package/dist/esm/Unreachable.js.map +1 -0
  189. package/dist/esm/Workspace.d.ts +62 -0
  190. package/dist/esm/Workspace.d.ts.map +1 -0
  191. package/dist/esm/Workspace.js +51 -0
  192. package/dist/esm/Workspace.js.map +1 -0
  193. package/dist/esm/index.d.ts +161 -0
  194. package/dist/esm/index.d.ts.map +1 -0
  195. package/dist/esm/index.js +151 -0
  196. package/dist/esm/index.js.map +1 -0
  197. package/dist/esm/internal/Containment.d.ts +24 -0
  198. package/dist/esm/internal/Containment.d.ts.map +1 -0
  199. package/dist/esm/internal/Containment.js +27 -0
  200. package/dist/esm/internal/Containment.js.map +1 -0
  201. package/dist/esm/internal/Pipeline.d.ts +18 -0
  202. package/dist/esm/internal/Pipeline.d.ts.map +1 -0
  203. package/dist/esm/internal/Pipeline.js +68 -0
  204. package/dist/esm/internal/Pipeline.js.map +1 -0
  205. package/dist/esm/internal/makeCapability.d.ts +16 -0
  206. package/dist/esm/internal/makeCapability.d.ts.map +1 -0
  207. package/dist/esm/internal/makeCapability.js +22 -0
  208. package/dist/esm/internal/makeCapability.js.map +1 -0
  209. package/dist/esm/test/FileSystemBatchContract.d.ts +15 -0
  210. package/dist/esm/test/FileSystemBatchContract.d.ts.map +1 -0
  211. package/dist/esm/test/FileSystemBatchContract.js +57 -0
  212. package/dist/esm/test/FileSystemBatchContract.js.map +1 -0
  213. package/dist/esm/test/HostContract.d.ts +225 -0
  214. package/dist/esm/test/HostContract.d.ts.map +1 -0
  215. package/dist/esm/test/HostContract.js +460 -0
  216. package/dist/esm/test/HostContract.js.map +1 -0
  217. package/dist/esm/test/TestGrantStore.d.ts +31 -0
  218. package/dist/esm/test/TestGrantStore.d.ts.map +1 -0
  219. package/dist/esm/test/TestGrantStore.js +57 -0
  220. package/dist/esm/test/TestGrantStore.js.map +1 -0
  221. package/docs/README.md +162 -0
  222. package/docs/api.md +1532 -0
  223. package/docs/concepts/decoration-in-place.md +117 -0
  224. package/docs/concepts/filesystem-batches.md +58 -0
  225. package/docs/concepts/filesystem-confinement.md +168 -0
  226. package/docs/concepts/grant-decisions.md +181 -0
  227. package/docs/concepts/process-containment.md +155 -0
  228. package/docs/contract.md +14 -0
  229. package/docs/guides/adapt-a-new-host-platform.md +148 -0
  230. package/docs/guides/answer-permission-requests.md +151 -0
  231. package/docs/guides/authorize-network-and-model-calls.md +118 -0
  232. package/docs/guides/contain-spawned-processes.md +118 -0
  233. package/docs/guides/guard-a-host-bundle.md +109 -0
  234. package/docs/guides/persist-grants-across-restarts.md +135 -0
  235. package/docs/guides/write-a-capability-policy.md +159 -0
  236. package/docs/installation.md +115 -0
  237. package/docs/quickstart.md +182 -0
  238. package/docs/testing.md +108 -0
  239. package/docs/troubleshooting.md +281 -0
  240. package/package.json +344 -3
  241. package/src/CapabilitySet.ts +6 -0
  242. package/src/ChildProcessEnvironment.ts +98 -0
  243. package/src/ChildProcessSpawner.ts +414 -0
  244. package/src/CommandLine.ts +250 -0
  245. package/src/ContainedSpawner.ts +284 -0
  246. package/src/FileSystem.ts +1655 -0
  247. package/src/FileSystemBatch.ts +90 -0
  248. package/src/GrantEvent.ts +174 -0
  249. package/src/GrantStore.ts +1345 -0
  250. package/src/HostError.ts +37 -0
  251. package/src/HostServices.ts +133 -0
  252. package/src/HttpClient.ts +406 -0
  253. package/src/Jj.ts +159 -0
  254. package/src/JournalGrantStore.ts +461 -0
  255. package/src/Path.ts +47 -0
  256. package/src/ProcessConfinement.ts +156 -0
  257. package/src/ProcessLedger.ts +423 -0
  258. package/src/Rooted.ts +128 -0
  259. package/src/Unreachable.ts +30 -0
  260. package/src/Workspace.ts +65 -0
  261. package/src/index.ts +181 -0
  262. package/src/internal/Containment.ts +37 -0
  263. package/src/internal/Pipeline.ts +85 -0
  264. package/src/internal/makeCapability.ts +26 -0
  265. package/src/test/FileSystemBatchContract.ts +59 -0
  266. package/src/test/HostContract.ts +785 -0
  267. package/src/test/TestGrantStore.ts +73 -0
@@ -0,0 +1,489 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var HostContract_exports = {};
30
+ __export(HostContract_exports, {
31
+ FileSystemOperations: () => FileSystemOperations,
32
+ JjOperations: () => JjOperations,
33
+ assertFailure: () => assertFailure,
34
+ checkFileSystemBatch: () => import_FileSystemBatchContract.check,
35
+ defaultScratchPath: () => defaultScratchPath,
36
+ errorCode: () => errorCode,
37
+ runHostContract: () => runHostContract
38
+ });
39
+ module.exports = __toCommonJS(HostContract_exports);
40
+ var import_vitest = require("@effect/vitest");
41
+ var JjService = __toESM(require("@smthrs/jj"), 1);
42
+ var import_effect = require("effect");
43
+ var import_HttpClient = require("effect/unstable/http/HttpClient");
44
+ var HttpClientRequest = __toESM(require("effect/unstable/http/HttpClientRequest"), 1);
45
+ var ChildProcess = __toESM(require("effect/unstable/process/ChildProcess"), 1);
46
+ var import_ChildProcessSpawner = require("effect/unstable/process/ChildProcessSpawner");
47
+ var import_node_os = require("node:os");
48
+ var import_node_path = require("node:path");
49
+ var FileSystemBatchContract = __toESM(require("./FileSystemBatchContract.js"), 1);
50
+ var import_FileSystemBatchContract = require("./FileSystemBatchContract.js");
51
+ const FileSystemOperations = [
52
+ "access",
53
+ "copy",
54
+ "copyFile",
55
+ "chmod",
56
+ "chown",
57
+ "glob",
58
+ "exists",
59
+ "link",
60
+ "makeDirectory",
61
+ "makeTempDirectory",
62
+ "makeTempDirectoryScoped",
63
+ "makeTempFile",
64
+ "makeTempFileScoped",
65
+ "open",
66
+ "readDirectory",
67
+ "readFile",
68
+ "readFileString",
69
+ "readLink",
70
+ "realPath",
71
+ "remove",
72
+ "rename",
73
+ "sink",
74
+ "stat",
75
+ "stream",
76
+ "symlink",
77
+ "truncate",
78
+ "utimes",
79
+ "watch",
80
+ "writeFile",
81
+ "writeFileString"
82
+ ];
83
+ const JjOperations = [
84
+ "snapshot",
85
+ "restore",
86
+ "diff",
87
+ "workspaceAdd",
88
+ "workspaceForget",
89
+ "status",
90
+ "root",
91
+ "revert"
92
+ ];
93
+ const errorCode = (error) => {
94
+ if (typeof error !== "object" || error === null) return void 0;
95
+ if ("code" in error && typeof error.code === "string") return error.code;
96
+ if ("reason" in error && typeof error.reason === "object" && error.reason !== null && "_tag" in error.reason && typeof error.reason._tag === "string") {
97
+ return error.reason._tag;
98
+ }
99
+ if ("_tag" in error && typeof error._tag === "string") return error._tag;
100
+ return void 0;
101
+ };
102
+ const assertFailure = (effect, code) => effect.pipe(
103
+ import_effect.Effect.match({
104
+ onFailure: (error) => {
105
+ (0, import_vitest.expect)(errorCode(error)).toBe(code);
106
+ },
107
+ onSuccess: () => {
108
+ throw new Error(`expected typed failure ${code}`);
109
+ }
110
+ })
111
+ );
112
+ let scratchSeq = 0;
113
+ const defaultScratchPath = (suite) => {
114
+ const slug = suite.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "host";
115
+ return (0, import_node_path.join)((0, import_node_os.tmpdir)(), `flows-host-contract-${process.pid}-${++scratchSeq}-${slug}`);
116
+ };
117
+ const provide = (effect, layer) => effect.pipe(import_effect.Effect.provide(layer));
118
+ const run = (effect, layer) => provide(effect, layer);
119
+ const unsupported = ChildProcess.make("host-contract-unsupported");
120
+ const unsupportedChildProcess = (operation, code) => import_effect.Effect.gen(function* () {
121
+ const spawner = yield* import_ChildProcessSpawner.ChildProcessSpawner;
122
+ yield* operation === "stream" ? assertFailure(import_effect.Stream.runDrain(spawner.streamString(unsupported)), code) : assertFailure(spawner.string(unsupported), code);
123
+ });
124
+ const fileSystemProbe = (fs, operation, root) => {
125
+ const at = (name) => `${root}/${operation}-${name}`;
126
+ const source = `${root}/source.txt`;
127
+ const bytes = new TextEncoder().encode("host-contract");
128
+ switch (operation) {
129
+ case "access":
130
+ return fs.access(source);
131
+ case "copy":
132
+ return fs.copy(source, at("copy.txt"));
133
+ case "copyFile":
134
+ return fs.copyFile(source, at("copy-file.txt"));
135
+ case "chmod":
136
+ return fs.chmod(source, 384);
137
+ case "chown":
138
+ return import_effect.Effect.flatMap(fs.stat(source), (info) => fs.chown(
139
+ source,
140
+ import_effect.Option.getOrElse(info.uid, () => 0),
141
+ import_effect.Option.getOrElse(info.gid, () => 0)
142
+ ));
143
+ case "glob":
144
+ return fs.glob("**/*.txt", { root });
145
+ case "exists":
146
+ return import_effect.Effect.tap(fs.exists(source), (exists) => import_effect.Effect.sync(() => (0, import_vitest.expect)(exists).toBe(true)));
147
+ case "link":
148
+ return fs.link(source, at("hard-link.txt"));
149
+ case "makeDirectory":
150
+ return fs.makeDirectory(at("directory"), { recursive: true });
151
+ case "makeTempDirectory":
152
+ return fs.makeTempDirectory({ directory: root });
153
+ case "makeTempDirectoryScoped":
154
+ return import_effect.Effect.scoped(fs.makeTempDirectoryScoped({ directory: root }));
155
+ case "makeTempFile":
156
+ return fs.makeTempFile({ directory: root });
157
+ case "makeTempFileScoped":
158
+ return import_effect.Effect.scoped(fs.makeTempFileScoped({ directory: root }));
159
+ case "open":
160
+ return import_effect.Effect.scoped(fs.open(source, { flag: "r" }));
161
+ case "readDirectory":
162
+ return import_effect.Effect.tap(fs.readDirectory(root), (entries) => import_effect.Effect.sync(() => {
163
+ (0, import_vitest.expect)(Array.isArray(entries)).toBe(true);
164
+ (0, import_vitest.expect)(entries.every((entry) => typeof entry === "string")).toBe(true);
165
+ }));
166
+ case "readFile":
167
+ return import_effect.Effect.gen(function* () {
168
+ const first = yield* fs.readFile(source);
169
+ (0, import_vitest.expect)(first).toBeInstanceOf(Uint8Array);
170
+ const original = first[0];
171
+ (0, import_vitest.expect)(original).toBeDefined();
172
+ first[0] = original ^ 255;
173
+ const second = yield* fs.readFile(source);
174
+ (0, import_vitest.expect)(second[0]).toBe(original);
175
+ });
176
+ case "readFileString":
177
+ return fs.readFileString(source);
178
+ case "readLink": {
179
+ const link = at("symbolic-link.txt");
180
+ return fs.symlink(source, link).pipe(import_effect.Effect.andThen(fs.readLink(link)));
181
+ }
182
+ case "realPath":
183
+ return fs.realPath(source);
184
+ case "remove": {
185
+ const path = at("remove.txt");
186
+ return fs.writeFile(path, bytes).pipe(import_effect.Effect.andThen(fs.remove(path)));
187
+ }
188
+ case "rename": {
189
+ const from = at("rename-from.txt");
190
+ return fs.writeFile(from, bytes).pipe(import_effect.Effect.andThen(fs.rename(from, at("rename-to.txt"))));
191
+ }
192
+ case "sink":
193
+ return import_effect.Stream.run(import_effect.Stream.succeed(bytes), fs.sink(at("sink.txt")));
194
+ case "stat":
195
+ return import_effect.Effect.tap(fs.stat(source), (info) => import_effect.Effect.sync(() => {
196
+ (0, import_vitest.expect)(typeof info.size).toBe("bigint");
197
+ (0, import_vitest.expect)(typeof info.type).toBe("string");
198
+ }));
199
+ case "stream":
200
+ return import_effect.Stream.runForEach(
201
+ fs.stream(source),
202
+ (chunk) => import_effect.Effect.sync(() => (0, import_vitest.expect)(chunk).toBeInstanceOf(Uint8Array))
203
+ );
204
+ case "symlink":
205
+ return fs.symlink(source, at("symlink.txt"));
206
+ case "truncate": {
207
+ const path = at("truncate.txt");
208
+ return fs.writeFile(path, bytes).pipe(import_effect.Effect.andThen(fs.truncate(path, 1)));
209
+ }
210
+ case "utimes":
211
+ return fs.utimes(source, /* @__PURE__ */ new Date(0), /* @__PURE__ */ new Date(0));
212
+ case "watch":
213
+ return import_effect.Effect.gen(function* () {
214
+ const watched = yield* import_effect.Stream.runHead(fs.watch(root)).pipe(
215
+ import_effect.Effect.timeout("5 seconds"),
216
+ import_effect.Effect.forkChild({ startImmediately: true })
217
+ );
218
+ yield* import_effect.Effect.raceFirst(
219
+ import_effect.Fiber.join(watched),
220
+ fs.writeFile(at("watched.txt"), bytes).pipe(
221
+ import_effect.Effect.andThen(import_effect.Effect.promise(() => new Promise((resolve) => setTimeout(resolve, 10)))),
222
+ import_effect.Effect.forever
223
+ )
224
+ );
225
+ });
226
+ case "writeFile":
227
+ return import_effect.Effect.gen(function* () {
228
+ const input = bytes.slice();
229
+ const expected = input[0];
230
+ (0, import_vitest.expect)(expected).toBeDefined();
231
+ yield* fs.writeFile(at("write.txt"), input);
232
+ input[0] = expected ^ 255;
233
+ (0, import_vitest.expect)((yield* fs.readFile(at("write.txt")))[0]).toBe(expected);
234
+ });
235
+ case "writeFileString":
236
+ return fs.writeFileString(at("write-string.txt"), "host-contract");
237
+ }
238
+ };
239
+ const defaultStdinCommand = ChildProcess.make(
240
+ process.execPath,
241
+ [
242
+ "-e",
243
+ `let input = ""; process.stdin.setEncoding("utf8"); process.stdin.on("data", chunk => input += chunk); process.stdin.on("end", () => process.stdout.write(input.replace(/\\r?\\n$/, "")));`
244
+ ],
245
+ { stdin: import_effect.Stream.fromArray([new TextEncoder().encode("stdin\n")]) }
246
+ );
247
+ const defaultPipelineCommand = ChildProcess.pipeTo(
248
+ ChildProcess.make(process.execPath, ["-e", `process.stdout.write("host-contract-pipeline")`]),
249
+ ChildProcess.make(process.execPath, ["-e", "process.stdin.pipe(process.stdout)"])
250
+ );
251
+ const defaultInterruptCommand = ChildProcess.pipeTo(
252
+ ChildProcess.make(process.execPath, ["-e", "setTimeout(() => {}, 10_000)"]),
253
+ ChildProcess.make(process.execPath, ["-e", "process.stdin.pipe(process.stdout)"])
254
+ );
255
+ const runHostContract = (name, layer, caps) => {
256
+ const fileSystemCap = caps.fileSystem;
257
+ const pathCap = caps.path;
258
+ const childProcessCap = caps.childProcess;
259
+ const jjCap = caps.jj;
260
+ const httpClientCap = caps.httpClient;
261
+ const scratchPath = fileSystemCap.expected === "success" ? fileSystemCap.scratchPath ?? defaultScratchPath(name) : "";
262
+ (0, import_vitest.describe)(`${name} Host contract`, () => {
263
+ import_vitest.it.live("provides every tag in the closed Host service list", () => run(
264
+ import_effect.Effect.gen(function* () {
265
+ yield* import_effect.FileSystem.FileSystem;
266
+ yield* import_effect.Path.Path;
267
+ yield* import_ChildProcessSpawner.ChildProcessSpawner;
268
+ yield* JjService.Jj;
269
+ yield* import_HttpClient.HttpClient;
270
+ }),
271
+ layer
272
+ ));
273
+ import_vitest.it.live("declares every FileSystem operation", () => run(
274
+ fileSystemCap.expected === "failure" ? import_effect.Effect.gen(function* () {
275
+ const fs = yield* import_effect.FileSystem.FileSystem;
276
+ yield* import_effect.Effect.forEach(
277
+ FileSystemOperations,
278
+ (operation) => assertFailure(
279
+ fileSystemProbe(fs, operation, "/host-contract/unsupported"),
280
+ fileSystemCap.code
281
+ ),
282
+ { discard: true }
283
+ );
284
+ }) : import_effect.Effect.gen(function* () {
285
+ const fs = yield* import_effect.FileSystem.FileSystem;
286
+ const root = scratchPath;
287
+ const bytes = new TextEncoder().encode("host-contract");
288
+ yield* import_effect.Effect.gen(function* () {
289
+ yield* fs.makeDirectory(root, { recursive: true });
290
+ yield* fs.writeFile(`${root}/source.txt`, bytes);
291
+ yield* FileSystemBatchContract.check(fs, root);
292
+ yield* import_effect.Effect.forEach(
293
+ FileSystemOperations,
294
+ (operation) => {
295
+ const probe = fileSystemProbe(fs, operation, root);
296
+ const code = fileSystemCap.unsupported?.[operation];
297
+ return code === void 0 ? probe : assertFailure(probe, code);
298
+ },
299
+ { discard: true }
300
+ );
301
+ }).pipe(
302
+ import_effect.Effect.ensuring(fs.remove(root, { recursive: true, force: true }).pipe(import_effect.Effect.ignore))
303
+ );
304
+ }),
305
+ layer
306
+ ));
307
+ import_vitest.it.live("declares Path behavior", () => run(
308
+ pathCap.expected === "failure" ? import_effect.Effect.gen(function* () {
309
+ const path = yield* import_effect.Path.Path;
310
+ yield* assertFailure(
311
+ import_effect.Effect.try({
312
+ try: () => path.fromFileUrl(new URL("file:///host-contract/value")),
313
+ catch: (error) => error
314
+ }),
315
+ pathCap.code
316
+ );
317
+ }) : import_effect.Effect.gen(function* () {
318
+ const path = yield* import_effect.Path.Path;
319
+ (0, import_vitest.expect)(path.normalize("/host-contract/./nested/../value")).toBe(`${path.sep}host-contract${path.sep}value`);
320
+ }),
321
+ layer
322
+ ));
323
+ import_vitest.it.live("declares buffered child-process behavior", () => run(
324
+ childProcessCap.expected === "failure" ? unsupportedChildProcess("string", childProcessCap.code) : import_effect.Effect.gen(function* () {
325
+ const spawner = yield* import_ChildProcessSpawner.ChildProcessSpawner;
326
+ const command = childProcessCap.execCommand ?? ChildProcess.make(process.execPath, ["-e", `process.stdout.write("host-contract")`]);
327
+ (0, import_vitest.expect)(yield* spawner.string(command)).toBe(childProcessCap.expectedStdout ?? "host-contract");
328
+ (0, import_vitest.expect)(yield* spawner.exitCode(command)).toBe(0);
329
+ }),
330
+ layer
331
+ ));
332
+ import_vitest.it.live("declares child-process streaming behavior", () => run(
333
+ childProcessCap.expected === "failure" ? unsupportedChildProcess("stream", childProcessCap.code) : import_effect.Effect.gen(function* () {
334
+ const spawner = yield* import_ChildProcessSpawner.ChildProcessSpawner;
335
+ const output = yield* import_effect.Stream.mkString(
336
+ spawner.streamString(
337
+ childProcessCap.streamCommand ?? ChildProcess.make(process.execPath, ["-e", `process.stdout.write("host-contract-stream")`])
338
+ )
339
+ );
340
+ (0, import_vitest.expect)(output).toContain(childProcessCap.expectedStreamText ?? "host-contract-stream");
341
+ }),
342
+ layer
343
+ ));
344
+ import_vitest.it.live("declares child-process cwd and env option behavior", () => run(
345
+ childProcessCap.expected === "failure" ? unsupportedChildProcess("string", childProcessCap.code) : import_effect.Effect.gen(function* () {
346
+ const spawner = yield* import_ChildProcessSpawner.ChildProcessSpawner;
347
+ const output = yield* spawner.string(
348
+ childProcessCap.optionsCommand ?? ChildProcess.make(process.execPath, ["-e", "process.stdout.write(process.env.HOST_CONTRACT_ENV)"], {
349
+ cwd: (0, import_node_os.tmpdir)(),
350
+ env: { HOST_CONTRACT_ENV: "env" },
351
+ extendEnv: true
352
+ })
353
+ );
354
+ (0, import_vitest.expect)(output).toBe(childProcessCap.expectedOptionsStdout ?? "env");
355
+ }),
356
+ layer
357
+ ));
358
+ import_vitest.it.live("declares child-process stdin behavior", () => run(
359
+ import_effect.Effect.gen(function* () {
360
+ const spawner = yield* import_ChildProcessSpawner.ChildProcessSpawner;
361
+ const stdinCap = childProcessCap.expected === "failure" ? childProcessCap : childProcessCap.stdin ?? { command: defaultStdinCommand, expectedStdout: "stdin" };
362
+ if ("expected" in stdinCap) {
363
+ yield* assertFailure(spawner.string(defaultStdinCommand), stdinCap.code);
364
+ return;
365
+ }
366
+ (0, import_vitest.expect)(yield* spawner.string(stdinCap.command)).toBe(stdinCap.expectedStdout);
367
+ }),
368
+ layer
369
+ ));
370
+ import_vitest.it.live("declares child-process pipeline behavior", () => run(
371
+ import_effect.Effect.gen(function* () {
372
+ const spawner = yield* import_ChildProcessSpawner.ChildProcessSpawner;
373
+ const pipelineCap = childProcessCap.expected === "failure" ? childProcessCap : childProcessCap.pipeline ?? {
374
+ command: defaultPipelineCommand,
375
+ expectedStdout: "host-contract-pipeline"
376
+ };
377
+ if ("expected" in pipelineCap) {
378
+ yield* assertFailure(spawner.string(defaultPipelineCommand), pipelineCap.code);
379
+ return;
380
+ }
381
+ (0, import_vitest.expect)(yield* spawner.string(pipelineCap.command)).toBe(pipelineCap.expectedStdout);
382
+ }),
383
+ layer
384
+ ));
385
+ import_vitest.it.live("declares child-process interruption behavior", () => run(
386
+ childProcessCap.expected === "failure" ? unsupportedChildProcess("stream", childProcessCap.code) : import_effect.Effect.gen(function* () {
387
+ const spawner = yield* import_ChildProcessSpawner.ChildProcessSpawner;
388
+ const ready = yield* import_effect.Deferred.make();
389
+ const fiber = yield* import_effect.Effect.scoped(
390
+ import_effect.Effect.gen(function* () {
391
+ const handle2 = yield* spawner.spawn(
392
+ childProcessCap.interruptCommand ?? defaultInterruptCommand
393
+ );
394
+ yield* import_effect.Deferred.succeed(ready, handle2);
395
+ yield* handle2.exitCode;
396
+ })
397
+ ).pipe(
398
+ import_effect.Effect.forkChild({ startImmediately: true })
399
+ );
400
+ const handle = yield* import_effect.Deferred.await(ready);
401
+ (0, import_vitest.expect)(yield* handle.isRunning).toBe(true);
402
+ yield* import_effect.Fiber.interrupt(fiber);
403
+ (0, import_vitest.expect)(yield* handle.isRunning).toBe(false);
404
+ }),
405
+ layer
406
+ ));
407
+ import_vitest.it.live("declares every Jj operation", () => run(
408
+ jjCap.expected === "failure" ? import_effect.Effect.gen(function* () {
409
+ const jj = yield* JjService.Jj;
410
+ const root = jj.root;
411
+ const revert = jj.revert;
412
+ (0, import_vitest.expect)(root).toBeTypeOf("function");
413
+ (0, import_vitest.expect)(revert).toBeTypeOf("function");
414
+ yield* import_effect.Effect.forEach([
415
+ jj.snapshot("host contract"),
416
+ jj.restore("host-contract-change"),
417
+ jj.diff("host-contract-from", "host-contract-to"),
418
+ jj.workspaceAdd("host-contract", "/host-contract/workspace", "host-contract-change"),
419
+ jj.workspaceForget("host-contract"),
420
+ jj.status(),
421
+ root("/host-contract"),
422
+ revert("host-contract-change")
423
+ ], (probe) => assertFailure(probe, jjCap.code), { discard: true });
424
+ }) : import_effect.Effect.gen(function* () {
425
+ const jj = yield* JjService.Jj;
426
+ const root = jj.root;
427
+ const revert = jj.revert;
428
+ (0, import_vitest.expect)(root).toBeTypeOf("function");
429
+ (0, import_vitest.expect)(revert).toBeTypeOf("function");
430
+ yield* jjCap.prepareChange?.("first") ?? import_effect.Effect.void;
431
+ const first = yield* jj.snapshot("host contract first");
432
+ (0, import_vitest.expect)(first.changeId.length).toBeGreaterThan(0);
433
+ yield* jjCap.prepareChange?.("second") ?? import_effect.Effect.void;
434
+ const second = yield* jj.snapshot("host contract second");
435
+ (0, import_vitest.expect)(second.changeId.length).toBeGreaterThan(0);
436
+ (0, import_vitest.expect)(typeof (yield* jj.diff(first.changeId, second.changeId))).toBe("string");
437
+ const revertCode = jjCap.unsupported?.revert;
438
+ if (revertCode === void 0) {
439
+ const reverted = yield* revert(second.changeId);
440
+ (0, import_vitest.expect)(Array.isArray(reverted.reverted)).toBe(true);
441
+ (0, import_vitest.expect)(reverted.reverted.every(
442
+ (path) => typeof path === "string"
443
+ )).toBe(true);
444
+ } else {
445
+ yield* assertFailure(revert(second.changeId), revertCode);
446
+ }
447
+ yield* jj.restore(first.changeId);
448
+ const workspaceName = `host-contract-${process.pid}-${++scratchSeq}`;
449
+ yield* jj.workspaceAdd(
450
+ workspaceName,
451
+ jjCap.workspacePath ?? defaultScratchPath(`${name}-jj-workspace`),
452
+ first.changeId
453
+ );
454
+ yield* jj.workspaceForget(workspaceName);
455
+ (0, import_vitest.expect)(typeof (yield* jj.status())).toBe("string");
456
+ const rootCode = jjCap.unsupported?.root;
457
+ const rootFrom = jjCap.rootFrom ?? ".";
458
+ if (rootCode === void 0) {
459
+ (0, import_vitest.expect)((yield* root(rootFrom)).length).toBeGreaterThan(0);
460
+ } else {
461
+ yield* assertFailure(root(rootFrom), rootCode);
462
+ }
463
+ }),
464
+ layer
465
+ ));
466
+ import_vitest.it.live("declares HTTP read, write, and redirect behavior", () => run(
467
+ httpClientCap.expected === "failure" ? import_effect.Effect.gen(function* () {
468
+ const client = yield* import_HttpClient.HttpClient;
469
+ yield* import_effect.Effect.forEach([
470
+ HttpClientRequest.get("http://127.0.0.1:1/host-contract/read"),
471
+ HttpClientRequest.post("http://127.0.0.1:1/host-contract/write").pipe(
472
+ HttpClientRequest.bodyText("host-contract")
473
+ ),
474
+ HttpClientRequest.get("http://127.0.0.1:1/host-contract/redirect")
475
+ ], (request) => assertFailure(client.execute(request), httpClientCap.code), { discard: true });
476
+ }) : import_effect.Effect.gen(function* () {
477
+ const client = yield* import_HttpClient.HttpClient;
478
+ for (const probe of [httpClientCap.read, httpClientCap.write, httpClientCap.redirect]) {
479
+ const response = yield* client.execute(probe.request);
480
+ (0, import_vitest.expect)(typeof response.status).toBe("number");
481
+ (0, import_vitest.expect)(typeof response.headers).toBe("object");
482
+ probe.assertResponse(response);
483
+ }
484
+ }),
485
+ layer
486
+ ));
487
+ });
488
+ };
489
+ //# sourceMappingURL=HostContract.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/test/HostContract.ts"],
4
+ "sourcesContent": ["/**\n * Shared contract suite for complete Host bundles.\n *\n * This module is emitted as ESM, CJS, and declarations and exported from\n * `@smthrs/kernel/test/contract`. It intentionally has a Vitest peer because\n * it registers a reusable behavioral contract for third-party Host bundles.\n *\n * @since 1.0.0-rc.0\n */\n\n// Every case here runs on real elapsed time \u2014 subprocess spawns, file locks,\n// mtimes, and poll loops \u2014 so the suite uses `it.live`; `it.effect`'s\n// TestClock never advances for them.\n\nimport { describe, expect, it } from \"@effect/vitest\"\nimport * as JjService from \"@smthrs/jj\"\nimport type { Jj, JjErrorCode } from \"@smthrs/jj\"\nimport { Deferred, Effect, Fiber, FileSystem, type Layer, Option, Path, Stream } from \"effect\"\nimport { HttpClient } from \"effect/unstable/http/HttpClient\"\nimport * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\"\nimport type * as HttpClientResponse from \"effect/unstable/http/HttpClientResponse\"\nimport * as ChildProcess from \"effect/unstable/process/ChildProcess\"\nimport { type ChildProcessHandle, ChildProcessSpawner } from \"effect/unstable/process/ChildProcessSpawner\"\nimport { tmpdir } from \"node:os\"\nimport { join } from \"node:path\"\nimport * as FileSystemBatchContract from \"./FileSystemBatchContract.ts\"\n\nexport { check as checkFileSystemBatch } from \"./FileSystemBatchContract.ts\"\n\n/**\n * A capability that must fail with a stable typed code.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface FailureCapability<Code extends string> {\n readonly expected: \"failure\"\n readonly code: Code\n}\n\n/**\n * Successful filesystem contract options.\n *\n * `scratchPath` is required only for hosts whose filesystem does not accept an\n * OS temp path \u2014 an in-memory double, say. Omitting it takes\n * {@link defaultScratchPath}, which is process-scoped and outside the working\n * tree.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface FileSystemSuccess {\n readonly expected: \"success\"\n readonly scratchPath?: string | undefined\n /** Operations this otherwise available host deliberately refuses. */\n readonly unsupported?: Partial<Record<FileSystemOperation, string>> | undefined\n}\n\n/**\n * Every method on Effect's closed filesystem service.\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const FileSystemOperations = [\n \"access\",\n \"copy\",\n \"copyFile\",\n \"chmod\",\n \"chown\",\n \"glob\",\n \"exists\",\n \"link\",\n \"makeDirectory\",\n \"makeTempDirectory\",\n \"makeTempDirectoryScoped\",\n \"makeTempFile\",\n \"makeTempFileScoped\",\n \"open\",\n \"readDirectory\",\n \"readFile\",\n \"readFileString\",\n \"readLink\",\n \"realPath\",\n \"remove\",\n \"rename\",\n \"sink\",\n \"stat\",\n \"stream\",\n \"symlink\",\n \"truncate\",\n \"utimes\",\n \"watch\",\n \"writeFile\",\n \"writeFileString\"\n] as const\n\n/**\n * One method of Effect's closed filesystem service.\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type FileSystemOperation = typeof FileSystemOperations[number]\n\n/**\n * Successful Path contract expectation.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface PathSuccess {\n readonly expected: \"success\"\n}\n\n/**\n * Successful `ChildProcessSpawner` contract options.\n *\n * Defaults use the current Node or Bun executable. In-process browser\n * doubles can provide their own scripted commands and expected output.\n *\n * There is no timeout case: a wall-clock budget is `Effect.timeout` around any\n * effect, not a per-spawn option, so there is nothing host-specific left to\n * assert.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface ChildProcessSuccess {\n readonly expected: \"success\"\n readonly execCommand?: ChildProcess.Command | undefined\n readonly expectedStdout?: string | undefined\n readonly streamCommand?: ChildProcess.Command | undefined\n readonly expectedStreamText?: string | undefined\n /** A command carrying `cwd` and `env` options through to the child. */\n readonly optionsCommand?: ChildProcess.Command | undefined\n readonly expectedOptionsStdout?: string | undefined\n /**\n * How the host handles a command fed from a `stdin` stream: the expected\n * stdout when it supports one, or the typed code when it does not.\n */\n readonly stdin?:\n | { readonly command: ChildProcess.Command; readonly expectedStdout: string }\n | FailureCapability<string>\n | undefined\n /** A two-leg pipeline, or the exact typed refusal for hosts without one. */\n readonly pipeline?:\n | { readonly command: ChildProcess.Command; readonly expectedStdout: string }\n | FailureCapability<string>\n | undefined\n readonly interruptCommand?: ChildProcess.Command | undefined\n}\n\n/**\n * Successful Jj contract expectation.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface JjSuccess {\n readonly expected: \"success\"\n /** Makes the first and second snapshots observably different. */\n readonly prepareChange?: ((phase: \"first\" | \"second\") => Effect.Effect<void, unknown>) | undefined\n /** Nonexistent path at which the contract may add one temporary workspace. */\n readonly workspacePath?: string | undefined\n /** Path whose repository root the host must resolve. */\n readonly rootFrom?: string | undefined\n /** Optional methods this otherwise available backend explicitly refuses. */\n readonly unsupported?: Partial<Record<\"root\" | \"revert\", JjErrorCode>> | undefined\n}\n\n/**\n * Every method on the closed Jj host service.\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const JjOperations = [\n \"snapshot\",\n \"restore\",\n \"diff\",\n \"workspaceAdd\",\n \"workspaceForget\",\n \"status\",\n \"root\",\n \"revert\"\n] as const\n\n/**\n * One method of the closed Jj host service.\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type JjOperation = typeof JjOperations[number]\n\n/**\n * Successful HTTP contract probe.\n *\n * A request is explicit so the shared suite never invents a live network call.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface HttpClientProbe {\n /** Exact request the host must execute. */\n readonly request: HttpClientRequest.HttpClientRequest\n /** Adapter-specific response proof. */\n readonly assertResponse: (response: HttpClientResponse.HttpClientResponse) => void\n}\n\n/**\n * Successful read/write/redirect HTTP contract probes.\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface HttpClientSuccess {\n readonly expected: \"success\"\n /** Safe read method. */\n readonly read: HttpClientProbe\n /** Body-carrying write method. */\n readonly write: HttpClientProbe\n /** Manual redirect response; the host must not follow it below the guard. */\n readonly redirect: HttpClientProbe\n}\n\n/**\n * Complete capability expectations for the closed five-tag Host surface.\n * Unsupported capabilities are asserted with their code and are never skipped.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface HostContractCapabilities {\n readonly fileSystem: FileSystemSuccess | FailureCapability<string>\n readonly path: PathSuccess | FailureCapability<string>\n readonly childProcess: ChildProcessSuccess | FailureCapability<string>\n readonly jj: JjSuccess | FailureCapability<JjErrorCode>\n readonly httpClient: HttpClientSuccess | FailureCapability<string>\n}\n\n/**\n * The full layer output required by the contract.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type HostContractLayer = Layer.Layer<\n FileSystem.FileSystem | Path.Path | ChildProcessSpawner | Jj | HttpClient,\n unknown\n>\n\n/**\n * Normalizes the code a Host failure is identified by, across the three shapes\n * the closed surface produces: a `code` field (`JjError`), a nested\n * `reason._tag` (`PlatformError`, `HttpClientError`), and a bare `_tag`.\n * Anything else is uncoded.\n *\n * @category testing\n * @since 1.0.0-rc.0\n */\nexport const errorCode = (error: unknown): string | undefined => {\n if (typeof error !== \"object\" || error === null) return undefined\n if (\"code\" in error && typeof error.code === \"string\") return error.code\n if (\n \"reason\" in error &&\n typeof error.reason === \"object\" &&\n error.reason !== null &&\n \"_tag\" in error.reason &&\n typeof error.reason._tag === \"string\"\n ) {\n return error.reason._tag\n }\n if (\"_tag\" in error && typeof error._tag === \"string\") return error._tag\n return undefined\n}\n\n/**\n * Asserts that `effect` fails with `code`. Succeeding is itself a contract\n * violation: a capability declared unsupported must never quietly work.\n *\n * @category testing\n * @since 1.0.0-rc.0\n */\nexport const assertFailure = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n code: string\n): Effect.Effect<void, never, R> =>\n effect.pipe(\n Effect.match({\n onFailure: (error) => {\n expect(errorCode(error)).toBe(code)\n },\n onSuccess: () => {\n throw new Error(`expected typed failure ${code}`)\n }\n })\n )\n\nlet scratchSeq = 0\n\n/**\n * Allocates the scratch file path a contract bundle writes through when the\n * caller declares no `scratchPath` of its own.\n *\n * The path is absolute under the OS temp directory and scoped by both process\n * id and an allocation counter. A repo-relative default would put the file in\n * the working tree, where it is neither ignored by git nor private to one test\n * process: concurrent `vitest run` invocations would then race the same path,\n * and the suite's `ensuring` remove could truncate a sibling's file between its\n * write and its read.\n *\n * @category testing\n * @since 1.0.0-rc.0\n */\nexport const defaultScratchPath = (suite: string): string => {\n const slug = suite.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-+|-+$/g, \"\") || \"host\"\n // Ambient `process.pid` on purpose: this is a Node-only test harness that\n // must name a path unique to THIS operating-system process before any layer\n // exists to ask. Injecting it would only move the same read one frame out.\n return join(tmpdir(), `flows-host-contract-${process.pid}-${++scratchSeq}-${slug}`)\n}\n\n/** Everything a {@link HostContractLayer} provides; a case may use nothing else. */\ntype HostServices = Layer.Success<HostContractLayer>\n\nconst provide = <A, E>(\n effect: Effect.Effect<A, E, HostServices>,\n layer: HostContractLayer\n): Effect.Effect<A, E | unknown> => effect.pipe(Effect.provide(layer))\n\nconst run = <A, E>(effect: Effect.Effect<A, E, HostServices>, layer: HostContractLayer) => provide(effect, layer)\n\nconst unsupported = ChildProcess.make(\"host-contract-unsupported\")\n\nconst unsupportedChildProcess = (operation: \"string\" | \"stream\", code: string) =>\n Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner\n yield* operation === \"stream\"\n ? assertFailure(Stream.runDrain(spawner.streamString(unsupported)), code)\n : assertFailure(spawner.string(unsupported), code)\n })\n\nconst fileSystemProbe = (\n fs: FileSystem.FileSystem,\n operation: FileSystemOperation,\n root: string\n): Effect.Effect<unknown, unknown> => {\n const at = (name: string): string => `${root}/${operation}-${name}`\n const source = `${root}/source.txt`\n const bytes = new TextEncoder().encode(\"host-contract\")\n switch (operation) {\n case \"access\":\n return fs.access(source)\n case \"copy\":\n return fs.copy(source, at(\"copy.txt\"))\n case \"copyFile\":\n return fs.copyFile(source, at(\"copy-file.txt\"))\n case \"chmod\":\n return fs.chmod(source, 0o600)\n case \"chown\":\n return Effect.flatMap(fs.stat(source), (info) =>\n fs.chown(\n source,\n Option.getOrElse(info.uid, () => 0),\n Option.getOrElse(info.gid, () => 0)\n ))\n case \"glob\":\n return fs.glob(\"**/*.txt\", { root })\n case \"exists\":\n return Effect.tap(fs.exists(source), (exists) => Effect.sync(() => expect(exists).toBe(true)))\n case \"link\":\n return fs.link(source, at(\"hard-link.txt\"))\n case \"makeDirectory\":\n return fs.makeDirectory(at(\"directory\"), { recursive: true })\n case \"makeTempDirectory\":\n return fs.makeTempDirectory({ directory: root })\n case \"makeTempDirectoryScoped\":\n return Effect.scoped(fs.makeTempDirectoryScoped({ directory: root }))\n case \"makeTempFile\":\n return fs.makeTempFile({ directory: root })\n case \"makeTempFileScoped\":\n return Effect.scoped(fs.makeTempFileScoped({ directory: root }))\n case \"open\":\n return Effect.scoped(fs.open(source, { flag: \"r\" }))\n case \"readDirectory\":\n return Effect.tap(fs.readDirectory(root), (entries) =>\n Effect.sync(() => {\n expect(Array.isArray(entries)).toBe(true)\n expect(entries.every((entry) => typeof entry === \"string\")).toBe(true)\n }))\n case \"readFile\":\n return Effect.gen(function*() {\n const first = yield* fs.readFile(source)\n expect(first).toBeInstanceOf(Uint8Array)\n const original = first[0]\n expect(original).toBeDefined()\n first[0] = original! ^ 0xff\n const second = yield* fs.readFile(source)\n expect(second[0]).toBe(original)\n })\n case \"readFileString\":\n return fs.readFileString(source)\n case \"readLink\": {\n const link = at(\"symbolic-link.txt\")\n return fs.symlink(source, link).pipe(Effect.andThen(fs.readLink(link)))\n }\n case \"realPath\":\n return fs.realPath(source)\n case \"remove\": {\n const path = at(\"remove.txt\")\n return fs.writeFile(path, bytes).pipe(Effect.andThen(fs.remove(path)))\n }\n case \"rename\": {\n const from = at(\"rename-from.txt\")\n return fs.writeFile(from, bytes).pipe(Effect.andThen(fs.rename(from, at(\"rename-to.txt\"))))\n }\n case \"sink\":\n return Stream.run(Stream.succeed(bytes), fs.sink(at(\"sink.txt\")))\n case \"stat\":\n return Effect.tap(fs.stat(source), (info) =>\n Effect.sync(() => {\n expect(typeof info.size).toBe(\"bigint\")\n expect(typeof info.type).toBe(\"string\")\n }))\n case \"stream\":\n return Stream.runForEach(\n fs.stream(source),\n (chunk) => Effect.sync(() => expect(chunk).toBeInstanceOf(Uint8Array))\n )\n case \"symlink\":\n return fs.symlink(source, at(\"symlink.txt\"))\n case \"truncate\": {\n const path = at(\"truncate.txt\")\n return fs.writeFile(path, bytes).pipe(Effect.andThen(fs.truncate(path, 1)))\n }\n case \"utimes\":\n return fs.utimes(source, new Date(0), new Date(0))\n case \"watch\":\n return Effect.gen(function*() {\n const watched = yield* Stream.runHead(fs.watch(root)).pipe(\n Effect.timeout(\"5 seconds\"),\n Effect.forkChild({ startImmediately: true })\n )\n // Keep producing events until the watcher observes one: subscribing\n // can take longer than any fixed initial delay. The foreign Promise\n // also works when the supplied host provides a frozen TestClock.\n yield* Effect.raceFirst(\n Fiber.join(watched),\n fs.writeFile(at(\"watched.txt\"), bytes).pipe(\n Effect.andThen(Effect.promise(() => new Promise((resolve) => setTimeout(resolve, 10)))),\n Effect.forever\n )\n )\n })\n case \"writeFile\":\n return Effect.gen(function*() {\n const input = bytes.slice()\n const expected = input[0]\n expect(expected).toBeDefined()\n yield* fs.writeFile(at(\"write.txt\"), input)\n input[0] = expected! ^ 0xff\n expect((yield* fs.readFile(at(\"write.txt\")))[0]).toBe(expected)\n })\n case \"writeFileString\":\n return fs.writeFileString(at(\"write-string.txt\"), \"host-contract\")\n }\n}\n\n/** The default stdin probe: echo back one line read from the child's stdin. */\nconst defaultStdinCommand = ChildProcess.make(\n process.execPath,\n [\n \"-e\",\n `let input = \"\"; process.stdin.setEncoding(\"utf8\"); process.stdin.on(\"data\", chunk => input += chunk); process.stdin.on(\"end\", () => process.stdout.write(input.replace(/\\\\r?\\\\n$/, \"\")));`\n ],\n { stdin: Stream.fromArray([new TextEncoder().encode(\"stdin\\n\")]) }\n)\n\n/** The default two-leg process probe. */\nconst defaultPipelineCommand = ChildProcess.pipeTo(\n ChildProcess.make(process.execPath, [\"-e\", `process.stdout.write(\"host-contract-pipeline\")`]),\n ChildProcess.make(process.execPath, [\"-e\", \"process.stdin.pipe(process.stdout)\"])\n)\n\n/** The default multi-leg cancellation probe. */\nconst defaultInterruptCommand = ChildProcess.pipeTo(\n ChildProcess.make(process.execPath, [\"-e\", \"setTimeout(() => {}, 10_000)\"]),\n ChildProcess.make(process.execPath, [\"-e\", \"process.stdin.pipe(process.stdout)\"])\n)\n\n/**\n * Registers the shared Host contract with Vitest.\n *\n * Every invocation creates ten cases: complete service presence,\n * FileSystem, Path, five child-process lifecycle cases, Jj, and\n * HttpClient.\n *\n * @category testing\n * @since 1.0.0-rc.0\n */\nexport const runHostContract = (\n name: string,\n layer: HostContractLayer,\n caps: HostContractCapabilities\n): void => {\n const fileSystemCap = caps.fileSystem\n const pathCap = caps.path\n const childProcessCap = caps.childProcess\n const jjCap = caps.jj\n const httpClientCap = caps.httpClient\n const scratchPath = fileSystemCap.expected === \"success\"\n ? fileSystemCap.scratchPath ?? defaultScratchPath(name)\n : \"\"\n\n describe(`${name} Host contract`, () => {\n it.live(\"provides every tag in the closed Host service list\", () =>\n run(\n Effect.gen(function*() {\n yield* FileSystem.FileSystem\n yield* Path.Path\n yield* ChildProcessSpawner\n yield* JjService.Jj\n yield* HttpClient\n }),\n layer\n ))\n\n it.live(\"declares every FileSystem operation\", () =>\n run(\n fileSystemCap.expected === \"failure\"\n ? Effect.gen(function*() {\n const fs = yield* FileSystem.FileSystem\n yield* Effect.forEach(\n FileSystemOperations,\n (operation) =>\n assertFailure(\n fileSystemProbe(fs, operation, \"/host-contract/unsupported\"),\n fileSystemCap.code\n ),\n { discard: true }\n )\n })\n : Effect.gen(function*() {\n const fs = yield* FileSystem.FileSystem\n const root = scratchPath\n const bytes = new TextEncoder().encode(\"host-contract\")\n yield* Effect.gen(function*() {\n yield* fs.makeDirectory(root, { recursive: true })\n yield* fs.writeFile(`${root}/source.txt`, bytes)\n yield* FileSystemBatchContract.check(fs, root)\n yield* Effect.forEach(\n FileSystemOperations,\n (operation) => {\n const probe = fileSystemProbe(fs, operation, root)\n const code = fileSystemCap.unsupported?.[operation]\n return code === undefined ? probe : assertFailure(probe, code)\n },\n { discard: true }\n )\n }).pipe(\n Effect.ensuring(fs.remove(root, { recursive: true, force: true }).pipe(Effect.ignore))\n )\n }),\n layer\n ))\n\n it.live(\"declares Path behavior\", () =>\n run(\n pathCap.expected === \"failure\"\n ? Effect.gen(function*() {\n const path = yield* Path.Path\n yield* assertFailure(\n Effect.try({\n try: () => path.fromFileUrl(new URL(\"file:///host-contract/value\")),\n catch: (error) => error\n }),\n pathCap.code\n )\n })\n : Effect.gen(function*() {\n const path = yield* Path.Path\n expect(path.normalize(\"/host-contract/./nested/../value\")).toBe(`${path.sep}host-contract${path.sep}value`)\n }),\n layer\n ))\n\n it.live(\"declares buffered child-process behavior\", () =>\n run(\n childProcessCap.expected === \"failure\"\n ? unsupportedChildProcess(\"string\", childProcessCap.code)\n : Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner\n const command = childProcessCap.execCommand ??\n ChildProcess.make(process.execPath, [\"-e\", `process.stdout.write(\"host-contract\")`])\n expect(yield* spawner.string(command)).toBe(childProcessCap.expectedStdout ?? \"host-contract\")\n expect(yield* spawner.exitCode(command)).toBe(0)\n }),\n layer\n ))\n\n it.live(\"declares child-process streaming behavior\", () =>\n run(\n childProcessCap.expected === \"failure\"\n ? unsupportedChildProcess(\"stream\", childProcessCap.code)\n : Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner\n const output = yield* Stream.mkString(\n spawner.streamString(\n childProcessCap.streamCommand ??\n ChildProcess.make(process.execPath, [\"-e\", `process.stdout.write(\"host-contract-stream\")`])\n )\n )\n expect(output).toContain(childProcessCap.expectedStreamText ?? \"host-contract-stream\")\n }),\n layer\n ))\n\n it.live(\"declares child-process cwd and env option behavior\", () =>\n run(\n childProcessCap.expected === \"failure\"\n ? unsupportedChildProcess(\"string\", childProcessCap.code)\n : Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner\n const output = yield* spawner.string(\n childProcessCap.optionsCommand ??\n ChildProcess.make(process.execPath, [\"-e\", \"process.stdout.write(process.env.HOST_CONTRACT_ENV)\"], {\n cwd: tmpdir(),\n env: { HOST_CONTRACT_ENV: \"env\" },\n extendEnv: true\n })\n )\n expect(output).toBe(childProcessCap.expectedOptionsStdout ?? \"env\")\n }),\n layer\n ))\n\n it.live(\"declares child-process stdin behavior\", () =>\n run(\n Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner\n const stdinCap = childProcessCap.expected === \"failure\"\n ? childProcessCap\n : childProcessCap.stdin ?? { command: defaultStdinCommand, expectedStdout: \"stdin\" }\n if (\"expected\" in stdinCap) {\n yield* assertFailure(spawner.string(defaultStdinCommand), stdinCap.code)\n return\n }\n expect(yield* spawner.string(stdinCap.command)).toBe(stdinCap.expectedStdout)\n }),\n layer\n ))\n\n it.live(\"declares child-process pipeline behavior\", () =>\n run(\n Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner\n const pipelineCap = childProcessCap.expected === \"failure\"\n ? childProcessCap\n : childProcessCap.pipeline ?? {\n command: defaultPipelineCommand,\n expectedStdout: \"host-contract-pipeline\"\n }\n if (\"expected\" in pipelineCap) {\n yield* assertFailure(spawner.string(defaultPipelineCommand), pipelineCap.code)\n return\n }\n expect(yield* spawner.string(pipelineCap.command)).toBe(pipelineCap.expectedStdout)\n }),\n layer\n ))\n\n it.live(\"declares child-process interruption behavior\", () =>\n run(\n childProcessCap.expected === \"failure\"\n ? unsupportedChildProcess(\"stream\", childProcessCap.code)\n : Effect.gen(function*() {\n const spawner = yield* ChildProcessSpawner\n const ready = yield* Deferred.make<ChildProcessHandle>()\n const fiber = yield* Effect.scoped(\n Effect.gen(function*() {\n const handle = yield* spawner.spawn(\n childProcessCap.interruptCommand ?? defaultInterruptCommand\n )\n yield* Deferred.succeed(ready, handle)\n yield* handle.exitCode\n })\n ).pipe(\n Effect.forkChild({ startImmediately: true })\n )\n const handle = yield* Deferred.await(ready)\n expect(yield* handle.isRunning).toBe(true)\n yield* Fiber.interrupt(fiber)\n expect(yield* handle.isRunning).toBe(false)\n }),\n layer\n ))\n\n it.live(\"declares every Jj operation\", () =>\n run(\n jjCap.expected === \"failure\"\n ? Effect.gen(function*() {\n const jj = yield* JjService.Jj\n const root = jj.root\n const revert = jj.revert\n expect(root).toBeTypeOf(\"function\")\n expect(revert).toBeTypeOf(\"function\")\n yield* Effect.forEach([\n jj.snapshot(\"host contract\"),\n jj.restore(\"host-contract-change\"),\n jj.diff(\"host-contract-from\", \"host-contract-to\"),\n jj.workspaceAdd(\"host-contract\", \"/host-contract/workspace\", \"host-contract-change\"),\n jj.workspaceForget(\"host-contract\"),\n jj.status(),\n root!(\"/host-contract\"),\n revert!(\"host-contract-change\")\n ], (probe) =>\n assertFailure(probe, jjCap.code), { discard: true })\n })\n : Effect.gen(function*() {\n const jj = yield* JjService.Jj\n const root = jj.root\n const revert = jj.revert\n expect(root).toBeTypeOf(\"function\")\n expect(revert).toBeTypeOf(\"function\")\n yield* (jjCap.prepareChange?.(\"first\") ?? Effect.void)\n const first = yield* jj.snapshot(\"host contract first\")\n expect(first.changeId.length).toBeGreaterThan(0)\n yield* (jjCap.prepareChange?.(\"second\") ?? Effect.void)\n const second = yield* jj.snapshot(\"host contract second\")\n expect(second.changeId.length).toBeGreaterThan(0)\n expect(typeof (yield* jj.diff(first.changeId, second.changeId))).toBe(\"string\")\n const revertCode = jjCap.unsupported?.revert\n if (revertCode === undefined) {\n const reverted = yield* revert!(second.changeId)\n expect(Array.isArray(reverted.reverted)).toBe(true)\n expect(reverted.reverted.every((path) =>\n typeof path === \"string\"\n )).toBe(true)\n } else {\n yield* assertFailure(revert!(second.changeId), revertCode)\n }\n yield* jj.restore(first.changeId)\n const workspaceName = `host-contract-${process.pid}-${++scratchSeq}`\n yield* jj.workspaceAdd(\n workspaceName,\n jjCap.workspacePath ?? defaultScratchPath(`${name}-jj-workspace`),\n first.changeId\n )\n yield* jj.workspaceForget(workspaceName)\n expect(typeof (yield* jj.status())).toBe(\"string\")\n const rootCode = jjCap.unsupported?.root\n const rootFrom = jjCap.rootFrom ?? \".\"\n if (rootCode === undefined) {\n expect((yield* root!(rootFrom)).length).toBeGreaterThan(0)\n } else {\n yield* assertFailure(root!(rootFrom), rootCode)\n }\n }),\n layer\n ))\n\n it.live(\"declares HTTP read, write, and redirect behavior\", () =>\n run(\n httpClientCap.expected === \"failure\"\n ? Effect.gen(function*() {\n const client = yield* HttpClient\n yield* Effect.forEach([\n HttpClientRequest.get(\"http://127.0.0.1:1/host-contract/read\"),\n HttpClientRequest.post(\"http://127.0.0.1:1/host-contract/write\").pipe(\n HttpClientRequest.bodyText(\"host-contract\")\n ),\n HttpClientRequest.get(\"http://127.0.0.1:1/host-contract/redirect\")\n ], (request) =>\n assertFailure(client.execute(request), httpClientCap.code), { discard: true })\n })\n : Effect.gen(function*() {\n const client = yield* HttpClient\n for (const probe of [httpClientCap.read, httpClientCap.write, httpClientCap.redirect]) {\n const response = yield* client.execute(probe.request)\n expect(typeof response.status).toBe(\"number\")\n expect(typeof response.headers).toBe(\"object\")\n probe.assertResponse(response)\n }\n }),\n layer\n ))\n })\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["handle"]
7
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Deterministic grant-store layers for tests.
3
+ *
4
+ * @since 1.0.0-rc.0
5
+ */
6
+ import { Layer } from "effect";
7
+ import { GrantStore, type Resolution } from "../GrantStore.ts";
8
+ /**
9
+ * An allow-all grant store.
10
+ *
11
+ * @category layers
12
+ * @since 1.0.0-rc.0
13
+ */
14
+ export declare const layerAllow: Layer.Layer<GrantStore>;
15
+ /**
16
+ * Provides a grant store that denies every capability.
17
+ *
18
+ * @category layers
19
+ * @since 1.0.0-rc.0
20
+ */
21
+ export declare const layerDeny: (reason?: string) => Layer.Layer<GrantStore>;
22
+ /**
23
+ * Provides a grant store whose checks consume a deterministic sequence of
24
+ * attended-style replies. `once`, `run`, and `remembered` allow the check;
25
+ * `deny` rejects it. Exhausting the script rejects further checks.
26
+ *
27
+ * @category layers
28
+ * @since 1.0.0-rc.0
29
+ */
30
+ export declare const layerScripted: (replies: ReadonlyArray<Resolution>) => Layer.Layer<GrantStore>;
31
+ //# sourceMappingURL=TestGrantStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestGrantStore.d.ts","sourceRoot":"","sources":["../../../src/test/TestGrantStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAA;AAEtC,OAAO,EAAE,UAAU,EAAa,KAAK,UAAU,EAAgB,MAAM,kBAAkB,CAAA;AAEvF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAa,CAAA;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,eAAyB,KAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAS3E,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACxB,SAAS,aAAa,CAAC,UAAU,CAAC,KACjC,KAAK,CAAC,KAAK,CAAC,UAAU,CA0BtB,CAAA"}