@anzusystems/common-admin 1.47.0-beta.dev-1771894837 → 1.47.0-beta.dev-1771894841

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.
@@ -18839,8 +18839,8 @@ export declare const ANotFoundView: DefineComponent<__VLS_Props_105, {}, {}, {},
18839
18839
  * Custom error class for Axios-related errors
18840
18840
  */
18841
18841
  export declare class AnzuApiAxiosError extends Error {
18842
- cause: AxiosError;
18843
- constructor(cause: AxiosError);
18842
+ cause: AxiosError<any, any>;
18843
+ constructor(cause: AxiosError<any, any>);
18844
18844
  }
18845
18845
 
18846
18846
  export declare class AnzuApiDependencyExistsError extends Error {
package/package.json CHANGED
@@ -2,7 +2,8 @@
2
2
  "name": "@anzusystems/common-admin",
3
3
  "packageManager": "yarn@4.13.0",
4
4
  "files": [
5
- "dist"
5
+ "dist",
6
+ "src/eslint"
6
7
  ],
7
8
  "module": "./dist/common-admin.es.js",
8
9
  "types": "./dist/common-admin.d.ts",
@@ -19,7 +20,7 @@
19
20
  "./eslint": "./src/eslint/plugin.mjs",
20
21
  "./*": "./*"
21
22
  },
22
- "version": "1.47.0-beta.dev-1771894837",
23
+ "version": "1.47.0-beta.dev-1771894841",
23
24
  "license": "Apache-2.0",
24
25
  "repository": {
25
26
  "type": "git",
@@ -0,0 +1,413 @@
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
+ ) return
224
+
225
+ const source = node.source.value
226
+ if (typeof source !== 'string') return
227
+
228
+ for (const rule of deprecationRules) {
229
+ const matchPath = rule.path || rule.module
230
+ if (!matchPath || source !== matchPath) continue
231
+
232
+ const deprecatedImports = node.specifiers
233
+ .filter((spec) => spec.type === 'ImportSpecifier')
234
+ .filter((spec) => rule.imports.includes(spec.imported.name))
235
+
236
+ for (const importSpec of deprecatedImports) {
237
+ context.report({
238
+ node: importSpec,
239
+ message: `'${importSpec.imported.name}' from '${matchPath}' is deprecated`,
240
+ })
241
+ }
242
+ }
243
+ },
244
+ }
245
+ },
246
+ },
247
+
248
+ 'no-fatal-error-axios-check': {
249
+ meta: {
250
+ type: 'problem',
251
+ docs: {
252
+ description:
253
+ 'Disallow isAnzuFatalError + axios.isAxiosError(error.cause) pattern.' +
254
+ ' Labs API throws AnzuApiAxiosError instead.',
255
+ },
256
+ schema: [],
257
+ },
258
+ create(context) {
259
+ return {
260
+ LogicalExpression(node) {
261
+ if (node.operator !== '&&') return
262
+ if (node.parent.type === 'LogicalExpression' && node.parent.operator === '&&') return
263
+
264
+ const parts = []
265
+ let current = node
266
+ while (current.type === 'LogicalExpression' && current.operator === '&&') {
267
+ parts.unshift(current.right)
268
+ current = current.left
269
+ }
270
+ parts.unshift(current)
271
+
272
+ const hasFatalCheck = parts.some(
273
+ (part) => part.type === 'CallExpression' && part.callee.name === 'isAnzuFatalError'
274
+ )
275
+ const hasInstanceofErrorCheck = parts.some(
276
+ (part) =>
277
+ part.type === 'BinaryExpression' &&
278
+ part.operator === 'instanceof' &&
279
+ part.right.type === 'Identifier' &&
280
+ part.right.name === 'Error'
281
+ )
282
+ const hasAxiosCheck = parts.some(
283
+ (part) =>
284
+ part.type === 'CallExpression' &&
285
+ part.callee.type === 'MemberExpression' &&
286
+ part.callee.object.name === 'axios' &&
287
+ part.callee.property.name === 'isAxiosError'
288
+ )
289
+
290
+ if (hasAxiosCheck && (hasFatalCheck || hasInstanceofErrorCheck)) {
291
+ context.report({
292
+ node,
293
+ message:
294
+ 'Replace error type check && axios.isAxiosError(error.cause)' +
295
+ ' with isAnzuApiAxiosError(error).' +
296
+ ' Labs API throws AnzuApiAxiosError with typed AxiosError cause.',
297
+ })
298
+ }
299
+ },
300
+ }
301
+ },
302
+ },
303
+ },
304
+ }
305
+
306
+ /**
307
+ * Creates an ESLint flat config entry for Anzu rules.
308
+ *
309
+ * @param {Object} [options]
310
+ * @param {boolean|'error'|'warn'|'off'} [options.noTsExtension='error'] - Severity for no-ts-extension rule.
311
+ * @param {boolean|'error'|'warn'|'off'} [options.noFatalErrorAxiosCheck='error']
312
+ * - Severity for no-fatal-error-axios-check rule.
313
+ * @param {boolean|'error'|'warn'|'off'|Object} [options.deprecatedImports='error'] - Severity or config object.
314
+ * @param {string[]} [options.deprecatedImports.exclude] - Import names to remove from the default list.
315
+ * @param {string[]} [options.deprecatedImports.include] - Additional import names to add to the default list.
316
+ * @param {Array} [options.deprecatedImports.extraRules]
317
+ * - Additional rule entries ({ path, imports } or { module, imports }).
318
+ * @param {string[]} [options.deprecatedImports.skipFiles] - Files to skip (matched by suffix).
319
+ * @param {'error'|'warn'} [options.deprecatedImports.severity='error'] - Severity level.
320
+ * @param {'consumer'|'internal'} [options.deprecatedImports.mode='consumer'] - 'consumer' uses module-based defaults,
321
+ * 'internal' uses path-based defaults for common-admin development.
322
+ * @returns {Object} ESLint flat config entry
323
+ */
324
+ export function recommended(options = {}) {
325
+ const {
326
+ noTsExtension = 'error',
327
+ noFatalErrorAxiosCheck = 'error',
328
+ deprecatedImports = 'error',
329
+ } = options
330
+
331
+ const rules = {}
332
+
333
+ // no-ts-extension
334
+ const tsExtSeverity = normalizeSeverity(noTsExtension)
335
+ if (tsExtSeverity) {
336
+ rules['anzu/no-ts-extension'] = tsExtSeverity
337
+ }
338
+
339
+ // no-fatal-error-axios-check
340
+ const fatalSeverity = normalizeSeverity(noFatalErrorAxiosCheck)
341
+ if (fatalSeverity) {
342
+ rules['anzu/no-fatal-error-axios-check'] = fatalSeverity
343
+ }
344
+
345
+ // no-deprecated-imports
346
+ if (deprecatedImports !== false && deprecatedImports !== 'off') {
347
+ let severity = 'error'
348
+ const ruleEntries = []
349
+ let skipFiles = []
350
+
351
+ if (typeof deprecatedImports === 'object') {
352
+ severity = deprecatedImports.severity || 'error'
353
+ const mode = deprecatedImports.mode || 'consumer'
354
+
355
+ if (mode === 'internal') {
356
+ // Internal mode: path-based rules for common-admin development
357
+ ruleEntries.push(...DEFAULT_INTERNAL_DEPRECATED_IMPORTS)
358
+ } else {
359
+ // Consumer mode: module-based rules for projects using common-admin
360
+ let importsList = [...DEFAULT_DEPRECATED_IMPORTS]
361
+ if (deprecatedImports.exclude) {
362
+ importsList = importsList.filter((name) => !deprecatedImports.exclude.includes(name))
363
+ }
364
+ if (deprecatedImports.include) {
365
+ importsList.push(...deprecatedImports.include)
366
+ }
367
+ ruleEntries.push({
368
+ module: '@anzusystems/common-admin',
369
+ imports: importsList,
370
+ })
371
+ }
372
+
373
+ if (deprecatedImports.extraRules) {
374
+ ruleEntries.push(...deprecatedImports.extraRules)
375
+ }
376
+ if (deprecatedImports.skipFiles) {
377
+ skipFiles = deprecatedImports.skipFiles
378
+ }
379
+ } else {
380
+ if (deprecatedImports === 'warn') {
381
+ severity = 'warn'
382
+ }
383
+ // Default consumer mode
384
+ ruleEntries.push({
385
+ module: '@anzusystems/common-admin',
386
+ imports: [...DEFAULT_DEPRECATED_IMPORTS],
387
+ })
388
+ }
389
+
390
+ const ruleConfig = { rules: ruleEntries }
391
+ if (skipFiles.length > 0) {
392
+ ruleConfig.skipFiles = skipFiles
393
+ }
394
+
395
+ rules['anzu/no-deprecated-imports'] = [severity, ruleConfig]
396
+ }
397
+
398
+ return {
399
+ plugins: {
400
+ anzu: anzuPlugin,
401
+ },
402
+ rules,
403
+ }
404
+ }
405
+
406
+ function normalizeSeverity(value) {
407
+ if (value === false || value === 'off') return null
408
+ if (value === true || value === 'error') return 'error'
409
+ if (value === 'warn') return 'warn'
410
+ return 'error'
411
+ }
412
+
413
+ export { anzuPlugin, DEFAULT_DEPRECATED_IMPORTS, DEFAULT_INTERNAL_DEPRECATED_IMPORTS }