@01-edu/shared 1.0.5 → 1.0.6

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.
@@ -1,31 +1,63 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { readFile, stat } from 'node:fs/promises'
3
+ import { readFile, stat, watch } from 'node:fs/promises'
4
4
 
5
5
  import { checkAndBuildDefinitions } from '../definitions-checker.js'
6
6
 
7
- const auditValidation = validation => validation.type.endsWith('_audit')
8
- try {
9
- const result = await checkAndBuildDefinitions(async key => {
10
- const referencePath = `content${key ? `/${key}` : ''}/def.json`
11
- const def = JSON.parse(await readFile(referencePath, 'utf8'))
12
- def.attrs || (def.attrs = {})
13
- def.referencePath = referencePath
14
- switch (def.type) {
15
- case 'project':
16
- // biome-ignore lint/suspicious/noFallthroughSwitchClause: We want to fallthrough
17
- case 'raid': {
18
- await stat(`content/${key}/audit/README.md`)
7
+ const isAudit = validation => validation.type.endsWith('_audit')
8
+ const readDef = async key => {
9
+ const path = key == null ? 'content/def.json' : `content/${key}/def.json`
10
+ const def = JSON.parse(await readFile(path, 'utf8'))
11
+ def.attrs || (def.attrs = {})
12
+ def.referencePath = path
13
+
14
+ switch (def.type) {
15
+ case 'project':
16
+ // biome-ignore lint/suspicious/noFallthroughSwitchClause: We want to fallthrough
17
+ case 'raid': {
18
+ const audit = (def.attrs.validations || []).find(isAudit)
19
+ if (!audit) {
20
+ throw Error('project and raid must have an audit validation specified')
21
+ }
22
+ if (audit.form) {
23
+ throw Error(
24
+ 'audit form attribute is automatically set to be ./audit/README.md, do not specify it',
25
+ )
19
26
  }
20
- case 'exercise': {
21
- await stat(`content/${key}/README.md`)
27
+ audit.form = `content/${key}/audit/README.md`
28
+ await stat(audit.form)
29
+ }
30
+ case 'exercise': {
31
+ if (def.attrs.subject) {
32
+ throw Error(
33
+ 'subject attribute is automatically set to be ./README.md, do not specify it',
34
+ )
22
35
  }
36
+ def.attrs.subject = `content/${key}/README.md`
37
+ await stat(def.attrs.subject)
23
38
  }
39
+ }
40
+
41
+ return def
42
+ }
43
+
44
+ const runChecks = async () => {
45
+ try {
46
+ return await checkAndBuildDefinitions(readDef)
47
+ } catch ({ message, stack, ...props }) {
48
+ console.error(message)
49
+ console.error(props)
50
+ }
51
+ }
24
52
 
25
- return def
26
- })
27
- } catch ({ message, ...props }) {
28
- console.error(message, props)
53
+ if (process.argv.includes('--watch') || process.argv.includes('-w')) {
54
+ await runChecks()
55
+ for await (const event of watch('.', { recursive: true })) {
56
+ console.clear()
57
+ console.log(event.eventType, 'on', event.filename, '\n')
58
+ await runChecks()
59
+ }
60
+ } else if (!(await runChecks())) {
29
61
  process.exit(1)
30
62
  }
31
63
 
@@ -31,7 +31,7 @@ const assertDef = def => {
31
31
  if (refId && typeof refId !== 'number') throw Error(`Invalid refId property`)
32
32
  if (childrenAttrs) throw Error(`childrenAttrs is no longer supported`)
33
33
 
34
- for (const [key, value] of Object.entries(attrs)) {
34
+ for (const key of Object.keys(attrs)) {
35
35
  if (relationAttributes[key]) {
36
36
  throw Error(
37
37
  `Attr ${key} should be defined in the relation with its parent, not on the object itself.`,
@@ -89,7 +89,7 @@ const assertRelation = (parent, key, relation) => {
89
89
  throw Error(`Self reference in child ${key}`)
90
90
  }
91
91
 
92
- for (const [key, value] of Object.entries(relation)) {
92
+ for (const key of Object.keys(relation)) {
93
93
  if (key === 'ref') continue
94
94
  const matches = attributes[key]
95
95
  if (matches?.[type]?.restrictive) {
@@ -138,29 +138,6 @@ const checkAttrs = object => {
138
138
  }
139
139
  }
140
140
 
141
- // TODO: replace by Set.intersection once available in node
142
- const intersection = (a, b) => {
143
- const result = new Set()
144
- for (const element of a) {
145
- b.has(element) && result.add(element)
146
- }
147
- return result
148
- }
149
-
150
- const generatePairs = arr => {
151
- const result = []
152
- let i = -1
153
- // Only go up to the second to last element
154
- while (++i < arr.length - 1) {
155
- let j = i
156
- // Start from the next element to avoid duplicates
157
- while (++j < arr.length) {
158
- result.push([arr[i], arr[j]])
159
- }
160
- }
161
- return result
162
- }
163
-
164
141
  const isExam = def => def.type === 'exam'
165
142
  const assertExams = definitions => {
166
143
  const groups = {}
@@ -197,7 +174,13 @@ const assertExams = definitions => {
197
174
  export const checkAndBuildDefinitions = async readDef => {
198
175
  const cache = {}
199
176
  const getDefs = async ([key, relation]) => {
200
- const def = cache[key] || (cache[key] = await readDef(key))
177
+ let def
178
+ try {
179
+ def = cache[key] || (cache[key] = await readDef(key))
180
+ } catch (err) {
181
+ err.name = key
182
+ throw err
183
+ }
201
184
  try {
202
185
  assertDef(def)
203
186
  } catch (err) {
@@ -207,7 +190,12 @@ export const checkAndBuildDefinitions = async readDef => {
207
190
  }
208
191
  relation && (relation.ref = def)
209
192
  const relations = Object.entries(def.children || {}).map(getDefs)
210
- return [def, ...(await Promise.all(relations)).flat()]
193
+ try {
194
+ return [def, ...(await Promise.all(relations)).flat()]
195
+ } catch (err) {
196
+ key && (err.parents || (err.parents = [])).push(key)
197
+ throw err
198
+ }
211
199
  }
212
200
 
213
201
  const definitions = await getDefs([])
@@ -215,7 +203,6 @@ export const checkAndBuildDefinitions = async readDef => {
215
203
  // Assert all relations looks ok, possible child / parent, allowed attributes
216
204
  for (const def of definitions) {
217
205
  if (!def.children) continue
218
- const allowedTypes = childTypes[def.type]
219
206
  try {
220
207
  for (const entry of Object.entries(def.children)) {
221
208
  assertRelation(def, entry[0], entry[1])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@01-edu/shared",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "scripts": {