@ontrails/warden 1.0.0-beta.12 → 1.0.0-beta.13

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 (182) hide show
  1. package/CHANGELOG.md +51 -31
  2. package/README.md +17 -17
  3. package/dist/cli.d.ts +1 -1
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +14 -10
  6. package/dist/cli.js.map +1 -1
  7. package/dist/drift.d.ts +6 -6
  8. package/dist/drift.d.ts.map +1 -1
  9. package/dist/drift.js +8 -8
  10. package/dist/drift.js.map +1 -1
  11. package/dist/formatters.js +2 -2
  12. package/dist/formatters.js.map +1 -1
  13. package/dist/index.d.ts +4 -4
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +5 -5
  16. package/dist/index.js.map +1 -1
  17. package/dist/rules/ast.d.ts +15 -11
  18. package/dist/rules/ast.d.ts.map +1 -1
  19. package/dist/rules/ast.js +34 -30
  20. package/dist/rules/ast.js.map +1 -1
  21. package/dist/rules/context-no-trailhead-types.d.ts +12 -0
  22. package/dist/rules/context-no-trailhead-types.d.ts.map +1 -0
  23. package/dist/rules/context-no-trailhead-types.js +96 -0
  24. package/dist/rules/context-no-trailhead-types.js.map +1 -0
  25. package/dist/rules/cross-declarations.d.ts +13 -0
  26. package/dist/rules/cross-declarations.d.ts.map +1 -0
  27. package/dist/rules/cross-declarations.js +264 -0
  28. package/dist/rules/cross-declarations.js.map +1 -0
  29. package/dist/rules/follow-declarations.d.ts +1 -1
  30. package/dist/rules/follow-declarations.js +5 -5
  31. package/dist/rules/follow-declarations.js.map +1 -1
  32. package/dist/rules/implementation-returns-result.d.ts +2 -2
  33. package/dist/rules/implementation-returns-result.js +6 -6
  34. package/dist/rules/implementation-returns-result.js.map +1 -1
  35. package/dist/rules/index.d.ts +4 -4
  36. package/dist/rules/index.d.ts.map +1 -1
  37. package/dist/rules/index.js +12 -12
  38. package/dist/rules/index.js.map +1 -1
  39. package/dist/rules/no-direct-impl-in-route.d.ts +4 -4
  40. package/dist/rules/no-direct-impl-in-route.js +14 -14
  41. package/dist/rules/no-direct-impl-in-route.js.map +1 -1
  42. package/dist/rules/no-direct-implementation-call.d.ts +3 -3
  43. package/dist/rules/no-direct-implementation-call.js +7 -7
  44. package/dist/rules/no-direct-implementation-call.js.map +1 -1
  45. package/dist/rules/no-sync-result-assumption.d.ts +1 -1
  46. package/dist/rules/no-sync-result-assumption.js +5 -5
  47. package/dist/rules/no-sync-result-assumption.js.map +1 -1
  48. package/dist/rules/no-throw-in-detour-target.js +2 -2
  49. package/dist/rules/no-throw-in-detour-target.js.map +1 -1
  50. package/dist/rules/no-throw-in-implementation.d.ts +1 -1
  51. package/dist/rules/no-throw-in-implementation.js +3 -3
  52. package/dist/rules/no-throw-in-implementation.js.map +1 -1
  53. package/dist/rules/provision-declarations.d.ts +14 -0
  54. package/dist/rules/provision-declarations.d.ts.map +1 -0
  55. package/dist/rules/provision-declarations.js +344 -0
  56. package/dist/rules/provision-declarations.js.map +1 -0
  57. package/dist/rules/provision-exists.d.ts +6 -0
  58. package/dist/rules/provision-exists.d.ts.map +1 -0
  59. package/dist/rules/provision-exists.js +89 -0
  60. package/dist/rules/provision-exists.js.map +1 -0
  61. package/dist/rules/service-declarations.d.ts +7 -5
  62. package/dist/rules/service-declarations.d.ts.map +1 -1
  63. package/dist/rules/service-declarations.js +106 -103
  64. package/dist/rules/service-declarations.js.map +1 -1
  65. package/dist/rules/service-exists.d.ts +3 -1
  66. package/dist/rules/service-exists.d.ts.map +1 -1
  67. package/dist/rules/service-exists.js +35 -33
  68. package/dist/rules/service-exists.js.map +1 -1
  69. package/dist/rules/specs.d.ts +1 -1
  70. package/dist/rules/specs.d.ts.map +1 -1
  71. package/dist/rules/specs.js +1 -1
  72. package/dist/rules/specs.js.map +1 -1
  73. package/dist/rules/types.d.ts +2 -2
  74. package/dist/rules/types.d.ts.map +1 -1
  75. package/dist/trails/context-no-surface-types.trail.js +1 -1
  76. package/dist/trails/context-no-trailhead-types.trail.d.ts +13 -0
  77. package/dist/trails/context-no-trailhead-types.trail.d.ts.map +1 -0
  78. package/dist/trails/context-no-trailhead-types.trail.js +21 -0
  79. package/dist/trails/context-no-trailhead-types.trail.js.map +1 -0
  80. package/dist/trails/cross-declarations.trail.d.ts +13 -0
  81. package/dist/trails/cross-declarations.trail.d.ts.map +1 -0
  82. package/dist/trails/cross-declarations.trail.js +22 -0
  83. package/dist/trails/cross-declarations.trail.js.map +1 -0
  84. package/dist/trails/follow-declarations.trail.js +1 -1
  85. package/dist/trails/implementation-returns-result.trail.js +1 -1
  86. package/dist/trails/index.d.ts +4 -4
  87. package/dist/trails/index.d.ts.map +1 -1
  88. package/dist/trails/index.js +4 -4
  89. package/dist/trails/index.js.map +1 -1
  90. package/dist/trails/no-direct-impl-in-route.trail.js +4 -4
  91. package/dist/trails/no-direct-impl-in-route.trail.js.map +1 -1
  92. package/dist/trails/no-direct-implementation-call.trail.js +2 -2
  93. package/dist/trails/no-direct-implementation-call.trail.js.map +1 -1
  94. package/dist/trails/no-sync-result-assumption.trail.js +2 -2
  95. package/dist/trails/no-sync-result-assumption.trail.js.map +1 -1
  96. package/dist/trails/no-throw-in-detour-target.trail.d.ts +1 -1
  97. package/dist/trails/no-throw-in-detour-target.trail.js +1 -1
  98. package/dist/trails/no-throw-in-implementation.trail.js +1 -1
  99. package/dist/trails/prefer-schema-inference.trail.js +1 -1
  100. package/dist/trails/provision-declarations.trail.d.ts +13 -0
  101. package/dist/trails/provision-declarations.trail.d.ts.map +1 -0
  102. package/dist/trails/provision-declarations.trail.js +25 -0
  103. package/dist/trails/provision-declarations.trail.js.map +1 -0
  104. package/dist/trails/provision-exists.trail.d.ts +15 -0
  105. package/dist/trails/provision-exists.trail.d.ts.map +1 -0
  106. package/dist/trails/provision-exists.trail.js +27 -0
  107. package/dist/trails/provision-exists.trail.js.map +1 -0
  108. package/dist/trails/run.d.ts +2 -2
  109. package/dist/trails/run.d.ts.map +1 -1
  110. package/dist/trails/run.js +6 -6
  111. package/dist/trails/run.js.map +1 -1
  112. package/dist/trails/schema.d.ts +1 -1
  113. package/dist/trails/schema.js +2 -2
  114. package/dist/trails/schema.js.map +1 -1
  115. package/dist/trails/service-declarations.trail.d.ts +13 -0
  116. package/dist/trails/service-declarations.trail.d.ts.map +1 -1
  117. package/dist/trails/service-declarations.trail.js +9 -7
  118. package/dist/trails/service-declarations.trail.js.map +1 -1
  119. package/dist/trails/service-exists.trail.d.ts +17 -0
  120. package/dist/trails/service-exists.trail.d.ts.map +1 -1
  121. package/dist/trails/service-exists.trail.js +10 -8
  122. package/dist/trails/service-exists.trail.js.map +1 -1
  123. package/dist/trails/valid-describe-refs.trail.d.ts +1 -1
  124. package/dist/trails/valid-detour-refs.trail.d.ts +1 -1
  125. package/dist/trails/valid-detour-refs.trail.js +2 -2
  126. package/dist/trails/wrap-rule.js +14 -14
  127. package/dist/trails/wrap-rule.js.map +1 -1
  128. package/package.json +1 -1
  129. package/src/__tests__/cli.test.ts +8 -8
  130. package/src/__tests__/{follow-declarations.test.ts → cross-declarations.test.ts} +78 -78
  131. package/src/__tests__/drift.test.ts +5 -5
  132. package/src/__tests__/formatters.test.ts +2 -2
  133. package/src/__tests__/implementation-returns-result.test.ts +11 -11
  134. package/src/__tests__/no-direct-implementation-call.test.ts +10 -10
  135. package/src/__tests__/no-sync-result-assumption.test.ts +6 -6
  136. package/src/__tests__/no-throw-in-detour-target.test.ts +6 -6
  137. package/src/__tests__/prefer-schema-inference.test.ts +4 -4
  138. package/src/__tests__/provision-declarations.test.ts +318 -0
  139. package/src/__tests__/provision-exists.test.ts +122 -0
  140. package/src/__tests__/rules.test.ts +38 -38
  141. package/src/__tests__/valid-describe-refs.test.ts +4 -4
  142. package/src/__tests__/wrap-rule.test.ts +4 -4
  143. package/src/cli.ts +17 -13
  144. package/src/drift.ts +12 -12
  145. package/src/formatters.ts +2 -2
  146. package/src/index.ts +8 -8
  147. package/src/rules/ast.ts +36 -31
  148. package/src/rules/{context-no-surface-types.ts → context-no-trailhead-types.ts} +8 -8
  149. package/src/rules/{follow-declarations.ts → cross-declarations.ts} +63 -56
  150. package/src/rules/implementation-returns-result.ts +6 -6
  151. package/src/rules/index.ts +12 -12
  152. package/src/rules/no-direct-impl-in-route.ts +17 -17
  153. package/src/rules/no-direct-implementation-call.ts +7 -7
  154. package/src/rules/no-sync-result-assumption.ts +5 -5
  155. package/src/rules/no-throw-in-detour-target.ts +2 -2
  156. package/src/rules/no-throw-in-implementation.ts +3 -3
  157. package/src/rules/{service-declarations.ts → provision-declarations.ts} +145 -129
  158. package/src/rules/{service-exists.ts → provision-exists.ts} +51 -46
  159. package/src/rules/specs.ts +4 -4
  160. package/src/rules/types.ts +2 -2
  161. package/src/trails/{context-no-surface-types.trail.ts → context-no-trailhead-types.trail.ts} +5 -5
  162. package/src/trails/cross-declarations.trail.ts +22 -0
  163. package/src/trails/implementation-returns-result.trail.ts +1 -1
  164. package/src/trails/index.ts +4 -4
  165. package/src/trails/no-direct-impl-in-route.trail.ts +4 -4
  166. package/src/trails/no-direct-implementation-call.trail.ts +2 -2
  167. package/src/trails/no-sync-result-assumption.trail.ts +2 -2
  168. package/src/trails/no-throw-in-detour-target.trail.ts +1 -1
  169. package/src/trails/no-throw-in-implementation.trail.ts +1 -1
  170. package/src/trails/prefer-schema-inference.trail.ts +1 -1
  171. package/src/trails/provision-declarations.trail.ts +25 -0
  172. package/src/trails/provision-exists.trail.ts +27 -0
  173. package/src/trails/run.ts +7 -7
  174. package/src/trails/schema.ts +2 -2
  175. package/src/trails/valid-detour-refs.trail.ts +2 -2
  176. package/src/trails/wrap-rule.ts +17 -17
  177. package/tsconfig.tsbuildinfo +1 -1
  178. package/src/__tests__/service-declarations.test.ts +0 -318
  179. package/src/__tests__/service-exists.test.ts +0 -122
  180. package/src/trails/follow-declarations.trail.ts +0 -22
  181. package/src/trails/service-declarations.trail.ts +0 -25
  182. package/src/trails/service-exists.trail.ts +0 -27
@@ -1,318 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
-
3
- import { serviceDeclarations } from '../rules/service-declarations.js';
4
-
5
- const TEST_FILE = 'test.ts';
6
-
7
- describe('service-declarations', () => {
8
- describe('clean cases', () => {
9
- test('declared services match service.from(ctx) usage', () => {
10
- const code = `
11
- import { Result, service, trail } from '@ontrails/core';
12
-
13
- const db = service('db.main', {
14
- create: () => Result.ok({ source: 'factory' }),
15
- });
16
-
17
- trail('entity.show', {
18
- services: [db],
19
- run: async (_input, ctx) => {
20
- return Result.ok({ source: db.from(ctx).source });
21
- },
22
- });
23
- `;
24
-
25
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
26
-
27
- expect(diagnostics.length).toBe(0);
28
- });
29
-
30
- test('local helper named service() is not treated as ctx lookup', () => {
31
- const code = `
32
- import { Result, service, trail } from '@ontrails/core';
33
-
34
- const db = service('db.main', {
35
- create: () => Result.ok({ source: 'factory' }),
36
- });
37
-
38
- trail('entity.show', {
39
- services: [db],
40
- run: async (_input, ctx) => {
41
- const service = (id: string) => id;
42
- return Result.ok({
43
- resolved: service('db.main'),
44
- source: db.from(ctx).source,
45
- });
46
- },
47
- });
48
- `;
49
-
50
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
51
-
52
- expect(diagnostics.length).toBe(0);
53
- });
54
-
55
- test('declared services match ctx.service() usage', () => {
56
- const code = `
57
- import { Result, service, trail } from '@ontrails/core';
58
-
59
- const db = service('db.main', {
60
- create: () => Result.ok({ source: 'factory' }),
61
- });
62
-
63
- trail('entity.show', {
64
- services: [db],
65
- run: async (_input, ctx) => {
66
- const resolved = ctx.service('db.main');
67
- return Result.ok(resolved);
68
- },
69
- });
70
- `;
71
-
72
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
73
-
74
- expect(diagnostics.length).toBe(0);
75
- });
76
-
77
- test('recognizes destructured service() calls', () => {
78
- const code = `
79
- import { Result, service, trail } from '@ontrails/core';
80
-
81
- const db = service('db.main', {
82
- create: () => Result.ok({ source: 'factory' }),
83
- });
84
-
85
- trail('entity.show', {
86
- services: [db],
87
- run: async (_input, ctx) => {
88
- const { service } = ctx;
89
- return Result.ok(service('db.main'));
90
- },
91
- });
92
- `;
93
-
94
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
95
-
96
- expect(diagnostics.length).toBe(0);
97
- });
98
-
99
- test('recognizes ctx.service(db) lookups by declared service object', () => {
100
- const code = `
101
- import { Result, service, trail } from '@ontrails/core';
102
-
103
- const db = service('db.main', {
104
- create: () => Result.ok({ source: 'factory' }),
105
- });
106
-
107
- trail('entity.show', {
108
- services: [db],
109
- run: async (_input, ctx) => {
110
- return Result.ok(ctx.service(db));
111
- },
112
- });
113
- `;
114
-
115
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
116
-
117
- expect(diagnostics.length).toBe(0);
118
- });
119
- });
120
-
121
- describe('error cases', () => {
122
- test('service.from(ctx) without a declaration produces an error', () => {
123
- const code = `
124
- import { Result, service, trail } from '@ontrails/core';
125
-
126
- const db = service('db.main', {
127
- create: () => Result.ok({ source: 'factory' }),
128
- });
129
-
130
- trail('entity.show', {
131
- run: async (_input, ctx) => {
132
- return Result.ok({ source: db.from(ctx).source });
133
- },
134
- });
135
- `;
136
-
137
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
138
-
139
- expect(diagnostics.length).toBe(1);
140
- expect(diagnostics[0]?.severity).toBe('error');
141
- expect(diagnostics[0]?.rule).toBe('service-declarations');
142
- expect(diagnostics[0]?.message).toContain('db.from(ctx)');
143
- expect(diagnostics[0]?.message).toContain('not declared in services');
144
- });
145
-
146
- test('ctx.service() without a declaration produces an error', () => {
147
- const code = `
148
- trail('entity.show', {
149
- run: async (_input, ctx) => {
150
- return Result.ok(ctx.service('db.main'));
151
- },
152
- });
153
- `;
154
-
155
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
156
-
157
- expect(diagnostics.length).toBe(1);
158
- expect(diagnostics[0]?.severity).toBe('error');
159
- expect(diagnostics[0]?.message).toContain("ctx.service('db.main')");
160
- });
161
-
162
- test('unresolved imported service declarations do not suppress lookup diagnostics', () => {
163
- const code = `
164
- import { Result, trail } from '@ontrails/core';
165
- import { db } from './services';
166
-
167
- // const db = service('db.main', {
168
- // create: () => Result.ok({ source: 'factory' }),
169
- // });
170
-
171
- trail('entity.show', {
172
- services: [db],
173
- run: async (_input, ctx) => {
174
- return Result.ok(ctx.service('db.main'));
175
- },
176
- });
177
- `;
178
-
179
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
180
-
181
- expect(diagnostics.length).toBe(1);
182
- expect(diagnostics[0]?.severity).toBe('error');
183
- expect(diagnostics[0]?.message).toContain("ctx.service('db.main')");
184
- });
185
-
186
- test('ctx.service(db) without a declaration produces an error', () => {
187
- const code = `
188
- import { Result, service, trail } from '@ontrails/core';
189
-
190
- const db = service('db.main', {
191
- create: () => Result.ok({ source: 'factory' }),
192
- });
193
-
194
- trail('entity.show', {
195
- run: async (_input, ctx) => {
196
- return Result.ok(ctx.service(db));
197
- },
198
- });
199
- `;
200
-
201
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
202
-
203
- expect(diagnostics.length).toBe(1);
204
- expect(diagnostics[0]?.severity).toBe('error');
205
- expect(diagnostics[0]?.message).toContain('ctx.service(db)');
206
- });
207
- });
208
-
209
- describe('warn cases', () => {
210
- test('declared but unused service produces a warning', () => {
211
- const code = `
212
- import { Result, service, trail } from '@ontrails/core';
213
-
214
- const db = service('db.main', {
215
- create: () => Result.ok({ source: 'factory' }),
216
- });
217
-
218
- trail('entity.show', {
219
- services: [db],
220
- run: async () => {
221
- return Result.ok({ ok: true });
222
- },
223
- });
224
- `;
225
-
226
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
227
-
228
- expect(diagnostics.length).toBe(1);
229
- expect(diagnostics[0]?.severity).toBe('warn');
230
- expect(diagnostics[0]?.rule).toBe('service-declarations');
231
- expect(diagnostics[0]?.message).toContain("'db' declared in services");
232
- expect(diagnostics[0]?.message).toContain('never used');
233
- });
234
- });
235
-
236
- describe('single-object overload', () => {
237
- test('recognizes trail({ id, services, run }) form', () => {
238
- const code = `
239
- import { Result, service, trail } from '@ontrails/core';
240
-
241
- const db = service('db.main', {
242
- create: () => Result.ok({ source: 'factory' }),
243
- });
244
-
245
- trail({
246
- id: 'entity.show',
247
- services: [db],
248
- run: async (_input, ctx) => {
249
- return Result.ok({ source: db.from(ctx).source });
250
- },
251
- });
252
- `;
253
-
254
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
255
-
256
- expect(diagnostics.length).toBe(0);
257
- });
258
- });
259
-
260
- describe('context parameter naming', () => {
261
- test('recognizes database.from(context) when second param is named context', () => {
262
- const code = `
263
- import { Result, service, trail } from '@ontrails/core';
264
-
265
- const database = service('db.main', {
266
- create: () => Result.ok({ source: 'factory' }),
267
- });
268
-
269
- trail('entity.show', {
270
- services: [database],
271
- run: async (_input, context) => {
272
- return Result.ok(database.from(context));
273
- },
274
- });
275
- `;
276
-
277
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
278
-
279
- expect(diagnostics.length).toBe(0);
280
- });
281
- });
282
-
283
- describe('nested run false positives', () => {
284
- test('metadata.run does not trigger false positives', () => {
285
- const code = `
286
- import { Result, service, trail } from '@ontrails/core';
287
-
288
- const db = service('db.main', {
289
- create: () => Result.ok({ source: 'factory' }),
290
- });
291
-
292
- trail('entity.show', {
293
- services: [db],
294
- metadata: { run: async () => ctx.service('phantom') },
295
- run: async (_input, ctx) => {
296
- return Result.ok(db.from(ctx));
297
- },
298
- });
299
- `;
300
-
301
- const diagnostics = serviceDeclarations.check(code, TEST_FILE);
302
-
303
- expect(diagnostics.length).toBe(0);
304
- });
305
- });
306
-
307
- test('skips test files', () => {
308
- const code = `
309
- trail('entity.show', {
310
- run: async (_input, ctx) => {
311
- return Result.ok(ctx.service('db.main'));
312
- },
313
- });
314
- `;
315
-
316
- expect(serviceDeclarations.check(code, 'entity.test.ts')).toEqual([]);
317
- });
318
- });
@@ -1,122 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
-
3
- import { serviceExists } from '../rules/service-exists.js';
4
-
5
- const TEST_FILE = 'entity.ts';
6
-
7
- describe('service-exists', () => {
8
- test('passes when a locally declared service exists', () => {
9
- const code = `
10
- import { Result, service, trail } from '@ontrails/core';
11
- import type { Service } from '@ontrails/core';
12
-
13
- const db: Service<{ source: string }> = service('db.main', {
14
- create: () => Result.ok({ source: 'factory' }),
15
- });
16
-
17
- trail('entity.show', {
18
- services: [db],
19
- run: async (_input, ctx) => Result.ok(db.from(ctx)),
20
- });
21
- `;
22
-
23
- expect(serviceExists.check(code, TEST_FILE)).toEqual([]);
24
- });
25
-
26
- test('ignores commented-out service declarations when resolving local ids', () => {
27
- const code = `
28
- import { Result, trail } from '@ontrails/core';
29
-
30
- trail('entity.show', {
31
- services: ['db.main'],
32
- run: async (_input, ctx) => Result.ok(ctx.service('db.main')),
33
- });
34
-
35
- // const db = service('db.main', {
36
- // create: () => Result.ok({ source: 'factory' }),
37
- // });
38
- `;
39
-
40
- const diagnostics = serviceExists.check(code, TEST_FILE);
41
-
42
- expect(diagnostics).toHaveLength(1);
43
- expect(diagnostics[0]?.rule).toBe('service-exists');
44
- expect(diagnostics[0]?.message).toContain('db.main');
45
- });
46
-
47
- test('flags a declared service missing from project context', () => {
48
- const code = `
49
- import { Result, service, trail } from '@ontrails/core';
50
-
51
- const db = service('db.main', {
52
- create: () => Result.ok({ source: 'factory' }),
53
- });
54
-
55
- trail('entity.show', {
56
- services: [db],
57
- run: async (_input, ctx) => Result.ok(db.from(ctx)),
58
- });
59
- `;
60
-
61
- const diagnostics = serviceExists.checkWithContext(code, TEST_FILE, {
62
- knownServiceIds: new Set(['db.other']),
63
- knownTrailIds: new Set(['entity.show']),
64
- });
65
-
66
- expect(diagnostics).toHaveLength(1);
67
- expect(diagnostics[0]?.rule).toBe('service-exists');
68
- expect(diagnostics[0]?.message).toContain('db.main');
69
- });
70
-
71
- test('passes when project context includes the declared service', () => {
72
- const code = `
73
- import { Result, service, trail } from '@ontrails/core';
74
-
75
- const db = service('db.main', {
76
- create: () => Result.ok({ source: 'factory' }),
77
- });
78
-
79
- trail('entity.show', {
80
- services: [db],
81
- run: async (_input, ctx) => Result.ok(db.from(ctx)),
82
- });
83
- `;
84
-
85
- const diagnostics = serviceExists.checkWithContext(code, TEST_FILE, {
86
- knownServiceIds: new Set(['db.main']),
87
- knownTrailIds: new Set(['entity.show']),
88
- });
89
-
90
- expect(diagnostics).toEqual([]);
91
- });
92
-
93
- test('skips unresolved imported services instead of guessing', () => {
94
- const code = `
95
- import { trail } from '@ontrails/core';
96
- import { db } from './services';
97
-
98
- trail('entity.show', {
99
- services: [db],
100
- run: async (_input, ctx) => Result.ok(db.from(ctx)),
101
- });
102
- `;
103
-
104
- expect(
105
- serviceExists.checkWithContext(code, TEST_FILE, {
106
- knownServiceIds: new Set(['db.main']),
107
- knownTrailIds: new Set(['entity.show']),
108
- })
109
- ).toEqual([]);
110
- });
111
-
112
- test('skips test files', () => {
113
- const code = `
114
- trail('entity.show', {
115
- services: ['db.main'],
116
- run: async (_input, ctx) => Result.ok(ctx.service('db.main')),
117
- });
118
- `;
119
-
120
- expect(serviceExists.check(code, 'entity.test.ts')).toEqual([]);
121
- });
122
- });
@@ -1,22 +0,0 @@
1
- import { followDeclarations } from '../rules/follow-declarations.js';
2
- import { wrapRule } from './wrap-rule.js';
3
-
4
- export const followDeclarationsTrail = wrapRule({
5
- examples: [
6
- {
7
- expected: { diagnostics: [] },
8
- input: {
9
- filePath: 'clean.ts',
10
- sourceCode: `trail("entity.onboard", {
11
- follow: ["entity.create"],
12
- run: async (input, ctx) => {
13
- const result = await ctx.follow("entity.create", input);
14
- return Result.ok(result);
15
- }
16
- })`,
17
- },
18
- name: 'Matched follow declarations and calls',
19
- },
20
- ],
21
- rule: followDeclarations,
22
- });
@@ -1,25 +0,0 @@
1
- import { serviceDeclarations } from '../rules/service-declarations.js';
2
- import { wrapRule } from './wrap-rule.js';
3
-
4
- export const serviceDeclarationsTrail = wrapRule({
5
- examples: [
6
- {
7
- expected: { diagnostics: [] },
8
- input: {
9
- filePath: 'clean.ts',
10
- sourceCode: `const db = service("db.main", {
11
- create: () => Result.ok({ source: "factory" }),
12
- });
13
-
14
- trail("entity.show", {
15
- services: [db],
16
- run: async (_input, ctx) => {
17
- return Result.ok(db.from(ctx));
18
- }
19
- })`,
20
- },
21
- name: 'Matched service declarations and usage',
22
- },
23
- ],
24
- rule: serviceDeclarations,
25
- });
@@ -1,27 +0,0 @@
1
- import { serviceExists } from '../rules/service-exists.js';
2
- import { wrapRule } from './wrap-rule.js';
3
-
4
- export const serviceExistsTrail = wrapRule({
5
- examples: [
6
- {
7
- expected: { diagnostics: [] },
8
- input: {
9
- filePath: 'clean.ts',
10
- knownServiceIds: ['db.main'],
11
- knownTrailIds: ['entity.show'],
12
- sourceCode: `const db = service("db.main", {
13
- create: () => Result.ok({ source: "factory" }),
14
- });
15
-
16
- trail("entity.show", {
17
- services: [db],
18
- run: async (_input, ctx) => {
19
- return Result.ok(db.from(ctx));
20
- }
21
- })`,
22
- },
23
- name: 'Declared services resolve to known project services',
24
- },
25
- ],
26
- rule: serviceExists,
27
- });