@typespec/versioning 0.57.0-dev.5 → 0.57.0-dev.7

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 (39) hide show
  1. package/dist/src/decorators.d.ts +64 -0
  2. package/dist/src/decorators.d.ts.map +1 -0
  3. package/dist/src/decorators.js +304 -0
  4. package/dist/src/decorators.js.map +1 -0
  5. package/dist/src/index.d.ts +2 -0
  6. package/dist/src/index.d.ts.map +1 -1
  7. package/dist/src/index.js +2 -0
  8. package/dist/src/index.js.map +1 -1
  9. package/dist/src/internal-projection-functions.d.ts +21 -0
  10. package/dist/src/internal-projection-functions.d.ts.map +1 -0
  11. package/dist/src/internal-projection-functions.js +88 -0
  12. package/dist/src/internal-projection-functions.js.map +1 -0
  13. package/dist/src/lib.d.ts +45 -45
  14. package/dist/src/lib.d.ts.map +1 -1
  15. package/dist/src/lib.js +15 -3
  16. package/dist/src/lib.js.map +1 -1
  17. package/dist/src/projection.d.ts +10 -0
  18. package/dist/src/projection.d.ts.map +1 -0
  19. package/dist/src/projection.js +38 -0
  20. package/dist/src/projection.js.map +1 -0
  21. package/dist/src/testing/index.d.ts +1 -1
  22. package/dist/src/testing/index.d.ts.map +1 -1
  23. package/dist/src/types.d.ts +1 -1
  24. package/dist/src/types.d.ts.map +1 -1
  25. package/dist/src/validate.d.ts +1 -1
  26. package/dist/src/validate.d.ts.map +1 -1
  27. package/dist/src/validate.js +3 -2
  28. package/dist/src/validate.js.map +1 -1
  29. package/dist/src/versioning-timeline.d.ts +2 -2
  30. package/dist/src/versioning-timeline.d.ts.map +1 -1
  31. package/dist/src/versioning-timeline.js.map +1 -1
  32. package/dist/src/versioning.d.ts +3 -89
  33. package/dist/src/versioning.d.ts.map +1 -1
  34. package/dist/src/versioning.js +88 -470
  35. package/dist/src/versioning.js.map +1 -1
  36. package/lib/decorators.tsp +180 -212
  37. package/lib/main.tsp +3 -0
  38. package/lib/{versioning.tsp → projection.tsp} +34 -2
  39. package/package.json +2 -2
@@ -1,383 +1,12 @@
1
- import { compilerAssert, getNamespaceFullName, } from "@typespec/compiler";
2
- import { createStateSymbol, reportDiagnostic } from "./lib.js";
3
- import { VersioningTimeline } from "./versioning-timeline.js";
4
- const addedOnKey = createStateSymbol("addedOn");
5
- const removedOnKey = createStateSymbol("removedOn");
6
- const versionsKey = createStateSymbol("versions");
7
- const versionDependencyKey = createStateSymbol("versionDependency");
8
- const useDependencyNamespaceKey = createStateSymbol("useDependencyNamespace");
9
- const useDependencyEnumKey = createStateSymbol("useDependencyEnum");
10
- const renamedFromKey = createStateSymbol("renamedFrom");
11
- const madeOptionalKey = createStateSymbol("madeOptional");
12
- const madeRequiredKey = createStateSymbol("madeRequired");
13
- const typeChangedFromKey = createStateSymbol("typeChangedFrom");
14
- const returnTypeChangedFromKey = createStateSymbol("returnTypeChangedFrom");
15
- export const namespace = "TypeSpec.Versioning";
16
- function checkIsVersion(program, enumMember, diagnosticTarget) {
17
- const version = getVersionForEnumMember(program, enumMember);
18
- if (!version) {
19
- reportDiagnostic(program, {
20
- code: "version-not-found",
21
- target: diagnosticTarget,
22
- format: { version: enumMember.name, enumName: enumMember.enum.name },
23
- });
24
- }
25
- return version;
26
- }
27
- export const $added = (context, t, v) => {
28
- const { program } = context;
29
- const version = checkIsVersion(context.program, v, context.getArgumentTarget(0));
30
- if (!version) {
31
- return;
32
- }
33
- // retrieve statemap to update or create a new one
34
- const record = program.stateMap(addedOnKey).get(t) ?? new Array();
35
- record.push(version);
36
- // ensure that records are stored in ascending order
37
- record.sort((a, b) => a.index - b.index);
38
- program.stateMap(addedOnKey).set(t, record);
39
- };
40
- export function $removed(context, t, v) {
41
- const { program } = context;
42
- const version = checkIsVersion(context.program, v, context.getArgumentTarget(0));
43
- if (!version) {
44
- return;
45
- }
46
- // retrieve statemap to update or create a new one
47
- const record = program.stateMap(removedOnKey).get(t) ?? new Array();
48
- record.push(version);
49
- // ensure that records are stored in ascending order
50
- record.sort((a, b) => a.index - b.index);
51
- program.stateMap(removedOnKey).set(t, record);
52
- }
53
- /**
54
- * Returns the mapping of versions to old type values, if applicable
55
- * @param p TypeSpec program
56
- * @param t type to query
57
- * @returns Map of versions to old types, if any
58
- */
59
- export function getTypeChangedFrom(p, t) {
60
- return p.stateMap(typeChangedFromKey).get(t);
61
- }
62
- export const $typeChangedFrom = (context, prop, v, oldType) => {
63
- const { program } = context;
64
- const version = checkIsVersion(context.program, v, context.getArgumentTarget(0));
65
- if (!version) {
66
- return;
67
- }
68
- // retrieve statemap to update or create a new one
69
- let record = getTypeChangedFrom(program, prop) ?? new Map();
70
- record.set(version, oldType);
71
- // ensure the map is sorted by version
72
- record = new Map([...record.entries()].sort((a, b) => a[0].index - b[0].index));
73
- program.stateMap(typeChangedFromKey).set(prop, record);
74
- };
75
- /**
76
- * Returns the mapping of versions to old return type values, if applicable
77
- * @param p TypeSpec program
78
- * @param t type to query
79
- * @returns Map of versions to old types, if any
80
- */
81
- export function getReturnTypeChangedFrom(p, t) {
82
- return p.stateMap(returnTypeChangedFromKey).get(t);
83
- }
84
- export const $returnTypeChangedFrom = (context, op, v, oldReturnType) => {
85
- const { program } = context;
86
- const version = checkIsVersion(context.program, v, context.getArgumentTarget(0));
87
- if (!version) {
88
- return;
89
- }
90
- // retrieve statemap to update or create a new one
91
- let record = getReturnTypeChangedFrom(program, op) ?? new Map();
92
- record.set(version, oldReturnType);
93
- // ensure the map is sorted by version
94
- record = new Map([...record.entries()].sort((a, b) => a[0].index - b[0].index));
95
- program.stateMap(returnTypeChangedFromKey).set(op, record);
96
- };
97
- export const $renamedFrom = (context, t, v, oldName) => {
98
- const { program } = context;
99
- const version = checkIsVersion(context.program, v, context.getArgumentTarget(0));
100
- if (!version) {
101
- return;
102
- }
103
- if (oldName === "") {
104
- reportDiagnostic(program, {
105
- code: "invalid-renamed-from-value",
106
- target: t,
107
- });
108
- }
109
- // retrieve statemap to update or create a new one
110
- const record = getRenamedFrom(program, t) ?? [];
111
- record.push({ version: version, oldName: oldName });
112
- // ensure that records are stored in ascending order
113
- record.sort((a, b) => a.version.index - b.version.index);
114
- program.stateMap(renamedFromKey).set(t, record);
115
- };
116
- export const $madeOptional = (context, t, v) => {
117
- const { program } = context;
118
- const version = checkIsVersion(context.program, v, context.getArgumentTarget(0));
119
- if (!version) {
120
- return;
121
- }
122
- program.stateMap(madeOptionalKey).set(t, version);
123
- };
124
- export const $madeRequired = (context, t, v) => {
125
- const { program } = context;
126
- const version = checkIsVersion(context.program, v, context.getArgumentTarget(0));
127
- if (!version) {
128
- return;
129
- }
130
- program.stateMap(madeRequiredKey).set(t, version);
131
- };
132
- /**
133
- * @returns the array of RenamedFrom metadata if applicable.
134
- */
135
- export function getRenamedFrom(p, t) {
136
- return p.stateMap(renamedFromKey).get(t);
137
- }
138
- /**
139
- * @returns the list of versions for which this decorator has been applied
140
- */
141
- export function getRenamedFromVersions(p, t) {
142
- return getRenamedFrom(p, t)?.map((x) => x.version);
143
- }
144
- /**
145
- * @returns get old name if applicable.
146
- */
147
- export function getNameAtVersion(p, t, versionKey) {
148
- const versioningState = getVersioningState(p, versionKey);
149
- const allValues = getRenamedFrom(p, t);
150
- if (!allValues)
151
- return "";
152
- for (const val of allValues) {
153
- if (versioningState.timeline.isBefore(versioningState.projectingMoment, val.version)) {
154
- return val.oldName;
155
- }
156
- }
157
- return "";
158
- }
159
- /**
160
- * @returns get old type if applicable.
161
- */
162
- export function getTypeBeforeVersion(p, t, versionKey) {
163
- const versioningState = getVersioningState(p, versionKey);
164
- const map = getTypeChangedFrom(p, t);
165
- if (!map)
166
- return undefined;
167
- for (const [changedAtVersion, oldType] of map) {
168
- if (versioningState.timeline.isBefore(versioningState.projectingMoment, changedAtVersion)) {
169
- return oldType;
170
- }
171
- }
172
- return undefined;
173
- }
174
- /**
175
- * @returns get old type if applicable.
176
- */
177
- export function getReturnTypeBeforeVersion(p, t, versionKey) {
178
- const versioningState = getVersioningState(p, versionKey);
179
- const map = getReturnTypeChangedFrom(p, t);
180
- if (!map)
181
- return "";
182
- for (const [changedAtVersion, val] of map) {
183
- if (versioningState.timeline.isBefore(versioningState.projectingMoment, changedAtVersion)) {
184
- return val;
185
- }
186
- }
187
- return "";
188
- }
189
- export function getAddedOnVersions(p, t) {
190
- return p.stateMap(addedOnKey).get(t);
191
- }
192
- export function getRemovedOnVersions(p, t) {
193
- return p.stateMap(removedOnKey).get(t);
194
- }
195
- /**
196
- * @returns version when the given type was made optional if applicable.
197
- */
198
- export function getMadeOptionalOn(p, t) {
199
- return p.stateMap(madeOptionalKey).get(t);
200
- }
201
- /**
202
- * @returns version when the given type was made required if applicable.
203
- */
204
- export function getMadeRequiredOn(p, t) {
205
- return p.stateMap(madeRequiredKey).get(t);
206
- }
207
- export class VersionMap {
208
- map = new Map();
209
- constructor(namespace, enumType) {
210
- let index = 0;
211
- for (const member of enumType.members.values()) {
212
- this.map.set(member, {
213
- name: member.name,
214
- value: member.value?.toString() ?? member.name,
215
- enumMember: member,
216
- index,
217
- namespace,
218
- });
219
- index++;
220
- }
221
- }
222
- getVersionForEnumMember(member) {
223
- return this.map.get(member);
224
- }
225
- getVersions() {
226
- return [...this.map.values()];
227
- }
228
- get size() {
229
- return this.map.size;
230
- }
231
- }
232
- export const $versioned = (context, t, versions) => {
233
- context.program.stateMap(versionsKey).set(t, new VersionMap(t, versions));
234
- };
235
- /**
236
- * Get the version map of the namespace.
237
- */
238
- export function getVersion(program, namespace) {
239
- return program.stateMap(versionsKey).get(namespace);
240
- }
241
- export function findVersionedNamespace(program, namespace) {
242
- let current = namespace;
243
- while (current) {
244
- if (program.stateMap(versionsKey).has(current)) {
245
- return current;
246
- }
247
- current = current.namespace;
248
- }
249
- return undefined;
250
- }
251
- export function $useDependency(context, target, ...versionRecords) {
252
- const versions = [];
253
- // ensure only valid versions are passed in
254
- for (const record of versionRecords) {
255
- const ver = checkIsVersion(context.program, record, context.getArgumentTarget(0));
256
- if (ver) {
257
- versions.push(ver);
258
- }
259
- }
260
- if (target.kind === "Namespace") {
261
- let state = context.program.stateMap(useDependencyNamespaceKey).get(target);
262
- if (!state) {
263
- state = versions;
264
- }
265
- else {
266
- state.push(...versions);
267
- }
268
- context.program.stateMap(useDependencyNamespaceKey).set(target, state);
269
- }
270
- else if (target.kind === "EnumMember") {
271
- const targetEnum = target.enum;
272
- let state = context.program.stateMap(useDependencyEnumKey).get(targetEnum);
273
- if (!state) {
274
- state = new Map();
275
- }
276
- // get any existing versions and combine them
277
- const currentVersions = state.get(target) ?? [];
278
- currentVersions.push(...versions);
279
- state.set(target, currentVersions);
280
- context.program.stateMap(useDependencyEnumKey).set(targetEnum, state);
281
- }
282
- }
283
- export function getUseDependencies(program, target, searchEnum = true) {
284
- const result = new Map();
285
- if (target.kind === "Namespace") {
286
- let current = target;
287
- while (current) {
288
- const data = program.stateMap(useDependencyNamespaceKey).get(current);
289
- if (!data) {
290
- // See if the namspace has a version enum
291
- if (searchEnum) {
292
- const versions = getVersion(program, current)?.getVersions();
293
- if (versions?.length) {
294
- const enumDeps = getUseDependencies(program, versions[0].enumMember.enum);
295
- if (enumDeps) {
296
- return enumDeps;
297
- }
298
- }
299
- }
300
- current = current.namespace;
301
- }
302
- else {
303
- for (const v of data) {
304
- result.set(v.namespace, v);
305
- }
306
- return result;
307
- }
308
- }
309
- return undefined;
310
- }
311
- else if (target.kind === "Enum") {
312
- const data = program.stateMap(useDependencyEnumKey).get(target);
313
- if (!data) {
314
- return undefined;
315
- }
316
- const resolved = resolveVersionDependency(program, data);
317
- if (resolved instanceof Map) {
318
- for (const [enumVer, value] of resolved) {
319
- for (const val of value) {
320
- const targetNamespace = val.enumMember.enum.namespace;
321
- if (!targetNamespace) {
322
- reportDiagnostic(program, {
323
- code: "version-not-found",
324
- target: val.enumMember.enum,
325
- format: { version: val.enumMember.name, enumName: val.enumMember.enum.name },
326
- });
327
- return undefined;
328
- }
329
- let subMap = result.get(targetNamespace);
330
- if (subMap) {
331
- subMap.set(enumVer, val);
332
- }
333
- else {
334
- subMap = new Map([[enumVer, val]]);
335
- }
336
- result.set(targetNamespace, subMap);
337
- }
338
- }
339
- }
340
- }
341
- return result;
342
- }
343
- function findVersionDependencyForNamespace(program, namespace) {
344
- let current = namespace;
345
- while (current) {
346
- const data = program.stateMap(versionDependencyKey).get(current);
347
- if (data) {
348
- return data;
349
- }
350
- current = current.namespace;
351
- }
352
- return undefined;
353
- }
1
+ import { getNamespaceFullName, } from "@typespec/compiler";
2
+ import { getAddedOnVersions, getRemovedOnVersions, getReturnTypeChangedFrom, getTypeChangedFrom, getUseDependencies, getVersion, } from "./decorators.js";
3
+ import { TimelineMoment, VersioningTimeline } from "./versioning-timeline.js";
354
4
  export function getVersionDependencies(program, namespace) {
355
5
  const useDeps = getUseDependencies(program, namespace);
356
6
  if (useDeps) {
357
7
  return useDeps;
358
8
  }
359
- const data = findVersionDependencyForNamespace(program, namespace);
360
- if (data === undefined) {
361
- return undefined;
362
- }
363
- const result = new Map();
364
- for (const [key, value] of data) {
365
- result.set(key, resolveVersionDependency(program, value));
366
- }
367
- return result;
368
- }
369
- function resolveVersionDependency(program, data) {
370
- if (!(data instanceof Map)) {
371
- return data;
372
- }
373
- const mapping = new Map();
374
- for (const [key, value] of data) {
375
- const sourceVersion = getVersionForEnumMember(program, key);
376
- if (sourceVersion !== undefined) {
377
- mapping.set(sourceVersion, value);
378
- }
379
- }
380
- return mapping;
9
+ return undefined;
381
10
  }
382
11
  /**
383
12
  * Resolve the version of dependencies
@@ -441,42 +70,6 @@ export function resolveVersions(program, namespace) {
441
70
  });
442
71
  }
443
72
  }
444
- /**
445
- * @internal
446
- */
447
- export function indexTimeline(program, timeline, projectingMoment) {
448
- const versionKey = program.checker.createType({
449
- kind: "Object",
450
- properties: {},
451
- });
452
- program.stateMap(versionIndexKey).set(versionKey, { timeline, projectingMoment });
453
- return versionKey;
454
- }
455
- function getVersioningState(program, versionKey) {
456
- return program.stateMap(versionIndexKey).get(versionKey);
457
- }
458
- const versionIndexKey = createStateSymbol("version-index");
459
- export function buildVersionProjections(program, rootNs) {
460
- const resolutions = resolveVersions(program, rootNs);
461
- const timeline = new VersioningTimeline(program, resolutions.map((x) => x.versions));
462
- return resolutions.map((resolution) => {
463
- if (resolution.versions.size === 0) {
464
- return { version: undefined, projections: [] };
465
- }
466
- else {
467
- const versionKey = indexTimeline(program, timeline, timeline.get(resolution.versions.values().next().value));
468
- return {
469
- version: resolution.rootVersion?.value,
470
- projections: [
471
- {
472
- projectionName: "v",
473
- arguments: [versionKey],
474
- },
475
- ],
476
- };
477
- }
478
- });
479
- }
480
73
  const versionCache = new WeakMap();
481
74
  function cacheVersion(key, versions) {
482
75
  versionCache.set(key, versions);
@@ -561,13 +154,58 @@ export var Availability;
561
154
  Availability["Available"] = "Available";
562
155
  Availability["Removed"] = "Removed";
563
156
  })(Availability || (Availability = {}));
157
+ function getParentAddedVersion(program, type, versions) {
158
+ let parentMap = undefined;
159
+ if (type.kind === "ModelProperty" && type.model !== undefined) {
160
+ parentMap = getAvailabilityMap(program, type.model);
161
+ }
162
+ else if (type.kind === "Operation" && type.interface !== undefined) {
163
+ parentMap = getAvailabilityMap(program, type.interface);
164
+ }
165
+ if (parentMap === undefined)
166
+ return undefined;
167
+ for (const [key, value] of parentMap.entries()) {
168
+ if (value === Availability.Added) {
169
+ return versions.find((x) => x.name === key);
170
+ }
171
+ }
172
+ return undefined;
173
+ }
174
+ function getParentAddedVersionInTimeline(program, type, timeline) {
175
+ let parentMap = undefined;
176
+ if (type.kind === "ModelProperty" && type.model !== undefined) {
177
+ parentMap = getAvailabilityMapInTimeline(program, type.model, timeline);
178
+ }
179
+ else if (type.kind === "Operation" && type.interface !== undefined) {
180
+ parentMap = getAvailabilityMapInTimeline(program, type.interface, timeline);
181
+ }
182
+ if (parentMap === undefined)
183
+ return undefined;
184
+ for (const [moment, availability] of parentMap.entries()) {
185
+ if (availability === Availability.Added) {
186
+ return moment.versions().next().value;
187
+ }
188
+ }
189
+ return undefined;
190
+ }
191
+ /**
192
+ * Returns true if the first version modifier was @added, false if @removed.
193
+ */
194
+ function resolveAddedFirst(added, removed) {
195
+ if (added.length === 0)
196
+ return false;
197
+ if (removed.length === 0)
198
+ return true;
199
+ return added[0].index < removed[0].index;
200
+ }
564
201
  export function getAvailabilityMap(program, type) {
565
202
  const avail = new Map();
566
203
  const allVersions = getAllVersions(program, type);
567
204
  // if unversioned then everything exists
568
205
  if (allVersions === undefined)
569
206
  return undefined;
570
- const added = getAddedOnVersions(program, type) ?? [];
207
+ const parentAdded = getParentAddedVersion(program, type, allVersions);
208
+ let added = getAddedOnVersions(program, type) ?? [];
571
209
  const removed = getRemovedOnVersions(program, type) ?? [];
572
210
  const typeChanged = getTypeChangedFrom(program, type);
573
211
  const returnTypeChanged = getReturnTypeChangedFrom(program, type);
@@ -579,28 +217,25 @@ export function getAvailabilityMap(program, type) {
579
217
  typeChanged === undefined &&
580
218
  returnTypeChanged === undefined)
581
219
  return undefined;
582
- let parentMap = undefined;
583
- if (type.kind === "ModelProperty" && type.model !== undefined) {
584
- parentMap = getAvailabilityMap(program, type.model);
220
+ const wasAddedFirst = resolveAddedFirst(added, removed);
221
+ // implicitly, all versioned things are assumed to have been added at
222
+ // v1 if not specified, or inherited from their parent.
223
+ if (!wasAddedFirst && !parentAdded) {
224
+ // if the first version modifier was @removed, and the parent is implicitly available,
225
+ // then assume the type was available.
226
+ added = [allVersions[0], ...added];
585
227
  }
586
- else if (type.kind === "Operation" && type.interface !== undefined) {
587
- parentMap = getAvailabilityMap(program, type.interface);
228
+ else if (!added.length && !parentAdded) {
229
+ // no version information on the item or its parent implicitly means it has always been available
230
+ added.push(allVersions[0]);
588
231
  }
589
- // implicitly, all versioned things are assumed to have been added at
590
- // v1 if not specified
591
- if (!added.length) {
592
- if (parentMap !== undefined) {
593
- parentMap.forEach((key, value) => {
594
- if (key === Availability.Added.valueOf()) {
595
- const match = allVersions.find((x) => x.name === value);
596
- compilerAssert(match !== undefined, "Version not found");
597
- added.push(match);
598
- }
599
- });
600
- }
601
- else {
602
- added.push(allVersions[0]);
603
- }
232
+ else if (!added.length && parentAdded) {
233
+ // if no version info on type but is on parent, inherit that parent's "added" version
234
+ added.push(parentAdded);
235
+ }
236
+ else if (added.length && parentAdded) {
237
+ // if "added" info on both the type and parent, combine them
238
+ added = [parentAdded, ...added];
604
239
  }
605
240
  // something isn't available by default
606
241
  let isAvail = false;
@@ -626,7 +261,8 @@ export function getAvailabilityMap(program, type) {
626
261
  }
627
262
  export function getAvailabilityMapInTimeline(program, type, timeline) {
628
263
  const avail = new Map();
629
- const added = getAddedOnVersions(program, type) ?? [];
264
+ const parentAdded = getParentAddedVersionInTimeline(program, type, timeline);
265
+ let added = getAddedOnVersions(program, type) ?? [];
630
266
  const removed = getRemovedOnVersions(program, type) ?? [];
631
267
  const typeChanged = getTypeChangedFrom(program, type);
632
268
  const returnTypeChanged = getReturnTypeChangedFrom(program, type);
@@ -638,10 +274,26 @@ export function getAvailabilityMapInTimeline(program, type, timeline) {
638
274
  typeChanged === undefined &&
639
275
  returnTypeChanged === undefined)
640
276
  return undefined;
277
+ const wasAddedFirst = resolveAddedFirst(added, removed);
641
278
  // implicitly, all versioned things are assumed to have been added at
642
- // v1 if not specified
643
- if (!added.length) {
644
- added.push(timeline.first().versions().next().value);
279
+ // v1 if not specified, or inherited from their parent.
280
+ const firstVersion = timeline.first().versions().next().value;
281
+ if (!wasAddedFirst && !parentAdded) {
282
+ // if the first version modifier was @removed, and the parent is implicitly available,
283
+ // then assume the type was available.
284
+ added = [firstVersion, ...added];
285
+ }
286
+ else if (!added.length && !parentAdded) {
287
+ // no version information on the item or its parent implicitly means it has always been available
288
+ added.push(firstVersion);
289
+ }
290
+ else if (!added.length && parentAdded) {
291
+ // if no version info on type but is on parent, inherit that parent's "added" version
292
+ added.push(parentAdded);
293
+ }
294
+ else if (added.length && parentAdded) {
295
+ // if "added" info on both the type and parent, combine them
296
+ added = [parentAdded, ...added];
645
297
  }
646
298
  // something isn't available by default
647
299
  let isAvail = false;
@@ -665,40 +317,6 @@ export function getAvailabilityMapInTimeline(program, type, timeline) {
665
317
  }
666
318
  return avail;
667
319
  }
668
- export function existsAtVersion(p, type, versionKey) {
669
- const versioningState = getVersioningState(p, versionKey);
670
- // if unversioned then everything exists
671
- const availability = getAvailabilityMapInTimeline(p, type, versioningState.timeline);
672
- if (!availability)
673
- return true;
674
- const isAvail = availability.get(versioningState.projectingMoment);
675
- return isAvail === Availability.Added || isAvail === Availability.Available;
676
- }
677
- export function hasDifferentNameAtVersion(p, type, version) {
678
- return getNameAtVersion(p, type, version) !== "";
679
- }
680
- export function madeOptionalAfter(program, type, versionKey) {
681
- const versioningState = getVersioningState(program, versionKey);
682
- const madeOptionalAtVersion = getMadeOptionalOn(program, type);
683
- if (madeOptionalAtVersion === undefined) {
684
- return false;
685
- }
686
- return versioningState.timeline.isBefore(versioningState.projectingMoment, madeOptionalAtVersion);
687
- }
688
- export function madeRequiredAfter(program, type, versionKey) {
689
- const versioningState = getVersioningState(program, versionKey);
690
- const madeRequiredAtVersion = getMadeRequiredOn(program, type);
691
- if (madeRequiredAtVersion === undefined) {
692
- return false;
693
- }
694
- return versioningState.timeline.isBefore(versioningState.projectingMoment, madeRequiredAtVersion);
695
- }
696
- export function hasDifferentTypeAtVersion(p, type, version) {
697
- return getTypeBeforeVersion(p, type, version) !== undefined;
698
- }
699
- export function hasDifferentReturnTypeAtVersion(p, type, version) {
700
- return getReturnTypeBeforeVersion(p, type, version) !== "";
701
- }
702
320
  export function getVersionForEnumMember(program, member) {
703
321
  // Always lookup for the original type. This ensure reference equality when comparing versions.
704
322
  member = member.projectionBase ?? member;