@anzusystems/common-admin 1.47.0-beta.36 → 1.47.0-beta.361
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/AFormRemoteAutocomplete.vue_vue_type_script_setup_true_lang-BNyX-8Ah.mjs +7442 -0
- package/dist/AFormRemoteAutocomplete.vue_vue_type_script_setup_true_lang-BNyX-8Ah.mjs.map +1 -0
- package/dist/common-admin.css +1 -0
- package/dist/common-admin.d.ts +26064 -0
- package/dist/common-admin.js +24103 -0
- package/dist/common-admin.js.map +1 -0
- package/dist/index-CGpu1VTe.mjs +21504 -0
- package/dist/index-CGpu1VTe.mjs.map +1 -0
- package/dist/labs.d.ts +1912 -0
- package/dist/labs.js +5219 -0
- package/dist/labs.js.map +1 -0
- package/dist/webfontloader-CHE2rJZS.mjs +454 -0
- package/dist/webfontloader-CHE2rJZS.mjs.map +1 -0
- package/package.json +101 -69
- package/src/eslint/plugin.mjs +574 -0
- package/dist/common-admin.es.d.ts +0 -11188
- package/dist/common-admin.es.js +0 -327
- package/dist/common-admin.es.js.map +0 -1
- package/dist/lib-C41x-F5b.js +0 -24211
- package/dist/lib-C41x-F5b.js.map +0 -1
- package/dist/style.css +0 -13
- package/dist/webfontloader-B64MebV6.js +0 -452
- package/dist/webfontloader-B64MebV6.js.map +0 -1
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
const DEFAULT_DEPRECATED_IMPORTS = [
|
|
2
|
+
'AFilterWrapper',
|
|
3
|
+
'AFilterBooleanSelect',
|
|
4
|
+
'AFilterBooleanGroup',
|
|
5
|
+
'AFilterDatetimePicker',
|
|
6
|
+
'AFilterInteger',
|
|
7
|
+
'AFilterRemoteAutocomplete',
|
|
8
|
+
'AFilterRemoteAutocompleteWithMinimal',
|
|
9
|
+
'AFilterString',
|
|
10
|
+
'AFilterValueObjectOptionsSelect',
|
|
11
|
+
'ADatatableOrdering',
|
|
12
|
+
'ADatatablePagination',
|
|
13
|
+
'AFormRemoteAutocomplete',
|
|
14
|
+
'ASubjectSelect',
|
|
15
|
+
'usePagination',
|
|
16
|
+
'useFilterHelpers',
|
|
17
|
+
'createDatatableColumnsConfig',
|
|
18
|
+
'useSubjectSelect',
|
|
19
|
+
'useApiQueryBuilder',
|
|
20
|
+
'useJobApi',
|
|
21
|
+
'Pagination',
|
|
22
|
+
'makeFilterHelper',
|
|
23
|
+
'apiFetchList',
|
|
24
|
+
'FilterBag',
|
|
25
|
+
'Filter',
|
|
26
|
+
'apiFetchByIds',
|
|
27
|
+
'apiAnyRequest',
|
|
28
|
+
'apiCreateOne',
|
|
29
|
+
'apiDeleteOne',
|
|
30
|
+
'apiFetchOne',
|
|
31
|
+
'apiUpdateOne',
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const DEFAULT_INTERNAL_DEPRECATED_IMPORTS = [
|
|
35
|
+
{
|
|
36
|
+
path: '@/services/api/apiFetchList',
|
|
37
|
+
imports: ['apiFetchList'],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
path: '@/services/api/apiFetchListBatch',
|
|
41
|
+
imports: ['apiFetchListBatch'],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
path: '@/composables/system/pagination',
|
|
45
|
+
imports: ['usePagination', 'Pagination'],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
path: '@/composables/filter/filterHelpers',
|
|
49
|
+
imports: ['useFilterHelpers', 'makeFilterHelper'],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
path: '@/composables/system/datatableColumns',
|
|
53
|
+
imports: ['createDatatableColumnsConfig'],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
path: '@/components/subjectSelect/useSubjectSelect',
|
|
57
|
+
imports: ['useSubjectSelect'],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
path: '@/services/api/queryBuilder',
|
|
61
|
+
imports: ['useApiQueryBuilder'],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
path: '@/services/api/job/jobApi',
|
|
65
|
+
imports: ['useJobApi'],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
path: '@/types/Filter',
|
|
69
|
+
imports: ['FilterBag', 'Filter'],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
path: '@/components/filter/AFilterWrapper',
|
|
73
|
+
imports: ['AFilterWrapper'],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
path: '@/components/filter/AFilterBooleanSelect',
|
|
77
|
+
imports: ['AFilterBooleanSelect'],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
path: '@/components/filter/AFilterBooleanGroup',
|
|
81
|
+
imports: ['AFilterBooleanGroup'],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
path: '@/components/filter/AFilterDatetimePicker',
|
|
85
|
+
imports: ['AFilterDatetimePicker'],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
path: '@/components/filter/AFilterInteger',
|
|
89
|
+
imports: ['AFilterInteger'],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
path: '@/components/filter/AFilterRemoteAutocomplete',
|
|
93
|
+
imports: ['AFilterRemoteAutocomplete'],
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
path: '@/components/filter/AFilterRemoteAutocompleteWithMinimal',
|
|
97
|
+
imports: ['AFilterRemoteAutocompleteWithMinimal'],
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
path: '@/components/filter/AFilterString',
|
|
101
|
+
imports: ['AFilterString'],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
path: '@/components/filter/AFilterValueObjectOptionsSelect',
|
|
105
|
+
imports: ['AFilterValueObjectOptionsSelect'],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
path: '@/components/ADatatableOrdering',
|
|
109
|
+
imports: ['ADatatableOrdering'],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
path: '@/components/ADatatablePagination',
|
|
113
|
+
imports: ['ADatatablePagination'],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
path: '@/components/form/AFormRemoteAutocomplete',
|
|
117
|
+
imports: ['AFormRemoteAutocomplete'],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
path: '@/components/subjectSelect/ASubjectSelect',
|
|
121
|
+
imports: ['ASubjectSelect'],
|
|
122
|
+
},
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
const anzuPlugin = {
|
|
126
|
+
rules: {
|
|
127
|
+
'no-ts-extension': {
|
|
128
|
+
meta: {
|
|
129
|
+
type: 'problem',
|
|
130
|
+
docs: {
|
|
131
|
+
description: 'Disallow .ts extension in import statements',
|
|
132
|
+
},
|
|
133
|
+
fixable: 'code',
|
|
134
|
+
schema: [],
|
|
135
|
+
},
|
|
136
|
+
create(context) {
|
|
137
|
+
return {
|
|
138
|
+
ImportDeclaration(node) {
|
|
139
|
+
const source = node.source.value
|
|
140
|
+
if (typeof source === 'string' && source.endsWith('.ts')) {
|
|
141
|
+
context.report({
|
|
142
|
+
node,
|
|
143
|
+
message: 'Do not include .ts extension in import paths',
|
|
144
|
+
fix(fixer) {
|
|
145
|
+
const sourceText = node.source.raw
|
|
146
|
+
const newSource = sourceText.replace(/\.ts(['"])$/, '$1')
|
|
147
|
+
return fixer.replaceText(node.source, newSource)
|
|
148
|
+
},
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
'no-deprecated-imports': {
|
|
157
|
+
meta: {
|
|
158
|
+
type: 'problem',
|
|
159
|
+
docs: {
|
|
160
|
+
description: 'Disallow usage of deprecated imports',
|
|
161
|
+
},
|
|
162
|
+
schema: [
|
|
163
|
+
{
|
|
164
|
+
type: 'object',
|
|
165
|
+
properties: {
|
|
166
|
+
rules: {
|
|
167
|
+
type: 'array',
|
|
168
|
+
items: {
|
|
169
|
+
type: 'object',
|
|
170
|
+
properties: {
|
|
171
|
+
path: { type: 'string' },
|
|
172
|
+
module: { type: 'string' },
|
|
173
|
+
imports: {
|
|
174
|
+
type: 'array',
|
|
175
|
+
items: { type: 'string' },
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
required: ['imports'],
|
|
179
|
+
additionalProperties: false,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
skipFiles: {
|
|
183
|
+
type: 'array',
|
|
184
|
+
items: { type: 'string' },
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
additionalProperties: false,
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
create(context) {
|
|
192
|
+
const options = context.options[0] || {}
|
|
193
|
+
const deprecationRules = options.rules || []
|
|
194
|
+
const skipFiles = options.skipFiles || []
|
|
195
|
+
|
|
196
|
+
// Collect source file paths from path-based rules for auto-skip
|
|
197
|
+
const ruleFilePaths = deprecationRules
|
|
198
|
+
.filter((rule) => rule.path)
|
|
199
|
+
.map((rule) => {
|
|
200
|
+
if (rule.path.startsWith('@/')) {
|
|
201
|
+
return rule.path.replace('@/', 'src/')
|
|
202
|
+
}
|
|
203
|
+
return rule.path
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
ImportDeclaration(node) {
|
|
208
|
+
const filename = context.filename
|
|
209
|
+
const normalizedFilename = filename.replace(/\\/g, '/')
|
|
210
|
+
|
|
211
|
+
// Check manual skip list
|
|
212
|
+
if (skipFiles.some((skip) => normalizedFilename.endsWith(skip))) return
|
|
213
|
+
|
|
214
|
+
// Auto-skip source files of path-based rules
|
|
215
|
+
if (
|
|
216
|
+
ruleFilePaths.some(
|
|
217
|
+
(rulePath) =>
|
|
218
|
+
normalizedFilename.endsWith(rulePath + '.ts') ||
|
|
219
|
+
normalizedFilename.endsWith(rulePath + '.js') ||
|
|
220
|
+
normalizedFilename.endsWith(rulePath + '.vue') ||
|
|
221
|
+
normalizedFilename.endsWith(rulePath),
|
|
222
|
+
)
|
|
223
|
+
)
|
|
224
|
+
return
|
|
225
|
+
|
|
226
|
+
const source = node.source.value
|
|
227
|
+
if (typeof source !== 'string') return
|
|
228
|
+
|
|
229
|
+
for (const rule of deprecationRules) {
|
|
230
|
+
const matchPath = rule.path || rule.module
|
|
231
|
+
if (!matchPath || source !== matchPath) continue
|
|
232
|
+
|
|
233
|
+
const deprecatedImports = node.specifiers
|
|
234
|
+
.filter((spec) => spec.type === 'ImportSpecifier')
|
|
235
|
+
.filter((spec) => rule.imports.includes(spec.imported.name))
|
|
236
|
+
|
|
237
|
+
for (const importSpec of deprecatedImports) {
|
|
238
|
+
context.report({
|
|
239
|
+
node: importSpec,
|
|
240
|
+
message: `'${importSpec.imported.name}' from '${matchPath}' is deprecated`,
|
|
241
|
+
})
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
'url-params-match-template': {
|
|
250
|
+
meta: {
|
|
251
|
+
type: 'problem',
|
|
252
|
+
docs: {
|
|
253
|
+
description:
|
|
254
|
+
'Ensure urlParams keys match the :placeholders declared in urlTemplate ' +
|
|
255
|
+
'for useApiRequest / useApiFetchList / useApiFetchByIds / useApiFetchListBatch calls.',
|
|
256
|
+
},
|
|
257
|
+
schema: [],
|
|
258
|
+
},
|
|
259
|
+
create(context) {
|
|
260
|
+
const TARGET_CALLEES = new Set([
|
|
261
|
+
'useApiRequest',
|
|
262
|
+
'useApiFetchList',
|
|
263
|
+
'useApiFetchByIds',
|
|
264
|
+
'useApiFetchListBatch',
|
|
265
|
+
])
|
|
266
|
+
|
|
267
|
+
const PLACEHOLDER_RE = /:([a-zA-Z_][\w]*)/g
|
|
268
|
+
|
|
269
|
+
const getCalleeName = (callee) => {
|
|
270
|
+
if (callee.type === 'Identifier') return callee.name
|
|
271
|
+
if (callee.type === 'MemberExpression' && callee.property.type === 'Identifier') {
|
|
272
|
+
return callee.property.name
|
|
273
|
+
}
|
|
274
|
+
return null
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const findProperty = (objectExpr, name) => {
|
|
278
|
+
for (const prop of objectExpr.properties) {
|
|
279
|
+
if (prop.type !== 'Property' || prop.computed) continue
|
|
280
|
+
const key = prop.key
|
|
281
|
+
const keyName =
|
|
282
|
+
key.type === 'Identifier' ? key.name : key.type === 'Literal' ? key.value : null
|
|
283
|
+
if (keyName === name) return prop
|
|
284
|
+
}
|
|
285
|
+
return null
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const resolveIdentifierToString = (identNode) => {
|
|
289
|
+
const scope = context.sourceCode.getScope(identNode)
|
|
290
|
+
let cur = scope
|
|
291
|
+
while (cur) {
|
|
292
|
+
const variable = cur.variables.find((v) => v.name === identNode.name)
|
|
293
|
+
if (variable && variable.defs.length === 1) {
|
|
294
|
+
const def = variable.defs[0]
|
|
295
|
+
if (
|
|
296
|
+
def.type === 'Variable' &&
|
|
297
|
+
def.node.type === 'VariableDeclarator' &&
|
|
298
|
+
def.parent &&
|
|
299
|
+
def.parent.kind === 'const' &&
|
|
300
|
+
def.node.init
|
|
301
|
+
) {
|
|
302
|
+
return resolveToString(def.node.init)
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
cur = cur.upper
|
|
306
|
+
}
|
|
307
|
+
return null
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const resolveToString = (node) => {
|
|
311
|
+
if (!node) return null
|
|
312
|
+
if (node.type === 'Literal' && typeof node.value === 'string') return node.value
|
|
313
|
+
if (node.type === 'TemplateLiteral') {
|
|
314
|
+
let out = ''
|
|
315
|
+
for (let i = 0; i < node.quasis.length; i++) {
|
|
316
|
+
out += node.quasis[i].value.cooked
|
|
317
|
+
if (i < node.expressions.length) {
|
|
318
|
+
const part = resolveToString(node.expressions[i])
|
|
319
|
+
if (part === null) return null
|
|
320
|
+
out += part
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return out
|
|
324
|
+
}
|
|
325
|
+
if (node.type === 'BinaryExpression' && node.operator === '+') {
|
|
326
|
+
const left = resolveToString(node.left)
|
|
327
|
+
const right = resolveToString(node.right)
|
|
328
|
+
if (left === null || right === null) return null
|
|
329
|
+
return left + right
|
|
330
|
+
}
|
|
331
|
+
if (node.type === 'Identifier') return resolveIdentifierToString(node)
|
|
332
|
+
return null
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const collectStaticKeys = (objectExpr) => {
|
|
336
|
+
const keys = []
|
|
337
|
+
for (const prop of objectExpr.properties) {
|
|
338
|
+
if (prop.type !== 'Property') return null
|
|
339
|
+
if (prop.computed) return null
|
|
340
|
+
const key = prop.key
|
|
341
|
+
if (key.type === 'Identifier') keys.push(key.name)
|
|
342
|
+
else if (key.type === 'Literal' && typeof key.value === 'string') keys.push(key.value)
|
|
343
|
+
else return null
|
|
344
|
+
}
|
|
345
|
+
return keys
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
CallExpression(node) {
|
|
350
|
+
const name = getCalleeName(node.callee)
|
|
351
|
+
if (!name || !TARGET_CALLEES.has(name)) return
|
|
352
|
+
|
|
353
|
+
const arg = node.arguments[0]
|
|
354
|
+
if (!arg || arg.type !== 'ObjectExpression') return
|
|
355
|
+
|
|
356
|
+
const templateProp = findProperty(arg, 'urlTemplate')
|
|
357
|
+
const paramsProp = findProperty(arg, 'urlParams')
|
|
358
|
+
if (!templateProp || !paramsProp) return
|
|
359
|
+
if (paramsProp.value.type !== 'ObjectExpression') return
|
|
360
|
+
|
|
361
|
+
const resolved = resolveToString(templateProp.value)
|
|
362
|
+
if (resolved === null) return
|
|
363
|
+
|
|
364
|
+
const placeholders = new Set()
|
|
365
|
+
let match
|
|
366
|
+
PLACEHOLDER_RE.lastIndex = 0
|
|
367
|
+
while ((match = PLACEHOLDER_RE.exec(resolved)) !== null) {
|
|
368
|
+
placeholders.add(match[1])
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const paramKeys = collectStaticKeys(paramsProp.value)
|
|
372
|
+
if (paramKeys === null) return
|
|
373
|
+
|
|
374
|
+
const paramKeySet = new Set(paramKeys)
|
|
375
|
+
|
|
376
|
+
for (const placeholder of placeholders) {
|
|
377
|
+
if (!paramKeySet.has(placeholder)) {
|
|
378
|
+
context.report({
|
|
379
|
+
node: paramsProp,
|
|
380
|
+
message:
|
|
381
|
+
`urlParams is missing key '${placeholder}' required by urlTemplate ` +
|
|
382
|
+
`'${resolved}'.`,
|
|
383
|
+
})
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
for (const key of paramKeys) {
|
|
388
|
+
if (!placeholders.has(key)) {
|
|
389
|
+
context.report({
|
|
390
|
+
node: paramsProp,
|
|
391
|
+
message:
|
|
392
|
+
`urlParams key '${key}' has no matching ':${key}' placeholder in urlTemplate ` +
|
|
393
|
+
`'${resolved}'.`,
|
|
394
|
+
})
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
|
|
402
|
+
'no-fatal-error-axios-check': {
|
|
403
|
+
meta: {
|
|
404
|
+
type: 'problem',
|
|
405
|
+
docs: {
|
|
406
|
+
description:
|
|
407
|
+
'Disallow isAnzuFatalError + axios.isAxiosError(error.cause) pattern.' +
|
|
408
|
+
' Labs API throws AnzuApiAxiosError instead.',
|
|
409
|
+
},
|
|
410
|
+
schema: [],
|
|
411
|
+
},
|
|
412
|
+
create(context) {
|
|
413
|
+
return {
|
|
414
|
+
LogicalExpression(node) {
|
|
415
|
+
if (node.operator !== '&&') return
|
|
416
|
+
if (node.parent.type === 'LogicalExpression' && node.parent.operator === '&&') return
|
|
417
|
+
|
|
418
|
+
const parts = []
|
|
419
|
+
let current = node
|
|
420
|
+
while (current.type === 'LogicalExpression' && current.operator === '&&') {
|
|
421
|
+
parts.unshift(current.right)
|
|
422
|
+
current = current.left
|
|
423
|
+
}
|
|
424
|
+
parts.unshift(current)
|
|
425
|
+
|
|
426
|
+
const hasFatalCheck = parts.some(
|
|
427
|
+
(part) => part.type === 'CallExpression' && part.callee.name === 'isAnzuFatalError',
|
|
428
|
+
)
|
|
429
|
+
const hasInstanceofErrorCheck = parts.some(
|
|
430
|
+
(part) =>
|
|
431
|
+
part.type === 'BinaryExpression' &&
|
|
432
|
+
part.operator === 'instanceof' &&
|
|
433
|
+
part.right.type === 'Identifier' &&
|
|
434
|
+
part.right.name === 'Error',
|
|
435
|
+
)
|
|
436
|
+
const hasAxiosCheck = parts.some(
|
|
437
|
+
(part) =>
|
|
438
|
+
part.type === 'CallExpression' &&
|
|
439
|
+
part.callee.type === 'MemberExpression' &&
|
|
440
|
+
part.callee.object.name === 'axios' &&
|
|
441
|
+
part.callee.property.name === 'isAxiosError',
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
if (hasAxiosCheck && (hasFatalCheck || hasInstanceofErrorCheck)) {
|
|
445
|
+
context.report({
|
|
446
|
+
node,
|
|
447
|
+
message:
|
|
448
|
+
'Replace error type check && axios.isAxiosError(error.cause)' +
|
|
449
|
+
' with isAnzuApiAxiosError(error).' +
|
|
450
|
+
' Labs API throws AnzuApiAxiosError with typed AxiosError cause.',
|
|
451
|
+
})
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Creates an ESLint flat config entry for Anzu rules.
|
|
462
|
+
*
|
|
463
|
+
* @param {Object} [options]
|
|
464
|
+
* @param {boolean|'error'|'warn'|'off'} [options.noTsExtension='error'] - Severity for no-ts-extension rule.
|
|
465
|
+
* @param {boolean|'error'|'warn'|'off'} [options.noFatalErrorAxiosCheck='error']
|
|
466
|
+
* - Severity for no-fatal-error-axios-check rule.
|
|
467
|
+
* @param {boolean|'error'|'warn'|'off'|Object} [options.deprecatedImports='error'] - Severity or config object.
|
|
468
|
+
* @param {string[]} [options.deprecatedImports.exclude] - Import names to remove from the default list.
|
|
469
|
+
* @param {string[]} [options.deprecatedImports.include] - Additional import names to add to the default list.
|
|
470
|
+
* @param {Array} [options.deprecatedImports.extraRules]
|
|
471
|
+
* - Additional rule entries ({ path, imports } or { module, imports }).
|
|
472
|
+
* @param {string[]} [options.deprecatedImports.skipFiles] - Files to skip (matched by suffix).
|
|
473
|
+
* @param {'error'|'warn'} [options.deprecatedImports.severity='error'] - Severity level.
|
|
474
|
+
* @param {'consumer'|'internal'} [options.deprecatedImports.mode='consumer'] - 'consumer' uses module-based defaults,
|
|
475
|
+
* 'internal' uses path-based defaults for common-admin development.
|
|
476
|
+
* @returns {Object} ESLint flat config entry
|
|
477
|
+
*/
|
|
478
|
+
export function recommended(options = {}) {
|
|
479
|
+
const {
|
|
480
|
+
noTsExtension = 'error',
|
|
481
|
+
noFatalErrorAxiosCheck = 'error',
|
|
482
|
+
urlParamsMatchTemplate = 'error',
|
|
483
|
+
deprecatedImports = 'error',
|
|
484
|
+
} = options
|
|
485
|
+
|
|
486
|
+
const rules = {}
|
|
487
|
+
|
|
488
|
+
// no-ts-extension
|
|
489
|
+
const tsExtSeverity = normalizeSeverity(noTsExtension)
|
|
490
|
+
if (tsExtSeverity) {
|
|
491
|
+
rules['anzu/no-ts-extension'] = tsExtSeverity
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// no-fatal-error-axios-check
|
|
495
|
+
const fatalSeverity = normalizeSeverity(noFatalErrorAxiosCheck)
|
|
496
|
+
if (fatalSeverity) {
|
|
497
|
+
rules['anzu/no-fatal-error-axios-check'] = fatalSeverity
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// url-params-match-template
|
|
501
|
+
const urlParamsSeverity = normalizeSeverity(urlParamsMatchTemplate)
|
|
502
|
+
if (urlParamsSeverity) {
|
|
503
|
+
rules['anzu/url-params-match-template'] = urlParamsSeverity
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// no-deprecated-imports
|
|
507
|
+
if (deprecatedImports !== false && deprecatedImports !== 'off') {
|
|
508
|
+
let severity = 'error'
|
|
509
|
+
const ruleEntries = []
|
|
510
|
+
let skipFiles = []
|
|
511
|
+
|
|
512
|
+
if (typeof deprecatedImports === 'object') {
|
|
513
|
+
severity = deprecatedImports.severity || 'error'
|
|
514
|
+
const mode = deprecatedImports.mode || 'consumer'
|
|
515
|
+
|
|
516
|
+
if (mode === 'internal') {
|
|
517
|
+
// Internal mode: path-based rules for common-admin development
|
|
518
|
+
ruleEntries.push(...DEFAULT_INTERNAL_DEPRECATED_IMPORTS)
|
|
519
|
+
} else {
|
|
520
|
+
// Consumer mode: module-based rules for projects using common-admin
|
|
521
|
+
let importsList = [...DEFAULT_DEPRECATED_IMPORTS]
|
|
522
|
+
if (deprecatedImports.exclude) {
|
|
523
|
+
importsList = importsList.filter((name) => !deprecatedImports.exclude.includes(name))
|
|
524
|
+
}
|
|
525
|
+
if (deprecatedImports.include) {
|
|
526
|
+
importsList.push(...deprecatedImports.include)
|
|
527
|
+
}
|
|
528
|
+
ruleEntries.push({
|
|
529
|
+
module: '@anzusystems/common-admin',
|
|
530
|
+
imports: importsList,
|
|
531
|
+
})
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
if (deprecatedImports.extraRules) {
|
|
535
|
+
ruleEntries.push(...deprecatedImports.extraRules)
|
|
536
|
+
}
|
|
537
|
+
if (deprecatedImports.skipFiles) {
|
|
538
|
+
skipFiles = deprecatedImports.skipFiles
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
541
|
+
if (deprecatedImports === 'warn') {
|
|
542
|
+
severity = 'warn'
|
|
543
|
+
}
|
|
544
|
+
// Default consumer mode
|
|
545
|
+
ruleEntries.push({
|
|
546
|
+
module: '@anzusystems/common-admin',
|
|
547
|
+
imports: [...DEFAULT_DEPRECATED_IMPORTS],
|
|
548
|
+
})
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const ruleConfig = { rules: ruleEntries }
|
|
552
|
+
if (skipFiles.length > 0) {
|
|
553
|
+
ruleConfig.skipFiles = skipFiles
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
rules['anzu/no-deprecated-imports'] = [severity, ruleConfig]
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return {
|
|
560
|
+
plugins: {
|
|
561
|
+
anzu: anzuPlugin,
|
|
562
|
+
},
|
|
563
|
+
rules,
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function normalizeSeverity(value) {
|
|
568
|
+
if (value === false || value === 'off') return null
|
|
569
|
+
if (value === true || value === 'error') return 'error'
|
|
570
|
+
if (value === 'warn') return 'warn'
|
|
571
|
+
return 'error'
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export { anzuPlugin, DEFAULT_DEPRECATED_IMPORTS, DEFAULT_INTERNAL_DEPRECATED_IMPORTS }
|