@opetope/lint 0.1.1 → 0.4.0
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/CHANGELOG.md +12 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{defineFeaturePropertyOrder as p}from"./rules/define-feature-property-order.js";import{idNaming as a}from"./rules/id-naming.js";import{layerPlacement as l}from"./rules/layer-placement.js";import{noSnapshotReadInRender as d}from"./rules/no-snapshot-read-in-render.js";import{noSubscribeOutsideModels as m}from"./rules/no-subscribe-outside-models.js";import{preferModelSelection as c}from"./rules/prefer-model-selection.js";import{requireDeclaredModels as u}from"./rules/require-declared-models.js";import{requireLiteralId as f}from"./rules/require-literal-id.js";import{whenPredicate as g}from"./rules/when-predicate.js";const b=["integration","models","ui"],n=["**/*.ts","**/*.tsx"],h=["**/__tests__/**","**/*.spec.ts","**/*.spec.tsx"],y={meta:{name:"@opetope/lint",version:"0.
|
|
1
|
+
import{defineFeaturePropertyOrder as p}from"./rules/define-feature-property-order.js";import{idNaming as a}from"./rules/id-naming.js";import{layerPlacement as l}from"./rules/layer-placement.js";import{noSnapshotReadInRender as d}from"./rules/no-snapshot-read-in-render.js";import{noSubscribeOutsideModels as m}from"./rules/no-subscribe-outside-models.js";import{preferModelSelection as c}from"./rules/prefer-model-selection.js";import{requireDeclaredModels as u}from"./rules/require-declared-models.js";import{requireLiteralId as f}from"./rules/require-literal-id.js";import{whenPredicate as g}from"./rules/when-predicate.js";const b=["integration","models","ui"],n=["**/*.ts","**/*.tsx"],h=["**/__tests__/**","**/*.spec.ts","**/*.spec.tsx"],y={meta:{name:"@opetope/lint",version:"0.4.0"},rules:{"define-feature-property-order":p,"id-naming":a,"layer-placement":l,"no-snapshot-read-in-render":d,"no-subscribe-outside-models":m,"prefer-model-selection":c,"require-declared-models":u,"require-literal-id":f,"when-predicate":g}},o=y,I={name:"opetope/recommended",plugins:{opetope:o},rules:{"opetope/define-feature-property-order":"error","opetope/id-naming":"error","opetope/layer-placement":"off","opetope/no-snapshot-read-in-render":"error","opetope/no-subscribe-outside-models":"off","opetope/prefer-model-selection":"off","opetope/require-declared-models":"error","opetope/require-literal-id":"error","opetope/when-predicate":"error"}},P=e=>b.flatMap(r=>{const t=e[r]??[];return t.length===0?[]:[{files:[...t],name:`opetope/layers-${r}`,plugins:{opetope:o},rules:{"opetope/layer-placement":["error",{layer:r}]}}]}),S=({models:e=[],tests:r=h})=>e.length===0?[]:[{files:n,name:"opetope/layers-subscriptions",plugins:{opetope:o},rules:{"opetope/no-subscribe-outside-models":"error"}},{files:[...e,...r],name:"opetope/layers-subscriptions-allowed",rules:{"opetope/no-subscribe-outside-models":"off"}}],_=e=>[...P(e),...S(e)],s={group:["@opetope/*/internal"],message:"The internal entries carry the runtime and its host integration. Feature UI, models and data layers import the safe entries."},E=({allow:e=[],files:r=n}={})=>[{files:[...r],...e.length===0?{}:{ignores:[...e]},name:"opetope/internal-imports",rules:{"no-restricted-imports":["error",{patterns:[s]}]}}],R=Object.assign(o,{configs:{internalImports:E,layers:_,recommended:I},internalImportPattern:s}),i=R;export{i as default,i as opetopeLint};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import type { ESLint, Linter } from 'eslint';\n\nimport { defineFeaturePropertyOrder } from './rules/define-feature-property-order';\nimport { idNaming } from './rules/id-naming';\nimport { layerPlacement } from './rules/layer-placement';\nimport { noSnapshotReadInRender } from './rules/no-snapshot-read-in-render';\nimport { noSubscribeOutsideModels } from './rules/no-subscribe-outside-models';\nimport { preferModelSelection } from './rules/prefer-model-selection';\nimport { requireDeclaredModels } from './rules/require-declared-models';\nimport { requireLiteralId } from './rules/require-literal-id';\nimport { whenPredicate } from './rules/when-predicate';\n\n/**\n * The layers a host names for itself, as globs of the files that hold each one, with the tests that are allowed\n * to reach past a layer. `tests` defaults to the usual two shapes of a test path.\n */\ntype LayerOptions = {\n readonly integration?: readonly string[];\n readonly models?: readonly string[];\n readonly tests?: readonly string[];\n readonly ui?: readonly string[];\n};\n\ntype InternalImportOptions = {\n readonly allow?: readonly string[];\n readonly files?: readonly string[];\n};\n\nconst LAYERS = ['integration', 'models', 'ui'] as const;\nconst SOURCE_FILES = ['**/*.ts', '**/*.tsx'];\nconst TEST_FILES = ['**/__tests__/**', '**/*.spec.ts', '**/*.spec.tsx'];\n\nconst plugin = {\n meta: { name: '@opetope/lint', version: '0.
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import type { ESLint, Linter } from 'eslint';\n\nimport { defineFeaturePropertyOrder } from './rules/define-feature-property-order';\nimport { idNaming } from './rules/id-naming';\nimport { layerPlacement } from './rules/layer-placement';\nimport { noSnapshotReadInRender } from './rules/no-snapshot-read-in-render';\nimport { noSubscribeOutsideModels } from './rules/no-subscribe-outside-models';\nimport { preferModelSelection } from './rules/prefer-model-selection';\nimport { requireDeclaredModels } from './rules/require-declared-models';\nimport { requireLiteralId } from './rules/require-literal-id';\nimport { whenPredicate } from './rules/when-predicate';\n\n/**\n * The layers a host names for itself, as globs of the files that hold each one, with the tests that are allowed\n * to reach past a layer. `tests` defaults to the usual two shapes of a test path.\n */\ntype LayerOptions = {\n readonly integration?: readonly string[];\n readonly models?: readonly string[];\n readonly tests?: readonly string[];\n readonly ui?: readonly string[];\n};\n\ntype InternalImportOptions = {\n readonly allow?: readonly string[];\n readonly files?: readonly string[];\n};\n\nconst LAYERS = ['integration', 'models', 'ui'] as const;\nconst SOURCE_FILES = ['**/*.ts', '**/*.tsx'];\nconst TEST_FILES = ['**/__tests__/**', '**/*.spec.ts', '**/*.spec.tsx'];\n\nconst plugin = {\n meta: { name: '@opetope/lint', version: '0.4.0' },\n rules: {\n 'define-feature-property-order': defineFeaturePropertyOrder,\n 'id-naming': idNaming,\n 'layer-placement': layerPlacement,\n 'no-snapshot-read-in-render': noSnapshotReadInRender,\n 'no-subscribe-outside-models': noSubscribeOutsideModels,\n 'prefer-model-selection': preferModelSelection,\n 'require-declared-models': requireDeclaredModels,\n 'require-literal-id': requireLiteralId,\n 'when-predicate': whenPredicate,\n },\n};\n\n/**\n * The laws every Opetope author writes against, with no assumption about where a host keeps its files. A rule that\n * needs such an assumption is off here and arrives through `layers`. The namespace is `opetope`, so a rule reads\n * `opetope/when-predicate` wherever a host names it.\n */\n// Rules use the parser's typed AST internally. The public bridge exposes the\n// supported ESLint rule API; package smoke tests execute it under both linters.\ntype NativeRule = NonNullable<ESLint.Plugin['rules']>[string];\ntype NativeRules = {\n [Name in keyof typeof plugin.rules]: Omit<(typeof plugin.rules)[Name], 'create'> & NativeRule;\n};\nconst nativePlugin = plugin as unknown as { meta: typeof plugin.meta; rules: NativeRules };\n\nconst recommended = {\n name: 'opetope/recommended',\n plugins: { opetope: nativePlugin },\n rules: {\n 'opetope/define-feature-property-order': 'error',\n 'opetope/id-naming': 'error',\n 'opetope/layer-placement': 'off',\n 'opetope/no-snapshot-read-in-render': 'error',\n 'opetope/no-subscribe-outside-models': 'off',\n 'opetope/prefer-model-selection': 'off',\n 'opetope/require-declared-models': 'error',\n 'opetope/require-literal-id': 'error',\n 'opetope/when-predicate': 'error',\n },\n} satisfies Linter.Config;\n\n/**\n * Placement is a convention of the project that names its layers, not a law of the framework: a layer without a\n * glob is a layer this host does not have, and it produces no configuration.\n */\nconst placement = (options: LayerOptions): readonly Linter.Config[] =>\n LAYERS.flatMap(layer => {\n const files = options[layer] ?? [];\n\n if (files.length === 0) return [];\n\n return [\n {\n files: [...files],\n name: `opetope/layers-${layer}`,\n plugins: { opetope: nativePlugin },\n rules: { 'opetope/layer-placement': ['error', { layer }] },\n } satisfies Linter.Config,\n ];\n });\n\n/**\n * A subscription is written where the state lives, so this pair arrives only with the model layer that owns it. The\n * restriction covers every source file and steps aside in that layer and in tests: a file no layer claims is\n * covered rather than forgotten.\n */\nconst subscriptions = ({ models = [], tests = TEST_FILES }: LayerOptions): readonly Linter.Config[] =>\n models.length === 0\n ? []\n : [\n {\n files: SOURCE_FILES,\n name: 'opetope/layers-subscriptions',\n plugins: { opetope: nativePlugin },\n rules: { 'opetope/no-subscribe-outside-models': 'error' },\n },\n {\n files: [...models, ...tests],\n name: 'opetope/layers-subscriptions-allowed',\n rules: { 'opetope/no-subscribe-outside-models': 'off' },\n },\n ];\n\nconst layers = (options: LayerOptions): readonly Linter.Config[] => [...placement(options), ...subscriptions(options)];\n\n/**\n * The one restriction this package expresses through a core rule rather than a rule of its own, so a project that\n * already configures `no-restricted-imports` adds this entry to its own list instead of losing it.\n */\nconst INTERNAL_IMPORT_PATTERN = {\n group: ['@opetope/*/internal'],\n message:\n 'The internal entries carry the runtime and its host integration. Feature UI, models and data layers import the safe entries.',\n};\n\n/**\n * The internal entries are for runtime implementation and host integration. `allow` names the files that do that\n * work; the restriction simply does not reach them, so whatever else a project restricts there stays in force.\n *\n * `no-restricted-imports` is a core rule with one value per file: in a flat config the last entry that names it\n * wins. A project that already configures it takes `internalImportPattern` into that entry instead of spreading\n * this config, which would replace the entry for every file it covers.\n */\nconst internalImports = ({\n allow = [],\n files = SOURCE_FILES,\n}: InternalImportOptions = {}): readonly Linter.Config[] => [\n {\n files: [...files],\n ...(allow.length === 0 ? {} : { ignores: [...allow] }),\n name: 'opetope/internal-imports',\n rules: { 'no-restricted-imports': ['error', { patterns: [INTERNAL_IMPORT_PATTERN] }] },\n },\n];\n\nconst configuredPlugin = Object.assign(nativePlugin, {\n configs: { internalImports, layers, recommended },\n internalImportPattern: INTERNAL_IMPORT_PATTERN,\n});\n\n// ESLint consumes the rule map. Config factories are additional plugin helpers;\n// expose both contracts without requiring casts at native flat-config call sites.\n// oxlint-disable-next-line typescript/no-unnecessary-type-assertion -- Required by native ESLint config typetests.\nconst opetopeLint = configuredPlugin as unknown as typeof configuredPlugin & Pick<ESLint.Plugin, 'configs'>;\n\n/*\n * Two shapes of one object. The default is what a tool reads when it loads a plugin by path — Oxlint's `jsPlugins`\n * takes `(await import(path)).default` — and what an ESLint flat config imports by convention; the named export is\n * for a config that prefers to say which binding it takes.\n */\n// oxlint-disable-next-line import/no-default-export\n// eslint-disable-next-line import-x/no-default-export\nexport default opetopeLint;\nexport { opetopeLint };\n"],"names":["LAYERS","SOURCE_FILES","TEST_FILES","plugin","defineFeaturePropertyOrder","idNaming","layerPlacement","noSnapshotReadInRender","noSubscribeOutsideModels","preferModelSelection","requireDeclaredModels","requireLiteralId","whenPredicate","nativePlugin","recommended","placement","options","layer","files","subscriptions","models","tests","layers","INTERNAL_IMPORT_PATTERN","internalImports","allow","configuredPlugin","opetopeLint"],"mappings":"knBA4BA,MAAMA,EAAS,CAAC,cAAe,SAAU,IAAI,EACvCC,EAAe,CAAC,UAAW,UAAU,EACrCC,EAAa,CAAC,kBAAmB,eAAgB,eAAe,EAEhEC,EAAS,CACb,KAAM,CAAE,KAAM,gBAAiB,QAAS,OAAO,EAC/C,MAAO,CACL,gCAAiCC,EACjC,YAAaC,EACb,kBAAmBC,EACnB,6BAA8BC,EAC9B,8BAA+BC,EAC/B,yBAA0BC,EAC1B,0BAA2BC,EAC3B,qBAAsBC,EACtB,iBAAkBC,CACnB,GAcGC,EAAeV,EAEfW,EAAc,CAClB,KAAM,sBACN,QAAS,CAAE,QAASD,CAAY,EAChC,MAAO,CACL,wCAAyC,QACzC,oBAAqB,QACrB,0BAA2B,MAC3B,qCAAsC,QACtC,sCAAuC,MACvC,iCAAkC,MAClC,kCAAmC,QACnC,6BAA8B,QAC9B,yBAA0B,OAC3B,GAOGE,EAAaC,GACjBhB,EAAO,QAAQiB,GAAQ,CACrB,MAAMC,EAAQF,EAAQC,CAAK,GAAK,CAAA,EAEhC,OAAIC,EAAM,SAAW,EAAU,CAAA,EAExB,CACL,CACE,MAAO,CAAC,GAAGA,CAAK,EAChB,KAAM,kBAAkBD,CAAK,GAC7B,QAAS,CAAE,QAASJ,CAAY,EAChC,MAAO,CAAE,0BAA2B,CAAC,QAAS,CAAE,MAAAI,CAAK,CAAE,CAAC,CACjC,EAE7B,CAAC,EAOGE,EAAgB,CAAC,CAAE,OAAAC,EAAS,CAAA,EAAI,MAAAC,EAAQnB,CAAU,IACtDkB,EAAO,SAAW,EACd,CAAA,EACA,CACE,CACE,MAAOnB,EACP,KAAM,+BACN,QAAS,CAAE,QAASY,CAAY,EAChC,MAAO,CAAE,sCAAuC,OAAO,CACxD,EACD,CACE,MAAO,CAAC,GAAGO,EAAQ,GAAGC,CAAK,EAC3B,KAAM,uCACN,MAAO,CAAE,sCAAuC,KAAK,CACtD,GAGHC,EAAUN,GAAoD,CAAC,GAAGD,EAAUC,CAAO,EAAG,GAAGG,EAAcH,CAAO,CAAC,EAM/GO,EAA0B,CAC9B,MAAO,CAAC,qBAAqB,EAC7B,QACE,gIAWEC,EAAkB,CAAC,CACvB,MAAAC,EAAQ,CAAA,EACR,MAAAP,EAAQjB,CAAY,EACK,KAAiC,CAC1D,CACE,MAAO,CAAC,GAAGiB,CAAK,EAChB,GAAIO,EAAM,SAAW,EAAI,CAAA,EAAK,CAAE,QAAS,CAAC,GAAGA,CAAK,GAClD,KAAM,2BACN,MAAO,CAAE,wBAAyB,CAAC,QAAS,CAAE,SAAU,CAACF,CAAuB,CAAC,CAAE,CAAC,CACrF,GAGGG,EAAmB,OAAO,OAAOb,EAAc,CACnD,QAAS,CAAE,gBAAAW,EAAiB,OAAAF,EAAQ,YAAAR,CAAW,EAC/C,sBAAuBS,CACxB,CAAA,EAKKI,EAAcD"}
|