@ontrails/trails 1.0.0-beta.14 → 1.0.0-beta.16

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 (197) hide show
  1. package/CHANGELOG.md +208 -0
  2. package/README.md +27 -0
  3. package/package.json +19 -8
  4. package/src/app.ts +17 -7
  5. package/src/clack.ts +1 -1
  6. package/src/cli.ts +304 -10
  7. package/src/completions.ts +240 -0
  8. package/src/load-app-mirror.ts +160 -0
  9. package/src/local-state-io.ts +153 -0
  10. package/src/project-writes.ts +320 -0
  11. package/src/run-collision.ts +125 -0
  12. package/src/run-completions-install.ts +179 -0
  13. package/src/run-example.ts +149 -0
  14. package/src/run-examples.ts +148 -0
  15. package/src/run-quiet.ts +75 -0
  16. package/src/run-trace.ts +273 -0
  17. package/src/run-warden.ts +39 -0
  18. package/src/run-watch.ts +432 -0
  19. package/src/scaffold-versions.generated.ts +12 -0
  20. package/src/trails/add-surface.ts +172 -0
  21. package/src/trails/add-trail.ts +73 -27
  22. package/src/trails/add-verify.ts +68 -23
  23. package/src/trails/completions-complete.ts +165 -0
  24. package/src/trails/completions.ts +47 -0
  25. package/src/trails/create-scaffold.ts +101 -35
  26. package/src/trails/create.ts +87 -74
  27. package/src/trails/dev-clean.ts +31 -22
  28. package/src/trails/dev-reset.ts +9 -3
  29. package/src/trails/dev-stats.ts +28 -20
  30. package/src/trails/dev-support.ts +109 -95
  31. package/src/trails/draft-promote.ts +351 -107
  32. package/src/trails/guide.ts +55 -38
  33. package/src/trails/load-app.ts +712 -38
  34. package/src/trails/root-dir.ts +21 -0
  35. package/src/trails/run-example.ts +482 -0
  36. package/src/trails/run-examples.ts +141 -0
  37. package/src/trails/run.ts +403 -0
  38. package/src/trails/survey.ts +517 -186
  39. package/src/trails/topo-activation.ts +385 -0
  40. package/src/trails/topo-compile.ts +55 -0
  41. package/src/trails/topo-history.ts +14 -11
  42. package/src/trails/topo-output-schemas.ts +175 -0
  43. package/src/trails/topo-pin.ts +25 -16
  44. package/src/trails/topo-read-support.ts +178 -238
  45. package/src/trails/topo-reports.ts +445 -63
  46. package/src/trails/topo-store-support.ts +67 -35
  47. package/src/trails/topo-support.ts +93 -147
  48. package/src/trails/topo-unpin.ts +17 -7
  49. package/src/trails/topo-verify.ts +19 -10
  50. package/src/trails/topo.ts +64 -31
  51. package/src/trails/warden-guide.ts +121 -0
  52. package/src/trails/warden.ts +137 -47
  53. package/src/versions.ts +28 -0
  54. package/.turbo/turbo-build.log +0 -1
  55. package/.turbo/turbo-lint.log +0 -3
  56. package/.turbo/turbo-typecheck.log +0 -1
  57. package/__tests__/examples.test.ts +0 -20
  58. package/dist/bin/trails.d.ts +0 -3
  59. package/dist/bin/trails.d.ts.map +0 -1
  60. package/dist/bin/trails.js +0 -4
  61. package/dist/bin/trails.js.map +0 -1
  62. package/dist/src/app.d.ts +0 -2
  63. package/dist/src/app.d.ts.map +0 -1
  64. package/dist/src/app.js +0 -22
  65. package/dist/src/app.js.map +0 -1
  66. package/dist/src/clack.d.ts +0 -9
  67. package/dist/src/clack.d.ts.map +0 -1
  68. package/dist/src/clack.js +0 -84
  69. package/dist/src/clack.js.map +0 -1
  70. package/dist/src/cli.d.ts +0 -2
  71. package/dist/src/cli.d.ts.map +0 -1
  72. package/dist/src/cli.js +0 -13
  73. package/dist/src/cli.js.map +0 -1
  74. package/dist/src/trails/add-surface.d.ts +0 -13
  75. package/dist/src/trails/add-surface.d.ts.map +0 -1
  76. package/dist/src/trails/add-surface.js +0 -88
  77. package/dist/src/trails/add-surface.js.map +0 -1
  78. package/dist/src/trails/add-trail.d.ts +0 -10
  79. package/dist/src/trails/add-trail.d.ts.map +0 -1
  80. package/dist/src/trails/add-trail.js +0 -77
  81. package/dist/src/trails/add-trail.js.map +0 -1
  82. package/dist/src/trails/add-trailhead.d.ts +0 -13
  83. package/dist/src/trails/add-trailhead.d.ts.map +0 -1
  84. package/dist/src/trails/add-trailhead.js +0 -88
  85. package/dist/src/trails/add-trailhead.js.map +0 -1
  86. package/dist/src/trails/add-verify.d.ts +0 -10
  87. package/dist/src/trails/add-verify.d.ts.map +0 -1
  88. package/dist/src/trails/add-verify.js +0 -67
  89. package/dist/src/trails/add-verify.js.map +0 -1
  90. package/dist/src/trails/create-scaffold.d.ts +0 -15
  91. package/dist/src/trails/create-scaffold.d.ts.map +0 -1
  92. package/dist/src/trails/create-scaffold.js +0 -288
  93. package/dist/src/trails/create-scaffold.js.map +0 -1
  94. package/dist/src/trails/create.d.ts +0 -22
  95. package/dist/src/trails/create.d.ts.map +0 -1
  96. package/dist/src/trails/create.js +0 -121
  97. package/dist/src/trails/create.js.map +0 -1
  98. package/dist/src/trails/dev-clean.d.ts +0 -9
  99. package/dist/src/trails/dev-clean.d.ts.map +0 -1
  100. package/dist/src/trails/dev-clean.js +0 -65
  101. package/dist/src/trails/dev-clean.js.map +0 -1
  102. package/dist/src/trails/dev-reset.d.ts +0 -6
  103. package/dist/src/trails/dev-reset.d.ts.map +0 -1
  104. package/dist/src/trails/dev-reset.js +0 -38
  105. package/dist/src/trails/dev-reset.js.map +0 -1
  106. package/dist/src/trails/dev-stats.d.ts +0 -7
  107. package/dist/src/trails/dev-stats.d.ts.map +0 -1
  108. package/dist/src/trails/dev-stats.js +0 -61
  109. package/dist/src/trails/dev-stats.js.map +0 -1
  110. package/dist/src/trails/dev-support.d.ts +0 -64
  111. package/dist/src/trails/dev-support.d.ts.map +0 -1
  112. package/dist/src/trails/dev-support.js +0 -178
  113. package/dist/src/trails/dev-support.js.map +0 -1
  114. package/dist/src/trails/draft-promote.d.ts +0 -18
  115. package/dist/src/trails/draft-promote.d.ts.map +0 -1
  116. package/dist/src/trails/draft-promote.js +0 -386
  117. package/dist/src/trails/draft-promote.js.map +0 -1
  118. package/dist/src/trails/guide.d.ts +0 -21
  119. package/dist/src/trails/guide.d.ts.map +0 -1
  120. package/dist/src/trails/guide.js +0 -64
  121. package/dist/src/trails/guide.js.map +0 -1
  122. package/dist/src/trails/load-app.d.ts +0 -6
  123. package/dist/src/trails/load-app.d.ts.map +0 -1
  124. package/dist/src/trails/load-app.js +0 -67
  125. package/dist/src/trails/load-app.js.map +0 -1
  126. package/dist/src/trails/project.d.ts +0 -8
  127. package/dist/src/trails/project.d.ts.map +0 -1
  128. package/dist/src/trails/project.js +0 -54
  129. package/dist/src/trails/project.js.map +0 -1
  130. package/dist/src/trails/survey.d.ts +0 -18
  131. package/dist/src/trails/survey.d.ts.map +0 -1
  132. package/dist/src/trails/survey.js +0 -212
  133. package/dist/src/trails/survey.js.map +0 -1
  134. package/dist/src/trails/topo-constants.d.ts +0 -3
  135. package/dist/src/trails/topo-constants.d.ts.map +0 -1
  136. package/dist/src/trails/topo-constants.js +0 -3
  137. package/dist/src/trails/topo-constants.js.map +0 -1
  138. package/dist/src/trails/topo-export.d.ts +0 -18
  139. package/dist/src/trails/topo-export.d.ts.map +0 -1
  140. package/dist/src/trails/topo-export.js +0 -34
  141. package/dist/src/trails/topo-export.js.map +0 -1
  142. package/dist/src/trails/topo-history.d.ts +0 -24
  143. package/dist/src/trails/topo-history.d.ts.map +0 -1
  144. package/dist/src/trails/topo-history.js +0 -33
  145. package/dist/src/trails/topo-history.js.map +0 -1
  146. package/dist/src/trails/topo-pin.d.ts +0 -21
  147. package/dist/src/trails/topo-pin.d.ts.map +0 -1
  148. package/dist/src/trails/topo-pin.js +0 -35
  149. package/dist/src/trails/topo-pin.js.map +0 -1
  150. package/dist/src/trails/topo-read-support.d.ts +0 -54
  151. package/dist/src/trails/topo-read-support.d.ts.map +0 -1
  152. package/dist/src/trails/topo-read-support.js +0 -178
  153. package/dist/src/trails/topo-read-support.js.map +0 -1
  154. package/dist/src/trails/topo-reports.d.ts +0 -50
  155. package/dist/src/trails/topo-reports.d.ts.map +0 -1
  156. package/dist/src/trails/topo-reports.js +0 -122
  157. package/dist/src/trails/topo-reports.js.map +0 -1
  158. package/dist/src/trails/topo-show.d.ts +0 -23
  159. package/dist/src/trails/topo-show.d.ts.map +0 -1
  160. package/dist/src/trails/topo-show.js +0 -53
  161. package/dist/src/trails/topo-show.js.map +0 -1
  162. package/dist/src/trails/topo-store-support.d.ts +0 -13
  163. package/dist/src/trails/topo-store-support.d.ts.map +0 -1
  164. package/dist/src/trails/topo-store-support.js +0 -55
  165. package/dist/src/trails/topo-store-support.js.map +0 -1
  166. package/dist/src/trails/topo-support.d.ts +0 -87
  167. package/dist/src/trails/topo-support.d.ts.map +0 -1
  168. package/dist/src/trails/topo-support.js +0 -165
  169. package/dist/src/trails/topo-support.js.map +0 -1
  170. package/dist/src/trails/topo-unpin.d.ts +0 -15
  171. package/dist/src/trails/topo-unpin.d.ts.map +0 -1
  172. package/dist/src/trails/topo-unpin.js +0 -39
  173. package/dist/src/trails/topo-unpin.js.map +0 -1
  174. package/dist/src/trails/topo-verify.d.ts +0 -5
  175. package/dist/src/trails/topo-verify.d.ts.map +0 -1
  176. package/dist/src/trails/topo-verify.js +0 -28
  177. package/dist/src/trails/topo-verify.js.map +0 -1
  178. package/dist/src/trails/topo.d.ts +0 -5
  179. package/dist/src/trails/topo.d.ts.map +0 -1
  180. package/dist/src/trails/topo.js +0 -67
  181. package/dist/src/trails/topo.js.map +0 -1
  182. package/dist/src/trails/warden.d.ts +0 -19
  183. package/dist/src/trails/warden.d.ts.map +0 -1
  184. package/dist/src/trails/warden.js +0 -89
  185. package/dist/src/trails/warden.js.map +0 -1
  186. package/dist/tsconfig.tsbuildinfo +0 -1
  187. package/src/__tests__/create.test.ts +0 -351
  188. package/src/__tests__/draft-promote.test.ts +0 -144
  189. package/src/__tests__/guide.test.ts +0 -91
  190. package/src/__tests__/load-app.test.ts +0 -58
  191. package/src/__tests__/survey.test.ts +0 -301
  192. package/src/__tests__/topo-dev.test.ts +0 -424
  193. package/src/__tests__/warden.test.ts +0 -74
  194. package/src/trails/add-trailhead.ts +0 -121
  195. package/src/trails/topo-export.ts +0 -39
  196. package/src/trails/topo-show.ts +0 -58
  197. package/tsconfig.json +0 -9
@@ -1,58 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { resolve } from 'node:path';
5
-
6
- import { loadApp } from '../trails/load-app.js';
7
-
8
- const writeLoadAppFixture = (cwd: string, name: string): void => {
9
- writeFileSync(
10
- resolve(cwd, 'src/app.ts'),
11
- `export const app = {
12
- name: '${name}',
13
- trails: new Map(),
14
- signals: new Map(),
15
- provisions: new Map()
16
- };`
17
- );
18
- };
19
-
20
- const assertLoadAppCaching = async (cwd: string): Promise<void> => {
21
- writeLoadAppFixture(cwd, 'first');
22
-
23
- const first = await loadApp('./src/app.ts', cwd);
24
-
25
- writeLoadAppFixture(cwd, 'second');
26
-
27
- const cached = await loadApp('./src/app.ts', cwd);
28
- const fresh = await loadApp('./src/app.ts', cwd, { fresh: true });
29
-
30
- expect(first.name).toBe('first');
31
- expect(cached.name).toBe('first');
32
- expect(fresh.name).toBe('second');
33
- };
34
-
35
- describe('loadApp', () => {
36
- test('resolves relative module paths from cwd', async () => {
37
- // import.meta.dir is src/__tests__/, go up two to get apps/trails/
38
- const cwd = resolve(import.meta.dir, '../..');
39
- const app = await loadApp('./src/app.ts', cwd);
40
-
41
- expect(app.name).toBe('trails');
42
- expect(app.get('survey')).toBeDefined();
43
- });
44
-
45
- test('can bypass module caching with fresh loading', async () => {
46
- const cwd = resolve(
47
- tmpdir(),
48
- `trails-load-app-${Date.now()}-${Math.random().toString(36).slice(2)}`
49
- );
50
-
51
- try {
52
- mkdirSync(resolve(cwd, 'src'), { recursive: true });
53
- await assertLoadAppCaching(cwd);
54
- } finally {
55
- rmSync(cwd, { force: true, recursive: true });
56
- }
57
- });
58
- });
@@ -1,301 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import {
3
- existsSync,
4
- mkdirSync,
5
- readFileSync,
6
- rmSync,
7
- writeFileSync,
8
- } from 'node:fs';
9
- import { join, resolve } from 'node:path';
10
-
11
- import { Result, provision, topo, trail } from '@ontrails/core';
12
- import {
13
- generateTrailheadMap,
14
- hashTrailheadMap,
15
- diffTrailheadMaps,
16
- } from '@ontrails/schema';
17
- import type { TrailheadMap } from '@ontrails/schema';
18
- import { z } from 'zod';
19
-
20
- import {
21
- generateBriefReport,
22
- generateSurveyList,
23
- generateTrailDetail,
24
- surveyTrail,
25
- } from '../trails/survey.js';
26
- import type {
27
- BriefReport,
28
- SurveyListReport,
29
- TrailDetailReport,
30
- } from '../trails/survey.js';
31
-
32
- // ---------------------------------------------------------------------------
33
- // Test fixtures
34
- // ---------------------------------------------------------------------------
35
-
36
- const helloTrail = trail('hello', {
37
- blaze: (input) => {
38
- const name = input.name ?? 'world';
39
- return Result.ok({ message: `Hello, ${name}!` });
40
- },
41
- description: 'Say hello',
42
- detours: {
43
- NotFoundError: ['search'],
44
- },
45
- examples: [
46
- {
47
- expected: { message: 'Hello, world!' },
48
- input: {},
49
- name: 'Default greeting',
50
- },
51
- ],
52
- input: z.object({ name: z.string().optional() }),
53
- intent: 'read',
54
- output: z.object({ message: z.string() }),
55
- provisions: [
56
- provision('db.main', {
57
- create: () => Result.ok({ source: 'factory' }),
58
- }),
59
- ],
60
- });
61
-
62
- const byeTrail = trail('bye', {
63
- blaze: (input) => Result.ok({ message: `Goodbye, ${input.name}!` }),
64
- description: 'Say goodbye',
65
- input: z.object({ name: z.string() }),
66
- output: z.object({ message: z.string() }),
67
- });
68
-
69
- const [dbProvision] = helloTrail.provisions;
70
- if (!dbProvision) {
71
- throw new Error('Expected helloTrail to declare db.main');
72
- }
73
-
74
- const app = topo('test-app', {
75
- bye: byeTrail,
76
- dbProvision,
77
- hello: helloTrail,
78
- });
79
-
80
- const expectOk = <T>(result: Result<T, Error>): T => {
81
- if (result.isErr()) {
82
- throw result.error;
83
- }
84
- return result.value;
85
- };
86
-
87
- const writeSurveyAppFixture = (dir: string): void => {
88
- mkdirSync(join(dir, 'src'), { recursive: true });
89
- writeFileSync(
90
- join(dir, 'src', 'app.ts'),
91
- `import { Result, provision, topo, trail } from '@ontrails/core';
92
- import { z } from 'zod';
93
-
94
- const hello = trail('hello', {
95
- blaze: async (input) => Result.ok({ message: \`Hello, \${input.name ?? 'world'}!\` }),
96
- input: z.object({ name: z.string().optional() }),
97
- intent: 'read',
98
- output: z.object({ message: z.string() }),
99
- provisions: [
100
- provision('db.main', {
101
- create: () => Result.ok({ source: 'factory' }),
102
- }),
103
- ],
104
- });
105
-
106
- const [dbMain] = hello.provisions;
107
- if (!dbMain) {
108
- throw new Error('expected hello to declare db.main');
109
- }
110
-
111
- export const app = topo('survey-fixture', { dbMain, hello });
112
- `
113
- );
114
- };
115
-
116
- const repoTempDir = (): string =>
117
- join(
118
- resolve(import.meta.dir, '../..'),
119
- '.tmp-tests',
120
- `trails-survey-${Date.now()}-${Math.random().toString(36).slice(2)}`
121
- );
122
-
123
- // ---------------------------------------------------------------------------
124
- // Tests
125
- // ---------------------------------------------------------------------------
126
-
127
- describe('trails survey', () => {
128
- test('generateTrailheadMap includes all trails', () => {
129
- const trailheadMap = generateTrailheadMap(app);
130
- expect(trailheadMap.entries.length).toBe(3);
131
- const ids = trailheadMap.entries.map((e) => e.id);
132
- expect(ids).toContain('hello');
133
- expect(ids).toContain('bye');
134
- expect(ids).toContain('db.main');
135
- });
136
-
137
- test('trailhead map entries have expected fields', () => {
138
- const trailheadMap = generateTrailheadMap(app);
139
- const hello = trailheadMap.entries.find((e) => e.id === 'hello');
140
- expect(hello).toBeDefined();
141
- expect(hello?.cli?.path).toEqual(['hello']);
142
- expect(hello?.kind).toBe('trail');
143
- expect(hello?.intent).toBe('read');
144
- expect(hello?.exampleCount).toBe(1);
145
- expect(hello?.provisions).toEqual(['db.main']);
146
- });
147
-
148
- test('JSON output is valid JSON', () => {
149
- const trailheadMap = generateTrailheadMap(app);
150
- const json = JSON.stringify(trailheadMap, null, 2);
151
- const parsed = JSON.parse(json) as TrailheadMap;
152
- expect(parsed.version).toBe('1.0');
153
- expect(parsed.entries.length).toBe(3);
154
- });
155
-
156
- test('hashTrailheadMap produces stable hash', () => {
157
- const trailheadMap = generateTrailheadMap(app);
158
- const hash1 = hashTrailheadMap(trailheadMap);
159
- const hash2 = hashTrailheadMap(trailheadMap);
160
- expect(hash1).toBe(hash2);
161
- // SHA-256 hex
162
- expect(hash1.length).toBe(64);
163
- });
164
-
165
- test('diffTrailheadMaps detects added trails', () => {
166
- const prev = generateTrailheadMap(topo('test', { hello: helloTrail }));
167
- const curr = generateTrailheadMap(app);
168
- const diff = diffTrailheadMaps(prev, curr);
169
-
170
- expect(diff.info.length).toBeGreaterThan(0);
171
- const addedBye = diff.info.find((e) => e.id === 'bye');
172
- expect(addedBye).toBeDefined();
173
- expect(addedBye?.change).toBe('added');
174
- });
175
-
176
- test('diffTrailheadMaps detects removed trails', () => {
177
- const prev = generateTrailheadMap(app);
178
- const curr = generateTrailheadMap(topo('test', { hello: helloTrail }));
179
- const diff = diffTrailheadMaps(prev, curr);
180
-
181
- expect(diff.hasBreaking).toBe(true);
182
- const removedBye = diff.breaking.find((e) => e.id === 'bye');
183
- expect(removedBye).toBeDefined();
184
- expect(removedBye?.change).toBe('removed');
185
- });
186
-
187
- test('diffTrailheadMaps returns empty for identical maps', () => {
188
- const trailheadMap = generateTrailheadMap(app);
189
- const diff = diffTrailheadMaps(trailheadMap, trailheadMap);
190
- expect(diff.entries.length).toBe(0);
191
- expect(diff.hasBreaking).toBe(false);
192
- });
193
- });
194
-
195
- // ---------------------------------------------------------------------------
196
- // Brief mode (formerly scout)
197
- // ---------------------------------------------------------------------------
198
-
199
- describe('trails survey --brief', () => {
200
- test('produces a valid capability report', () => {
201
- const report = generateBriefReport(app);
202
- expect(report.name).toBe('test-app');
203
- expect(report.contractVersion).toBe('2026-03');
204
- });
205
-
206
- test('report includes correct trail count', () => {
207
- const report = generateBriefReport(app);
208
- expect(report.trails).toBe(2);
209
- expect(report.signals).toBe(0);
210
- expect(report.provisions).toBe(1);
211
- });
212
-
213
- test('detects features in use', () => {
214
- const report = generateBriefReport(app);
215
- expect(report.features.outputSchemas).toBe(true);
216
- expect(report.features.examples).toBe(true);
217
- expect(report.features.detours).toBe(true);
218
- expect(report.features.signals).toBe(false);
219
- expect(report.features.provisions).toBe(true);
220
- });
221
-
222
- test('JSON output is valid', () => {
223
- const report = generateBriefReport(app);
224
- const json = JSON.stringify(report, null, 2);
225
- const parsed = JSON.parse(json) as BriefReport;
226
- expect(parsed.name).toBe('test-app');
227
- expect(parsed.trails).toBe(2);
228
- expect(parsed.provisions).toBe(1);
229
- });
230
-
231
- test('empty app reports zero features', () => {
232
- const emptyApp = topo('empty', {});
233
- const report = generateBriefReport(emptyApp);
234
- expect(report.trails).toBe(0);
235
- expect(report.features.outputSchemas).toBe(false);
236
- expect(report.features.examples).toBe(false);
237
- expect(report.features.detours).toBe(false);
238
- expect(report.features.provisions).toBe(false);
239
- });
240
- });
241
-
242
- describe('trails survey detail', () => {
243
- test('trail detail includes declared provisions, crossings, and intent', () => {
244
- const detail = generateTrailDetail(helloTrail);
245
- const parsed = structuredClone(detail) as TrailDetailReport;
246
-
247
- expect(parsed.crosses).toEqual([]);
248
- expect(parsed.intent).toBe('read');
249
- expect(parsed.provisions).toEqual(['db.main']);
250
- });
251
- });
252
-
253
- describe('trails survey provisions section', () => {
254
- test('list output includes provision lifetime and health status', () => {
255
- const report = generateSurveyList(app);
256
- const parsed = structuredClone(report) as SurveyListReport;
257
- const db = parsed.provisions.find((entry) => entry.id === 'db.main');
258
-
259
- expect(parsed.provisionCount).toBe(1);
260
- expect(db).toEqual({
261
- description: null,
262
- health: 'none',
263
- id: 'db.main',
264
- kind: 'provision',
265
- lifetime: 'singleton',
266
- usedBy: ['hello'],
267
- });
268
- });
269
- });
270
-
271
- describe('trails survey generate', () => {
272
- test('delegates to topo export and writes a structured lock', async () => {
273
- const dir = repoTempDir();
274
-
275
- try {
276
- writeSurveyAppFixture(dir);
277
-
278
- const generated = expectOk(
279
- await surveyTrail.blaze({ generate: true, module: './src/app.ts' }, {
280
- cwd: dir,
281
- } as never)
282
- ) as {
283
- readonly hash: string;
284
- readonly lockPath: string;
285
- readonly mapPath: string;
286
- };
287
-
288
- expect(generated.hash).toHaveLength(64);
289
- expect(existsSync(join(dir, '.trails', '_trailhead.json'))).toBe(true);
290
- expect(existsSync(join(dir, '.trails', 'trails.lock'))).toBe(true);
291
- expect(
292
- JSON.parse(readFileSync(join(dir, '.trails', 'trails.lock'), 'utf8'))
293
- ).toMatchObject({
294
- hash: generated.hash,
295
- version: 1,
296
- });
297
- } finally {
298
- rmSync(dir, { force: true, recursive: true });
299
- }
300
- });
301
- });