@dotbep/core 0.2.7 → 0.2.8

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 (77) hide show
  1. package/dist/index.d.ts +7 -5
  2. package/dist/index.js +604 -596
  3. package/package.json +4 -1
  4. package/examples/01-participants.ts +0 -127
  5. package/examples/02-files.ts +0 -100
  6. package/examples/03-workflows.ts +0 -149
  7. package/examples/04-bim-uses.ts +0 -70
  8. package/examples/05-standards.ts +0 -60
  9. package/examples/06-schedule.ts +0 -124
  10. package/examples/07-loin.ts +0 -133
  11. package/examples/08-deliverables.ts +0 -126
  12. package/examples/09-notes.ts +0 -73
  13. package/examples/10-llm.ts +0 -109
  14. package/examples/11-resolved.ts +0 -133
  15. package/examples/12-history.ts +0 -166
  16. package/examples/13-engine.ts +0 -152
  17. package/examples/bep.d.ts +0 -38
  18. package/examples/example.bep +0 -0
  19. package/examples/run-all.ts +0 -38
  20. package/src/base/entity.ts +0 -148
  21. package/src/base/history.ts +0 -497
  22. package/src/base/index.ts +0 -5
  23. package/src/base/singleton.ts +0 -26
  24. package/src/entities/actions.ts +0 -25
  25. package/src/entities/adapters.ts +0 -16
  26. package/src/entities/annexes.ts +0 -17
  27. package/src/entities/assetTypes.ts +0 -30
  28. package/src/entities/automations.ts +0 -24
  29. package/src/entities/bimUses.ts +0 -50
  30. package/src/entities/deliverables.ts +0 -66
  31. package/src/entities/disciplines.ts +0 -21
  32. package/src/entities/effects.ts +0 -28
  33. package/src/entities/env.ts +0 -17
  34. package/src/entities/events.ts +0 -24
  35. package/src/entities/extensions.ts +0 -16
  36. package/src/entities/flags.ts +0 -17
  37. package/src/entities/guides.ts +0 -26
  38. package/src/entities/index.ts +0 -32
  39. package/src/entities/lbsNodes.ts +0 -193
  40. package/src/entities/lods.ts +0 -22
  41. package/src/entities/loin.ts +0 -127
  42. package/src/entities/lois.ts +0 -22
  43. package/src/entities/members.ts +0 -137
  44. package/src/entities/milestones.ts +0 -32
  45. package/src/entities/notes.ts +0 -27
  46. package/src/entities/objectives.ts +0 -17
  47. package/src/entities/phases.ts +0 -17
  48. package/src/entities/remoteData.ts +0 -17
  49. package/src/entities/resolvers.ts +0 -20
  50. package/src/entities/roles.ts +0 -29
  51. package/src/entities/softwares.ts +0 -26
  52. package/src/entities/standards.ts +0 -68
  53. package/src/entities/teams.ts +0 -42
  54. package/src/entities/workflows.ts +0 -256
  55. package/src/index.ts +0 -464
  56. package/src/runtime/Engine.ts +0 -352
  57. package/src/runtime/MemoryStorage.ts +0 -31
  58. package/src/runtime/Runtime.ts +0 -106
  59. package/src/runtime/index.ts +0 -4
  60. package/src/runtime/transitions.ts +0 -456
  61. package/src/runtime/types.ts +0 -279
  62. package/src/types/history.ts +0 -37
  63. package/src/types/index.ts +0 -24
  64. package/src/types/resolved.ts +0 -137
  65. package/src/types/schema.ts +0 -757
  66. package/src/utils/diff.ts +0 -109
  67. package/src/utils/index.ts +0 -9
  68. package/src/utils/integrity.ts +0 -108
  69. package/src/utils/lbs.ts +0 -116
  70. package/src/utils/mermaid.ts +0 -110
  71. package/src/utils/naming.ts +0 -62
  72. package/src/utils/nomenclature.ts +0 -107
  73. package/src/utils/normalize.ts +0 -35
  74. package/src/utils/raci.ts +0 -25
  75. package/src/utils/textFile.ts +0 -24
  76. package/tsconfig.json +0 -12
  77. package/vite.config.ts +0 -24
@@ -1,497 +0,0 @@
1
- import { compare, applyPatch, type Operation } from 'fast-json-patch'
2
- import type JSZip from 'jszip'
3
- import type { BEP, BEPVersion, Changelog, Standard } from '../types/schema.js'
4
- import { diffBep } from '../utils/diff.js'
5
- import { normalizeBep } from '../utils/normalize.js'
6
- import type { BepDiff, BepStatus, StandardChange, CommitParams, SquashParams } from '../types/history.js'
7
-
8
- export type { BepStatus, StandardChange, CommitParams, SquashParams }
9
-
10
- export type CompareResult = {
11
- diff: Operation[]
12
- standards: {
13
- added: { id: string; name: string }[]
14
- removed: { id: string; name: string }[]
15
- contentModified: { id: string; name: string; changedIn: string[] }[]
16
- }
17
- }
18
-
19
- export type BEPVersionResolved = {
20
- version: string
21
- type: 'patch' | 'version'
22
- date: string
23
- description: string
24
- diff: string | null
25
- isCurrent: boolean
26
- author: { email: string; name: string | null } | null
27
- approvedBy?: { email: string; name: string | null }[]
28
- }
29
-
30
- // ─── History ──────────────────────────────────────────────────────────────────
31
-
32
- export class History {
33
- constructor(
34
- private getBep: () => BEP,
35
- private setBep: (bep: BEP) => void,
36
- private getZip: () => JSZip,
37
- ) {}
38
-
39
- // ─── Version helpers ──────────────────────────────────────────────────────
40
-
41
- private static parseVersion(v: string): { major: number; minor: number } {
42
- const [major, minor] = v.split('.').map(Number)
43
- return { major, minor }
44
- }
45
-
46
- static compareVersions(a: string, b: string): number {
47
- const pa = History.parseVersion(a)
48
- const pb = History.parseVersion(b)
49
- if (pa.major !== pb.major) return pa.major - pb.major
50
- return pa.minor - pb.minor
51
- }
52
-
53
- private static bumpVersion(current: string, type: BEPVersion['type']): string {
54
- const [major, minor] = current.split('.').map(Number)
55
- return type === 'version' ? `${major + 1}.0` : `${major}.${minor + 1}`
56
- }
57
-
58
- // ─── Zip helpers ──────────────────────────────────────────────────────────
59
-
60
- private async readChangelog(): Promise<Changelog | null> {
61
- const file = this.getZip().file('changelog.json')
62
- if (!file) return null
63
- return JSON.parse(await file.async('string')) as Changelog
64
- }
65
-
66
- private async readBaseline(): Promise<BEP | null> {
67
- const file = this.getZip().file('baseline/bep.json')
68
- if (!file) return null
69
- return normalizeBep(JSON.parse(await file.async('string')) as BEP)
70
- }
71
-
72
- // ─── Standards versioning helpers ─────────────────────────────────────────
73
-
74
- /**
75
- * At commit time: for each standard whose .md content changed since the last
76
- * snapshot, saves changelog/standards/{id}/v{version}.md.
77
- */
78
- private async snapshotChangedStandards(bep: BEP, newVersion: string): Promise<void> {
79
- const zip = this.getZip()
80
- for (const standard of bep.standards) {
81
- const currentFile = zip.file(standard.contentPath)
82
- if (!currentFile) continue
83
- const currentContent = await currentFile.async('string')
84
-
85
- const prefix = `changelog/standards/${standard.id}/`
86
- const existingVersions = Object.keys(zip.files)
87
- .filter(k => k.startsWith(prefix) && k.endsWith('.md') && k.slice(prefix.length).startsWith('v'))
88
- .map(k => k.slice(prefix.length + 1, -3)) // strip prefix+'v' and '.md' → "0.1"
89
-
90
- let prevContent: string | null = null
91
- if (existingVersions.length > 0) {
92
- const latest = existingVersions.sort((a, b) => History.compareVersions(b, a))[0]
93
- const snapshotFile = zip.file(`${prefix}v${latest}.md`)
94
- if (snapshotFile) prevContent = await snapshotFile.async('string')
95
- }
96
-
97
- if (prevContent !== currentContent) {
98
- zip.file(`${prefix}v${newVersion}.md`, currentContent)
99
- }
100
- }
101
- }
102
-
103
- /**
104
- * Copies each standards/{uuid}.md to baseline/standards/{id}.md so that
105
- * discard() can restore the .md files to their last committed state.
106
- */
107
- private async snapshotBaseStandards(bep: BEP): Promise<void> {
108
- const zip = this.getZip()
109
- for (const standard of bep.standards) {
110
- const currentFile = zip.file(standard.contentPath)
111
- if (!currentFile) continue
112
- const content = await currentFile.async('string')
113
- zip.file(`baseline/standards/${standard.id}.md`, content)
114
- }
115
- }
116
-
117
- /**
118
- * Resolves the .md content of a standard at a specific historical version.
119
- * Finds the latest snapshot in changelog/standards/{id}/ with version ≤ target.
120
- * Falls back to the current file if no snapshot exists (content never changed).
121
- */
122
- async resolveStandardContent(standard: Standard, targetVersion: string): Promise<string | null> {
123
- const zip = this.getZip()
124
- const prefix = `changelog/standards/${standard.id}/`
125
- const candidates = Object.keys(zip.files)
126
- .filter(k => k.startsWith(prefix) && k.endsWith('.md') && k.slice(prefix.length).startsWith('v'))
127
- .map(k => k.slice(prefix.length + 1, -3)) // strip 'v' and '.md'
128
- .filter(v => History.compareVersions(v, targetVersion) <= 0)
129
- .sort((a, b) => History.compareVersions(b, a))
130
-
131
- if (candidates.length === 0) {
132
- const currentFile = zip.file(standard.contentPath)
133
- return currentFile ? currentFile.async('string') : null
134
- }
135
-
136
- const file = zip.file(`${prefix}v${candidates[0]}.md`)
137
- return file ? file.async('string') : null
138
- }
139
-
140
- // ─── Public API ───────────────────────────────────────────────────────────
141
-
142
- async current(): Promise<string> {
143
- const changelog = await this.readChangelog()
144
- return changelog?.current ?? '0.0'
145
- }
146
-
147
- async list(): Promise<BEPVersion[]> {
148
- const changelog = await this.readChangelog()
149
- return changelog?.versions ?? []
150
- }
151
-
152
- async commit(params: CommitParams, force = false): Promise<BEPVersion> {
153
- const zip = this.getZip()
154
- const currentBep = this.getBep()
155
- const changelog = await this.readChangelog()
156
- const baseline = await this.readBaseline()
157
- const date = new Date().toISOString()
158
-
159
- if (!baseline) throw new Error('No baseline found — create a BEP with Bep.create() or open one with Bep.open()')
160
-
161
- if (params.type === 'version') {
162
- const missing = params.approvedBy.filter(email => !currentBep.members.some(m => m.email === email))
163
- if (missing.length) throw new Error(`Members not found: ${missing.join(', ')}`)
164
- }
165
-
166
- if (!force) {
167
- const hasChanges = await this.hasPendingChanges()
168
- if (!hasChanges) throw new Error('No pending changes since last commit')
169
- }
170
-
171
- // Bump from current version (defaults to '0.0' — the hidden terminus — on first commit,
172
- // so the first user commit always produces '0.1' for patch or '1.0' for version).
173
- const currentVersion = changelog?.current ?? '0.0'
174
- const newVersionStr = History.bumpVersion(currentVersion, params.type)
175
- const diffPath = `changelog/v${newVersionStr}.diff.json`
176
- const inverseDiff: Operation[] = compare(currentBep, baseline)
177
-
178
- const version: BEPVersion = params.type === 'patch'
179
- ? { version: newVersionStr, type: 'patch', date, author: params.author, description: params.description, diff: diffPath }
180
- : { version: newVersionStr, type: 'version', date, author: params.author, description: params.description, approvedBy: params.approvedBy, diff: diffPath }
181
-
182
- const newChangelog: Changelog = {
183
- current: newVersionStr,
184
- versions: [...(changelog?.versions ?? []), version],
185
- }
186
-
187
- zip.file(diffPath, JSON.stringify(inverseDiff, null, 2))
188
- await this.snapshotChangedStandards(currentBep, newVersionStr)
189
- zip.file('baseline/bep.json', JSON.stringify(currentBep, null, 2))
190
- await this.snapshotBaseStandards(currentBep)
191
- zip.file('changelog.json', JSON.stringify(newChangelog, null, 2))
192
-
193
- return version
194
- }
195
-
196
- /**
197
- * Reconstructs the BEP state at the given version (read-only).
198
- * Applies inverse diffs backward from the current state.
199
- */
200
- async get(version: string): Promise<BEP> {
201
- const changelog = await this.readChangelog()
202
- if (!changelog) throw new Error('No changelog found — call commit() first')
203
-
204
- // Current version — return a clone of the live state
205
- if (version === changelog.current)
206
- return JSON.parse(JSON.stringify(this.getBep()))
207
-
208
- const targetIndex = changelog.versions.findIndex(v => v.version === version)
209
-
210
- // Terminus not in versions[] (e.g. v0.0 created by Bep.create() before any commit)
211
- // — fall back to loading the snapshot file directly
212
- if (targetIndex === -1) {
213
- const file = this.getZip().file(`changelog/v${version}.json`)
214
- if (!file) throw new Error(`Version not found: ${version}`)
215
- return normalizeBep(JSON.parse(await file.async('string')))
216
- }
217
-
218
- // Terminus (diff === null) — load the full snapshot for that version
219
- if (changelog.versions[targetIndex].diff === null) {
220
- const file = this.getZip().file(`changelog/v${version}.json`)
221
- if (!file) throw new Error(`Missing terminus: changelog/v${version}.json`)
222
- return normalizeBep(JSON.parse(await file.async('string')))
223
- }
224
-
225
- // Apply inverse diffs backward from current state to reach target version
226
- const newerVersions = changelog.versions
227
- .filter(v => History.compareVersions(v.version, version) > 0)
228
- .sort((a, b) => History.compareVersions(b.version, a.version))
229
-
230
- const state: BEP = JSON.parse(JSON.stringify(this.getBep()))
231
- for (const v of newerVersions) {
232
- if (!v.diff) break
233
- const diffFile = this.getZip().file(v.diff)
234
- if (!diffFile) throw new Error(`Missing diff file: ${v.diff}`)
235
- const ops: Operation[] = JSON.parse(await diffFile.async('string'))
236
- applyPatch(state, ops)
237
- }
238
- return normalizeBep(state)
239
- }
240
-
241
- /** Returns the RFC 6902 diff and standards summary between two versions. */
242
- async compare(versionA: string, versionB: string): Promise<CompareResult> {
243
- const [stateA, stateB, changelog] = await Promise.all([
244
- this.get(versionA),
245
- this.get(versionB),
246
- this.readChangelog(),
247
- ])
248
- const diff = compare(stateA, stateB)
249
-
250
- const fromStdIds = new Set(stateA.standards.map(s => s.id))
251
- const toStdIds = new Set(stateB.standards.map(s => s.id))
252
- const added = stateB.standards.filter(s => !fromStdIds.has(s.id)).map(s => ({ id: s.id, name: s.name }))
253
- const removed = stateA.standards.filter(s => !toStdIds.has(s.id)).map(s => ({ id: s.id, name: s.name }))
254
-
255
- const versions = changelog?.versions ?? []
256
- const versionsInRange = versions
257
- .filter(v => History.compareVersions(v.version, versionA) > 0 && History.compareVersions(v.version, versionB) <= 0)
258
- .map(v => v.version)
259
-
260
- const zip = this.getZip()
261
- const contentModified = (await Promise.all(
262
- stateB.standards.filter(s => fromStdIds.has(s.id)).map(async s => {
263
- const changedIn = (await Promise.all(
264
- versionsInRange.map(async v => {
265
- const file = zip.file(`changelog/standards/${s.id}/v${v}.md`)
266
- return file !== null ? v : null
267
- })
268
- )).filter((v): v is string => v !== null)
269
- return changedIn.length > 0 ? { id: s.id, name: s.name, changedIn } : null
270
- })
271
- )).filter((r): r is NonNullable<typeof r> => r !== null)
272
-
273
- return { diff, standards: { added, removed, contentModified } }
274
- }
275
-
276
- /**
277
- * Resets in-memory BEP and restores .md files to the last committed baseline.
278
- * Standards added since the baseline have their .md deleted.
279
- */
280
- async discard(): Promise<void> {
281
- const zip = this.getZip()
282
- const baseline = await this.readBaseline()
283
- if (!baseline) throw new Error('No baseline found — call commit() first')
284
-
285
- const baseIds = new Set(baseline.standards.map(s => s.id))
286
-
287
- // Delete .md files for standards added since baseline
288
- for (const standard of this.getBep().standards) {
289
- if (!baseIds.has(standard.id)) zip.remove(standard.contentPath)
290
- }
291
-
292
- // Restore .md files for standards that existed at baseline
293
- for (const standard of baseline.standards) {
294
- const baseFile = zip.file(`baseline/standards/${standard.id}.md`)
295
- if (!baseFile) continue
296
- const content = await baseFile.async('string')
297
- zip.file(standard.contentPath, content)
298
- }
299
-
300
- this.setBep(baseline)
301
- }
302
-
303
- /**
304
- * Non-destructive revert: restores BEP state and .md files to a historical
305
- * version and immediately commits it as a new version.
306
- */
307
- async revert(version: string, params: CommitParams): Promise<BEPVersion> {
308
- const zip = this.getZip()
309
- const historical = await this.get(version)
310
-
311
- // Restore .md content for each standard to its state at target version
312
- for (const standard of historical.standards) {
313
- const content = await this.resolveStandardContent(standard, version)
314
- if (content !== null) zip.file(standard.contentPath, content)
315
- }
316
-
317
- this.setBep(historical)
318
- return this.commit(params)
319
- }
320
-
321
- /**
322
- * Returns a structured diff of the current BEP state vs the last committed baseline.
323
- * Includes .md content changes for standards (added, removed, modified, content-modified).
324
- */
325
- async status(): Promise<BepStatus> {
326
- const zip = this.getZip()
327
- const baseline = await this.readBaseline()
328
- if (!baseline) return { hasPendingChanges: false, project: null, sections: {}, changedKeys: [], standards: [] }
329
-
330
- const currentBep = this.getBep()
331
- const diff = diffBep(currentBep, baseline)
332
-
333
- const standards: StandardChange[] = []
334
- const baseStdMap = new Map(baseline.standards.map(s => [s.id, s]))
335
- const currStdIds = new Set(currentBep.standards.map(s => s.id))
336
-
337
- for (const s of currentBep.standards) {
338
- if (!baseStdMap.has(s.id)) {
339
- standards.push({ id: s.id, name: s.name, status: 'added' })
340
- } else {
341
- const jsonChanged = JSON.stringify(baseStdMap.get(s.id)) !== JSON.stringify(s)
342
- const baseFile = zip.file(`baseline/standards/${s.id}.md`)
343
- const currFile = zip.file(s.contentPath)
344
- const baseContent = baseFile ? await baseFile.async('string') : ''
345
- const currContent = currFile ? await currFile.async('string') : ''
346
- if (jsonChanged) standards.push({ id: s.id, name: s.name, status: 'modified' })
347
- else if (baseContent !== currContent) standards.push({ id: s.id, name: s.name, status: 'content-modified' })
348
- }
349
- }
350
- for (const s of baseline.standards) {
351
- if (!currStdIds.has(s.id)) standards.push({ id: s.id, name: s.name, status: 'removed' })
352
- }
353
-
354
- const hasPendingChanges = diff.changedKeys.length > 0 || standards.length > 0
355
- return { hasPendingChanges, standards, ...diff }
356
- }
357
-
358
- /** Shorthand — true if there are uncommitted changes since the last commit. */
359
- async hasPendingChanges(): Promise<boolean> {
360
- return (await this.status()).hasPendingChanges
361
- }
362
-
363
- /** Returns all versions sorted ascending, with author/approvedBy resolved to { email, name } objects. */
364
- async listResolved(): Promise<BEPVersionResolved[]> {
365
- const [versions, current] = await Promise.all([this.list(), this.current()])
366
- const members = this.getBep().members
367
- return versions
368
- .sort((a, b) => History.compareVersions(a.version, b.version))
369
- .map(v => ({
370
- version: v.version,
371
- type: v.type,
372
- date: v.date,
373
- description: v.description,
374
- diff: v.diff,
375
- isCurrent: v.version === current,
376
- author: v.author ? { email: v.author, name: members.find(m => m.email === v.author)?.name ?? null } : null,
377
- ...(v.type === 'version' ? {
378
- approvedBy: v.approvedBy.map(email => ({
379
- email,
380
- name: members.find(m => m.email === email)?.name ?? null,
381
- })),
382
- } : {}),
383
- }))
384
- }
385
-
386
- /**
387
- * Resolves the markdown content of a standard at a specific historical version.
388
- * Returns null if the standard did not exist at that version.
389
- */
390
- async getStandardContent(standardId: string, version: string): Promise<string | null> {
391
- const historical = await this.get(version)
392
- const standard = historical.standards.find(s => s.id === standardId)
393
- if (!standard) return null
394
- return this.resolveStandardContent(standard, version)
395
- }
396
-
397
- /**
398
- * ⚠️ Destructive: resets the BEP to a historical version and permanently
399
- * deletes all subsequent diffs, standard snapshots, and changelog entries.
400
- */
401
- async reset(version: string): Promise<void> {
402
- const zip = this.getZip()
403
- const changelog = await this.readChangelog()
404
- if (!changelog) throw new Error('No changelog found')
405
- const versionInHistory = changelog.versions.find(v => v.version === version)
406
- const versionFileExists = !!this.getZip().file(`changelog/v${version}.json`)
407
- if (!versionInHistory && !versionFileExists)
408
- throw new Error(`Version not found: ${version}`)
409
- if (version === changelog.current)
410
- throw new Error(`Already at version ${version}`)
411
-
412
- const toRemove = changelog.versions.filter(v => History.compareVersions(v.version, version) > 0)
413
- const targetState = await this.get(version)
414
-
415
- // Restore .md files to target version content
416
- for (const standard of targetState.standards) {
417
- const content = await this.resolveStandardContent(standard, version)
418
- if (content !== null) zip.file(standard.contentPath, content)
419
- }
420
- await this.snapshotBaseStandards(targetState)
421
-
422
- // Remove diffs and standard snapshots of deleted versions
423
- for (const v of toRemove) {
424
- if (v.diff) zip.remove(v.diff)
425
- Object.keys(zip.files)
426
- .filter(k => k.startsWith('changelog/standards/') && k.includes(`/v${v.version}.md`))
427
- .forEach(k => zip.remove(k))
428
- }
429
-
430
- const targetSnapshot = JSON.stringify(targetState, null, 2)
431
- zip.file('changelog.json', JSON.stringify({
432
- current: version,
433
- versions: changelog.versions.filter(v => History.compareVersions(v.version, version) <= 0),
434
- } satisfies Changelog, null, 2))
435
- zip.file('bep.json', targetSnapshot)
436
- zip.file('baseline/bep.json', targetSnapshot)
437
- this.setBep(targetState)
438
- }
439
-
440
- /**
441
- * ⚠️ Destructive: collapses all history into a single new terminus version.
442
- * All intermediate diffs and snapshots are permanently deleted.
443
- * newBase must be in X.0 format and greater than the current version.
444
- */
445
- async squash(params: SquashParams): Promise<BEPVersion> {
446
- const zip = this.getZip()
447
- const changelog = await this.readChangelog()
448
- if (!changelog) throw new Error('No changelog found')
449
- if (!/^\d+\.0$/.test(params.newBase))
450
- throw new Error(`newBase must be in X.0 format (e.g. "2.0"), got "${params.newBase}"`)
451
- if (History.compareVersions(params.newBase, changelog.current) <= 0)
452
- throw new Error(`newBase "${params.newBase}" must be greater than current version "${changelog.current}"`)
453
-
454
- const bep = this.getBep()
455
- const missing = params.approvedBy.filter(email => !bep.members.some(m => m.email === email))
456
- if (missing.length) throw new Error(`Members not found: ${missing.join(', ')}`)
457
-
458
- // Remove all existing diffs and the old terminus snapshot
459
- for (const v of changelog.versions) {
460
- if (v.diff) zip.remove(v.diff)
461
- }
462
- Object.keys(zip.files)
463
- .filter(k => /^changelog\/v[\d.]+\.json$/.test(k))
464
- .forEach(k => zip.remove(k))
465
-
466
- // Remove all standard snapshots from changelog
467
- Object.keys(zip.files)
468
- .filter(k => k.startsWith('changelog/standards/') && k.endsWith('.md'))
469
- .forEach(k => zip.remove(k))
470
-
471
- // Create new terminus + standard snapshots at newBase
472
- zip.file(`changelog/v${params.newBase}.json`, JSON.stringify(bep, null, 2))
473
- for (const standard of bep.standards) {
474
- const currentFile = zip.file(standard.contentPath)
475
- if (!currentFile) continue
476
- const content = await currentFile.async('string')
477
- zip.file(`changelog/standards/${standard.id}/v${params.newBase}.md`, content)
478
- }
479
-
480
- // Sync baseline to current state
481
- zip.file('baseline/bep.json', JSON.stringify(bep, null, 2))
482
- await this.snapshotBaseStandards(bep)
483
-
484
- const newEntry: BEPVersion = {
485
- version: params.newBase,
486
- type: 'version',
487
- date: new Date().toISOString(),
488
- author: params.author,
489
- description: params.description,
490
- approvedBy: params.approvedBy,
491
- diff: null,
492
- }
493
- zip.file('changelog.json', JSON.stringify({ current: params.newBase, versions: [newEntry] } satisfies Changelog, null, 2))
494
-
495
- return newEntry
496
- }
497
- }
package/src/base/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export { Entity } from './entity.js'
2
- export type { BulkResult } from './entity.js'
3
- export { Singleton } from './singleton.js'
4
- export { History } from './history.js'
5
- export type { CompareResult, BEPVersionResolved } from './history.js'
@@ -1,26 +0,0 @@
1
- import { z } from 'zod'
2
- import type { BEP } from '../types/schema.js'
3
-
4
- export class Singleton<T extends object> {
5
- constructor(
6
- private getItem: () => T,
7
- private setItem: (value: T) => void,
8
- private schema: z.ZodType<T>,
9
- private validate?: (item: T, bep: BEP) => string[],
10
- private getBep?: () => BEP,
11
- ) {}
12
-
13
- get(): T {
14
- return this.getItem()
15
- }
16
-
17
- update(patch: { [K in keyof T]?: T[K] }): T {
18
- const merged = this.schema.parse({ ...this.getItem(), ...patch })
19
- if (this.validate && this.getBep) {
20
- const errors = this.validate(merged, this.getBep())
21
- if (errors.length) throw new Error(errors.join('; '))
22
- }
23
- this.setItem(merged)
24
- return merged
25
- }
26
- }
@@ -1,25 +0,0 @@
1
- import type { BEP, Action } from '../types/schema.js'
2
- import { Entity } from '../base/entity.js'
3
- import { ActionSchema } from '../types/schema.js'
4
-
5
- export class Actions extends Entity<Action, true> {
6
- constructor(getBep: () => BEP) {
7
- super(
8
- () => getBep().actions,
9
- getBep,
10
- {
11
- key: 'actions',
12
- schema: ActionSchema,
13
- autoId: true,
14
- beforeRemove: (id, bep) => {
15
- for (const wf of bep.workflows) {
16
- for (const [nodeKey, node] of Object.entries(wf.diagram.nodes)) {
17
- if (node.type === 'process' && node.actionId === id)
18
- throw new Error(`Referenced by: workflows["${wf.id}"].diagram.nodes["${nodeKey}"].actionId`)
19
- }
20
- }
21
- },
22
- },
23
- )
24
- }
25
- }
@@ -1,16 +0,0 @@
1
- import type { BEP, Adapter } from '../types/schema.js'
2
- import { Entity } from '../base/entity.js'
3
- import { AdapterSchema } from '../types/schema.js'
4
-
5
- export class Adapters extends Entity<Adapter> {
6
- constructor(getBep: () => BEP) {
7
- super(
8
- () => getBep().adapters,
9
- getBep,
10
- {
11
- key: 'adapters',
12
- schema: AdapterSchema,
13
- },
14
- )
15
- }
16
- }
@@ -1,17 +0,0 @@
1
- import type { BEP, Annex } from '../types/schema.js'
2
- import { Entity } from '../base/entity.js'
3
- import { AnnexSchema } from '../types/schema.js'
4
-
5
- export class Annexes extends Entity<Annex, true> {
6
- constructor(getBep: () => BEP) {
7
- super(
8
- () => getBep().annexes,
9
- getBep,
10
- {
11
- key: 'annexes',
12
- schema: AnnexSchema,
13
- autoId: true,
14
- },
15
- )
16
- }
17
- }
@@ -1,30 +0,0 @@
1
- import type { BEP, AssetType, Extension } from '../types/schema.js'
2
- import { Entity } from '../base/entity.js'
3
- import { AssetTypeSchema } from '../types/schema.js'
4
- import type { AssetTypeResolved } from '../types/resolved.js'
5
- import { validateTokenValue } from '../utils/naming.js'
6
-
7
- export class AssetTypes extends Entity<AssetType> {
8
- constructor(getBep: () => BEP) {
9
- super(
10
- () => getBep().assetTypes,
11
- getBep,
12
- {
13
- key: 'assetTypes',
14
- schema: AssetTypeSchema,
15
- validate: (a, bep) => {
16
- const err = validateTokenValue('assetType', a.id, bep.deliverableNamingConvention)
17
- return err ? [err] : []
18
- },
19
- },
20
- )
21
- }
22
-
23
- listResolved(): AssetTypeResolved[] {
24
- const bep = this.getBep()
25
- return bep.assetTypes.map(dt => ({
26
- ...dt,
27
- extensions: (dt.extensionIds ?? []).map(id => bep.extensions.find(e => e.id === id)).filter(Boolean) as Extension[],
28
- }))
29
- }
30
- }
@@ -1,24 +0,0 @@
1
- import type { BEP, FlowAutomation } from '../types/schema.js'
2
- import { Entity } from '../base/entity.js'
3
- import { FlowAutomationSchema } from '../types/schema.js'
4
-
5
- export class Automations extends Entity<FlowAutomation> {
6
- constructor(getBep: () => BEP) {
7
- super(
8
- () => getBep().automations,
9
- getBep,
10
- {
11
- key: 'automations',
12
- schema: FlowAutomationSchema,
13
- beforeRemove: (id, bep) => {
14
- for (const wf of bep.workflows) {
15
- for (const [nodeKey, node] of Object.entries(wf.diagram.nodes)) {
16
- if (node.type === 'automation' && node.automationId === id)
17
- throw new Error(`Referenced by: workflows["${wf.id}"].diagram.nodes["${nodeKey}"].automationId`)
18
- }
19
- }
20
- },
21
- },
22
- )
23
- }
24
- }