@01-edu/shared 2.0.5 → 2.0.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.
- package/dist/attrs-defs.js +1 -0
- package/dist/attrs.js +1 -0
- package/dist/bin/check-definitions.js +3 -0
- package/dist/chunk-727IHWVW.js +1 -0
- package/dist/chunk-7ZTI6THC.js +1 -0
- package/dist/chunk-CBWHFDVB.js +1 -0
- package/dist/chunk-EI7MMDWY.js +1 -0
- package/dist/chunk-EOY6G4KE.js +1 -0
- package/dist/chunk-K5Z4W5GV.js +1 -0
- package/dist/chunk-LDUPRVV4.js +1 -0
- package/dist/chunk-NQCTSDJE.js +1 -0
- package/dist/chunk-V47RDOUO.js +1 -0
- package/dist/chunk-XYW3ROIR.js +1 -0
- package/dist/definitions-checker.js +1 -0
- package/dist/event-utils.js +1 -0
- package/dist/games-utils.js +1 -0
- package/dist/graph.js +1 -0
- package/dist/hasura-core.js +1 -0
- package/dist/hasura-model.js +34 -0
- package/dist/hasura-prepare.js +1 -0
- package/dist/modular-steps-utils.js +1 -0
- package/dist/object-structure.js +1 -0
- package/dist/onboarding.js +1 -0
- package/dist/path.js +1 -0
- package/dist/qa-utils.js +1 -0
- package/dist/score.js +1 -0
- package/dist/skill-definitions.js +1 -0
- package/dist/toolbox.js +1 -0
- package/package.json +17 -6
- package/attrs-defs.js +0 -4273
- package/attrs.js +0 -423
- package/bin/check-definitions.js +0 -74
- package/definitions-checker.js +0 -233
- package/event-utils.js +0 -58
- package/graph.js +0 -96
- package/hasura-core.js +0 -217
- package/hasura-model.js +0 -138
- package/hasura-prepare.js +0 -44
- package/languages.js +0 -147
- package/onboarding.js +0 -25
- package/path.js +0 -73
- package/programming-languages.js +0 -21
- package/qa-utils.js +0 -13
- package/score.js +0 -80
- package/skill-definitions.js +0 -359
- package/toolbox.js +0 -532
package/attrs.js
DELETED
|
@@ -1,423 +0,0 @@
|
|
|
1
|
-
import { attrs, relationAttrs } from './attrs-defs.js'
|
|
2
|
-
import { languages } from './languages.js'
|
|
3
|
-
import { mapEntries, mapValues } from './toolbox.js'
|
|
4
|
-
|
|
5
|
-
// ⚡ description placeholder
|
|
6
|
-
|
|
7
|
-
const typeCheckers = {
|
|
8
|
-
boolean: b => typeof b === 'boolean',
|
|
9
|
-
number: n => typeof n === 'number',
|
|
10
|
-
string: s => typeof s === 'string',
|
|
11
|
-
object: o => typeof o === 'object' && o !== null,
|
|
12
|
-
array: Array.isArray,
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const determinType = value => {
|
|
16
|
-
if (Array.isArray(value)) return 'array'
|
|
17
|
-
if (typeof value === 'object' && value !== null) return value.type || 'object'
|
|
18
|
-
return typeof value
|
|
19
|
-
}
|
|
20
|
-
const typeChecker = (defs, value, object, key) => {
|
|
21
|
-
const { type, check, options } = defs
|
|
22
|
-
|
|
23
|
-
if (value == null) {
|
|
24
|
-
if (!defs.required || defs.value !== undefined) return true
|
|
25
|
-
// if no value for required attribute without a default value, reject
|
|
26
|
-
throw Error(`missing value for required attribute ${key}`)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (!type) throw Error(`attribute type definition is missing for ${key}`)
|
|
30
|
-
|
|
31
|
-
if (value?.type === 'function') {
|
|
32
|
-
if (defs.functionsByName[value.name]) return true
|
|
33
|
-
throw Error(`function associated not allowed for ${key}`)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// if a check is defined and don't pass, reject
|
|
37
|
-
check?.(value, object, key)
|
|
38
|
-
|
|
39
|
-
if (options) {
|
|
40
|
-
const opts =
|
|
41
|
-
typeof options === 'function' ? options(object, value) : options
|
|
42
|
-
if (opts.length === 1) {
|
|
43
|
-
if (opts[0] !== value) {
|
|
44
|
-
throw Error(`${key} must be ${opts[0]} but was ${value}`)
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
const isAnOption = opts.includes(value)
|
|
48
|
-
if (!isAnOption) {
|
|
49
|
-
throw Error(
|
|
50
|
-
`invalid option for ${key}: should be included in ${opts.join(', ')}`,
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// basic case
|
|
57
|
-
if (typeCheckers[type]) {
|
|
58
|
-
if (!typeCheckers[type](value)) throw Error(`Expect ${type} for ${key}`)
|
|
59
|
-
return true
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// complex cases: array
|
|
63
|
-
if (Array.isArray(type)) {
|
|
64
|
-
if (!Array.isArray(value)) {
|
|
65
|
-
throw Error(`invalid attribute value: expects an array for ${key}`)
|
|
66
|
-
}
|
|
67
|
-
// every value have to match one of the type definition
|
|
68
|
-
|
|
69
|
-
const uniqueDef = type.length === 1 && type[0]
|
|
70
|
-
// convert array type into object for better accessibility
|
|
71
|
-
const types =
|
|
72
|
-
!uniqueDef &&
|
|
73
|
-
Object.fromEntries(
|
|
74
|
-
type.map(t => [
|
|
75
|
-
Array.isArray(t.type) ? 'array' : t.type?.type?.value || t.type,
|
|
76
|
-
t,
|
|
77
|
-
]),
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
for (const [index, v] of value.entries()) {
|
|
81
|
-
const err = Error('checks failed for all types')
|
|
82
|
-
err.index = index
|
|
83
|
-
err.key = key
|
|
84
|
-
err.label = defs.label
|
|
85
|
-
const subdefs = uniqueDef || types[determinType(v)]
|
|
86
|
-
|
|
87
|
-
if (!subdefs) {
|
|
88
|
-
err.details = {
|
|
89
|
-
label: 'Unknown structure',
|
|
90
|
-
err: Error('no type matches the value'),
|
|
91
|
-
}
|
|
92
|
-
throw err
|
|
93
|
-
}
|
|
94
|
-
try {
|
|
95
|
-
typeChecker(subdefs, v, object, key)
|
|
96
|
-
} catch (error) {
|
|
97
|
-
err.details = error.details || {
|
|
98
|
-
label: subdefs.label || error.label,
|
|
99
|
-
err: error,
|
|
100
|
-
}
|
|
101
|
-
throw err
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// TODO: check "one of" also one day - meaning there is no duplicate
|
|
106
|
-
|
|
107
|
-
return true
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (typeof type !== 'object') throw Error('invalid attribute type definition')
|
|
111
|
-
|
|
112
|
-
if (typeof value !== 'object' || value === null) {
|
|
113
|
-
throw Error('invalid attribute value: expects an object')
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// then is necessarily an object. Let's check!
|
|
117
|
-
const typeEntries = Object.entries(type)
|
|
118
|
-
|
|
119
|
-
// check that every key fulfilled is defined in the type definitions
|
|
120
|
-
const invalidKey = Object.keys(value).find(key => !type[key])
|
|
121
|
-
if (invalidKey) throw Error(`${invalidKey} is invalid.`)
|
|
122
|
-
|
|
123
|
-
for (const [key, defs] of typeEntries) {
|
|
124
|
-
typeChecker(defs, value[key], object, key)
|
|
125
|
-
}
|
|
126
|
-
return true
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// same as attrs with the check & function by name generated and descriptions form markdown files
|
|
130
|
-
export const attributes = mapEntries(attrs, ([attrKey, matches]) => [
|
|
131
|
-
attrKey,
|
|
132
|
-
mapValues(matches, (defs /* type */) => ({
|
|
133
|
-
...defs,
|
|
134
|
-
check: (value, object) => typeChecker(defs, value, object, attrKey),
|
|
135
|
-
})),
|
|
136
|
-
])
|
|
137
|
-
|
|
138
|
-
export const relationAttributes = mapEntries(
|
|
139
|
-
relationAttrs,
|
|
140
|
-
([attrKey, byParent]) => [
|
|
141
|
-
attrKey,
|
|
142
|
-
mapValues(byParent, (matches /* parentType */) =>
|
|
143
|
-
mapValues(matches, (defs /* childType */) => ({
|
|
144
|
-
...defs,
|
|
145
|
-
check: (value, object) => typeChecker(defs, value, object, attrKey),
|
|
146
|
-
})),
|
|
147
|
-
),
|
|
148
|
-
],
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
// white list of attributes that can be applied in bulk
|
|
152
|
-
const allowedBulkAttrs = {
|
|
153
|
-
codeEditor: { enabled: {} },
|
|
154
|
-
validations: {
|
|
155
|
-
// this is for the different options of validation,
|
|
156
|
-
// we know that raids for now is the only one that contains multiple validations
|
|
157
|
-
// and we **don't** want admin_selection
|
|
158
|
-
type: [
|
|
159
|
-
'admin_audit',
|
|
160
|
-
'tester',
|
|
161
|
-
'dedicated_auditors_for_event',
|
|
162
|
-
'user_audit',
|
|
163
|
-
],
|
|
164
|
-
ratio: {},
|
|
165
|
-
required: {},
|
|
166
|
-
matchInfluence: {},
|
|
167
|
-
cooldown: {},
|
|
168
|
-
preQuestions: {},
|
|
169
|
-
postQuestions: {},
|
|
170
|
-
matchWhere: {},
|
|
171
|
-
},
|
|
172
|
-
}
|
|
173
|
-
export const getAllBulkAttrs = (parentType, childType) => {
|
|
174
|
-
const relationAttrs = getDefaultRelAttrs(parentType, childType)
|
|
175
|
-
const attrs = getDefaultAttrs({ type: childType })
|
|
176
|
-
const allAttrs = { ...relationAttrs, ...attrs }
|
|
177
|
-
return filterBulkAttrs(allAttrs, allowedBulkAttrs)
|
|
178
|
-
}
|
|
179
|
-
export const filterBulkAttrs = (attrs, allowedAttrs) => {
|
|
180
|
-
if (!attrs) return {}
|
|
181
|
-
if (Array.isArray(attrs.type)) {
|
|
182
|
-
const { type, ...rest } = attrs
|
|
183
|
-
// if it is type array and from the validation attribute we need to filter the validation type
|
|
184
|
-
const types = type
|
|
185
|
-
.map(a => filterBulkAttrs(a, allowedAttrs))
|
|
186
|
-
.filter(({ type }) => allowedAttrs.type.includes(type.type.value))
|
|
187
|
-
return { ...rest, type: types }
|
|
188
|
-
}
|
|
189
|
-
if (attrs.type && typeof attrs.type === 'object') {
|
|
190
|
-
const { type, ...rest } = attrs
|
|
191
|
-
const filtered = { type: {}, ...rest }
|
|
192
|
-
const typesKeys = Object.keys(type)
|
|
193
|
-
for (const t of typesKeys) {
|
|
194
|
-
if (allowedAttrs?.[t]) {
|
|
195
|
-
filtered.type[t] = type[t]
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
return filtered
|
|
199
|
-
}
|
|
200
|
-
if (typeof attrs === 'object' && !attrs.type) {
|
|
201
|
-
const filtered = {}
|
|
202
|
-
const keys = Object.keys(attrs)
|
|
203
|
-
for (const k of keys) {
|
|
204
|
-
if (allowedAttrs[k]) {
|
|
205
|
-
filtered[k] = filterBulkAttrs(attrs[k], allowedAttrs[k])
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return filtered
|
|
209
|
-
}
|
|
210
|
-
return null
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// map from attrs[name][type] to attrs[type][name]
|
|
214
|
-
export const attrsByType = {}
|
|
215
|
-
|
|
216
|
-
const languagesEntries = Object.entries(languages)
|
|
217
|
-
for (const [name, matches] of Object.entries(attributes)) {
|
|
218
|
-
for (const [type, defs] of Object.entries(matches)) {
|
|
219
|
-
const ofType = attrsByType[type] || (attrsByType[type] = {})
|
|
220
|
-
ofType[name] = defs
|
|
221
|
-
// handle translations: generate translation attrs and required status
|
|
222
|
-
const { label, ...restDefs } = defs
|
|
223
|
-
if (defs.functionsByName?.translate) {
|
|
224
|
-
// perf measures done: increase from 0.671ms loadtime to 13.261ms
|
|
225
|
-
// should not impact the perfs
|
|
226
|
-
for (const [code, language] of languagesEntries) {
|
|
227
|
-
const newLabel = `${label} - ${language}`
|
|
228
|
-
ofType[`${name}-${code}`] = {
|
|
229
|
-
...restDefs,
|
|
230
|
-
label: newLabel,
|
|
231
|
-
lgCode: code,
|
|
232
|
-
required: false,
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// map from attrs[name][parentType][childType]
|
|
240
|
-
// to attrs[parentType][childType][name]
|
|
241
|
-
export const relationAttrsByParentType = {}
|
|
242
|
-
for (const [name, byParent] of Object.entries(relationAttributes)) {
|
|
243
|
-
for (const [parentType, byChild] of Object.entries(byParent)) {
|
|
244
|
-
for (const [childType, defs] of Object.entries(byChild)) {
|
|
245
|
-
const ofParentType =
|
|
246
|
-
relationAttrsByParentType[parentType] ||
|
|
247
|
-
(relationAttrsByParentType[parentType] = {})
|
|
248
|
-
const ofParentChildType =
|
|
249
|
-
ofParentType[childType] || (ofParentType[childType] = {})
|
|
250
|
-
ofParentChildType[name] = defs
|
|
251
|
-
// for now, there is no relation attr that is translatable
|
|
252
|
-
// if it is created one day, add handling of translations here
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
const attrsEntriesByType = mapValues(attrsByType, Object.entries)
|
|
257
|
-
const relAttrsEntriesByParentType = mapValues(
|
|
258
|
-
relationAttrsByParentType,
|
|
259
|
-
byParent => mapValues(byParent, Object.entries),
|
|
260
|
-
)
|
|
261
|
-
export const getDefaultAttrsEntries = object =>
|
|
262
|
-
attrsEntriesByType[object.type] || []
|
|
263
|
-
export const getDefaultRelAttrsEntries = (parentType, childType) =>
|
|
264
|
-
relAttrsEntriesByParentType[parentType]?.[childType] || []
|
|
265
|
-
|
|
266
|
-
export const getDefaultAttrs = object => attrsByType[object.type]
|
|
267
|
-
export const getDefaultRelAttrs = (parentType, childType) =>
|
|
268
|
-
relationAttrsByParentType[parentType]?.[childType]
|
|
269
|
-
|
|
270
|
-
const findDefaultOrNamedFunction = (value, defs) => {
|
|
271
|
-
// Should be true only for required impure default value functions
|
|
272
|
-
if (value === undefined || value === null) return defs.required && defs.value
|
|
273
|
-
if (value.type !== 'function') return
|
|
274
|
-
// Otherwise we only care about when the default function was overridden
|
|
275
|
-
// by another impure function
|
|
276
|
-
|
|
277
|
-
return defs.functionsByName?.[value.name]
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const applyDefs = (key, value, defs, object, getUser) => {
|
|
281
|
-
// xp, child.attrs.rewards, defs.type.xp, object
|
|
282
|
-
// reward, child.attrs, defs, object
|
|
283
|
-
if (value === undefined || value === null) return
|
|
284
|
-
const fn = findDefaultOrNamedFunction(value[key], defs)
|
|
285
|
-
if (typeof fn === 'function') {
|
|
286
|
-
if (getUser) {
|
|
287
|
-
Object.defineProperty(value, key, {
|
|
288
|
-
get: () => fn(object, getUser(), key),
|
|
289
|
-
enumerable: true,
|
|
290
|
-
})
|
|
291
|
-
} else if (fn.name === 'translate') {
|
|
292
|
-
// if we don't have a user, assume english language
|
|
293
|
-
value[key] = value[`${key}-en`]
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const expandAttr = (key, value, defs, object, getUser) => {
|
|
299
|
-
const isFunction = value[key]?.type === 'function'
|
|
300
|
-
if (Array.isArray(defs.type) && value[key] && !isFunction) {
|
|
301
|
-
// handle multiple sub-types defs for array items
|
|
302
|
-
// there can be different subtypes defs of type object,
|
|
303
|
-
// as long as they all have a type property (mandatory - to distinguish def to check)
|
|
304
|
-
// and one subtype def for each primary data type
|
|
305
|
-
const types =
|
|
306
|
-
defs.type.length > 1 &&
|
|
307
|
-
Object.fromEntries(defs.type.map(t => [t.type.type?.value || t.type, t]))
|
|
308
|
-
|
|
309
|
-
for (let i = 0; i < value[key].length; i++) {
|
|
310
|
-
let def
|
|
311
|
-
if (types) {
|
|
312
|
-
const isObject = typeof value[key][i] === 'object'
|
|
313
|
-
|
|
314
|
-
// when type is set to "object" for items that cannot be defined in attrs because
|
|
315
|
-
// the key cannot be known (like types.graphArcContentWithSubContents)
|
|
316
|
-
const typeCouldNotBeDefined = isObject && Boolean(types.object)
|
|
317
|
-
|
|
318
|
-
const invalidType =
|
|
319
|
-
!value[key][i].type || typeof value[key][i].type !== 'string'
|
|
320
|
-
const allowedTypes = Object.keys(types).join(',').slice(0, -1)
|
|
321
|
-
|
|
322
|
-
if (isObject && invalidType && !typeCouldNotBeDefined) {
|
|
323
|
-
console.warn(
|
|
324
|
-
`Type not allowed. Object item for ${key} array (#${i} item) must have one of these "type" property: ${allowedTypes}.`,
|
|
325
|
-
)
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
def = isObject ? types[value[key][i].type] : types[typeof value[key][i]]
|
|
329
|
-
|
|
330
|
-
if (!def && !typeCouldNotBeDefined) {
|
|
331
|
-
console.warn(
|
|
332
|
-
`Missing type definition. Object item for ${key} array (#${i} item) must have one of these "type" property: ${allowedTypes}.`,
|
|
333
|
-
)
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
expandAttr(i, value[key], def || defs.type[0], object, getUser)
|
|
338
|
-
}
|
|
339
|
-
} else if (typeof defs.type === 'object' && value[key] && !isFunction) {
|
|
340
|
-
for (const [childKey, subDefs] of Object.entries(defs.type)) {
|
|
341
|
-
expandAttr(childKey, value[key], subDefs, object, getUser)
|
|
342
|
-
}
|
|
343
|
-
} else {
|
|
344
|
-
applyDefs(key, value, defs, object, getUser)
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// same as the `expandDynamicAttrs` this function would resolve dynamic attributes
|
|
349
|
-
// the special use of this function is that we can resolve certain attributes
|
|
350
|
-
// by providing a filter function
|
|
351
|
-
export const partialExpandDynamicAttrs = (object, getUser, filterFn) => {
|
|
352
|
-
if (!object.children) return (object.children = {})
|
|
353
|
-
if (!Object.keys(object.children).length) return
|
|
354
|
-
|
|
355
|
-
const defautlAttrs = getDefaultAttrsEntries(object)
|
|
356
|
-
const filteredDefaultAttrs = defautlAttrs.filter(filterFn)
|
|
357
|
-
|
|
358
|
-
processAttributes(filteredDefaultAttrs, object, getUser)
|
|
359
|
-
let prev
|
|
360
|
-
for (const child of Object.values(object.children)) {
|
|
361
|
-
// we only add the parent if it does not exist
|
|
362
|
-
if (!child.parent) child.parent = object
|
|
363
|
-
prev && (prev.next = child) && (child.prev = prev)
|
|
364
|
-
prev = child
|
|
365
|
-
|
|
366
|
-
const childDefaultAttrs = getDefaultAttrsEntries(child)
|
|
367
|
-
const childRelAttrs = getDefaultRelAttrsEntries(object.type, child.type)
|
|
368
|
-
const [filteredChildAttrs, filteredRelAttrs] = [
|
|
369
|
-
childDefaultAttrs.filter(filterFn),
|
|
370
|
-
childRelAttrs.filter(filterFn),
|
|
371
|
-
]
|
|
372
|
-
|
|
373
|
-
// apply missing default functions
|
|
374
|
-
// a function can only be missing if it require the user,
|
|
375
|
-
// the event or current time
|
|
376
|
-
processAttributes(filteredChildAttrs, child, getUser)
|
|
377
|
-
processAttributes(filteredRelAttrs, child, getUser)
|
|
378
|
-
partialExpandDynamicAttrs(child, getUser, filterFn)
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// this function allows us to resolve dynamic attributes
|
|
383
|
-
// by converting them into functions that can be re-evaluated
|
|
384
|
-
// this enables attributes to return updated values when re-checked
|
|
385
|
-
// without requiring additional api queries
|
|
386
|
-
// so the result can be recalculated as needed
|
|
387
|
-
export const expandDynamicAttrs = (object, getUser) => {
|
|
388
|
-
if (!object.children) return (object.children = {})
|
|
389
|
-
if (!Object.keys(object.children).length) return
|
|
390
|
-
|
|
391
|
-
const defautlAttrs = getDefaultAttrsEntries(object)
|
|
392
|
-
|
|
393
|
-
processAttributes(defautlAttrs, object, getUser)
|
|
394
|
-
let prev
|
|
395
|
-
for (const child of Object.values(object.children)) {
|
|
396
|
-
child.parent = object
|
|
397
|
-
prev && (prev.next = child) && (child.prev = prev)
|
|
398
|
-
prev = child
|
|
399
|
-
|
|
400
|
-
const childDefaultAttrs = getDefaultAttrsEntries(child)
|
|
401
|
-
const childRelAttrs = getDefaultRelAttrsEntries(object.type, child.type)
|
|
402
|
-
|
|
403
|
-
// apply missing default functions
|
|
404
|
-
// a function can only be missing if it require the user,
|
|
405
|
-
// the event or current time
|
|
406
|
-
processAttributes(childDefaultAttrs, child, getUser)
|
|
407
|
-
processAttributes(childRelAttrs, child, getUser)
|
|
408
|
-
expandDynamicAttrs(child, getUser)
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const processAttributes = (attrEntries, targetObject, getUser) => {
|
|
413
|
-
for (const [key, defs] of attrEntries) {
|
|
414
|
-
if (targetObject.attrs[key] === null) {
|
|
415
|
-
console.warn(
|
|
416
|
-
`value is null for ${targetObject.name} - ${key} - ${targetObject.id}`,
|
|
417
|
-
)
|
|
418
|
-
}
|
|
419
|
-
expandAttr(key, targetObject.attrs, defs, targetObject, getUser)
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
export { attrs, relationAttrs }
|
package/bin/check-definitions.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { readFile, stat, watch } from 'node:fs/promises'
|
|
4
|
-
|
|
5
|
-
import { checkAndBuildDefinitions } from '../definitions-checker.js'
|
|
6
|
-
|
|
7
|
-
const rootTypes = ['module', 'piscine', 'signup', 'onboarding']
|
|
8
|
-
const isAudit = validation => validation.type.endsWith('_audit')
|
|
9
|
-
const readDef = async key => {
|
|
10
|
-
const path = key == null ? 'content/def.json' : `content/${key}/def.json`
|
|
11
|
-
const def = JSON.parse(await readFile(path, 'utf8'))
|
|
12
|
-
def.attrs || (def.attrs = {})
|
|
13
|
-
def.referencePath = path
|
|
14
|
-
|
|
15
|
-
if (key == null && !rootTypes.includes(def.type)) {
|
|
16
|
-
throw Error(
|
|
17
|
-
`Root definition must be one of ${rootTypes.join(', ')}, found: ${def.type}`,
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
switch (def.type) {
|
|
22
|
-
case 'project':
|
|
23
|
-
// biome-ignore lint/suspicious/noFallthroughSwitchClause: We want to fallthrough
|
|
24
|
-
case 'raid': {
|
|
25
|
-
const audit = (def.attrs.validations || []).find(isAudit)
|
|
26
|
-
if (!audit) {
|
|
27
|
-
throw Error('project and raid must have an audit validation specified')
|
|
28
|
-
}
|
|
29
|
-
if (audit.form) {
|
|
30
|
-
throw Error(
|
|
31
|
-
'audit form attribute is automatically set to be ./audit/README.md, do not specify it',
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
audit.form = `content/${key}/audit/README.md`
|
|
35
|
-
await stat(audit.form)
|
|
36
|
-
}
|
|
37
|
-
case 'exercise': {
|
|
38
|
-
if (def.attrs.subject) {
|
|
39
|
-
throw Error(
|
|
40
|
-
'subject attribute is automatically set to be ./README.md, do not specify it',
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
def.attrs.subject = `content/${key}/README.md`
|
|
44
|
-
await stat(def.attrs.subject)
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return def
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const runChecks = async () => {
|
|
52
|
-
try {
|
|
53
|
-
return await checkAndBuildDefinitions(readDef)
|
|
54
|
-
} catch ({ message, stack, ...props }) {
|
|
55
|
-
console.error(message)
|
|
56
|
-
console.error(props)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (process.argv.includes('--watch') || process.argv.includes('-w')) {
|
|
61
|
-
await runChecks()
|
|
62
|
-
for await (const event of watch('.', { recursive: true })) {
|
|
63
|
-
console.clear()
|
|
64
|
-
if (!event.filename.endsWith('def.json')) continue
|
|
65
|
-
console.log(event.eventType, 'on', event.filename, '\n')
|
|
66
|
-
await runChecks()
|
|
67
|
-
}
|
|
68
|
-
} else if (!(await runChecks())) {
|
|
69
|
-
process.exit(1)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
console.log('All checks passed, no errors')
|
|
73
|
-
// Extra checks:
|
|
74
|
-
// - Orphan files (defs files not referenced anywhere)
|