@dotbep/core 0.2.7 → 0.2.9
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.
- package/dist/index.d.ts +7 -40
- package/dist/index.js +1142 -1179
- package/package.json +4 -1
- package/examples/01-participants.ts +0 -127
- package/examples/02-files.ts +0 -100
- package/examples/03-workflows.ts +0 -149
- package/examples/04-bim-uses.ts +0 -70
- package/examples/05-standards.ts +0 -60
- package/examples/06-schedule.ts +0 -124
- package/examples/07-loin.ts +0 -133
- package/examples/08-deliverables.ts +0 -126
- package/examples/09-notes.ts +0 -73
- package/examples/10-llm.ts +0 -109
- package/examples/11-resolved.ts +0 -133
- package/examples/12-history.ts +0 -166
- package/examples/13-engine.ts +0 -152
- package/examples/bep.d.ts +0 -38
- package/examples/example.bep +0 -0
- package/examples/run-all.ts +0 -38
- package/src/base/entity.ts +0 -148
- package/src/base/history.ts +0 -497
- package/src/base/index.ts +0 -5
- package/src/base/singleton.ts +0 -26
- package/src/entities/actions.ts +0 -25
- package/src/entities/adapters.ts +0 -16
- package/src/entities/annexes.ts +0 -17
- package/src/entities/assetTypes.ts +0 -30
- package/src/entities/automations.ts +0 -24
- package/src/entities/bimUses.ts +0 -50
- package/src/entities/deliverables.ts +0 -66
- package/src/entities/disciplines.ts +0 -21
- package/src/entities/effects.ts +0 -28
- package/src/entities/env.ts +0 -17
- package/src/entities/events.ts +0 -24
- package/src/entities/extensions.ts +0 -16
- package/src/entities/flags.ts +0 -17
- package/src/entities/guides.ts +0 -26
- package/src/entities/index.ts +0 -32
- package/src/entities/lbsNodes.ts +0 -193
- package/src/entities/lods.ts +0 -22
- package/src/entities/loin.ts +0 -127
- package/src/entities/lois.ts +0 -22
- package/src/entities/members.ts +0 -137
- package/src/entities/milestones.ts +0 -32
- package/src/entities/notes.ts +0 -27
- package/src/entities/objectives.ts +0 -17
- package/src/entities/phases.ts +0 -17
- package/src/entities/remoteData.ts +0 -17
- package/src/entities/resolvers.ts +0 -20
- package/src/entities/roles.ts +0 -29
- package/src/entities/softwares.ts +0 -26
- package/src/entities/standards.ts +0 -68
- package/src/entities/teams.ts +0 -42
- package/src/entities/workflows.ts +0 -256
- package/src/index.ts +0 -464
- package/src/runtime/Engine.ts +0 -352
- package/src/runtime/MemoryStorage.ts +0 -31
- package/src/runtime/Runtime.ts +0 -106
- package/src/runtime/index.ts +0 -4
- package/src/runtime/transitions.ts +0 -456
- package/src/runtime/types.ts +0 -279
- package/src/types/history.ts +0 -37
- package/src/types/index.ts +0 -24
- package/src/types/resolved.ts +0 -137
- package/src/types/schema.ts +0 -757
- package/src/utils/diff.ts +0 -109
- package/src/utils/index.ts +0 -9
- package/src/utils/integrity.ts +0 -108
- package/src/utils/lbs.ts +0 -116
- package/src/utils/mermaid.ts +0 -110
- package/src/utils/naming.ts +0 -62
- package/src/utils/nomenclature.ts +0 -107
- package/src/utils/normalize.ts +0 -35
- package/src/utils/raci.ts +0 -25
- package/src/utils/textFile.ts +0 -24
- package/tsconfig.json +0 -12
- package/vite.config.ts +0 -24
package/src/index.ts
DELETED
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
import JSZip from 'jszip'
|
|
2
|
-
import type { BEP, NamingConvention, Project } from './types/schema.js'
|
|
3
|
-
import { NamingConventionSchema, ProjectSchema } from './types/schema.js'
|
|
4
|
-
import { normalizeBep } from './utils/normalize.js'
|
|
5
|
-
import { validateTokenValue, validateAllTokens } from './utils/naming.js'
|
|
6
|
-
import { Singleton } from './base/singleton.js'
|
|
7
|
-
import { Actions } from './entities/actions.js'
|
|
8
|
-
import { Adapters } from './entities/adapters.js'
|
|
9
|
-
import { Annexes } from './entities/annexes.js'
|
|
10
|
-
import { Effects } from './entities/effects.js'
|
|
11
|
-
import { Automations } from './entities/automations.js'
|
|
12
|
-
import { Env } from './entities/env.js'
|
|
13
|
-
import { Events } from './entities/events.js'
|
|
14
|
-
import { Deliverables } from './entities/deliverables.js'
|
|
15
|
-
import { Flags } from './entities/flags.js'
|
|
16
|
-
import { Notes } from './entities/notes.js'
|
|
17
|
-
import { BIMUses } from './entities/bimUses.js'
|
|
18
|
-
import { Disciplines } from './entities/disciplines.js'
|
|
19
|
-
import { Guides } from './entities/guides.js'
|
|
20
|
-
import { LODs } from './entities/lods.js'
|
|
21
|
-
import { LOIs } from './entities/lois.js'
|
|
22
|
-
import { LOINEntity } from './entities/loin.js'
|
|
23
|
-
import { AssetTypes } from './entities/assetTypes.js'
|
|
24
|
-
import { Extensions } from './entities/extensions.js'
|
|
25
|
-
import { Roles } from './entities/roles.js'
|
|
26
|
-
import { LBSNodes } from './entities/lbsNodes.js'
|
|
27
|
-
import { Members } from './entities/members.js'
|
|
28
|
-
import { Milestones } from './entities/milestones.js'
|
|
29
|
-
import { Objectives } from './entities/objectives.js'
|
|
30
|
-
import { Phases } from './entities/phases.js'
|
|
31
|
-
import { RemoteDataEntity } from './entities/remoteData.js'
|
|
32
|
-
import { Resolvers } from './entities/resolvers.js'
|
|
33
|
-
import { Softwares } from './entities/softwares.js'
|
|
34
|
-
import { Standards } from './entities/standards.js'
|
|
35
|
-
import { Teams } from './entities/teams.js'
|
|
36
|
-
import { Workflows } from './entities/workflows.js'
|
|
37
|
-
import { History } from './base/history.js'
|
|
38
|
-
import { Nomenclature } from './utils/nomenclature.js'
|
|
39
|
-
import { TextFile } from './utils/textFile.js'
|
|
40
|
-
import { Engine } from './runtime/Engine.js'
|
|
41
|
-
|
|
42
|
-
export class Bep {
|
|
43
|
-
// ─── Singleton fields ─────────────────────────────────────────────────────
|
|
44
|
-
|
|
45
|
-
readonly project: Singleton<Project>
|
|
46
|
-
|
|
47
|
-
// ─── Entities ─────────────────────────────────────────────────────────────
|
|
48
|
-
|
|
49
|
-
readonly actions: Actions
|
|
50
|
-
readonly adapters: Adapters
|
|
51
|
-
readonly annexes: Annexes
|
|
52
|
-
readonly deliverables: Deliverables
|
|
53
|
-
readonly effects: Effects
|
|
54
|
-
readonly automations: Automations
|
|
55
|
-
readonly env: Env
|
|
56
|
-
readonly events: Events
|
|
57
|
-
readonly notes: Notes
|
|
58
|
-
readonly flags: Flags
|
|
59
|
-
readonly bimUses: BIMUses
|
|
60
|
-
readonly disciplines: Disciplines
|
|
61
|
-
readonly guides: Guides
|
|
62
|
-
readonly lods: LODs
|
|
63
|
-
readonly lois: LOIs
|
|
64
|
-
readonly loin: LOINEntity
|
|
65
|
-
readonly lbsNodes: LBSNodes
|
|
66
|
-
readonly assetTypes: AssetTypes
|
|
67
|
-
readonly extensions: Extensions
|
|
68
|
-
readonly roles: Roles
|
|
69
|
-
readonly members: Members
|
|
70
|
-
readonly milestones: Milestones
|
|
71
|
-
readonly objectives: Objectives
|
|
72
|
-
readonly phases: Phases
|
|
73
|
-
readonly remoteData: RemoteDataEntity
|
|
74
|
-
readonly resolvers: Resolvers
|
|
75
|
-
readonly softwares: Softwares
|
|
76
|
-
readonly standards: Standards
|
|
77
|
-
readonly teams: Teams
|
|
78
|
-
readonly workflows: Workflows
|
|
79
|
-
|
|
80
|
-
// ─── Engine ───────────────────────────────────────────────────────────────
|
|
81
|
-
|
|
82
|
-
readonly engine: Engine
|
|
83
|
-
|
|
84
|
-
// ─── History ──────────────────────────────────────────────────────────────
|
|
85
|
-
|
|
86
|
-
readonly history: History
|
|
87
|
-
|
|
88
|
-
// ─── Nomenclature ─────────────────────────────────────────────────────────
|
|
89
|
-
|
|
90
|
-
readonly nomenclature: Nomenclature
|
|
91
|
-
|
|
92
|
-
// ─── Project files ────────────────────────────────────────────────────────
|
|
93
|
-
|
|
94
|
-
readonly memory: TextFile
|
|
95
|
-
readonly skill: TextFile
|
|
96
|
-
readonly icon: TextFile
|
|
97
|
-
|
|
98
|
-
private constructor(
|
|
99
|
-
private _data: BEP,
|
|
100
|
-
private _zip: JSZip,
|
|
101
|
-
) {
|
|
102
|
-
const bep = () => this._data
|
|
103
|
-
this.project = new Singleton(
|
|
104
|
-
() => this._data.project,
|
|
105
|
-
(p) => { this._data.project = p },
|
|
106
|
-
ProjectSchema,
|
|
107
|
-
(p, bep) => {
|
|
108
|
-
const errors: string[] = []
|
|
109
|
-
const tokenErr = validateTokenValue('project', p.code, bep.deliverableNamingConvention)
|
|
110
|
-
if (tokenErr) errors.push(tokenErr)
|
|
111
|
-
if (p.clientId && !bep.teams.some(t => t.id === p.clientId))
|
|
112
|
-
errors.push(`teams["${p.clientId}"] not found`)
|
|
113
|
-
return errors
|
|
114
|
-
},
|
|
115
|
-
bep,
|
|
116
|
-
)
|
|
117
|
-
this.actions = new Actions(bep)
|
|
118
|
-
this.adapters = new Adapters(bep)
|
|
119
|
-
this.annexes = new Annexes(bep)
|
|
120
|
-
this.env = new Env(bep)
|
|
121
|
-
this.events = new Events(bep)
|
|
122
|
-
this.effects = new Effects(bep)
|
|
123
|
-
this.automations = new Automations(bep)
|
|
124
|
-
this.bimUses = new BIMUses(bep, () => this.workflows)
|
|
125
|
-
this.disciplines = new Disciplines(bep)
|
|
126
|
-
this.guides = new Guides(bep)
|
|
127
|
-
this.lods = new LODs(bep)
|
|
128
|
-
this.lois = new LOIs(bep)
|
|
129
|
-
this.loin = new LOINEntity(bep)
|
|
130
|
-
this.lbsNodes = new LBSNodes(bep)
|
|
131
|
-
this.assetTypes = new AssetTypes(bep)
|
|
132
|
-
this.extensions = new Extensions(bep)
|
|
133
|
-
this.roles = new Roles(bep)
|
|
134
|
-
this.members = new Members(bep)
|
|
135
|
-
this.milestones = new Milestones(bep)
|
|
136
|
-
this.objectives = new Objectives(bep)
|
|
137
|
-
this.phases = new Phases(bep)
|
|
138
|
-
this.remoteData = new RemoteDataEntity(bep)
|
|
139
|
-
this.resolvers = new Resolvers(bep)
|
|
140
|
-
this.softwares = new Softwares(bep, () => this.assetTypes)
|
|
141
|
-
this.standards = new Standards(bep, () => this._zip)
|
|
142
|
-
this.teams = new Teams(bep, () => this.members)
|
|
143
|
-
this.workflows = new Workflows(bep, () => this.members, () => this.teams)
|
|
144
|
-
this.deliverables = new Deliverables(bep, () => this.teams, () => this.assetTypes, () => this.lbsNodes, () => this.milestones)
|
|
145
|
-
this.notes = new Notes(bep, () => this.members)
|
|
146
|
-
this.flags = new Flags(bep)
|
|
147
|
-
this.engine = new Engine(
|
|
148
|
-
() => this._data,
|
|
149
|
-
(version) => this.history.get(version),
|
|
150
|
-
)
|
|
151
|
-
this.history = new History(
|
|
152
|
-
bep,
|
|
153
|
-
(newBep) => { this._data = newBep },
|
|
154
|
-
() => this._zip,
|
|
155
|
-
)
|
|
156
|
-
this.nomenclature = new Nomenclature(bep)
|
|
157
|
-
this.memory = new TextFile('memory.md', () => this._zip)
|
|
158
|
-
this.skill = new TextFile('skills/bep-authoring/SKILL.md', () => this._zip)
|
|
159
|
-
this.icon = new TextFile('icon.svg', () => this._zip)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// ─── Factory ──────────────────────────────────────────────────────────────
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Opens a .bep archive from a buffer.
|
|
166
|
-
* The caller is responsible for obtaining the buffer (fs.readFile in Node,
|
|
167
|
-
* fetch + arrayBuffer() in the browser, etc.).
|
|
168
|
-
*
|
|
169
|
-
* Automatically initializes any missing files (memory.md, skills/bep-authoring/SKILL.md,
|
|
170
|
-
* standards content, baseline and v0.0 terminus) so the instance is always
|
|
171
|
-
* fully operational after open(). Idempotent — existing files are untouched.
|
|
172
|
-
*/
|
|
173
|
-
static async open(buffer: Uint8Array | ArrayBuffer | Buffer): Promise<Bep> {
|
|
174
|
-
const zip = await JSZip.loadAsync(buffer)
|
|
175
|
-
const bepJsonFile = zip.file('bep.json')
|
|
176
|
-
if (!bepJsonFile) throw new Error('Invalid .bep file: missing bep.json')
|
|
177
|
-
const raw = await bepJsonFile.async('string')
|
|
178
|
-
const data = normalizeBep(JSON.parse(raw) as BEP)
|
|
179
|
-
await Bep._initialize(data, zip)
|
|
180
|
-
return new Bep(data, zip)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Ensures all expected files exist in the zip.
|
|
185
|
-
* Called by open() after loading bep.json. Safe to call multiple times.
|
|
186
|
-
*
|
|
187
|
-
* Does NOT create changelog.json — that is created on the first commit().
|
|
188
|
-
* The v0.0 terminus snapshot (changelog/v0.0.json) is the hidden root of
|
|
189
|
-
* the diff chain; it is never exposed as a user-facing version. The first
|
|
190
|
-
* commit() bumps to v0.1 (patch) or v1.0 (version) and writes the inverse
|
|
191
|
-
* diff against this terminus. The baseline is written so history.status()
|
|
192
|
-
* and history.discard() work before the first commit.
|
|
193
|
-
*/
|
|
194
|
-
private static async _initialize(data: BEP, zip: JSZip): Promise<void> {
|
|
195
|
-
// Text files
|
|
196
|
-
if (!zip.file('memory.md')) zip.file('memory.md', '')
|
|
197
|
-
if (!zip.file('skills/bep-authoring/SKILL.md')) zip.file('skills/bep-authoring/SKILL.md', '')
|
|
198
|
-
|
|
199
|
-
// Standards content files — ensure each .md referenced in bep.json exists
|
|
200
|
-
for (const standard of data.standards) {
|
|
201
|
-
if (!zip.file(standard.contentPath)) zip.file(standard.contentPath, '')
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Versioning bootstrap — only if no baseline exists yet
|
|
205
|
-
// baseline/bep.json is used as the sentinel: if it's present, the zip
|
|
206
|
-
// was already initialized (either by a previous open() or by commit()).
|
|
207
|
-
if (!zip.file('baseline/bep.json')) {
|
|
208
|
-
const snapshot = JSON.stringify(data, null, 2)
|
|
209
|
-
zip.file('baseline/bep.json', snapshot)
|
|
210
|
-
zip.file('changelog/v0.0.json', snapshot)
|
|
211
|
-
for (const standard of data.standards) {
|
|
212
|
-
const content = await zip.file(standard.contentPath)!.async('string')
|
|
213
|
-
zip.file(`baseline/standards/${standard.id}.md`, content)
|
|
214
|
-
zip.file(`changelog/standards/${standard.id}/v0.0.md`, content)
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
static create(project: Project): Bep {
|
|
220
|
-
const data = normalizeBep({
|
|
221
|
-
project: { name: project.name, code: project.code, clientId: project.clientId, description: project.description },
|
|
222
|
-
roles: [],
|
|
223
|
-
members: [],
|
|
224
|
-
teams: [],
|
|
225
|
-
phases: [],
|
|
226
|
-
milestones: [],
|
|
227
|
-
lbs: [],
|
|
228
|
-
disciplines: [],
|
|
229
|
-
extensions: [],
|
|
230
|
-
assetTypes: [],
|
|
231
|
-
softwares: [],
|
|
232
|
-
objectives: [],
|
|
233
|
-
bimUses: [],
|
|
234
|
-
actions: [],
|
|
235
|
-
events: [],
|
|
236
|
-
effects: [],
|
|
237
|
-
workflows: [],
|
|
238
|
-
guides: [],
|
|
239
|
-
annexes: [],
|
|
240
|
-
standards: [],
|
|
241
|
-
lods: [],
|
|
242
|
-
lois: [],
|
|
243
|
-
loin: [],
|
|
244
|
-
deliverables: [],
|
|
245
|
-
notes: [],
|
|
246
|
-
flags: [],
|
|
247
|
-
env: [],
|
|
248
|
-
automations: [],
|
|
249
|
-
} as unknown as BEP)
|
|
250
|
-
const zip = new JSZip()
|
|
251
|
-
// Initialize required files so the zip is fully functional from the start.
|
|
252
|
-
// changelog.json is omitted — commit() creates it. The v0.0 terminus is the
|
|
253
|
-
// hidden root; the first commit() bumps to v0.1 (patch) or v1.0 (version).
|
|
254
|
-
const snapshot = JSON.stringify(data, null, 2)
|
|
255
|
-
zip.file('memory.md', '')
|
|
256
|
-
zip.file('skills/bep-authoring/SKILL.md', '')
|
|
257
|
-
zip.file('baseline/bep.json', snapshot)
|
|
258
|
-
zip.file('changelog/v0.0.json', snapshot)
|
|
259
|
-
return new Bep(data, zip)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
// ─── Accessors ────────────────────────────────────────────────────────────
|
|
264
|
-
|
|
265
|
-
get data(): BEP {
|
|
266
|
-
return this._data
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// ─── Deliverable naming convention ────────────────────────────────────────
|
|
270
|
-
|
|
271
|
-
getNamingConvention(): NamingConvention | undefined {
|
|
272
|
-
return this._data.deliverableNamingConvention
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/** Pass null to remove the convention and fall back to the default format. */
|
|
276
|
-
setNamingConvention(convention: NamingConvention | null): void {
|
|
277
|
-
if (convention === null) {
|
|
278
|
-
delete this._data.deliverableNamingConvention
|
|
279
|
-
return
|
|
280
|
-
}
|
|
281
|
-
const parsed = NamingConventionSchema.parse(convention)
|
|
282
|
-
const errors = validateAllTokens(this._data, parsed)
|
|
283
|
-
if (errors.length) throw new Error(`Naming convention incompatible with existing data:\n${errors.join('\n')}`)
|
|
284
|
-
this._data.deliverableNamingConvention = parsed
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// ─── File access ──────────────────────────────────────────────────────────
|
|
288
|
-
|
|
289
|
-
/** Reads any text file stored inside the .bep archive by its zip path. */
|
|
290
|
-
async readFile(path: string): Promise<string | null> {
|
|
291
|
-
const file = this._zip.file(path)
|
|
292
|
-
return file ? file.async('string') : null
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// ─── Skills ───────────────────────────────────────────────────────────────
|
|
296
|
-
|
|
297
|
-
/** Returns the names of all skills present in the archive. */
|
|
298
|
-
listSkills(): string[] {
|
|
299
|
-
const names = new Set<string>()
|
|
300
|
-
this._zip.forEach((path) => {
|
|
301
|
-
const match = path.match(/^skills\/([^/]+)\/SKILL\.md$/)
|
|
302
|
-
if (match) names.add(match[1]!)
|
|
303
|
-
})
|
|
304
|
-
return [...names]
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/** Returns the SKILL.md content for the given skill, or null if it does not exist. */
|
|
308
|
-
async getSkill(name: string): Promise<string | null> {
|
|
309
|
-
const file = this._zip.file(`skills/${name}/SKILL.md`)
|
|
310
|
-
return file ? file.async('string') : null
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/** Writes the SKILL.md content for the given skill, creating it if needed. */
|
|
314
|
-
async setSkill(name: string, content: string): Promise<void> {
|
|
315
|
-
this._zip.file(`skills/${name}/SKILL.md`, content)
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/** Returns the names of all resource files for the given skill. */
|
|
319
|
-
listSkillResources(name: string): string[] {
|
|
320
|
-
const prefix = `skills/${name}/resources/`
|
|
321
|
-
const files: string[] = []
|
|
322
|
-
this._zip.forEach((path) => {
|
|
323
|
-
if (path.startsWith(prefix) && path !== prefix) {
|
|
324
|
-
files.push(path.slice(prefix.length))
|
|
325
|
-
}
|
|
326
|
-
})
|
|
327
|
-
return files
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/** Returns the content of a resource file for the given skill, or null if it does not exist. */
|
|
331
|
-
async getSkillResource(name: string, filename: string): Promise<string | null> {
|
|
332
|
-
const file = this._zip.file(`skills/${name}/resources/${filename}`)
|
|
333
|
-
return file ? file.async('string') : null
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/** Writes a resource file for the given skill, creating it if needed. */
|
|
337
|
-
async setSkillResource(name: string, filename: string, content: string): Promise<void> {
|
|
338
|
-
this._zip.file(`skills/${name}/resources/${filename}`, content)
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/** Removes a skill's SKILL.md and all its resources from the archive. No-op if not found. */
|
|
342
|
-
removeSkill(name: string): void {
|
|
343
|
-
const prefix = `skills/${name}/`
|
|
344
|
-
const toDelete: string[] = []
|
|
345
|
-
this._zip.forEach((path) => { if (path.startsWith(prefix)) toDelete.push(path) })
|
|
346
|
-
toDelete.forEach(path => this._zip.remove(path))
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/** Removes a single resource file from a skill. No-op if not found. */
|
|
350
|
-
removeSkillResource(name: string, filename: string): void {
|
|
351
|
-
this._zip.remove(`skills/${name}/resources/${filename}`)
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// ─── Type generation ──────────────────────────────────────────────────────
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Generates a TypeScript declaration string with typed contracts for this BEP.
|
|
358
|
-
* Write the output to
|
|
359
|
-
* a `.d.ts` file to get full type safety when writing a runtime.
|
|
360
|
-
*
|
|
361
|
-
* @example
|
|
362
|
-
* import { writeFileSync } from 'node:fs'
|
|
363
|
-
* writeFileSync('bep.d.ts', bep.generateRuntimeTypes())
|
|
364
|
-
*/
|
|
365
|
-
generateRuntimeTypes(): string {
|
|
366
|
-
const tsType = (t: string) => t === 'url' ? 'string' : t
|
|
367
|
-
|
|
368
|
-
const jsdoc = (description: string) => ` /** ${description} */\n`
|
|
369
|
-
|
|
370
|
-
const inlineType = (fields: { key: string; type: string; required: boolean }[]): string =>
|
|
371
|
-
`{ ${fields.map(f => `${f.key}${f.required ? '' : '?'}: ${tsType(f.type)}`).join('; ')} }`
|
|
372
|
-
|
|
373
|
-
const effectSig = (e: { payload?: { key: string; type: string; required: boolean }[] }): string => {
|
|
374
|
-
if (!e.payload || e.payload.length === 0) return '() => void'
|
|
375
|
-
return `(payload: ${inlineType(e.payload)}) => void`
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
const automationSig = (a: { payload?: { key: string; type: string; required: boolean }[]; output: { key: string; type: string; required: boolean }[] }): string => {
|
|
379
|
-
const param = a.payload && a.payload.length > 0 ? `payload: ${inlineType(a.payload)}` : ''
|
|
380
|
-
const ret = a.output.length === 0
|
|
381
|
-
? '{ eventId: string }'
|
|
382
|
-
: `{ eventId: string; ${a.output.map(f => `${f.key}${f.required ? '' : '?'}: ${tsType(f.type)}`).join('; ')} }`
|
|
383
|
-
return `(${param}) => ${ret}`
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
const resolverSig = (r: { envKeys: string[] }): string => {
|
|
387
|
-
if (r.envKeys.length === 0) return '(url: string) => unknown'
|
|
388
|
-
const envType = `{ ${r.envKeys.map(k => `${k}: string`).join('; ')} }`
|
|
389
|
-
return `(url: string, env: ${envType}) => unknown`
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
const effectLines = this._data.effects.length
|
|
393
|
-
? this._data.effects.map(e => `${jsdoc(e.description)} '${e.id}': ${effectSig(e)}`).join('\n')
|
|
394
|
-
: ' [key: string]: () => void'
|
|
395
|
-
|
|
396
|
-
const automationLines = this._data.automations.length
|
|
397
|
-
? this._data.automations.map(a => `${jsdoc(a.description)} '${a.id}': ${automationSig(a)}`).join('\n')
|
|
398
|
-
: ' [key: string]: () => { eventId: string }'
|
|
399
|
-
|
|
400
|
-
const resolverLines = this._data.resolvers.length
|
|
401
|
-
? this._data.resolvers.map(r => `${jsdoc(r.description)} '${r.id}': ${resolverSig(r)}`).join('\n')
|
|
402
|
-
: ' [key: string]: (url: string) => unknown'
|
|
403
|
-
|
|
404
|
-
const adapterLines = this._data.adapters.length
|
|
405
|
-
? this._data.adapters.map(a => `${jsdoc(a.description)} '${a.id}': (data: unknown) => unknown`).join('\n')
|
|
406
|
-
: ' [key: string]: (data: unknown) => unknown'
|
|
407
|
-
|
|
408
|
-
return [
|
|
409
|
-
'// Generated by bep.generateRuntimeTypes() — do not edit manually',
|
|
410
|
-
'',
|
|
411
|
-
'// ─── Effects ──────────────────────────────────────────────────────────────────',
|
|
412
|
-
'',
|
|
413
|
-
'export interface BepEffects {',
|
|
414
|
-
effectLines,
|
|
415
|
-
'}',
|
|
416
|
-
'',
|
|
417
|
-
'// ─── Automations ─────────────────────────────────────────────────────────────',
|
|
418
|
-
'',
|
|
419
|
-
'export interface BepAutomations {',
|
|
420
|
-
automationLines,
|
|
421
|
-
'}',
|
|
422
|
-
'',
|
|
423
|
-
'// ─── Resolvers ────────────────────────────────────────────────────────────────',
|
|
424
|
-
'',
|
|
425
|
-
'export interface BepResolvers {',
|
|
426
|
-
resolverLines,
|
|
427
|
-
'}',
|
|
428
|
-
'',
|
|
429
|
-
'// ─── Adapters ─────────────────────────────────────────────────────────────────',
|
|
430
|
-
'',
|
|
431
|
-
'export interface BepAdapters {',
|
|
432
|
-
adapterLines,
|
|
433
|
-
'}',
|
|
434
|
-
'',
|
|
435
|
-
'// ─── Combined ─────────────────────────────────────────────────────────────────',
|
|
436
|
-
'',
|
|
437
|
-
'export interface BepTypes {',
|
|
438
|
-
' effects: BepEffects',
|
|
439
|
-
' automations: BepAutomations',
|
|
440
|
-
' resolvers: BepResolvers',
|
|
441
|
-
' adapters: BepAdapters',
|
|
442
|
-
'}',
|
|
443
|
-
'',
|
|
444
|
-
].join('\n')
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// ─── Serialization ────────────────────────────────────────────────────────
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Serializes the .bep archive to a Uint8Array.
|
|
451
|
-
* The caller is responsible for persisting it (fs.writeFile in Node,
|
|
452
|
-
* a download link in the browser, etc.).
|
|
453
|
-
*/
|
|
454
|
-
async save(): Promise<Uint8Array> {
|
|
455
|
-
this._zip.file('bep.json', JSON.stringify(this._data, null, 2))
|
|
456
|
-
return this._zip.generateAsync({ type: 'uint8array' })
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
export * from "./base"
|
|
461
|
-
export * from './entities'
|
|
462
|
-
export * from './utils'
|
|
463
|
-
export * from './types'
|
|
464
|
-
export * from './runtime'
|