@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/entities/members.ts
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import type { BEP, Member, Team } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { MemberSchema } from '../types/schema.js'
|
|
4
|
-
import type { MemberResolved } from '../types/resolved.js'
|
|
5
|
-
|
|
6
|
-
export class Members extends Entity<Member> {
|
|
7
|
-
constructor(getBep: () => BEP) {
|
|
8
|
-
super(
|
|
9
|
-
() => getBep().members,
|
|
10
|
-
getBep,
|
|
11
|
-
{
|
|
12
|
-
key: 'members',
|
|
13
|
-
idField: 'email',
|
|
14
|
-
schema: MemberSchema,
|
|
15
|
-
},
|
|
16
|
-
)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
listResolved(): MemberResolved[] {
|
|
20
|
-
const bep = this.getBep()
|
|
21
|
-
return bep.members.map(m => {
|
|
22
|
-
const team = bep.teams.find(t => (t.memberEmails ?? []).includes(m.email))
|
|
23
|
-
return {
|
|
24
|
-
...m,
|
|
25
|
-
role: bep.roles.find(r => r.id === m.roleId) ?? null,
|
|
26
|
-
team: team ? { id: team.id, name: team.name } : null,
|
|
27
|
-
isRepresentative: team?.representativeEmail === m.email,
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
addToTeam(items: Array<Member & { teamId: Team['id']; isRepresentative?: boolean }>): {
|
|
33
|
-
succeeded: MemberResolved[]
|
|
34
|
-
failed: { input: unknown; error: string }[]
|
|
35
|
-
} {
|
|
36
|
-
const succeeded: MemberResolved[] = []
|
|
37
|
-
const failed: { input: unknown; error: string }[] = []
|
|
38
|
-
|
|
39
|
-
for (const item of items) {
|
|
40
|
-
const bep = this.getBep()
|
|
41
|
-
const team = bep.teams.find(t => t.id === item.teamId)
|
|
42
|
-
if (!team) { failed.push({ input: item, error: `Team not found: ${item.teamId}` }); continue }
|
|
43
|
-
|
|
44
|
-
const { teamId, isRepresentative, ...member } = item
|
|
45
|
-
const result = this.add([member])
|
|
46
|
-
if (result.failed.length > 0) { failed.push({ input: item, error: result.failed[0].error }); continue }
|
|
47
|
-
|
|
48
|
-
team.memberEmails ??= []
|
|
49
|
-
if (!team.memberEmails.includes(item.email)) team.memberEmails.push(item.email)
|
|
50
|
-
if (isRepresentative) team.representativeEmail = item.email
|
|
51
|
-
|
|
52
|
-
const resolved = this.listResolved().find(m => m.email === item.email)!
|
|
53
|
-
succeeded.push(resolved)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return { succeeded, failed }
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
updateInTeam(items: Array<Partial<Member> & { email: Member['email']; teamId?: Team['id']; isRepresentative?: boolean }>): {
|
|
60
|
-
succeeded: Array<{ email: Member['email']; after: MemberResolved }>
|
|
61
|
-
failed: { email: Member['email']; error: string }[]
|
|
62
|
-
} {
|
|
63
|
-
const succeeded: Array<{ email: Member['email']; after: MemberResolved }> = []
|
|
64
|
-
const failed: { email: Member['email']; error: string }[] = []
|
|
65
|
-
|
|
66
|
-
for (const item of items) {
|
|
67
|
-
const bep = this.getBep()
|
|
68
|
-
const { teamId, isRepresentative, ...fields } = item
|
|
69
|
-
|
|
70
|
-
if (teamId !== undefined && !bep.teams.find(t => t.id === teamId)) {
|
|
71
|
-
failed.push({ email: item.email, error: `Team not found: ${teamId}` }); continue
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const result = this.update([fields])
|
|
75
|
-
if (result.failed.length > 0) { failed.push({ email: item.email, error: result.failed[0].error }); continue }
|
|
76
|
-
|
|
77
|
-
if (teamId !== undefined) {
|
|
78
|
-
const newTeam = bep.teams.find(t => t.id === teamId)!
|
|
79
|
-
const oldTeam = bep.teams.find(t => (t.memberEmails ?? []).includes(item.email))
|
|
80
|
-
if (oldTeam && oldTeam.id !== teamId) {
|
|
81
|
-
oldTeam.memberEmails = (oldTeam.memberEmails ?? []).filter(e => e !== item.email)
|
|
82
|
-
if (oldTeam.representativeEmail === item.email) oldTeam.representativeEmail = undefined
|
|
83
|
-
}
|
|
84
|
-
newTeam.memberEmails ??= []
|
|
85
|
-
if (!newTeam.memberEmails.includes(item.email)) newTeam.memberEmails.push(item.email)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (isRepresentative !== undefined) {
|
|
89
|
-
const team = bep.teams.find(t => (t.memberEmails ?? []).includes(item.email))
|
|
90
|
-
if (team) team.representativeEmail = isRepresentative ? item.email : (team.representativeEmail === item.email ? undefined : team.representativeEmail)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const resolved = this.listResolved().find(m => m.email === item.email)!
|
|
94
|
-
succeeded.push({ email: item.email, after: resolved })
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return { succeeded, failed }
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
removeFromBep(emails: Member['email'][]): {
|
|
101
|
-
succeeded: MemberResolved[]
|
|
102
|
-
failed: { email: Member['email']; error: string }[]
|
|
103
|
-
} {
|
|
104
|
-
const succeeded: MemberResolved[] = []
|
|
105
|
-
const failed: { email: Member['email']; error: string }[] = []
|
|
106
|
-
|
|
107
|
-
for (const email of emails) {
|
|
108
|
-
const bep = this.getBep()
|
|
109
|
-
const snapshot = this.listResolved().find(m => m.email === email)
|
|
110
|
-
if (!snapshot) { failed.push({ email, error: `Not found: ${email}` }); continue }
|
|
111
|
-
|
|
112
|
-
// Clean team refs so integrity check doesn't block removal
|
|
113
|
-
for (const t of bep.teams) {
|
|
114
|
-
if (t.memberEmails) t.memberEmails = t.memberEmails.filter(e => e !== email)
|
|
115
|
-
if (t.representativeEmail === email) t.representativeEmail = undefined
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const result = this.remove([email])
|
|
119
|
-
if (result.failed.length > 0) {
|
|
120
|
-
// Restore team refs on failure (e.g. notes blocking)
|
|
121
|
-
if (snapshot.team) {
|
|
122
|
-
const team = bep.teams.find(t => t.id === snapshot.team!.id)
|
|
123
|
-
if (team) {
|
|
124
|
-
team.memberEmails ??= []
|
|
125
|
-
if (!team.memberEmails.includes(email)) team.memberEmails.push(email)
|
|
126
|
-
if (snapshot.isRepresentative) team.representativeEmail = email
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
failed.push({ email, error: result.failed[0].error }); continue
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
succeeded.push(snapshot)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return { succeeded, failed }
|
|
136
|
-
}
|
|
137
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { BEP, Milestone } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { MilestoneSchema } from '../types/schema.js'
|
|
4
|
-
import type { MilestoneResolved } from '../types/resolved.js'
|
|
5
|
-
|
|
6
|
-
export class Milestones extends Entity<Milestone, true> {
|
|
7
|
-
constructor(getBep: () => BEP) {
|
|
8
|
-
super(
|
|
9
|
-
() => getBep().milestones,
|
|
10
|
-
getBep,
|
|
11
|
-
{
|
|
12
|
-
key: 'milestones',
|
|
13
|
-
schema: MilestoneSchema,
|
|
14
|
-
autoId: true,
|
|
15
|
-
beforeRemove: (id, bep) => {
|
|
16
|
-
for (const loin of bep.loin) {
|
|
17
|
-
const ref = loin.milestones?.find(m => m.milestoneId === id)
|
|
18
|
-
if (ref) throw new Error(`Referenced by: loin["${loin.id}"].milestones[milestoneId="${id}"]`)
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
listResolved(): MilestoneResolved[] {
|
|
26
|
-
const bep = this.getBep()
|
|
27
|
-
return bep.milestones.map(m => ({
|
|
28
|
-
...m,
|
|
29
|
-
phase: bep.phases.find(p => p.id === m.phaseId) ?? null,
|
|
30
|
-
}))
|
|
31
|
-
}
|
|
32
|
-
}
|
package/src/entities/notes.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { BEP, Note } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { NoteSchema } from '../types/schema.js'
|
|
4
|
-
import type { NoteResolved } from '../types/resolved.js'
|
|
5
|
-
import type { Members } from './members.js'
|
|
6
|
-
|
|
7
|
-
export class Notes extends Entity<Note, true> {
|
|
8
|
-
constructor(getBep: () => BEP, private readonly getMembers: () => Members) {
|
|
9
|
-
super(
|
|
10
|
-
() => getBep().notes,
|
|
11
|
-
getBep,
|
|
12
|
-
{
|
|
13
|
-
key: 'notes',
|
|
14
|
-
schema: NoteSchema,
|
|
15
|
-
autoId: true,
|
|
16
|
-
},
|
|
17
|
-
)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
listResolved(): NoteResolved[] {
|
|
21
|
-
const memberMap = new Map(this.getMembers().listResolved().map(m => [m.email, m]))
|
|
22
|
-
return this.getBep().notes.map(n => ({
|
|
23
|
-
...n,
|
|
24
|
-
member: memberMap.get(n.memberEmail) ?? null,
|
|
25
|
-
}))
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { BEP, Objective } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { ObjectiveSchema } from '../types/schema.js'
|
|
4
|
-
|
|
5
|
-
export class Objectives extends Entity<Objective, true> {
|
|
6
|
-
constructor(getBep: () => BEP) {
|
|
7
|
-
super(
|
|
8
|
-
() => getBep().objectives,
|
|
9
|
-
getBep,
|
|
10
|
-
{
|
|
11
|
-
key: 'objectives',
|
|
12
|
-
schema: ObjectiveSchema,
|
|
13
|
-
autoId: true,
|
|
14
|
-
},
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
}
|
package/src/entities/phases.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { BEP, Phase } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { PhaseSchema } from '../types/schema.js'
|
|
4
|
-
|
|
5
|
-
export class Phases extends Entity<Phase, true> {
|
|
6
|
-
constructor(getBep: () => BEP) {
|
|
7
|
-
super(
|
|
8
|
-
() => getBep().phases,
|
|
9
|
-
getBep,
|
|
10
|
-
{
|
|
11
|
-
key: 'phases',
|
|
12
|
-
schema: PhaseSchema,
|
|
13
|
-
autoId: true,
|
|
14
|
-
},
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { BEP, RemoteData } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { RemoteDataSchema } from '../types/schema.js'
|
|
4
|
-
|
|
5
|
-
export class RemoteDataEntity extends Entity<RemoteData, true> {
|
|
6
|
-
constructor(getBep: () => BEP) {
|
|
7
|
-
super(
|
|
8
|
-
() => getBep().remoteData,
|
|
9
|
-
getBep,
|
|
10
|
-
{
|
|
11
|
-
key: 'remoteData',
|
|
12
|
-
schema: RemoteDataSchema,
|
|
13
|
-
autoId: true,
|
|
14
|
-
},
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { BEP, Resolver } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { ResolverSchema } from '../types/schema.js'
|
|
4
|
-
|
|
5
|
-
export class Resolvers extends Entity<Resolver> {
|
|
6
|
-
constructor(getBep: () => BEP) {
|
|
7
|
-
super(
|
|
8
|
-
() => getBep().resolvers,
|
|
9
|
-
getBep,
|
|
10
|
-
{
|
|
11
|
-
key: 'resolvers',
|
|
12
|
-
schema: ResolverSchema,
|
|
13
|
-
beforeRemove: (id, bep) => {
|
|
14
|
-
const ref = bep.remoteData.find(r => r.resolverId === id)
|
|
15
|
-
if (ref) throw new Error(`Referenced by: remoteData["${ref.id}"].resolverId`)
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
}
|
package/src/entities/roles.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { BEP, Role } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { RoleSchema } from '../types/schema.js'
|
|
4
|
-
|
|
5
|
-
export class Roles extends Entity<Role, true> {
|
|
6
|
-
constructor(getBep: () => BEP) {
|
|
7
|
-
super(
|
|
8
|
-
() => getBep().roles,
|
|
9
|
-
getBep,
|
|
10
|
-
{
|
|
11
|
-
key: 'roles',
|
|
12
|
-
schema: RoleSchema,
|
|
13
|
-
autoId: true,
|
|
14
|
-
beforeRemove: (id, bep) => {
|
|
15
|
-
const raciFields = ['responsibleRoleIds', 'accountableRoleIds', 'consultedRoleIds', 'informedRoleIds'] as const
|
|
16
|
-
for (const wf of bep.workflows) {
|
|
17
|
-
for (const [nodeKey, node] of Object.entries(wf.diagram.nodes)) {
|
|
18
|
-
if (node.type !== 'process') continue
|
|
19
|
-
for (const field of raciFields) {
|
|
20
|
-
if (node[field]?.includes(id))
|
|
21
|
-
throw new Error(`Referenced by: workflows["${wf.id}"].diagram.nodes["${nodeKey}"].${field}`)
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { BEP, Software } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { SoftwareSchema } from '../types/schema.js'
|
|
4
|
-
import type { AssetTypeResolved, SoftwareResolved } from '../types/resolved.js'
|
|
5
|
-
import type { AssetTypes } from './assetTypes.js'
|
|
6
|
-
|
|
7
|
-
export class Softwares extends Entity<Software> {
|
|
8
|
-
constructor(getBep: () => BEP, private readonly getAssetTypes: () => AssetTypes) {
|
|
9
|
-
super(
|
|
10
|
-
() => getBep().softwares,
|
|
11
|
-
getBep,
|
|
12
|
-
{
|
|
13
|
-
key: 'softwares',
|
|
14
|
-
schema: SoftwareSchema,
|
|
15
|
-
},
|
|
16
|
-
)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
listResolved(): SoftwareResolved[] {
|
|
20
|
-
const assetTypeMap = new Map(this.getAssetTypes().listResolved().map(dt => [dt.id, dt]))
|
|
21
|
-
return this.getBep().softwares.map(s => ({
|
|
22
|
-
...s,
|
|
23
|
-
assetTypes: (s.assetTypeIds ?? []).map(id => assetTypeMap.get(id)).filter(Boolean) as AssetTypeResolved[],
|
|
24
|
-
}))
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import type JSZip from 'jszip'
|
|
2
|
-
import type { BEP, Standard } from '../types/schema.js'
|
|
3
|
-
import { Entity, type BulkResult } from '../base/entity.js'
|
|
4
|
-
import { StandardSchema } from '../types/schema.js'
|
|
5
|
-
|
|
6
|
-
/** Input for Standards.add(): accepts markdown text in `content` instead of a file path. */
|
|
7
|
-
export type StandardAddInput = Omit<Standard, 'id' | 'contentPath'> & { content: string }
|
|
8
|
-
|
|
9
|
-
export class Standards extends Entity<Standard, true> {
|
|
10
|
-
constructor(getBep: () => BEP, private getZip: () => JSZip) {
|
|
11
|
-
super(
|
|
12
|
-
() => getBep().standards,
|
|
13
|
-
getBep,
|
|
14
|
-
{ key: 'standards', schema: StandardSchema, autoId: true },
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Accepts markdown text in `content` (user-facing).
|
|
20
|
-
* Generates a UUID-based path, writes the text to the zip,
|
|
21
|
-
* and stores the path in Standard.contentPath.
|
|
22
|
-
* Union with AddInput<Standard> satisfies the base class contract.
|
|
23
|
-
*/
|
|
24
|
-
override add(inputs: (StandardAddInput | Omit<Standard, 'id'>)[]): BulkResult<Standard> {
|
|
25
|
-
const withPaths = inputs.map(input => {
|
|
26
|
-
const path = `standards/${globalThis.crypto.randomUUID()}.md`
|
|
27
|
-
if ('content' in input) {
|
|
28
|
-
const { content, ...rest } = input
|
|
29
|
-
this.getZip().file(path, content)
|
|
30
|
-
return { ...rest, contentPath: path }
|
|
31
|
-
}
|
|
32
|
-
this.getZip().file(path, '')
|
|
33
|
-
return { ...input, contentPath: path }
|
|
34
|
-
})
|
|
35
|
-
return super.add(withPaths)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Removes standards and deletes their .md files from the zip. */
|
|
39
|
-
override remove(ids: Standard['id'][]) {
|
|
40
|
-
const paths = new Map(
|
|
41
|
-
ids
|
|
42
|
-
.map(id => [id, this.list().find(s => s.id === id)?.contentPath])
|
|
43
|
-
.filter((e): e is [string, string] => e[1] !== undefined),
|
|
44
|
-
)
|
|
45
|
-
const result = super.remove(ids)
|
|
46
|
-
for (const id of result.succeeded) {
|
|
47
|
-
const path = paths.get(id)
|
|
48
|
-
if (path) this.getZip().remove(path)
|
|
49
|
-
}
|
|
50
|
-
return result
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** Returns the markdown text content of the given standard. */
|
|
54
|
-
async getContent(id: Standard['id']): Promise<string> {
|
|
55
|
-
const std = this.list().find(s => s.id === id)
|
|
56
|
-
if (!std) throw new Error(`Standard not found: ${id}`)
|
|
57
|
-
const file = this.getZip().file(std.contentPath)
|
|
58
|
-
if (!file) throw new Error(`Content file not found: ${std.contentPath}`)
|
|
59
|
-
return file.async('string')
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Writes new markdown text content for the given standard. */
|
|
63
|
-
setContent(id: Standard['id'], text: string): void {
|
|
64
|
-
const std = this.list().find(s => s.id === id)
|
|
65
|
-
if (!std) throw new Error(`Standard not found: ${id}`)
|
|
66
|
-
this.getZip().file(std.contentPath, text)
|
|
67
|
-
}
|
|
68
|
-
}
|
package/src/entities/teams.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { BEP, Discipline, Team } from '../types/schema.js'
|
|
2
|
-
import { Entity } from '../base/entity.js'
|
|
3
|
-
import { TeamSchema } from '../types/schema.js'
|
|
4
|
-
import type { MemberResolved, TeamResolved } from '../types/resolved.js'
|
|
5
|
-
import type { Members } from './members.js'
|
|
6
|
-
import { validateTokenValue } from '../utils/naming.js'
|
|
7
|
-
|
|
8
|
-
export class Teams extends Entity<Team> {
|
|
9
|
-
constructor(getBep: () => BEP, private readonly getMembers: () => Members) {
|
|
10
|
-
super(
|
|
11
|
-
() => getBep().teams,
|
|
12
|
-
getBep,
|
|
13
|
-
{
|
|
14
|
-
key: 'teams',
|
|
15
|
-
schema: TeamSchema,
|
|
16
|
-
validate: (team, bep) => {
|
|
17
|
-
const errors: string[] = []
|
|
18
|
-
const tokenErr = validateTokenValue('team', team.id, bep.deliverableNamingConvention)
|
|
19
|
-
if (tokenErr) errors.push(tokenErr)
|
|
20
|
-
if (team.representativeEmail && !(team.memberEmails ?? []).includes(team.representativeEmail))
|
|
21
|
-
errors.push(`representativeEmail "${team.representativeEmail}" is not a member of this team`)
|
|
22
|
-
return errors
|
|
23
|
-
},
|
|
24
|
-
beforeRemove: (id, bep) => {
|
|
25
|
-
if (bep.project.clientId === id)
|
|
26
|
-
throw new Error('Referenced by: project.clientId')
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
listResolved(): TeamResolved[] {
|
|
33
|
-
const bep = this.getBep()
|
|
34
|
-
const memberMap = new Map(this.getMembers().listResolved().map(m => [m.email, m]))
|
|
35
|
-
return bep.teams.map(t => ({
|
|
36
|
-
...t,
|
|
37
|
-
representative: memberMap.get(t.representativeEmail ?? '') ?? null,
|
|
38
|
-
members: (t.memberEmails ?? []).map(email => memberMap.get(email)).filter(Boolean) as MemberResolved[],
|
|
39
|
-
disciplines: (t.disciplineIds ?? []).map(id => bep.disciplines.find(d => d.id === id)).filter(Boolean) as Discipline[],
|
|
40
|
-
}))
|
|
41
|
-
}
|
|
42
|
-
}
|