@endo/compartment-mapper 1.6.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/package.json +12 -16
  2. package/src/archive-lite.d.ts +7 -7
  3. package/src/archive-lite.d.ts.map +1 -1
  4. package/src/archive-lite.js +78 -27
  5. package/src/archive.d.ts.map +1 -1
  6. package/src/archive.js +7 -0
  7. package/src/bundle-lite.d.ts +3 -3
  8. package/src/bundle-lite.d.ts.map +1 -1
  9. package/src/bundle-lite.js +19 -24
  10. package/src/bundle.d.ts +3 -3
  11. package/src/bundle.d.ts.map +1 -1
  12. package/src/bundle.js +19 -24
  13. package/src/capture-lite.d.ts +2 -2
  14. package/src/capture-lite.d.ts.map +1 -1
  15. package/src/capture-lite.js +217 -25
  16. package/src/compartment-map.d.ts +9 -2
  17. package/src/compartment-map.d.ts.map +1 -1
  18. package/src/compartment-map.js +737 -254
  19. package/src/digest.d.ts +22 -2
  20. package/src/digest.d.ts.map +1 -1
  21. package/src/digest.js +179 -56
  22. package/src/generic-graph.d.ts.map +1 -1
  23. package/src/generic-graph.js +8 -3
  24. package/src/guards.d.ts +18 -0
  25. package/src/guards.d.ts.map +1 -0
  26. package/src/guards.js +109 -0
  27. package/src/hooks.md +124 -0
  28. package/src/import-archive-lite.d.ts.map +1 -1
  29. package/src/import-archive-lite.js +15 -11
  30. package/src/import-archive.d.ts +5 -19
  31. package/src/import-archive.d.ts.map +1 -1
  32. package/src/import-archive.js +7 -27
  33. package/src/import-hook.d.ts +4 -3
  34. package/src/import-hook.d.ts.map +1 -1
  35. package/src/import-hook.js +138 -69
  36. package/src/import-lite.d.ts +6 -6
  37. package/src/import-lite.d.ts.map +1 -1
  38. package/src/import-lite.js +8 -5
  39. package/src/import.d.ts +3 -3
  40. package/src/import.d.ts.map +1 -1
  41. package/src/import.js +16 -6
  42. package/src/infer-exports.d.ts.map +1 -1
  43. package/src/infer-exports.js +16 -6
  44. package/src/link.d.ts +4 -3
  45. package/src/link.d.ts.map +1 -1
  46. package/src/link.js +70 -58
  47. package/src/node-modules.d.ts +4 -3
  48. package/src/node-modules.d.ts.map +1 -1
  49. package/src/node-modules.js +482 -114
  50. package/src/parse-cjs-shared-export-wrapper.d.ts.map +1 -1
  51. package/src/parse-cjs-shared-export-wrapper.js +3 -1
  52. package/src/policy-format.d.ts +22 -5
  53. package/src/policy-format.d.ts.map +1 -1
  54. package/src/policy-format.js +342 -108
  55. package/src/policy.d.ts +13 -28
  56. package/src/policy.d.ts.map +1 -1
  57. package/src/policy.js +161 -106
  58. package/src/types/canonical-name.d.ts +97 -0
  59. package/src/types/canonical-name.d.ts.map +1 -0
  60. package/src/types/canonical-name.ts +151 -0
  61. package/src/types/compartment-map-schema.d.ts +114 -35
  62. package/src/types/compartment-map-schema.d.ts.map +1 -1
  63. package/src/types/compartment-map-schema.ts +202 -37
  64. package/src/types/external.d.ts +168 -28
  65. package/src/types/external.d.ts.map +1 -1
  66. package/src/types/external.ts +215 -26
  67. package/src/types/internal.d.ts +23 -42
  68. package/src/types/internal.d.ts.map +1 -1
  69. package/src/types/internal.ts +51 -50
  70. package/src/types/node-modules.d.ts +71 -10
  71. package/src/types/node-modules.d.ts.map +1 -1
  72. package/src/types/node-modules.ts +107 -9
  73. package/src/types/policy-schema.d.ts +26 -11
  74. package/src/types/policy-schema.d.ts.map +1 -1
  75. package/src/types/policy-schema.ts +29 -16
  76. package/src/types/policy.d.ts +6 -2
  77. package/src/types/policy.d.ts.map +1 -1
  78. package/src/types/policy.ts +7 -2
  79. package/src/types/typescript.d.ts +28 -0
  80. package/src/types/typescript.d.ts.map +1 -1
  81. package/src/types/typescript.ts +37 -1
package/src/digest.d.ts CHANGED
@@ -1,5 +1,25 @@
1
- export function digestCompartmentMap(compartmentMap: CompartmentMapDescriptor, sources: Sources): DigestResult;
2
- import type { CompartmentMapDescriptor } from './types.js';
1
+ /**
2
+ * @template {string} [OldCompartmentName=FileUrlString]
3
+ * @template {string} [NewCompartmentName=PackageCompartmentDescriptorName]
4
+ * @overload
5
+ * @param {PackageCompartmentMapDescriptor} compartmentMap
6
+ * @param {Sources} sources
7
+ * @param {DigestCompartmentMapOptions<OldCompartmentName, NewCompartmentName>} [options]
8
+ * @returns {DigestResult<OldCompartmentName, NewCompartmentName>}
9
+ */
10
+ export function digestCompartmentMap<OldCompartmentName extends string = `file://${string}`, NewCompartmentName extends string = PackageCompartmentDescriptorName>(compartmentMap: PackageCompartmentMapDescriptor, sources: Sources, options?: DigestCompartmentMapOptions<OldCompartmentName, NewCompartmentName> | undefined): DigestResult<OldCompartmentName, NewCompartmentName>;
11
+ /**
12
+ * @overload
13
+ * @param {PackageCompartmentMapDescriptor} compartmentMap
14
+ * @param {Sources} sources
15
+ * @param {DigestCompartmentMapOptions<FileUrlString, PackageCompartmentDescriptorName>} [options]
16
+ * @returns {DigestResult<FileUrlString, PackageCompartmentDescriptorName>}
17
+ */
18
+ export function digestCompartmentMap(compartmentMap: PackageCompartmentMapDescriptor, sources: Sources, options?: DigestCompartmentMapOptions<`file://${string}`, PackageCompartmentDescriptorName> | undefined): DigestResult<FileUrlString, PackageCompartmentDescriptorName>;
19
+ import type { PackageCompartmentDescriptorName } from './types.js';
20
+ import type { PackageCompartmentMapDescriptor } from './types.js';
3
21
  import type { Sources } from './types.js';
22
+ import type { DigestCompartmentMapOptions } from './types.js';
4
23
  import type { DigestResult } from './types.js';
24
+ import type { FileUrlString } from './types.js';
5
25
  //# sourceMappingURL=digest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["digest.js"],"names":[],"mappings":"AAqLO,qDAJI,wBAAwB,WACxB,OAAO,GACL,YAAY,CAoDxB;8CAxNS,YAAY;6BAAZ,YAAY;kCAAZ,YAAY"}
1
+ {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["digest.js"],"names":[],"mappings":";;;;;;;;;AAiQG,qCA5JoB,kBAAkB,SAA5B,MAAQ,uBACE,kBAAkB,SAA5B,MAAQ,qDA4JV,+BAA+B,WAC/B,OAAO,8FAEL,aAAa,kBAAkB,EAAE,kBAAkB,CAAC,CAChE;;;;;;;;AAGE,qDACQ,+BAA+B,WAC/B,OAAO,4GAEL,aAAa,aAAa,EAAE,gCAAgC,CAAC,CACzE;sDAlPS,YAAY;qDAAZ,YAAY;6BAAZ,YAAY;iDAAZ,YAAY;kCAAZ,YAAY;mCAAZ,YAAY"}
package/src/digest.js CHANGED
@@ -8,18 +8,41 @@
8
8
 
9
9
  /**
10
10
  * @import {
11
- * CompartmentDescriptor,
12
- * CompartmentMapDescriptor,
11
+ * DigestedCompartmentDescriptors,
13
12
  * DigestResult,
14
- * ModuleDescriptor,
13
+ * PackageCompartmentDescriptors,
14
+ * PackageCompartmentMapDescriptor,
15
+ * ModuleConfiguration,
15
16
  * Sources,
17
+ * ExitModuleConfiguration,
18
+ * FileModuleConfiguration,
19
+ * ErrorModuleConfiguration,
20
+ * DigestedCompartmentMapDescriptor,
21
+ * DigestedCompartmentDescriptor,
22
+ * DigestCompartmentMapOptions,
23
+ * PackageCompartmentDescriptor,
24
+ * PackageCompartmentDescriptorName,
25
+ * CompartmentModuleConfiguration,
26
+ * CanonicalName,
27
+ * CompartmentsRenameFn,
28
+ FileUrlString,
16
29
  * } from './types.js'
17
30
  */
18
31
 
19
- import { pathCompare } from '@endo/path-compare';
20
- import { assertCompartmentMap, stringCompare } from './compartment-map.js';
32
+ import {
33
+ assertDigestedCompartmentMap,
34
+ stringCompare,
35
+ } from './compartment-map.js';
36
+ import {
37
+ isErrorModuleSource,
38
+ isExitModuleSource,
39
+ isLocalModuleSource,
40
+ } from './guards.js';
21
41
 
22
- const { create, fromEntries, entries, keys } = Object;
42
+ const { create, fromEntries, entries, keys, values } = Object;
43
+ const { quote: q } = assert;
44
+
45
+ const noop = () => {};
23
46
 
24
47
  /**
25
48
  * We attempt to produce compartment maps that are consistent regardless of
@@ -49,71 +72,94 @@ const { create, fromEntries, entries, keys } = Object;
49
72
  * actual installation location, so should be orthogonal to the vagaries of the
50
73
  * package manager's deduplication algorithm.
51
74
  *
52
- * @param {Record<string, CompartmentDescriptor>} compartments
53
- * @returns {Record<string, string>} map from old to new compartment names.
75
+ * @type {CompartmentsRenameFn<FileUrlString, PackageCompartmentDescriptorName>}
54
76
  */
55
- const renameCompartments = compartments => {
56
- /** @type {Record<string, string>} */
77
+ const defaultRenameCompartments = compartments => {
78
+ /** @type {Record<FileUrlString, PackageCompartmentDescriptorName>} */
57
79
  const compartmentRenames = create(null);
58
- let index = 0;
59
- let prev = '';
60
80
 
61
81
  // The sort below combines two comparators to avoid depending on sort
62
82
  // stability, which became standard as recently as 2019.
63
83
  // If that date seems quaint, please accept my regards from the distant past.
64
84
  // We are very proud of you.
65
- const compartmentsByPath = Object.entries(compartments)
66
- .map(([name, compartment]) => ({
67
- name,
68
- path: compartment.path,
69
- label: compartment.label,
70
- }))
71
- .sort((a, b) => {
72
- if (a.label === b.label) {
73
- assert(a.path !== undefined && b.path !== undefined);
74
- return pathCompare(a.path, b.path);
75
- }
76
- return stringCompare(a.label, b.label);
77
- });
78
-
79
- for (const { name, label } of compartmentsByPath) {
80
- if (label === prev) {
81
- compartmentRenames[name] = `${label}-n${index}`;
82
- index += 1;
83
- } else {
84
- compartmentRenames[name] = label;
85
- prev = label;
86
- index = 1;
87
- }
85
+ const comaprtmentNamesToLabel =
86
+ /** @type {Array<{name: FileUrlString, label: PackageCompartmentDescriptorName}>} */ (
87
+ Object.entries(compartments)
88
+ .map(([name, compartment]) => ({
89
+ name,
90
+ label: compartment.label,
91
+ }))
92
+ .sort((a, b) => stringCompare(a.label, b.label))
93
+ );
94
+
95
+ for (const { name, label } of comaprtmentNamesToLabel) {
96
+ compartmentRenames[name] = label;
88
97
  }
89
98
  return compartmentRenames;
90
99
  };
91
100
 
92
101
  /**
93
- * @param {Record<string, CompartmentDescriptor>} compartments
102
+ * @template {string} [OldCompartmentName=FileUrlString]
103
+ * @template {string} [NewCompartmentName=PackageCompartmentDescriptorName]
104
+ * @overload
105
+ * @param {PackageCompartmentDescriptors} compartmentDescriptors
94
106
  * @param {Sources} sources
95
- * @param {Record<string, string>} compartmentRenames
107
+ * @param {Record<OldCompartmentName, NewCompartmentName>} compartmentRenames
108
+ * @param {DigestCompartmentMapOptions<OldCompartmentName, NewCompartmentName>} [options]
109
+ * @returns {DigestedCompartmentDescriptors}
96
110
  */
97
- const translateCompartmentMap = (compartments, sources, compartmentRenames) => {
111
+ /**
112
+ * @overload
113
+ * @param {PackageCompartmentDescriptors} compartmentDescriptors
114
+ * @param {Sources} sources
115
+ * @param {Record<FileUrlString, PackageCompartmentDescriptorName>} compartmentRenames
116
+ * @param {DigestCompartmentMapOptions} [options]
117
+ * @returns {DigestedCompartmentDescriptors}
118
+ */
119
+
120
+ /**
121
+ * @template {string} [OldCompartmentName=FileUrlString]
122
+ * @template {string} [NewCompartmentName=PackageCompartmentDescriptorName]
123
+ * @param {PackageCompartmentDescriptors} compartmentDescriptors
124
+ * @param {Sources} sources
125
+ * @param {Record<OldCompartmentName, NewCompartmentName>} compartmentRenames
126
+ * @param {DigestCompartmentMapOptions<OldCompartmentName, NewCompartmentName>} [options]
127
+ */
128
+ const translateCompartmentMap = (
129
+ compartmentDescriptors,
130
+ sources,
131
+ compartmentRenames,
132
+ { packageConnectionsHook, log = noop } = {},
133
+ ) => {
98
134
  const result = create(null);
99
135
  for (const compartmentName of keys(compartmentRenames)) {
100
- const compartment = compartments[compartmentName];
101
- const { name, label, retained: compartmentRetained, policy } = compartment;
136
+ /** @type {PackageCompartmentDescriptor} */
137
+ const compartmentDescriptor = compartmentDescriptors[compartmentName];
138
+ const {
139
+ name,
140
+ label,
141
+ retained: compartmentRetained,
142
+ policy,
143
+ } = compartmentDescriptor;
144
+ /** @type {Record<string, PackageCompartmentDescriptorName>} */
145
+ const renamedModuleConfigurations = {};
102
146
  if (compartmentRetained) {
103
147
  // rename module compartments
104
- /** @type {Record<string, ModuleDescriptor>} */
148
+ /** @type {Record<string, ModuleConfiguration>} */
105
149
  const modules = create(null);
106
- const compartmentModules = compartment.modules;
107
- if (compartment.modules) {
150
+ const compartmentModules = compartmentDescriptor.modules;
151
+ if (compartmentDescriptor.modules) {
108
152
  for (const name of keys(compartmentModules).sort()) {
109
153
  const { retained: moduleRetained, ...retainedModule } =
110
154
  compartmentModules[name];
111
155
  if (moduleRetained) {
112
156
  if (retainedModule.compartment !== undefined) {
157
+ /** @type {CompartmentModuleConfiguration} */
113
158
  modules[name] = {
114
159
  ...retainedModule,
115
160
  compartment: compartmentRenames[retainedModule.compartment],
116
161
  };
162
+ renamedModuleConfigurations[name] = retainedModule.compartment;
117
163
  } else {
118
164
  modules[name] = retainedModule;
119
165
  }
@@ -126,25 +172,40 @@ const translateCompartmentMap = (compartments, sources, compartmentRenames) => {
126
172
  if (compartmentSources) {
127
173
  for (const name of keys(compartmentSources).sort()) {
128
174
  const source = compartmentSources[name];
129
- const { location, parser, exit, sha512, deferredError } = source;
130
- if (location !== undefined) {
175
+ if (isLocalModuleSource(source)) {
176
+ const { location, parser, sha512 } = source;
177
+ /** @type {FileModuleConfiguration} */
131
178
  modules[name] = {
132
179
  location,
133
180
  parser,
134
181
  sha512,
182
+ __createdBy: 'digest',
135
183
  };
136
- } else if (exit !== undefined) {
184
+ } else if (isExitModuleSource(source)) {
185
+ const { exit } = source;
186
+ /** @type {ExitModuleConfiguration} */
137
187
  modules[name] = {
138
188
  exit,
189
+ __createdBy: 'digest',
139
190
  };
140
- } else if (deferredError !== undefined) {
191
+ } else if (isErrorModuleSource(source)) {
192
+ const { deferredError } = source;
193
+ /** @type {ErrorModuleConfiguration} */
141
194
  modules[name] = {
142
195
  deferredError,
196
+ __createdBy: 'digest',
143
197
  };
198
+ } else {
199
+ throw new TypeError(
200
+ `Unexpected source type for compartment ${compartmentName} module ${name}: ${q(
201
+ source,
202
+ )}`,
203
+ );
144
204
  }
145
205
  }
146
206
  }
147
207
 
208
+ /** @type {DigestedCompartmentDescriptor} */
148
209
  result[compartmentRenames[compartmentName]] = {
149
210
  name,
150
211
  label,
@@ -154,6 +215,23 @@ const translateCompartmentMap = (compartments, sources, compartmentRenames) => {
154
215
  // `scopes`, `types`, and `parsers` are not necessary since every
155
216
  // loadable module is captured in `modules`.
156
217
  };
218
+
219
+ const links = /** @type {Set<CanonicalName>} */ (
220
+ values(modules).reduce((acc, moduleDescriptorConfig) => {
221
+ if ('compartment' in moduleDescriptorConfig) {
222
+ acc.add(moduleDescriptorConfig.compartment);
223
+ }
224
+ return acc;
225
+ }, new Set())
226
+ );
227
+
228
+ if (packageConnectionsHook) {
229
+ packageConnectionsHook({
230
+ canonicalName: label,
231
+ connections: links,
232
+ log,
233
+ });
234
+ }
157
235
  }
158
236
  }
159
237
 
@@ -175,26 +253,53 @@ const renameSources = (sources, compartmentRenames) => {
175
253
  };
176
254
 
177
255
  /**
178
- * @param {CompartmentMapDescriptor} compartmentMap
256
+ * @template {string} [OldCompartmentName=FileUrlString]
257
+ * @template {string} [NewCompartmentName=PackageCompartmentDescriptorName]
258
+ * @overload
259
+ * @param {PackageCompartmentMapDescriptor} compartmentMap
260
+ * @param {Sources} sources
261
+ * @param {DigestCompartmentMapOptions<OldCompartmentName, NewCompartmentName>} [options]
262
+ * @returns {DigestResult<OldCompartmentName, NewCompartmentName>}
263
+ */
264
+
265
+ /**
266
+ * @overload
267
+ * @param {PackageCompartmentMapDescriptor} compartmentMap
179
268
  * @param {Sources} sources
180
- * @returns {DigestResult}
269
+ * @param {DigestCompartmentMapOptions<FileUrlString, PackageCompartmentDescriptorName>} [options]
270
+ * @returns {DigestResult<FileUrlString, PackageCompartmentDescriptorName>}
181
271
  */
182
- export const digestCompartmentMap = (compartmentMap, sources) => {
272
+
273
+ /**
274
+ * @template {string} [OldCompartmentName=FileUrlString]
275
+ * @template {string} [NewCompartmentName=PackageCompartmentDescriptorName]
276
+ * @param {PackageCompartmentMapDescriptor} compartmentMap
277
+ * @param {Sources} sources
278
+ * @param {DigestCompartmentMapOptions<OldCompartmentName, NewCompartmentName>} [options]
279
+ */
280
+ export const digestCompartmentMap = (
281
+ compartmentMap,
282
+ sources,
283
+ { packageConnectionsHook, log = noop, renameCompartments } = {},
284
+ ) => {
183
285
  const {
184
286
  compartments,
185
287
  entry: { compartment: entryCompartmentName, module: entryModuleSpecifier },
186
288
  } = compartmentMap;
187
289
 
188
- const oldToNewCompartmentNames = renameCompartments(compartments);
290
+ const renameCompartmentsFn = renameCompartments ?? defaultRenameCompartments;
291
+ const oldToNewCompartmentNames = renameCompartmentsFn(compartments);
189
292
  const digestCompartments = translateCompartmentMap(
190
293
  compartments,
191
294
  sources,
192
295
  oldToNewCompartmentNames,
296
+ { packageConnectionsHook, log },
193
297
  );
194
298
  const digestEntryCompartmentName =
195
299
  oldToNewCompartmentNames[entryCompartmentName];
196
300
  const digestSources = renameSources(sources, oldToNewCompartmentNames);
197
301
 
302
+ /** @type {DigestedCompartmentMapDescriptor} */
198
303
  const digestCompartmentMap = {
199
304
  // TODO graceful migration from tags to conditions
200
305
  // https://github.com/endojs/endo/issues/2388
@@ -210,8 +315,18 @@ export const digestCompartmentMap = (compartmentMap, sources) => {
210
315
  // We assert that we have constructed a valid compartment map, not because it
211
316
  // might not be, but to ensure that the assertCompartmentMap function can
212
317
  // accept all valid compartment maps.
213
- assertCompartmentMap(digestCompartmentMap);
318
+ try {
319
+ assertDigestedCompartmentMap(digestCompartmentMap);
320
+ } catch (err) {
321
+ throw new TypeError(
322
+ `Invalid compartment map; ${JSON.stringify(
323
+ digestCompartmentMap,
324
+ )}:\n${err.message}`,
325
+ { cause: err },
326
+ );
327
+ }
214
328
 
329
+ /** @type {Record<NewCompartmentName, OldCompartmentName>} */
215
330
  const newToOldCompartmentNames = fromEntries(
216
331
  entries(oldToNewCompartmentNames).map(([oldName, newName]) => [
217
332
  newName,
@@ -219,14 +334,22 @@ export const digestCompartmentMap = (compartmentMap, sources) => {
219
334
  ]),
220
335
  );
221
336
 
222
- /** @type {DigestResult} */
223
- const digestResult = {
337
+ if (renameCompartments === defaultRenameCompartments) {
338
+ /** @type {DigestResult} */
339
+ return {
340
+ compartmentMap: digestCompartmentMap,
341
+ sources: digestSources,
342
+ oldToNewCompartmentNames,
343
+ newToOldCompartmentNames,
344
+ compartmentRenames: newToOldCompartmentNames,
345
+ };
346
+ }
347
+ /** @type {DigestResult<OldCompartmentName, NewCompartmentName>} */
348
+ return {
224
349
  compartmentMap: digestCompartmentMap,
225
350
  sources: digestSources,
226
351
  oldToNewCompartmentNames,
227
352
  newToOldCompartmentNames,
228
353
  compartmentRenames: newToOldCompartmentNames,
229
354
  };
230
-
231
- return digestResult;
232
355
  };
@@ -1 +1 @@
1
- {"version":3,"file":"generic-graph.d.ts","sourceRoot":"","sources":["generic-graph.js"],"names":[],"mappings":"AAoHA;;;;;;GAMG;AACH,0BANc,CAAC;IA+Bb;;OAEG;IACH,oBAEC;IAED;;;;;;OAMG;IACH,cAHW,CAAC,GACC,IAAI,CAUhB;IAED;;;;;OAKG;IACH,iBAHW,CAAC,GACC,IAAI,CAShB;IAED;;;;OAIG;IACH,eAHW,CAAC,GACC,GAAG,CAAC,CAAC,CAAC,GAAC,SAAS,CAI5B;IAED;;;;;;;OAOG;IACH,sBALW,CAAC,UACD,CAAC,UACD,MAAM,GACJ,IAAI,CAWhB;IAED;;;;;;OAMG;IACH,sBAJW,CAAC,UACD,CAAC,GACC,MAAM,CAUlB;IAED;;;;;;;;;;;;OAYG;IACH,gBALW,CAAC,UACD,CAAC,UACD,MAAM,GACJ,IAAI,CAWhB;IAED;;;;;;;OAOG;IACH,mBAJW,CAAC,UACD,CAAC,GACC,IAAI,CAKhB;IAED;;;;;OAKG;IACH,gBAJW,CAAC,UACD,CAAC,GACC,OAAO,CAInB;;CACF;AA6DM,iCAHO,CAAC,kBACJ,YAAY,CAAC,CAAC,CAAC,YAIb,OAAO,CAAC,CAAC,CAAC,UACV,OAAO,CAAC,CAAC,CAAC,KACR,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAO5B"}
1
+ {"version":3,"file":"generic-graph.d.ts","sourceRoot":"","sources":["generic-graph.js"],"names":[],"mappings":"AAyHA;;;;;;GAMG;AACH,0BANc,CAAC;IA+Bb;;OAEG;IACH,oBAEC;IAED;;;;;;OAMG;IACH,cAHW,CAAC,GACC,IAAI,CAUhB;IAED;;;;;OAKG;IACH,iBAHW,CAAC,GACC,IAAI,CAShB;IAED;;;;OAIG;IACH,eAHW,CAAC,GACC,GAAG,CAAC,CAAC,CAAC,GAAC,SAAS,CAI5B;IAED;;;;;;;OAOG;IACH,sBALW,CAAC,UACD,CAAC,UACD,MAAM,GACJ,IAAI,CAWhB;IAED;;;;;;OAMG;IACH,sBAJW,CAAC,UACD,CAAC,GACC,MAAM,CAUlB;IAED;;;;;;;;;;;;OAYG;IACH,gBALW,CAAC,UACD,CAAC,UACD,MAAM,GACJ,IAAI,CAWhB;IAED;;;;;;;OAOG;IACH,mBAJW,CAAC,UACD,CAAC,GACC,IAAI,CAKhB;IAED;;;;;OAKG;IACH,gBAJW,CAAC,UACD,CAAC,GACC,OAAO,CAInB;;CACF;AA6DM,iCAHO,CAAC,kBACJ,YAAY,CAAC,CAAC,CAAC,YAIb,OAAO,CAAC,CAAC,CAAC,UACV,OAAO,CAAC,CAAC,CAAC,KACR,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAO5B"}
@@ -2,7 +2,7 @@
2
2
  * Provides {@link GenericGraph} and {@link makeShortestPath}.
3
3
  *
4
4
  * Portions adapted from
5
- * {@link https://github.com/datavis-tech/graph-data-structure graph-data-structure},
5
+ * [graph data structure](https://github.com/datavis-tech/graph-data-structure),
6
6
  * which is Copyright (c) 2016 Curran Kelleher and licensed under the MIT
7
7
  * License.
8
8
  *
@@ -13,7 +13,7 @@
13
13
  * @import {TraversalContext} from './types/generic-graph.js';
14
14
  */
15
15
 
16
- const { stringify: q } = JSON;
16
+ const { quote: q } = assert;
17
17
 
18
18
  /**
19
19
  * Remove the node with the minimum weight from the priority queue.
@@ -94,6 +94,11 @@ const getPath = ({ predecessors }, source, target) => {
94
94
  /** @type {T[]} */
95
95
  const nodeList = [];
96
96
 
97
+ assert(
98
+ source !== target,
99
+ `Source ${q(source)} cannot be the same as target ${q(target)}`,
100
+ );
101
+
97
102
  let node = target;
98
103
 
99
104
  while (predecessors.has(node)) {
@@ -108,7 +113,7 @@ const getPath = ({ predecessors }, source, target) => {
108
113
 
109
114
  assert(
110
115
  nodeList.length >= 2,
111
- `The path from ${source} to ${target} should have a least two nodes`,
116
+ `The path from ${source} to ${target} should have at least two nodes`,
112
117
  );
113
118
 
114
119
  return /** @type {[T, T, ...T[]]} */ (nodeList.reverse());
@@ -0,0 +1,18 @@
1
+ export function isErrorModuleConfiguration(value: ModuleConfiguration): value is ErrorModuleConfiguration;
2
+ export function isFileModuleConfiguration(value: ModuleConfiguration): value is FileModuleConfiguration;
3
+ export function isExitModuleConfiguration(value: ModuleConfiguration): value is ExitModuleConfiguration;
4
+ export function isCompartmentModuleConfiguration(value: ModuleConfiguration): value is CompartmentModuleConfiguration;
5
+ export function isErrorModuleSource(value: ModuleSource): value is ErrorModuleSource;
6
+ export function isExitModuleSource(value: ModuleSource): value is ExitModuleSource;
7
+ export function isLocalModuleSource(value: ModuleSource): value is LocalModuleSource;
8
+ export function isNonNullableObject(value: unknown): value is object;
9
+ import type { ModuleConfiguration } from './types.js';
10
+ import type { ErrorModuleConfiguration } from './types.js';
11
+ import type { FileModuleConfiguration } from './types.js';
12
+ import type { ExitModuleConfiguration } from './types.js';
13
+ import type { CompartmentModuleConfiguration } from './types.js';
14
+ import type { ModuleSource } from './types.js';
15
+ import type { ErrorModuleSource } from './types.js';
16
+ import type { ExitModuleSource } from './types.js';
17
+ import type { LocalModuleSource } from './types.js';
18
+ //# sourceMappingURL=guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["guards.js"],"names":[],"mappings":"AA2BO,kDAHI,mBAAmB,GACjB,KAAK,IAAI,wBAAwB,CAIU;AAQjD,iDAHI,mBAAmB,GACjB,KAAK,IAAI,uBAAuB,CAKT;AAO7B,iDAHI,mBAAmB,GACjB,KAAK,IAAI,uBAAuB,CAKT;AAO7B,wDAHI,mBAAmB,GACjB,KAAK,IAAI,8BAA8B,CAOhB;AAO7B,2CAHI,YAAY,GACV,KAAK,IAAI,iBAAiB,CAIiB;AAQjD,0CAHI,YAAY,GACV,KAAK,IAAI,gBAAgB,CAKT;AAQtB,2CAHI,YAAY,GACV,KAAK,IAAI,iBAAiB,CAWV;AAQtB,2CAHI,OAAO,GACL,KAAK,IAAI,MAAM,CAGiB;yCAzFnC,YAAY;8CAAZ,YAAY;6CAAZ,YAAY;6CAAZ,YAAY;oDAAZ,YAAY;kCAAZ,YAAY;uCAAZ,YAAY;sCAAZ,YAAY;uCAAZ,YAAY"}
package/src/guards.js ADDED
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Common type guards.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ const { hasOwn } = Object;
8
+
9
+ /**
10
+ * @import {
11
+ * ModuleConfiguration,
12
+ * FileModuleConfiguration,
13
+ * ErrorModuleConfiguration,
14
+ * ModuleSource,
15
+ * ExitModuleSource,
16
+ * ErrorModuleSource,
17
+ * LocalModuleSource,
18
+ * ExitModuleConfiguration,
19
+ * CompartmentModuleConfiguration
20
+ * } from './types.js';
21
+ */
22
+
23
+ /**
24
+ * Type guard for an {@link ErrorModuleConfiguration}.
25
+ * @param {ModuleConfiguration} value
26
+ * @returns {value is ErrorModuleConfiguration}
27
+ */
28
+ export const isErrorModuleConfiguration = value =>
29
+ hasOwn(value, 'deferredError') &&
30
+ /** @type {any} */ (value).deferredError !== undefined;
31
+
32
+ /**
33
+ * Type guard for a {@link FileModuleConfiguration}.
34
+ *
35
+ * @param {ModuleConfiguration} value
36
+ * @returns {value is FileModuleConfiguration}
37
+ */
38
+ export const isFileModuleConfiguration = value =>
39
+ hasOwn(value, 'parser') &&
40
+ /** @type {any} */ (value).parser !== undefined &&
41
+ !isErrorModuleConfiguration(value);
42
+
43
+ /**
44
+ * Type guard for an {@link ExitModuleConfiguration}.
45
+ * @param {ModuleConfiguration} value
46
+ * @returns {value is ExitModuleConfiguration}
47
+ */
48
+ export const isExitModuleConfiguration = value =>
49
+ hasOwn(value, 'exit') &&
50
+ /** @type {any} */ (value).exit !== undefined &&
51
+ !isErrorModuleConfiguration(value);
52
+
53
+ /**
54
+ * Type guard for an {@link CompartmentModuleConfiguration}.
55
+ * @param {ModuleConfiguration} value
56
+ * @returns {value is CompartmentModuleConfiguration}
57
+ */
58
+ export const isCompartmentModuleConfiguration = value =>
59
+ hasOwn(value, 'compartment') &&
60
+ /** @type {any} */ (value).compartment !== undefined &&
61
+ hasOwn(value, 'module') &&
62
+ /** @type {any} */ (value).module !== undefined &&
63
+ !isErrorModuleConfiguration(value);
64
+ /**
65
+ * Type guard for an {@link ErrorModuleSource}.
66
+ *
67
+ * @param {ModuleSource} value
68
+ * @returns {value is ErrorModuleSource}
69
+ */
70
+ export const isErrorModuleSource = value =>
71
+ hasOwn(value, 'deferredError') &&
72
+ /** @type {any} */ (value).deferredError !== undefined;
73
+
74
+ /**
75
+ * Type guard for an {@link ExitModuleSource}.
76
+ *
77
+ * @param {ModuleSource} value
78
+ * @returns {value is ExitModuleSource}
79
+ */
80
+ export const isExitModuleSource = value =>
81
+ hasOwn(value, 'exit') &&
82
+ /** @type {any} */ (value).exit !== undefined &&
83
+ !isErrorModuleSource(value);
84
+
85
+ /**
86
+ * Type guard for an {@link LocalModuleSource}.
87
+ *
88
+ * @param {ModuleSource} value
89
+ * @returns {value is LocalModuleSource}
90
+ */
91
+ export const isLocalModuleSource = value =>
92
+ hasOwn(value, 'bytes') &&
93
+ /** @type {any} */ (value).bytes !== undefined &&
94
+ hasOwn(value, 'parser') &&
95
+ /** @type {any} */ (value).parser !== undefined &&
96
+ hasOwn(value, 'sourceDirname') &&
97
+ /** @type {any} */ (value).sourceDirname !== undefined &&
98
+ hasOwn(value, 'location') &&
99
+ /** @type {any} */ (value).location !== undefined &&
100
+ !isErrorModuleSource(value);
101
+
102
+ /**
103
+ * Type guard for a non-nullable object
104
+ *
105
+ * @param {unknown} value
106
+ * @returns {value is object}
107
+ */
108
+ export const isNonNullableObject = value =>
109
+ typeof value === 'object' && value !== null;