chore(lint): remove stale migration guard rules
- Drop custom rules that only protected deleted legacy app/test paths - Keep permanent package boundary, alias, naming, and type-safety rules - Reuse filename guard helper for the remaining file-layout rules
This commit is contained in:
parent
dffe1f5646
commit
554e9d5232
207
lint/plugin.js
207
lint/plugin.js
|
|
@ -8,6 +8,25 @@ function importSource(node) {
|
|||
return typeof node.source?.value === 'string' ? node.source.value : null
|
||||
}
|
||||
|
||||
function createProgramFilenameRule({ description, check }) {
|
||||
return {
|
||||
meta: {
|
||||
docs: { description }
|
||||
},
|
||||
create(context) {
|
||||
const file = normalizedFilename(context)
|
||||
const message = check(file)
|
||||
if (!message) return {}
|
||||
|
||||
return {
|
||||
Program(node) {
|
||||
context.report({ node, message })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createImportSourceRule({
|
||||
description,
|
||||
applies = () => true,
|
||||
|
|
@ -306,24 +325,6 @@ const noTypeofWindowCheck = {
|
|||
}
|
||||
}
|
||||
|
||||
const legacyAppImportPrefixes = [
|
||||
'@/ai/',
|
||||
'@/automation/',
|
||||
'@/stores/',
|
||||
'@/composables/use-canvas',
|
||||
'@/composables/use-canvas-input',
|
||||
'@/composables/use-collab',
|
||||
'@/composables/use-keyboard'
|
||||
]
|
||||
|
||||
const noLegacyAppImports = createImportSourceRule({
|
||||
description:
|
||||
'Disallow imports from removed app/store compatibility shims — import canonical src/app modules instead',
|
||||
check: (source) =>
|
||||
legacyAppImportPrefixes.some((prefix) => source === prefix || source.startsWith(prefix)) &&
|
||||
`Import from the canonical src/app module instead of legacy shim '${source}'.`
|
||||
})
|
||||
|
||||
const noVueSelfPackageImports = createImportSourceRule({
|
||||
description: 'Disallow @open-pencil/vue self-imports inside the Vue SDK — use #vue/* aliases',
|
||||
applies: (file) => file.includes('/packages/vue/src/'),
|
||||
|
|
@ -342,36 +343,6 @@ const noCrossPackageSourceImports = createImportSourceRule({
|
|||
`Use workspace package exports or package-local aliases instead of cross-package source import '${source}'.`
|
||||
})
|
||||
|
||||
const noStaleViteAppPaths = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: 'Disallow stale Vite config paths to removed top-level app folders'
|
||||
}
|
||||
},
|
||||
create(context) {
|
||||
const file = normalizedFilename(context)
|
||||
if (!file.endsWith('/vite.config.ts')) return {}
|
||||
|
||||
function reportIfStale(node, value) {
|
||||
if (typeof value !== 'string') return
|
||||
if (!value.includes('src/automation') && !value.includes('src/shims')) return
|
||||
context.report({
|
||||
node,
|
||||
message: 'Use current src/app/* paths instead of removed src/automation or src/shims paths.'
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
Literal(node) {
|
||||
reportIfStale(node, node.value)
|
||||
},
|
||||
TemplateElement(node) {
|
||||
reportIfStale(node, node.value?.raw)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createParentRelativeImportRule({ description, applies, message, minDepth = 1 }) {
|
||||
return {
|
||||
meta: {
|
||||
|
|
@ -437,27 +408,6 @@ const noCliParentRelativeImports = createParentRelativeImportRule({
|
|||
message: 'Use the #cli/* package-local alias instead of parent-relative CLI imports.'
|
||||
})
|
||||
|
||||
const noRootDemoModule = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: 'Disallow root src/demo.ts — keep demo builders under src/app/demo'
|
||||
}
|
||||
},
|
||||
create(context) {
|
||||
const file = normalizedFilename(context)
|
||||
if (!file.endsWith('/src/demo.ts')) return {}
|
||||
|
||||
return {
|
||||
Program(node) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'Move demo document builders under src/app/demo instead of root src/demo.ts.'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createExactCoreBarrelImportRule({ description, applies, message }) {
|
||||
return createImportSourceRule({
|
||||
description,
|
||||
|
|
@ -517,13 +467,6 @@ const noInlinePromptConstants = {
|
|||
}
|
||||
}
|
||||
|
||||
const noLegacyAppSupportImports = createImportSourceRule({
|
||||
description: 'Disallow imports from legacy top-level app support folders',
|
||||
check: (source) =>
|
||||
/^@\/(?:utils|engine)\//.test(source) &&
|
||||
'Move app support imports to cohesive src/app modules instead of using legacy @/utils/* or @/engine/* paths.'
|
||||
})
|
||||
|
||||
const noAppVueCoreBarrelImports = createExactCoreBarrelImportRule({
|
||||
description:
|
||||
'Disallow app and Vue SDK imports from @open-pencil/core root barrel — use domain subpaths',
|
||||
|
|
@ -582,59 +525,6 @@ const noDirectStorageAccess = {
|
|||
}
|
||||
}
|
||||
|
||||
const noLegacyShimFiles = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: 'Disallow recreating removed compatibility shim files'
|
||||
}
|
||||
},
|
||||
create(context) {
|
||||
const file = normalizedFilename(context)
|
||||
const blocked = [
|
||||
'/src/stores/editor.ts',
|
||||
'/src/stores/tabs.ts',
|
||||
'/src/composables/use-canvas.ts',
|
||||
'/src/composables/use-canvas-input.ts',
|
||||
'/src/composables/use-collab.ts',
|
||||
'/src/composables/use-keyboard.ts'
|
||||
]
|
||||
const blockedDirs = ['/src/ai/', '/src/automation/']
|
||||
const isBlocked =
|
||||
blocked.some((suffix) => file.endsWith(suffix)) ||
|
||||
blockedDirs.some((segment) => file.includes(segment))
|
||||
|
||||
if (!isBlocked) return {}
|
||||
|
||||
return {
|
||||
Program(node) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'Do not recreate removed compatibility shims; use the canonical src/app module.'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const noLegacyTestAppImports = createImportSourceRule({
|
||||
description: 'Disallow tests importing removed top-level app modules',
|
||||
applies: (file) => file.includes('/tests/'),
|
||||
includeExports: true,
|
||||
check: (source) =>
|
||||
/^(?:\.\.\/)+src\/(?:ai|automation|composables|stores|utils|engine)\//.test(source) &&
|
||||
'Use the current src/app/* module path instead of a removed top-level app module.'
|
||||
})
|
||||
|
||||
const noTestCoreSourceImports = createImportSourceRule({
|
||||
description: 'Disallow tests importing non-vendored core internals by relative source path',
|
||||
applies: (file) => file.includes('/tests/'),
|
||||
includeExports: true,
|
||||
includeDynamic: true,
|
||||
check: (source) =>
|
||||
/^(?:\.\.\/)+packages\/core\/src\/(?!kiwi\/kiwi-schema)/.test(source) &&
|
||||
'Use #core/* instead of a relative packages/core/src import in tests.'
|
||||
})
|
||||
|
||||
const noBroadDoubleCast = {
|
||||
meta: {
|
||||
docs: {
|
||||
|
|
@ -1206,54 +1096,28 @@ const noFunctionAliasImports = {
|
|||
}
|
||||
}
|
||||
|
||||
const noTopLevelPrefixedTestFiles = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: 'Disallow top-level test files that encode domains as filename prefixes'
|
||||
}
|
||||
},
|
||||
create(context) {
|
||||
const file = normalizedFilename(context)
|
||||
const noTopLevelPrefixedTestFiles = createProgramFilenameRule({
|
||||
description: 'Disallow top-level test files that encode domains as filename prefixes',
|
||||
check(file) {
|
||||
const match = file.match(/\/tests\/(engine|e2e)\/([^/]+-[^/]+\.(?:test|spec)\.ts)$/)
|
||||
if (!match) return {}
|
||||
|
||||
return {
|
||||
Program(node) {
|
||||
context.report({
|
||||
node,
|
||||
message: `Move '${match[2]}' under a domain folder instead of encoding the domain as a filename prefix.`
|
||||
if (!match) return false
|
||||
return `Move '${match[2]}' under a domain folder instead of encoding the domain as a filename prefix.`
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const noFlatKiwiModules = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: 'Disallow flat top-level Kiwi modules — group code under Kiwi subdomains'
|
||||
}
|
||||
},
|
||||
create(context) {
|
||||
const file = normalizedFilename(context)
|
||||
const noFlatKiwiModules = createProgramFilenameRule({
|
||||
description: 'Disallow flat top-level Kiwi modules — group code under Kiwi subdomains',
|
||||
check(file) {
|
||||
const marker = '/packages/core/src/kiwi/'
|
||||
const start = file.indexOf(marker)
|
||||
if (start === -1) return {}
|
||||
if (start === -1) return false
|
||||
|
||||
const relativePath = file.slice(start + marker.length)
|
||||
if (relativePath.includes('/') || relativePath === 'index.ts') return {}
|
||||
if (relativePath.includes('/') || relativePath === 'index.ts') return false
|
||||
|
||||
return {
|
||||
Program(node) {
|
||||
context.report({
|
||||
node,
|
||||
message:
|
||||
'Move Kiwi modules under binary/, fig/, node-change/, instance-overrides/, or kiwi-schema/ instead of adding flat top-level files.'
|
||||
return 'Move Kiwi modules under binary/, fig/, node-change/, instance-overrides/, or kiwi-schema/ instead of adding flat top-level files.'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const plugin = {
|
||||
meta: { name: 'open-pencil' },
|
||||
|
|
@ -1265,29 +1129,22 @@ const plugin = {
|
|||
'no-raw-console-format': noRawConsoleFormat,
|
||||
'no-silent-catch': noSilentCatch,
|
||||
'no-typeof-window-check': noTypeofWindowCheck,
|
||||
'no-legacy-app-imports': noLegacyAppImports,
|
||||
'no-vue-self-package-imports': noVueSelfPackageImports,
|
||||
'no-cross-package-source-imports': noCrossPackageSourceImports,
|
||||
'no-deep-parent-relative-imports': noDeepParentRelativeImports,
|
||||
'no-core-parent-relative-imports': noCoreParentRelativeImports,
|
||||
'no-mcp-parent-relative-imports': noMcpParentRelativeImports,
|
||||
'no-vue-parent-relative-imports': noVueParentRelativeImports,
|
||||
'no-stale-vite-app-paths': noStaleViteAppPaths,
|
||||
'no-cli-parent-relative-imports': noCliParentRelativeImports,
|
||||
'no-root-demo-module': noRootDemoModule,
|
||||
'no-mcp-core-barrel-imports': noMcpCoreBarrelImports,
|
||||
'no-cli-core-barrel-imports': noCliCoreBarrelImports,
|
||||
'no-script-core-barrel-imports': noScriptCoreBarrelImports,
|
||||
'no-core-self-package-imports': noCoreSelfPackageImports,
|
||||
'no-inline-prompt-constants': noInlinePromptConstants,
|
||||
'no-legacy-app-support-imports': noLegacyAppSupportImports,
|
||||
'no-app-vue-core-barrel-imports': noAppVueCoreBarrelImports,
|
||||
'no-app-imports-in-packages': noAppImportsInPackages,
|
||||
'no-core-framework-imports': noCoreFrameworkImports,
|
||||
'no-direct-storage-access': noDirectStorageAccess,
|
||||
'no-legacy-shim-files': noLegacyShimFiles,
|
||||
'no-legacy-test-app-imports': noLegacyTestAppImports,
|
||||
'no-test-core-source-imports': noTestCoreSourceImports,
|
||||
'no-broad-double-cast': noBroadDoubleCast,
|
||||
'no-unknown-record-double-cast': noUnknownRecordDoubleCast,
|
||||
'no-ts-suppression-comments': noTsSuppressionComments,
|
||||
|
|
|
|||
|
|
@ -113,13 +113,11 @@
|
|||
"open-pencil/no-raw-console-format": "off",
|
||||
"open-pencil/no-silent-catch": "error",
|
||||
"open-pencil/no-typeof-window-check": "error",
|
||||
"open-pencil/no-legacy-app-imports": "error",
|
||||
"open-pencil/no-vue-self-package-imports": "error",
|
||||
"open-pencil/no-cross-package-source-imports": "error",
|
||||
"open-pencil/no-app-imports-in-packages": "error",
|
||||
"open-pencil/no-core-framework-imports": "error",
|
||||
"open-pencil/no-direct-storage-access": "error",
|
||||
"open-pencil/no-legacy-shim-files": "error",
|
||||
"open-pencil/no-deep-parent-relative-imports": "error",
|
||||
"open-pencil/no-broad-double-cast": "error",
|
||||
"open-pencil/no-unknown-record-double-cast": "error",
|
||||
|
|
@ -137,18 +135,13 @@
|
|||
"open-pencil/no-core-parent-relative-imports": "error",
|
||||
"open-pencil/no-mcp-parent-relative-imports": "error",
|
||||
"open-pencil/no-vue-parent-relative-imports": "error",
|
||||
"open-pencil/no-stale-vite-app-paths": "error",
|
||||
"open-pencil/no-cli-parent-relative-imports": "error",
|
||||
"open-pencil/no-root-demo-module": "error",
|
||||
"open-pencil/no-mcp-core-barrel-imports": "error",
|
||||
"open-pencil/no-cli-core-barrel-imports": "error",
|
||||
"open-pencil/no-script-core-barrel-imports": "error",
|
||||
"open-pencil/no-core-self-package-imports": "error",
|
||||
"open-pencil/no-inline-prompt-constants": "error",
|
||||
"open-pencil/no-legacy-app-support-imports": "error",
|
||||
"open-pencil/no-app-vue-core-barrel-imports": "error",
|
||||
"open-pencil/no-legacy-test-app-imports": "error",
|
||||
"open-pencil/no-test-core-source-imports": "error",
|
||||
"open-pencil/no-direct-graph-emitter-subscriptions": "error",
|
||||
"open-pencil/no-on-unmounted-in-composition-roots": "error",
|
||||
"open-pencil/no-composable-state-wrappers": "error",
|
||||
|
|
|
|||
Loading…
Reference in a new issue