@opetope/lint 0.12.0 → 0.12.2

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.
@@ -1,2 +1,2 @@
1
- import{AST_NODE_TYPES as i,TSESLint as l}from"@typescript-eslint/utils";import{propertyName as s}from"./ast.js";import{localValue as y,unwrap as g,isFunction as a,isFeatureSection as h,isApi as x,definitionOf as S}from"./model-bindings.js";const w=new Map([["event",1],["scope.each",2],["scope.switch",1],["scope.while",1]]),I=new Map([["attach",{argument:1,property:"open"}],["resource.live",{argument:0,property:"connect"}]]);function E(n){const[t]=n.params;if(t?.type===i.Identifier||t?.type===i.ObjectPattern)return t}function p(n,t){const e=E(t)?.typeAnnotation?.typeAnnotation;if(e?.type!==i.TSTypeReference)return!1;const{typeName:r}=e;return r.type===i.Identifier&&x(n,r,"@opetope/core","ModelContext",!0)}function c(n,t){const e=S(n,t);if(!(e?.type!==l.Scope.DefinitionType.Parameter||!a(e.node)))return{fn:e.node,name:e.name}}function P(n,t){const e=c(n,t);return e!==void 0&&e.name===e.fn.params[0]?e.fn:void 0}function b(n,t){const e=c(n,t),r=e?.name.parent;if(e===void 0||r?.type!==i.Property)return;const o=r.parent===e.fn.params[0]?s(r):void 0;return o===void 0?void 0:{fn:e.fn,method:o}}function C(n){const t=[];let e=n;for(;e.type===i.MemberExpression;){if(e.computed||e.property.type!==i.Identifier)return;t.unshift(e.property.name),e=e.object}return{root:e,steps:t}}function u(n,t){const e=C(t);if(e?.root.type!==i.Identifier)return;const r=e.steps.length===0?void 0:P(n,e.root);if(r!==void 0)return{fn:r,method:e.steps.join(".")};const o=b(n,e.root);return o===void 0?void 0:{fn:o.fn,method:[o.method,...e.steps].join(".")}}function m(n,t){const e=t.parent;if(e.type!==i.CallExpression||e.arguments[1]!==t)return;const r=u(n,e.callee);return r?.method==="model"?r.fn:void 0}function d(n,t){const e=new Set;let r=t;for(;r!==void 0&&!e.has(r);){if(e.add(r),h(n,r,"own",!0)||p(n,r))return!0;r=m(n,r)}return!1}function M(n,t){if(p(n,t))return!0;const e=m(n,t);return e!==void 0&&d(n,e)}function A(n,t,e){if(w.get(n)===t)return!0;const r=I.get(n);return r?.argument===t&&r.property===e}function O(n,t,e,r){const o=u(n,t.callee);return o!==void 0&&A(o.method,e,r)&&d(n,o.fn)}function T(n,t,e){return n.type!==i.ObjectExpression||t.type!==i.Property?e:s(t)}function j(n,t){let e=t,r;for(const o of n.getAncestors(t).reverse()){if(o.type===i.CallExpression){const f=o.arguments.indexOf(e);if(f!==-1&&O(n,o,f,r))return!0;r=void 0}else r=T(o,e,r);e=o}return!1}function v(n,t){const[e]=t.arguments;if(e===void 0||e.type===i.SpreadElement)return;const r=y(n,g(e));return a(r)?r:void 0}export{v as commandBody,d as isContextFunction,j as isDeclaredIngress,M as isModelContextFunction,u as methodPath};
1
+ import{AST_NODE_TYPES as i,TSESLint as l}from"@typescript-eslint/utils";import{propertyName as s}from"./ast.js";import{localValue as y,unwrap as g,isFunction as a,isFeatureSection as h,isApi as x,definitionOf as S}from"./model-bindings.js";const w=new Map([["event",2],["scope.each",2],["scope.switch",1],["scope.while",1]]),I=new Map([["attach",{argument:1,property:"open"}],["resource.live",{argument:0,property:"connect"}]]);function E(n){const[t]=n.params;if(t?.type===i.Identifier||t?.type===i.ObjectPattern)return t}function p(n,t){const e=E(t)?.typeAnnotation?.typeAnnotation;if(e?.type!==i.TSTypeReference)return!1;const{typeName:r}=e;return r.type===i.Identifier&&x(n,r,"@opetope/core","ModelContext",!0)}function c(n,t){const e=S(n,t);if(!(e?.type!==l.Scope.DefinitionType.Parameter||!a(e.node)))return{fn:e.node,name:e.name}}function P(n,t){const e=c(n,t);return e!==void 0&&e.name===e.fn.params[0]?e.fn:void 0}function b(n,t){const e=c(n,t),r=e?.name.parent;if(e===void 0||r?.type!==i.Property)return;const o=r.parent===e.fn.params[0]?s(r):void 0;return o===void 0?void 0:{fn:e.fn,method:o}}function C(n){const t=[];let e=n;for(;e.type===i.MemberExpression;){if(e.computed||e.property.type!==i.Identifier)return;t.unshift(e.property.name),e=e.object}return{root:e,steps:t}}function u(n,t){const e=C(t);if(e?.root.type!==i.Identifier)return;const r=e.steps.length===0?void 0:P(n,e.root);if(r!==void 0)return{fn:r,method:e.steps.join(".")};const o=b(n,e.root);return o===void 0?void 0:{fn:o.fn,method:[o.method,...e.steps].join(".")}}function m(n,t){const e=t.parent;if(e.type!==i.CallExpression||e.arguments[1]!==t)return;const r=u(n,e.callee);return r?.method==="model"?r.fn:void 0}function d(n,t){const e=new Set;let r=t;for(;r!==void 0&&!e.has(r);){if(e.add(r),h(n,r,"own",!0)||p(n,r))return!0;r=m(n,r)}return!1}function M(n,t){if(p(n,t))return!0;const e=m(n,t);return e!==void 0&&d(n,e)}function A(n,t,e){if(w.get(n)===t)return!0;const r=I.get(n);return r?.argument===t&&r.property===e}function O(n,t,e,r){const o=u(n,t.callee);return o!==void 0&&A(o.method,e,r)&&d(n,o.fn)}function T(n,t,e){return n.type!==i.ObjectExpression||t.type!==i.Property?e:s(t)}function j(n,t){let e=t,r;for(const o of n.getAncestors(t).reverse()){if(o.type===i.CallExpression){const f=o.arguments.indexOf(e);if(f!==-1&&O(n,o,f,r))return!0;r=void 0}else r=T(o,e,r);e=o}return!1}function v(n,t){const[e]=t.arguments;if(e===void 0||e.type===i.SpreadElement)return;const r=y(n,g(e));return a(r)?r:void 0}export{v as commandBody,d as isContextFunction,j as isDeclaredIngress,M as isModelContextFunction,u as methodPath};
2
2
  //# sourceMappingURL=declaration-ingress.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"declaration-ingress.js","sources":["../src/declaration-ingress.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils';\n\nimport { propertyName } from './ast';\nimport type { FunctionNode } from './model-bindings';\nimport { definitionOf, isApi, isFeatureSection, isFunction, localValue, unwrap } from './model-bindings';\n\n/**\n * The callbacks a declared node opens its work in and owns the release of: the disposer they return is run by the\n * node, in the drain of the generation that opened it. The argument index is part of the contract — `run`, `load`,\n * `filter` and `key` sit in the same calls and are not ingress.\n */\nconst positionalIngress = new Map([\n ['event', 1],\n // D378: the key of `each` stands between the source and the child, so the callback that opens is the third argument.\n ['scope.each', 2],\n ['scope.switch', 1],\n ['scope.while', 1],\n]);\n\n/**\n * The callbacks written as a record member. `attach`'s `close` is a release, not an opening; D349 puts the connection\n * of a live Resource under `connect` in the one options record, so that is where the ingress of a subscription is.\n */\nconst recordIngress = new Map([\n ['attach', { argument: 1, property: 'open' }],\n ['resource.live', { argument: 0, property: 'connect' }],\n]);\n\ntype Annotated = TSESTree.Identifier | TSESTree.ObjectPattern;\ntype NamedMethod = { readonly fn: FunctionNode; readonly method: string };\ntype ParameterOf = { readonly fn: FunctionNode; readonly name: TSESTree.BindingName };\n\nfunction annotatedParameter(fn: FunctionNode): Annotated | undefined {\n const [parameter] = fn.params;\n\n if (parameter?.type === AST_NODE_TYPES.Identifier || parameter?.type === AST_NODE_TYPES.ObjectPattern) {\n return parameter;\n }\n\n return undefined;\n}\n\n/** The factory of a model says so in the parameter it takes: the name `ModelContext` carries where it is exported. */\nfunction declaresModelContext(source: TSESLint.SourceCode, fn: FunctionNode): boolean {\n const annotation = annotatedParameter(fn)?.typeAnnotation?.typeAnnotation;\n\n if (annotation?.type !== AST_NODE_TYPES.TSTypeReference) return false;\n\n const { typeName } = annotation;\n\n return typeName.type === AST_NODE_TYPES.Identifier && isApi(source, typeName, '@opetope/core', 'ModelContext', true);\n}\n\n/** The function this name is a parameter of, and the pattern node that bound it there. */\nfunction parameterOf(source: TSESLint.SourceCode, node: TSESTree.Identifier): ParameterOf | undefined {\n const definition = definitionOf(source, node);\n\n if (definition?.type !== TSESLint.Scope.DefinitionType.Parameter || !isFunction(definition.node)) return undefined;\n\n return { fn: definition.node, name: definition.name };\n}\n\n/** `own` itself: the plain name a context parameter was given, whichever function that parameter belongs to. */\nfunction contextName(source: TSESLint.SourceCode, node: TSESTree.Identifier): FunctionNode | undefined {\n const parameter = parameterOf(source, node);\n\n return parameter !== undefined && parameter.name === parameter.fn.params[0] ? parameter.fn : undefined;\n}\n\n/** `({ resource }) => resource.live(…)`: the method under the key the destructuring took it from, alias included. */\nfunction destructuredMethod(source: TSESLint.SourceCode, node: TSESTree.Identifier): NamedMethod | undefined {\n const parameter = parameterOf(source, node);\n const property = parameter?.name.parent;\n\n if (parameter === undefined || property?.type !== AST_NODE_TYPES.Property) return undefined;\n\n const method = property.parent === parameter.fn.params[0] ? propertyName(property) : undefined;\n\n return method === undefined ? undefined : { fn: parameter.fn, method };\n}\n\n/** The dotted steps of a member chain and the name it starts from: `own.scope.while` is `own` and `scope.while`. */\nfunction memberSteps(callee: TSESTree.Node): { root: TSESTree.Node; steps: readonly string[] } | undefined {\n const steps: string[] = [];\n let current: TSESTree.Node = callee;\n\n while (current.type === AST_NODE_TYPES.MemberExpression) {\n if (current.computed || current.property.type !== AST_NODE_TYPES.Identifier) return undefined;\n\n steps.unshift(current.property.name);\n current = current.object;\n }\n\n return { root: current, steps };\n}\n\n/**\n * The method this callee names on the first parameter of some function, and that function. Whether the parameter\n * really is a declaring context is a separate question: answering it here would make the two questions circular.\n */\nfunction methodPath(source: TSESLint.SourceCode, callee: TSESTree.Node): NamedMethod | undefined {\n const chain = memberSteps(callee);\n\n if (chain?.root.type !== AST_NODE_TYPES.Identifier) return undefined;\n\n const named = chain.steps.length === 0 ? undefined : contextName(source, chain.root);\n\n if (named !== undefined) return { fn: named, method: chain.steps.join('.') };\n\n const destructured = destructuredMethod(source, chain.root);\n\n return destructured === undefined\n ? undefined\n : { fn: destructured.fn, method: [destructured.method, ...chain.steps].join('.') };\n}\n\n/** One step outward: the context whose `model(…)` call declares this factory, where that is how it was written. */\nfunction declaringContext(source: TSESLint.SourceCode, fn: FunctionNode): FunctionNode | undefined {\n const call = fn.parent;\n\n if (call.type !== AST_NODE_TYPES.CallExpression || call.arguments[1] !== fn) return undefined;\n\n const declaring = methodPath(source, call.callee);\n\n return declaring?.method === 'model' ? declaring.fn : undefined;\n}\n\n/**\n * The two functions that hand an author a declaring context: the `own` section written right where `defineFeature`\n * takes it, and the factory of a model — which is either annotated as one or written where a feature declares it,\n * as the second argument of `model(Declaration, factory)`. That second form is proved by walking outward one\n * `model(…)` at a time, and the set of functions already visited ends a chain that would come back to its start.\n */\nfunction isContextFunction(source: TSESLint.SourceCode, fn: FunctionNode): boolean {\n const seen = new Set<FunctionNode>();\n let current: FunctionNode | undefined = fn;\n\n while (current !== undefined && !seen.has(current)) {\n seen.add(current);\n\n if (isFeatureSection(source, current, 'own', true) || declaresModelContext(source, current)) return true;\n\n current = declaringContext(source, current);\n }\n\n return false;\n}\n\n/**\n * D330: the context of a model and nothing else. The `own` section of a feature is a declaring context too, but its\n * `command` takes the body second and hands it no writer (D139, D385), so a rule about the writer of a command asks\n * this.\n */\nfunction isModelContextFunction(source: TSESLint.SourceCode, fn: FunctionNode): boolean {\n if (declaresModelContext(source, fn)) return true;\n\n const declaring = declaringContext(source, fn);\n\n return declaring !== undefined && isContextFunction(source, declaring);\n}\n\nfunction admitsIngress(method: string, position: number, property: string | undefined): boolean {\n if (positionalIngress.get(method) === position) return true;\n\n const record = recordIngress.get(method);\n\n return record?.argument === position && record.property === property;\n}\n\n/** The shape decides first and the import second: a call that cannot be ingress never pays for the resolution. */\nfunction isIngressArgument(\n source: TSESLint.SourceCode,\n call: TSESTree.CallExpression,\n position: number,\n property: string | undefined,\n): boolean {\n const named = methodPath(source, call.callee);\n\n return named !== undefined && admitsIngress(named.method, position, property) && isContextFunction(source, named.fn);\n}\n\n/** The record member the walk came through since the last call boundary: the `{ open }` of an `attach`. */\nfunction memberProperty(parent: TSESTree.Node, child: TSESTree.Node, current: string | undefined): string | undefined {\n if (parent.type !== AST_NODE_TYPES.ObjectExpression || child.type !== AST_NODE_TYPES.Property) return current;\n\n return propertyName(child);\n}\n\n/**\n * Whether this node stands lexically inside a callback whose opened work the declared node releases. The walk goes\n * all the way out, so a nested function body counts; only the resolved context and the position decide.\n */\nfunction isDeclaredIngress(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n let child: TSESTree.Node = node;\n let property: string | undefined;\n\n for (const parent of source.getAncestors(node).reverse()) {\n if (parent.type === AST_NODE_TYPES.CallExpression) {\n const position = parent.arguments.indexOf(child as TSESTree.CallExpressionArgument);\n\n if (position !== -1 && isIngressArgument(source, parent, position, property)) return true;\n\n property = undefined;\n } else {\n property = memberProperty(parent, child, property);\n }\n\n child = parent;\n }\n\n return false;\n}\n\n/**\n * `context.command(run, options?)`: the body a model command is declared with, inline or bound to a local name.\n * D447: two rules read the writes of one command body — `capture-command-cleanup` where the declaration stands, and\n * `no-write-after-source-write` where a run invokes the name that holds it — so the resolution is one function here\n * rather than the same six lines twice.\n */\nfunction commandBody(source: TSESLint.SourceCode, call: TSESTree.CallExpression): FunctionNode | undefined {\n const [body] = call.arguments;\n\n if (body === undefined || body.type === AST_NODE_TYPES.SpreadElement) return undefined;\n\n const value = localValue(source, unwrap(body));\n\n return isFunction(value) ? value : undefined;\n}\n\n/**\n * D323: a rule that rewrites code has to resolve its package exactly (D309), and this pair is that resolution: the\n * method a callee names on a declaring context, and whether that parameter really is one.\n */\nexport { commandBody, isContextFunction, isDeclaredIngress, isModelContextFunction, methodPath };\n"],"names":["positionalIngress","recordIngress","annotatedParameter","fn","parameter","AST_NODE_TYPES","declaresModelContext","source","annotation","typeName","isApi","parameterOf","node","definition","definitionOf","TSESLint","isFunction","contextName","destructuredMethod","property","method","propertyName","memberSteps","callee","steps","current","methodPath","chain","named","destructured","declaringContext","call","declaring","isContextFunction","seen","isFeatureSection","isModelContextFunction","admitsIngress","position","record","isIngressArgument","memberProperty","parent","child","isDeclaredIngress","commandBody","body","value","localValue","unwrap"],"mappings":"gPAYA,MAAMA,EAAoB,IAAI,IAAI,CAChC,CAAC,QAAS,CAAC,EAEX,CAAC,aAAc,CAAC,EAChB,CAAC,eAAgB,CAAC,EAClB,CAAC,cAAe,CAAC,CAClB,CAAA,EAMKC,EAAgB,IAAI,IAAI,CAC5B,CAAC,SAAU,CAAE,SAAU,EAAG,SAAU,MAAM,CAAE,EAC5C,CAAC,gBAAiB,CAAE,SAAU,EAAG,SAAU,SAAS,CAAE,CACvD,CAAA,EAMD,SAASC,EAAmBC,EAAgB,CAC1C,KAAM,CAACC,CAAS,EAAID,EAAG,OAEvB,GAAIC,GAAW,OAASC,EAAe,YAAcD,GAAW,OAASC,EAAe,cACtF,OAAOD,CAIX,CAGA,SAASE,EAAqBC,EAA6BJ,EAAgB,CACzE,MAAMK,EAAaN,EAAmBC,CAAE,GAAG,gBAAgB,eAE3D,GAAIK,GAAY,OAASH,EAAe,gBAAiB,MAAO,GAEhE,KAAM,CAAE,SAAAI,CAAQ,EAAKD,EAErB,OAAOC,EAAS,OAASJ,EAAe,YAAcK,EAAMH,EAAQE,EAAU,gBAAiB,eAAgB,EAAI,CACrH,CAGA,SAASE,EAAYJ,EAA6BK,EAAyB,CACzE,MAAMC,EAAaC,EAAaP,EAAQK,CAAI,EAE5C,GAAI,EAAAC,GAAY,OAASE,EAAS,MAAM,eAAe,WAAa,CAACC,EAAWH,EAAW,IAAI,GAE/F,MAAO,CAAE,GAAIA,EAAW,KAAM,KAAMA,EAAW,IAAI,CACrD,CAGA,SAASI,EAAYV,EAA6BK,EAAyB,CACzE,MAAMR,EAAYO,EAAYJ,EAAQK,CAAI,EAE1C,OAAOR,IAAc,QAAaA,EAAU,OAASA,EAAU,GAAG,OAAO,CAAC,EAAIA,EAAU,GAAK,MAC/F,CAGA,SAASc,EAAmBX,EAA6BK,EAAyB,CAChF,MAAMR,EAAYO,EAAYJ,EAAQK,CAAI,EACpCO,EAAWf,GAAW,KAAK,OAEjC,GAAIA,IAAc,QAAae,GAAU,OAASd,EAAe,SAAU,OAE3E,MAAMe,EAASD,EAAS,SAAWf,EAAU,GAAG,OAAO,CAAC,EAAIiB,EAAaF,CAAQ,EAAI,OAErF,OAAOC,IAAW,OAAY,OAAY,CAAE,GAAIhB,EAAU,GAAI,OAAAgB,CAAM,CACtE,CAGA,SAASE,EAAYC,EAAqB,CACxC,MAAMC,EAAkB,CAAA,EACxB,IAAIC,EAAyBF,EAE7B,KAAOE,EAAQ,OAASpB,EAAe,kBAAkB,CACvD,GAAIoB,EAAQ,UAAYA,EAAQ,SAAS,OAASpB,EAAe,WAAY,OAE7EmB,EAAM,QAAQC,EAAQ,SAAS,IAAI,EACnCA,EAAUA,EAAQ,MACpB,CAEA,MAAO,CAAE,KAAMA,EAAS,MAAAD,CAAK,CAC/B,CAMA,SAASE,EAAWnB,EAA6BgB,EAAqB,CACpE,MAAMI,EAAQL,EAAYC,CAAM,EAEhC,GAAII,GAAO,KAAK,OAAStB,EAAe,WAAY,OAEpD,MAAMuB,EAAQD,EAAM,MAAM,SAAW,EAAI,OAAYV,EAAYV,EAAQoB,EAAM,IAAI,EAEnF,GAAIC,IAAU,OAAW,MAAO,CAAE,GAAIA,EAAO,OAAQD,EAAM,MAAM,KAAK,GAAG,CAAC,EAE1E,MAAME,EAAeX,EAAmBX,EAAQoB,EAAM,IAAI,EAE1D,OAAOE,IAAiB,OACpB,OACA,CAAE,GAAIA,EAAa,GAAI,OAAQ,CAACA,EAAa,OAAQ,GAAGF,EAAM,KAAK,EAAE,KAAK,GAAG,CAAC,CACpF,CAGA,SAASG,EAAiBvB,EAA6BJ,EAAgB,CACrE,MAAM4B,EAAO5B,EAAG,OAEhB,GAAI4B,EAAK,OAAS1B,EAAe,gBAAkB0B,EAAK,UAAU,CAAC,IAAM5B,EAAI,OAE7E,MAAM6B,EAAYN,EAAWnB,EAAQwB,EAAK,MAAM,EAEhD,OAAOC,GAAW,SAAW,QAAUA,EAAU,GAAK,MACxD,CAQA,SAASC,EAAkB1B,EAA6BJ,EAAgB,CACtE,MAAM+B,EAAO,IAAI,IACjB,IAAIT,EAAoCtB,EAExC,KAAOsB,IAAY,QAAa,CAACS,EAAK,IAAIT,CAAO,GAAG,CAGlD,GAFAS,EAAK,IAAIT,CAAO,EAEZU,EAAiB5B,EAAQkB,EAAS,MAAO,EAAI,GAAKnB,EAAqBC,EAAQkB,CAAO,EAAG,MAAO,GAEpGA,EAAUK,EAAiBvB,EAAQkB,CAAO,CAC5C,CAEA,MAAO,EACT,CAOA,SAASW,EAAuB7B,EAA6BJ,EAAgB,CAC3E,GAAIG,EAAqBC,EAAQJ,CAAE,EAAG,MAAO,GAE7C,MAAM6B,EAAYF,EAAiBvB,EAAQJ,CAAE,EAE7C,OAAO6B,IAAc,QAAaC,EAAkB1B,EAAQyB,CAAS,CACvE,CAEA,SAASK,EAAcjB,EAAgBkB,EAAkBnB,EAA4B,CACnF,GAAInB,EAAkB,IAAIoB,CAAM,IAAMkB,EAAU,MAAO,GAEvD,MAAMC,EAAStC,EAAc,IAAImB,CAAM,EAEvC,OAAOmB,GAAQ,WAAaD,GAAYC,EAAO,WAAapB,CAC9D,CAGA,SAASqB,EACPjC,EACAwB,EACAO,EACAnB,EAA4B,CAE5B,MAAMS,EAAQF,EAAWnB,EAAQwB,EAAK,MAAM,EAE5C,OAAOH,IAAU,QAAaS,EAAcT,EAAM,OAAQU,EAAUnB,CAAQ,GAAKc,EAAkB1B,EAAQqB,EAAM,EAAE,CACrH,CAGA,SAASa,EAAeC,EAAuBC,EAAsBlB,EAA2B,CAC9F,OAAIiB,EAAO,OAASrC,EAAe,kBAAoBsC,EAAM,OAAStC,EAAe,SAAiBoB,EAE/FJ,EAAasB,CAAK,CAC3B,CAMA,SAASC,EAAkBrC,EAA6BK,EAAmB,CACzE,IAAI+B,EAAuB/B,EACvBO,EAEJ,UAAWuB,KAAUnC,EAAO,aAAaK,CAAI,EAAE,UAAW,CACxD,GAAI8B,EAAO,OAASrC,EAAe,eAAgB,CACjD,MAAMiC,EAAWI,EAAO,UAAU,QAAQC,CAAwC,EAElF,GAAIL,IAAa,IAAME,EAAkBjC,EAAQmC,EAAQJ,EAAUnB,CAAQ,EAAG,MAAO,GAErFA,EAAW,MACb,MACEA,EAAWsB,EAAeC,EAAQC,EAAOxB,CAAQ,EAGnDwB,EAAQD,CACV,CAEA,MAAO,EACT,CAQA,SAASG,EAAYtC,EAA6BwB,EAA6B,CAC7E,KAAM,CAACe,CAAI,EAAIf,EAAK,UAEpB,GAAIe,IAAS,QAAaA,EAAK,OAASzC,EAAe,cAAe,OAEtE,MAAM0C,EAAQC,EAAWzC,EAAQ0C,EAAOH,CAAI,CAAC,EAE7C,OAAO9B,EAAW+B,CAAK,EAAIA,EAAQ,MACrC"}
1
+ {"version":3,"file":"declaration-ingress.js","sources":["../src/declaration-ingress.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils';\n\nimport { propertyName } from './ast';\nimport type { FunctionNode } from './model-bindings';\nimport { definitionOf, isApi, isFeatureSection, isFunction, localValue, unwrap } from './model-bindings';\n\n/**\n * The callbacks a declared node opens its work in and owns the release of: the disposer they return is run by the\n * node, in the drain of the generation that opened it. The argument index is part of the contract — `run`, `load`,\n * `filter` and `key` sit in the same calls and are not ingress.\n *\n * D458: the subscription of an event is the third argument, because `run` moved in front of it.\n */\nconst positionalIngress = new Map([\n ['event', 2],\n // D378: the key of `each` stands between the source and the child, so the callback that opens is the third argument.\n ['scope.each', 2],\n ['scope.switch', 1],\n ['scope.while', 1],\n]);\n\n/**\n * The callbacks written as a record member. `attach`'s `close` is a release, not an opening; D349 puts the connection\n * of a live Resource under `connect` in the one options record, so that is where the ingress of a subscription is.\n */\nconst recordIngress = new Map([\n ['attach', { argument: 1, property: 'open' }],\n ['resource.live', { argument: 0, property: 'connect' }],\n]);\n\ntype Annotated = TSESTree.Identifier | TSESTree.ObjectPattern;\ntype NamedMethod = { readonly fn: FunctionNode; readonly method: string };\ntype ParameterOf = { readonly fn: FunctionNode; readonly name: TSESTree.BindingName };\n\nfunction annotatedParameter(fn: FunctionNode): Annotated | undefined {\n const [parameter] = fn.params;\n\n if (parameter?.type === AST_NODE_TYPES.Identifier || parameter?.type === AST_NODE_TYPES.ObjectPattern) {\n return parameter;\n }\n\n return undefined;\n}\n\n/** The factory of a model says so in the parameter it takes: the name `ModelContext` carries where it is exported. */\nfunction declaresModelContext(source: TSESLint.SourceCode, fn: FunctionNode): boolean {\n const annotation = annotatedParameter(fn)?.typeAnnotation?.typeAnnotation;\n\n if (annotation?.type !== AST_NODE_TYPES.TSTypeReference) return false;\n\n const { typeName } = annotation;\n\n return typeName.type === AST_NODE_TYPES.Identifier && isApi(source, typeName, '@opetope/core', 'ModelContext', true);\n}\n\n/** The function this name is a parameter of, and the pattern node that bound it there. */\nfunction parameterOf(source: TSESLint.SourceCode, node: TSESTree.Identifier): ParameterOf | undefined {\n const definition = definitionOf(source, node);\n\n if (definition?.type !== TSESLint.Scope.DefinitionType.Parameter || !isFunction(definition.node)) return undefined;\n\n return { fn: definition.node, name: definition.name };\n}\n\n/** `own` itself: the plain name a context parameter was given, whichever function that parameter belongs to. */\nfunction contextName(source: TSESLint.SourceCode, node: TSESTree.Identifier): FunctionNode | undefined {\n const parameter = parameterOf(source, node);\n\n return parameter !== undefined && parameter.name === parameter.fn.params[0] ? parameter.fn : undefined;\n}\n\n/** `({ resource }) => resource.live(…)`: the method under the key the destructuring took it from, alias included. */\nfunction destructuredMethod(source: TSESLint.SourceCode, node: TSESTree.Identifier): NamedMethod | undefined {\n const parameter = parameterOf(source, node);\n const property = parameter?.name.parent;\n\n if (parameter === undefined || property?.type !== AST_NODE_TYPES.Property) return undefined;\n\n const method = property.parent === parameter.fn.params[0] ? propertyName(property) : undefined;\n\n return method === undefined ? undefined : { fn: parameter.fn, method };\n}\n\n/** The dotted steps of a member chain and the name it starts from: `own.scope.while` is `own` and `scope.while`. */\nfunction memberSteps(callee: TSESTree.Node): { root: TSESTree.Node; steps: readonly string[] } | undefined {\n const steps: string[] = [];\n let current: TSESTree.Node = callee;\n\n while (current.type === AST_NODE_TYPES.MemberExpression) {\n if (current.computed || current.property.type !== AST_NODE_TYPES.Identifier) return undefined;\n\n steps.unshift(current.property.name);\n current = current.object;\n }\n\n return { root: current, steps };\n}\n\n/**\n * The method this callee names on the first parameter of some function, and that function. Whether the parameter\n * really is a declaring context is a separate question: answering it here would make the two questions circular.\n */\nfunction methodPath(source: TSESLint.SourceCode, callee: TSESTree.Node): NamedMethod | undefined {\n const chain = memberSteps(callee);\n\n if (chain?.root.type !== AST_NODE_TYPES.Identifier) return undefined;\n\n const named = chain.steps.length === 0 ? undefined : contextName(source, chain.root);\n\n if (named !== undefined) return { fn: named, method: chain.steps.join('.') };\n\n const destructured = destructuredMethod(source, chain.root);\n\n return destructured === undefined\n ? undefined\n : { fn: destructured.fn, method: [destructured.method, ...chain.steps].join('.') };\n}\n\n/** One step outward: the context whose `model(…)` call declares this factory, where that is how it was written. */\nfunction declaringContext(source: TSESLint.SourceCode, fn: FunctionNode): FunctionNode | undefined {\n const call = fn.parent;\n\n if (call.type !== AST_NODE_TYPES.CallExpression || call.arguments[1] !== fn) return undefined;\n\n const declaring = methodPath(source, call.callee);\n\n return declaring?.method === 'model' ? declaring.fn : undefined;\n}\n\n/**\n * The two functions that hand an author a declaring context: the `own` section written right where `defineFeature`\n * takes it, and the factory of a model — which is either annotated as one or written where a feature declares it,\n * as the second argument of `model(Declaration, factory)`. That second form is proved by walking outward one\n * `model(…)` at a time, and the set of functions already visited ends a chain that would come back to its start.\n */\nfunction isContextFunction(source: TSESLint.SourceCode, fn: FunctionNode): boolean {\n const seen = new Set<FunctionNode>();\n let current: FunctionNode | undefined = fn;\n\n while (current !== undefined && !seen.has(current)) {\n seen.add(current);\n\n if (isFeatureSection(source, current, 'own', true) || declaresModelContext(source, current)) return true;\n\n current = declaringContext(source, current);\n }\n\n return false;\n}\n\n/**\n * D330: the context of a model and nothing else. The `own` section of a feature is a declaring context too, but its\n * `command` takes the body second and hands it no writer (D139, D385), so a rule about the writer of a command asks\n * this.\n */\nfunction isModelContextFunction(source: TSESLint.SourceCode, fn: FunctionNode): boolean {\n if (declaresModelContext(source, fn)) return true;\n\n const declaring = declaringContext(source, fn);\n\n return declaring !== undefined && isContextFunction(source, declaring);\n}\n\nfunction admitsIngress(method: string, position: number, property: string | undefined): boolean {\n if (positionalIngress.get(method) === position) return true;\n\n const record = recordIngress.get(method);\n\n return record?.argument === position && record.property === property;\n}\n\n/** The shape decides first and the import second: a call that cannot be ingress never pays for the resolution. */\nfunction isIngressArgument(\n source: TSESLint.SourceCode,\n call: TSESTree.CallExpression,\n position: number,\n property: string | undefined,\n): boolean {\n const named = methodPath(source, call.callee);\n\n return named !== undefined && admitsIngress(named.method, position, property) && isContextFunction(source, named.fn);\n}\n\n/** The record member the walk came through since the last call boundary: the `{ open }` of an `attach`. */\nfunction memberProperty(parent: TSESTree.Node, child: TSESTree.Node, current: string | undefined): string | undefined {\n if (parent.type !== AST_NODE_TYPES.ObjectExpression || child.type !== AST_NODE_TYPES.Property) return current;\n\n return propertyName(child);\n}\n\n/**\n * Whether this node stands lexically inside a callback whose opened work the declared node releases. The walk goes\n * all the way out, so a nested function body counts; only the resolved context and the position decide.\n */\nfunction isDeclaredIngress(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n let child: TSESTree.Node = node;\n let property: string | undefined;\n\n for (const parent of source.getAncestors(node).reverse()) {\n if (parent.type === AST_NODE_TYPES.CallExpression) {\n const position = parent.arguments.indexOf(child as TSESTree.CallExpressionArgument);\n\n if (position !== -1 && isIngressArgument(source, parent, position, property)) return true;\n\n property = undefined;\n } else {\n property = memberProperty(parent, child, property);\n }\n\n child = parent;\n }\n\n return false;\n}\n\n/**\n * `context.command(run, options?)`: the body a model command is declared with, inline or bound to a local name.\n * D447: two rules read the writes of one command body — `capture-command-cleanup` where the declaration stands, and\n * `no-write-after-source-write` where a run invokes the name that holds it — so the resolution is one function here\n * rather than the same six lines twice.\n */\nfunction commandBody(source: TSESLint.SourceCode, call: TSESTree.CallExpression): FunctionNode | undefined {\n const [body] = call.arguments;\n\n if (body === undefined || body.type === AST_NODE_TYPES.SpreadElement) return undefined;\n\n const value = localValue(source, unwrap(body));\n\n return isFunction(value) ? value : undefined;\n}\n\n/**\n * D323: a rule that rewrites code has to resolve its package exactly (D309), and this pair is that resolution: the\n * method a callee names on a declaring context, and whether that parameter really is one.\n */\nexport { commandBody, isContextFunction, isDeclaredIngress, isModelContextFunction, methodPath };\n"],"names":["positionalIngress","recordIngress","annotatedParameter","fn","parameter","AST_NODE_TYPES","declaresModelContext","source","annotation","typeName","isApi","parameterOf","node","definition","definitionOf","TSESLint","isFunction","contextName","destructuredMethod","property","method","propertyName","memberSteps","callee","steps","current","methodPath","chain","named","destructured","declaringContext","call","declaring","isContextFunction","seen","isFeatureSection","isModelContextFunction","admitsIngress","position","record","isIngressArgument","memberProperty","parent","child","isDeclaredIngress","commandBody","body","value","localValue","unwrap"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -44,7 +44,7 @@ declare const plugin: {
44
44
  'no-redundant-const-tuple': import("@typescript-eslint/utils/ts-eslint").RuleModule<"redundantConstTuple", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
45
45
  name: string;
46
46
  };
47
- 'no-retired-vocabulary': import("@typescript-eslint/utils/ts-eslint").RuleModule<"commandLane" | "commandName" | "commandOnce" | "commandOutcomeStatus" | "commandPolicy" | "commandQueueBy" | "conditionFrom" | "contextCall" | "contextCalls" | "contributionWhen" | "deliveryKey" | "deliveryKind" | "deliveryReject" | "devtoolsResourceActivity" | "effectOnDispose" | "effectSkipInitial" | "effectWhen" | "eventBackpressure" | "fromExternal" | "loadingActivity" | "navigatorPolicy" | "resourceDisposer" | "resourceInvalidate" | "runtimeInternalEntry" | "scopeKeyed" | "useCommands", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
47
+ 'no-retired-vocabulary': import("@typescript-eslint/utils/ts-eslint").RuleModule<"commandLane" | "commandLatest" | "commandName" | "commandOnce" | "commandOutcomeStatus" | "commandPolicy" | "commandQueueBy" | "conditionFrom" | "contextCall" | "contextCalls" | "contributionWhen" | "deliveryKey" | "deliveryKind" | "deliveryReject" | "effectOnDispose" | "effectSkipInitial" | "effectWhen" | "eventBackpressure" | "fromExternal" | "navigatorPolicy" | "resourceActivity" | "resourceDisposer" | "resourceInvalidate" | "runtimeInternalEntry" | "scopeKeyed" | "stateActivity" | "useCommands", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
48
48
  name: string;
49
49
  };
50
50
  'no-snapshot-in-update': import("@typescript-eslint/utils/ts-eslint").RuleModule<"snapshotInUpdate" | "writeFromPrevious", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{captureCommandCleanup as p}from"./rules/capture-command-cleanup.js";import{defineFeaturePropertyOrder as s}from"./rules/define-feature-property-order.js";import{idNaming as i}from"./rules/id-naming.js";import{layerPlacement as a}from"./rules/layer-placement.js";import{noCommandInDeps as m}from"./rules/no-command-in-deps.js";import{noInternalImports as l}from"./rules/no-internal-imports.js";import{noRedundantConstTuple as d}from"./rules/no-redundant-const-tuple.js";import{noRetiredVocabulary as c}from"./rules/no-retired-vocabulary.js";import{noSnapshotInUpdate as u}from"./rules/no-snapshot-in-update.js";import{noSnapshotReadInRender as f}from"./rules/no-snapshot-read-in-render.js";import{noSubscribeOutsideModels as b}from"./rules/no-subscribe-outside-models.js";import{noWriteAfterSourceWrite as g}from"./rules/no-write-after-source-write.js";import{preferEffectCurrent as y}from"./rules/prefer-effect-current.js";import{preferModelSelection as S}from"./rules/prefer-model-selection.js";import{requireDeclaredModels as h}from"./rules/require-declared-models.js";import{requireLiteralId as I}from"./rules/require-literal-id.js";import{enabledPredicate as q}from"./rules/enabled-predicate.js";const C=["integration","models","ui"],E=["**/*.ts","**/*.tsx"],R=["**/__tests__/**","**/*.spec.ts","**/*.spec.tsx"],_={meta:{name:"@opetope/lint",version:"0.12.0"},rules:{"capture-command-cleanup":p,"define-feature-property-order":s,"id-naming":i,"layer-placement":a,"no-command-in-deps":m,"no-internal-imports":l,"no-redundant-const-tuple":d,"no-retired-vocabulary":c,"no-snapshot-in-update":u,"no-snapshot-read-in-render":f,"no-subscribe-outside-models":b,"no-write-after-source-write":g,"prefer-effect-current":y,"prefer-model-selection":S,"require-declared-models":h,"require-literal-id":I,"enabled-predicate":q}},r=_,j={name:"opetope/recommended",plugins:{opetope:r},rules:{"opetope/capture-command-cleanup":"error","opetope/define-feature-property-order":"error","opetope/id-naming":"error","opetope/layer-placement":"off","opetope/no-command-in-deps":"error","opetope/no-internal-imports":"error","opetope/no-redundant-const-tuple":"error","opetope/no-retired-vocabulary":"error","opetope/no-snapshot-in-update":"error","opetope/no-snapshot-read-in-render":"error","opetope/no-subscribe-outside-models":"off","opetope/no-write-after-source-write":"error","opetope/prefer-effect-current":"error","opetope/prefer-model-selection":"off","opetope/require-declared-models":"error","opetope/require-literal-id":"error","opetope/enabled-predicate":"error"}},w=e=>C.flatMap(o=>{const t=e[o]??[];return t.length===0?[]:[{files:[...t],name:`opetope/layers-${o}`,plugins:{opetope:r},rules:{"opetope/layer-placement":["error",{layer:o}]}}]}),x=({models:e=[],tests:o=R})=>e.length===0?[]:[{files:E,name:"opetope/layers-subscriptions",plugins:{opetope:r},rules:{"opetope/no-subscribe-outside-models":"error"}},{files:[...e,...o],name:"opetope/layers-subscriptions-allowed",rules:{"opetope/no-subscribe-outside-models":"off"}}],L=e=>[...w(e),...x(e)],P=({allow:e=[],files:o=["**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}"]}={})=>[{files:[...o],name:"opetope/internal-imports",plugins:{opetope:r},rules:{"opetope/no-internal-imports":"error"}},...e.length===0?[]:[{files:[...e],name:"opetope/internal-imports-allowed",rules:{"opetope/no-internal-imports":"off"}}]],v=Object.assign(r,{configs:{internalImports:P,layers:L,recommended:j}}),n=v;export{n as default,n as opetopeLint};
1
+ import{captureCommandCleanup as p}from"./rules/capture-command-cleanup.js";import{defineFeaturePropertyOrder as s}from"./rules/define-feature-property-order.js";import{idNaming as i}from"./rules/id-naming.js";import{layerPlacement as a}from"./rules/layer-placement.js";import{noCommandInDeps as m}from"./rules/no-command-in-deps.js";import{noInternalImports as l}from"./rules/no-internal-imports.js";import{noRedundantConstTuple as d}from"./rules/no-redundant-const-tuple.js";import{noRetiredVocabulary as c}from"./rules/no-retired-vocabulary.js";import{noSnapshotInUpdate as u}from"./rules/no-snapshot-in-update.js";import{noSnapshotReadInRender as f}from"./rules/no-snapshot-read-in-render.js";import{noSubscribeOutsideModels as b}from"./rules/no-subscribe-outside-models.js";import{noWriteAfterSourceWrite as g}from"./rules/no-write-after-source-write.js";import{preferEffectCurrent as y}from"./rules/prefer-effect-current.js";import{preferModelSelection as S}from"./rules/prefer-model-selection.js";import{requireDeclaredModels as h}from"./rules/require-declared-models.js";import{requireLiteralId as I}from"./rules/require-literal-id.js";import{enabledPredicate as q}from"./rules/enabled-predicate.js";const C=["integration","models","ui"],E=["**/*.ts","**/*.tsx"],R=["**/__tests__/**","**/*.spec.ts","**/*.spec.tsx"],_={meta:{name:"@opetope/lint",version:"0.12.2"},rules:{"capture-command-cleanup":p,"define-feature-property-order":s,"id-naming":i,"layer-placement":a,"no-command-in-deps":m,"no-internal-imports":l,"no-redundant-const-tuple":d,"no-retired-vocabulary":c,"no-snapshot-in-update":u,"no-snapshot-read-in-render":f,"no-subscribe-outside-models":b,"no-write-after-source-write":g,"prefer-effect-current":y,"prefer-model-selection":S,"require-declared-models":h,"require-literal-id":I,"enabled-predicate":q}},r=_,j={name:"opetope/recommended",plugins:{opetope:r},rules:{"opetope/capture-command-cleanup":"error","opetope/define-feature-property-order":"error","opetope/id-naming":"error","opetope/layer-placement":"off","opetope/no-command-in-deps":"error","opetope/no-internal-imports":"error","opetope/no-redundant-const-tuple":"error","opetope/no-retired-vocabulary":"error","opetope/no-snapshot-in-update":"error","opetope/no-snapshot-read-in-render":"error","opetope/no-subscribe-outside-models":"off","opetope/no-write-after-source-write":"error","opetope/prefer-effect-current":"error","opetope/prefer-model-selection":"off","opetope/require-declared-models":"error","opetope/require-literal-id":"error","opetope/enabled-predicate":"error"}},w=e=>C.flatMap(o=>{const t=e[o]??[];return t.length===0?[]:[{files:[...t],name:`opetope/layers-${o}`,plugins:{opetope:r},rules:{"opetope/layer-placement":["error",{layer:o}]}}]}),x=({models:e=[],tests:o=R})=>e.length===0?[]:[{files:E,name:"opetope/layers-subscriptions",plugins:{opetope:r},rules:{"opetope/no-subscribe-outside-models":"error"}},{files:[...e,...o],name:"opetope/layers-subscriptions-allowed",rules:{"opetope/no-subscribe-outside-models":"off"}}],L=e=>[...w(e),...x(e)],P=({allow:e=[],files:o=["**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}"]}={})=>[{files:[...o],name:"opetope/internal-imports",plugins:{opetope:r},rules:{"opetope/no-internal-imports":"error"}},...e.length===0?[]:[{files:[...e],name:"opetope/internal-imports-allowed",rules:{"opetope/no-internal-imports":"off"}}]],v=Object.assign(r,{configs:{internalImports:P,layers:L,recommended:j}}),n=v;export{n as default,n 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 { captureCommandCleanup } from './rules/capture-command-cleanup';\nimport { defineFeaturePropertyOrder } from './rules/define-feature-property-order';\nimport { idNaming } from './rules/id-naming';\nimport { layerPlacement } from './rules/layer-placement';\nimport { noCommandInDeps } from './rules/no-command-in-deps';\nimport { noInternalImports } from './rules/no-internal-imports';\nimport { noRedundantConstTuple } from './rules/no-redundant-const-tuple';\nimport { noRetiredVocabulary } from './rules/no-retired-vocabulary';\nimport { noSnapshotInUpdate } from './rules/no-snapshot-in-update';\nimport { noSnapshotReadInRender } from './rules/no-snapshot-read-in-render';\nimport { noSubscribeOutsideModels } from './rules/no-subscribe-outside-models';\nimport { noWriteAfterSourceWrite } from './rules/no-write-after-source-write';\nimport { preferEffectCurrent } from './rules/prefer-effect-current';\nimport { preferModelSelection } from './rules/prefer-model-selection';\nimport { requireDeclaredModels } from './rules/require-declared-models';\nimport { requireLiteralId } from './rules/require-literal-id';\nimport { enabledPredicate } from './rules/enabled-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.12.0' },\n rules: {\n 'capture-command-cleanup': captureCommandCleanup,\n 'define-feature-property-order': defineFeaturePropertyOrder,\n 'id-naming': idNaming,\n 'layer-placement': layerPlacement,\n 'no-command-in-deps': noCommandInDeps,\n 'no-internal-imports': noInternalImports,\n 'no-redundant-const-tuple': noRedundantConstTuple,\n 'no-retired-vocabulary': noRetiredVocabulary,\n 'no-snapshot-in-update': noSnapshotInUpdate,\n 'no-snapshot-read-in-render': noSnapshotReadInRender,\n 'no-subscribe-outside-models': noSubscribeOutsideModels,\n 'no-write-after-source-write': noWriteAfterSourceWrite,\n 'prefer-effect-current': preferEffectCurrent,\n 'prefer-model-selection': preferModelSelection,\n 'require-declared-models': requireDeclaredModels,\n 'require-literal-id': requireLiteralId,\n 'enabled-predicate': enabledPredicate,\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/enabled-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/capture-command-cleanup': 'error',\n 'opetope/define-feature-property-order': 'error',\n 'opetope/id-naming': 'error',\n 'opetope/layer-placement': 'off',\n 'opetope/no-command-in-deps': 'error',\n 'opetope/no-internal-imports': 'error',\n 'opetope/no-redundant-const-tuple': 'error',\n 'opetope/no-retired-vocabulary': 'error',\n 'opetope/no-snapshot-in-update': 'error',\n 'opetope/no-snapshot-read-in-render': 'error',\n 'opetope/no-subscribe-outside-models': 'off',\n 'opetope/no-write-after-source-write': 'error',\n 'opetope/prefer-effect-current': 'error',\n 'opetope/prefer-model-selection': 'off',\n 'opetope/require-declared-models': 'error',\n 'opetope/require-literal-id': 'error',\n 'opetope/enabled-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 * Only library implementation and explicitly named host integration can cross the internal ABI. A dedicated rule\n * leaves the project's `no-restricted-imports` untouched and also covers literal dynamic imports in JS tests.\n * Allowed files explicitly override `recommended`, which enables this rule as well.\n */\nconst internalImports = ({\n allow = [],\n files = ['**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}'],\n}: InternalImportOptions = {}): readonly Linter.Config[] => [\n {\n files: [...files],\n name: 'opetope/internal-imports',\n plugins: { opetope: nativePlugin },\n rules: { 'opetope/no-internal-imports': 'error' },\n },\n ...(allow.length === 0\n ? []\n : [\n {\n files: [...allow],\n name: 'opetope/internal-imports-allowed',\n rules: { 'opetope/no-internal-imports': 'off' as const },\n },\n ]),\n];\n\nconst configuredPlugin = Object.assign(nativePlugin, {\n configs: { internalImports, layers, recommended },\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","captureCommandCleanup","defineFeaturePropertyOrder","idNaming","layerPlacement","noCommandInDeps","noInternalImports","noRedundantConstTuple","noRetiredVocabulary","noSnapshotInUpdate","noSnapshotReadInRender","noSubscribeOutsideModels","noWriteAfterSourceWrite","preferEffectCurrent","preferModelSelection","requireDeclaredModels","requireLiteralId","enabledPredicate","nativePlugin","recommended","placement","options","layer","files","subscriptions","models","tests","layers","internalImports","allow","configuredPlugin","opetopeLint"],"mappings":"urCAoCA,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,QAAQ,EAChD,MAAO,CACL,0BAA2BC,EAC3B,gCAAiCC,EACjC,YAAaC,EACb,kBAAmBC,EACnB,qBAAsBC,EACtB,sBAAuBC,EACvB,2BAA4BC,EAC5B,wBAAyBC,EACzB,wBAAyBC,EACzB,6BAA8BC,EAC9B,8BAA+BC,EAC/B,8BAA+BC,EAC/B,wBAAyBC,EACzB,yBAA0BC,EAC1B,0BAA2BC,EAC3B,qBAAsBC,EACtB,oBAAqBC,CACtB,GAcGC,EAAelB,EAEfmB,EAAc,CAClB,KAAM,sBACN,QAAS,CAAE,QAASD,CAAY,EAChC,MAAO,CACL,kCAAmC,QACnC,wCAAyC,QACzC,oBAAqB,QACrB,0BAA2B,MAC3B,6BAA8B,QAC9B,8BAA+B,QAC/B,mCAAoC,QACpC,gCAAiC,QACjC,gCAAiC,QACjC,qCAAsC,QACtC,sCAAuC,MACvC,sCAAuC,QACvC,gCAAiC,QACjC,iCAAkC,MAClC,kCAAmC,QACnC,6BAA8B,QAC9B,4BAA6B,OAC9B,GAOGE,EAAaC,GACjBxB,EAAO,QAAQyB,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,EAAQ3B,CAAU,IACtD0B,EAAO,SAAW,EACd,CAAA,EACA,CACE,CACE,MAAO3B,EACP,KAAM,+BACN,QAAS,CAAE,QAASoB,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,EAO/GO,EAAkB,CAAC,CACvB,MAAAC,EAAQ,CAAA,EACR,MAAAN,EAAQ,CAAC,sCAAsC,CAAC,EACvB,KAAiC,CAC1D,CACE,MAAO,CAAC,GAAGA,CAAK,EAChB,KAAM,2BACN,QAAS,CAAE,QAASL,CAAY,EAChC,MAAO,CAAE,8BAA+B,OAAO,CAChD,EACD,GAAIW,EAAM,SAAW,EACjB,CAAA,EACA,CACE,CACE,MAAO,CAAC,GAAGA,CAAK,EAChB,KAAM,mCACN,MAAO,CAAE,8BAA+B,KAAc,CACvD,IAIHC,EAAmB,OAAO,OAAOZ,EAAc,CACnD,QAAS,CAAE,gBAAAU,EAAiB,OAAAD,EAAQ,YAAAR,CAAW,CAChD,CAAA,EAKKY,EAAcD"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import type { ESLint, Linter } from 'eslint';\n\nimport { captureCommandCleanup } from './rules/capture-command-cleanup';\nimport { defineFeaturePropertyOrder } from './rules/define-feature-property-order';\nimport { idNaming } from './rules/id-naming';\nimport { layerPlacement } from './rules/layer-placement';\nimport { noCommandInDeps } from './rules/no-command-in-deps';\nimport { noInternalImports } from './rules/no-internal-imports';\nimport { noRedundantConstTuple } from './rules/no-redundant-const-tuple';\nimport { noRetiredVocabulary } from './rules/no-retired-vocabulary';\nimport { noSnapshotInUpdate } from './rules/no-snapshot-in-update';\nimport { noSnapshotReadInRender } from './rules/no-snapshot-read-in-render';\nimport { noSubscribeOutsideModels } from './rules/no-subscribe-outside-models';\nimport { noWriteAfterSourceWrite } from './rules/no-write-after-source-write';\nimport { preferEffectCurrent } from './rules/prefer-effect-current';\nimport { preferModelSelection } from './rules/prefer-model-selection';\nimport { requireDeclaredModels } from './rules/require-declared-models';\nimport { requireLiteralId } from './rules/require-literal-id';\nimport { enabledPredicate } from './rules/enabled-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.12.2' },\n rules: {\n 'capture-command-cleanup': captureCommandCleanup,\n 'define-feature-property-order': defineFeaturePropertyOrder,\n 'id-naming': idNaming,\n 'layer-placement': layerPlacement,\n 'no-command-in-deps': noCommandInDeps,\n 'no-internal-imports': noInternalImports,\n 'no-redundant-const-tuple': noRedundantConstTuple,\n 'no-retired-vocabulary': noRetiredVocabulary,\n 'no-snapshot-in-update': noSnapshotInUpdate,\n 'no-snapshot-read-in-render': noSnapshotReadInRender,\n 'no-subscribe-outside-models': noSubscribeOutsideModels,\n 'no-write-after-source-write': noWriteAfterSourceWrite,\n 'prefer-effect-current': preferEffectCurrent,\n 'prefer-model-selection': preferModelSelection,\n 'require-declared-models': requireDeclaredModels,\n 'require-literal-id': requireLiteralId,\n 'enabled-predicate': enabledPredicate,\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/enabled-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/capture-command-cleanup': 'error',\n 'opetope/define-feature-property-order': 'error',\n 'opetope/id-naming': 'error',\n 'opetope/layer-placement': 'off',\n 'opetope/no-command-in-deps': 'error',\n 'opetope/no-internal-imports': 'error',\n 'opetope/no-redundant-const-tuple': 'error',\n 'opetope/no-retired-vocabulary': 'error',\n 'opetope/no-snapshot-in-update': 'error',\n 'opetope/no-snapshot-read-in-render': 'error',\n 'opetope/no-subscribe-outside-models': 'off',\n 'opetope/no-write-after-source-write': 'error',\n 'opetope/prefer-effect-current': 'error',\n 'opetope/prefer-model-selection': 'off',\n 'opetope/require-declared-models': 'error',\n 'opetope/require-literal-id': 'error',\n 'opetope/enabled-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 * Only library implementation and explicitly named host integration can cross the internal ABI. A dedicated rule\n * leaves the project's `no-restricted-imports` untouched and also covers literal dynamic imports in JS tests.\n * Allowed files explicitly override `recommended`, which enables this rule as well.\n */\nconst internalImports = ({\n allow = [],\n files = ['**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}'],\n}: InternalImportOptions = {}): readonly Linter.Config[] => [\n {\n files: [...files],\n name: 'opetope/internal-imports',\n plugins: { opetope: nativePlugin },\n rules: { 'opetope/no-internal-imports': 'error' },\n },\n ...(allow.length === 0\n ? []\n : [\n {\n files: [...allow],\n name: 'opetope/internal-imports-allowed',\n rules: { 'opetope/no-internal-imports': 'off' as const },\n },\n ]),\n];\n\nconst configuredPlugin = Object.assign(nativePlugin, {\n configs: { internalImports, layers, recommended },\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","captureCommandCleanup","defineFeaturePropertyOrder","idNaming","layerPlacement","noCommandInDeps","noInternalImports","noRedundantConstTuple","noRetiredVocabulary","noSnapshotInUpdate","noSnapshotReadInRender","noSubscribeOutsideModels","noWriteAfterSourceWrite","preferEffectCurrent","preferModelSelection","requireDeclaredModels","requireLiteralId","enabledPredicate","nativePlugin","recommended","placement","options","layer","files","subscriptions","models","tests","layers","internalImports","allow","configuredPlugin","opetopeLint"],"mappings":"urCAoCA,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,QAAQ,EAChD,MAAO,CACL,0BAA2BC,EAC3B,gCAAiCC,EACjC,YAAaC,EACb,kBAAmBC,EACnB,qBAAsBC,EACtB,sBAAuBC,EACvB,2BAA4BC,EAC5B,wBAAyBC,EACzB,wBAAyBC,EACzB,6BAA8BC,EAC9B,8BAA+BC,EAC/B,8BAA+BC,EAC/B,wBAAyBC,EACzB,yBAA0BC,EAC1B,0BAA2BC,EAC3B,qBAAsBC,EACtB,oBAAqBC,CACtB,GAcGC,EAAelB,EAEfmB,EAAc,CAClB,KAAM,sBACN,QAAS,CAAE,QAASD,CAAY,EAChC,MAAO,CACL,kCAAmC,QACnC,wCAAyC,QACzC,oBAAqB,QACrB,0BAA2B,MAC3B,6BAA8B,QAC9B,8BAA+B,QAC/B,mCAAoC,QACpC,gCAAiC,QACjC,gCAAiC,QACjC,qCAAsC,QACtC,sCAAuC,MACvC,sCAAuC,QACvC,gCAAiC,QACjC,iCAAkC,MAClC,kCAAmC,QACnC,6BAA8B,QAC9B,4BAA6B,OAC9B,GAOGE,EAAaC,GACjBxB,EAAO,QAAQyB,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,EAAQ3B,CAAU,IACtD0B,EAAO,SAAW,EACd,CAAA,EACA,CACE,CACE,MAAO3B,EACP,KAAM,+BACN,QAAS,CAAE,QAASoB,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,EAO/GO,EAAkB,CAAC,CACvB,MAAAC,EAAQ,CAAA,EACR,MAAAN,EAAQ,CAAC,sCAAsC,CAAC,EACvB,KAAiC,CAC1D,CACE,MAAO,CAAC,GAAGA,CAAK,EAChB,KAAM,2BACN,QAAS,CAAE,QAASL,CAAY,EAChC,MAAO,CAAE,8BAA+B,OAAO,CAChD,EACD,GAAIW,EAAM,SAAW,EACjB,CAAA,EACA,CACE,CACE,MAAO,CAAC,GAAGA,CAAK,EAChB,KAAM,mCACN,MAAO,CAAE,8BAA+B,KAAc,CACvD,IAIHC,EAAmB,OAAO,OAAOZ,EAAc,CACnD,QAAS,CAAE,gBAAAU,EAAiB,OAAAD,EAAQ,YAAAR,CAAW,CAChD,CAAA,EAKKY,EAAcD"}
@@ -18,14 +18,14 @@ declare function isResourceHook(source: TSESLint.SourceCode, node: TSESTree.Node
18
18
  */
19
19
  declare function isSurfaceValue(source: TSESLint.SourceCode, node: TSESTree.Node): boolean;
20
20
  /**
21
- * D375: `activity` left the `loading` state and stayed on the `ready` one, so a read of it is retired only where a
22
- * narrowing proves which branch it is about. Both halves are asked: the expression is a `ResourceState` of this
23
- * library, and the read stands inside a guard written about that same expression.
21
+ * D462: `activity` is gone from every member of `ResourceState`, so a read of it is retired wherever the expression
22
+ * is one of ours — there is no branch left in which the field survives. D375 had retired it on `loading` alone, so
23
+ * the rule had to prove which branch a read stood in; that machinery is gone with the half-retirement it served.
24
24
  */
25
- declare function isLoadingActivity(source: TSESLint.SourceCode, node: TSESTree.MemberExpression): boolean;
25
+ declare function isStateActivity(source: TSESLint.SourceCode, node: TSESTree.MemberExpression): boolean;
26
26
  /**
27
27
  * D411: the settled answer a consumer keeps — `.outcome` read on a `useCommand`, or the name it was destructured
28
28
  * into. `status` is a common word, so the rule asks the symbol: nothing but this object is reported.
29
29
  */
30
30
  declare function isCommandOutcome(source: TSESLint.SourceCode, node: TSESTree.Node): boolean;
31
- export { isCommandOutcome, isLoadingActivity, isResourceHook, isResourceValue, isSurfaceValue };
31
+ export { isCommandOutcome, isResourceHook, isResourceValue, isStateActivity, isSurfaceValue };
@@ -1,2 +1,2 @@
1
- import{AST_NODE_TYPES as r,TSESLint as b}from"@typescript-eslint/utils";import{within as g,propertyName as x}from"./ast.js";import{methodPath as S,isContextFunction as C}from"./declaration-ingress.js";import{localValue as p,isApi as a,unwrap as u,definitionOf as h}from"./model-bindings.js";const v=new Set(["resource.live","resource.load"]),I="loading";function c(e,t){const n=p(e,t);if(n.type!==r.CallExpression)return!1;const i=S(e,n.callee);return i!==void 0&&v.has(i.method)&&C(e,i.fn)}function s(e,t){const n=p(e,t);return n.type===r.CallExpression&&a(e,n.callee,"@opetope/react","useResource",!0)}function y(e,t){const n=p(e,t);return n.type===r.CallExpression&&a(e,n.callee,"@opetope/react","useCommand",!0)}function O(e,t){const n=p(e,t);return n.type===r.CallExpression&&a(e,n.callee,"@opetope/navigation/react","defineSurface",!0)}function m(e,t){if(t.type!==r.MemberExpression||t.computed||t.property.type!==r.Identifier||t.property.name!=="state")return!1;const n=u(t.object);return c(e,n)||s(e,n)}function R(e,t){return t.type!==r.MemberExpression||t.computed||t.property.type!==r.Identifier||t.property.name!=="getSnapshot"?!1:m(e,u(t.object))}function d(e,t,n){const i=h(e,t);if(i?.type!==b.Scope.DefinitionType.Variable)return;const{init:o}=i.node,f=i.name.parent;if(!(o===null||f.type!==r.Property)&&!(x(f)!==n||f.parent!==i.node.id))return o}function T(e,t){if(t.type===r.Identifier){const i=d(e,t,"state");if(i!==void 0)return s(e,i)}const n=p(e,t);return n.type===r.CallExpression?R(e,n.callee):m(e,n)}function j(e,t,n){return t.type!==r.MemberExpression||t.computed||t.property.type!==r.Identifier||t.property.name!=="kind"?!1:e.getText(t.object)===n}function E(e,t,n,i){return n.type===r.Literal&&n.value===I&&j(e,t,i)}function l(e,t,n){return t.type===r.LogicalExpression&&t.operator==="&&"?l(e,t.left,n)||l(e,t.right,n):t.type!==r.BinaryExpression||t.operator!=="==="?!1:E(e,t.left,t.right,n)||E(e,t.right,t.left,n)}function L(e){if(e.type===r.IfStatement)return{body:e.consequent,test:e.test};if(e.type===r.ConditionalExpression)return{body:e.consequent,test:e.test};if(e.type===r.LogicalExpression&&e.operator==="&&")return{body:e.right,test:e.left}}function k(e,t){if(!T(e,t.object))return!1;const n=e.getText(t.object);return e.getAncestors(t).some(i=>{const o=L(i);return o!==void 0&&g(t,o.body)&&l(e,o.test,n)})}function A(e,t){if(t.type===r.Identifier){const i=d(e,t,"outcome");if(i!==void 0)return y(e,i)}const n=p(e,t);return n.type!==r.MemberExpression||n.computed||n.property.type!==r.Identifier||n.property.name!=="outcome"?!1:y(e,u(n.object))}export{A as isCommandOutcome,k as isLoadingActivity,s as isResourceHook,c as isResourceValue,O as isSurfaceValue};
1
+ import{AST_NODE_TYPES as i,TSESLint as y}from"@typescript-eslint/utils";import{propertyName as S}from"./ast.js";import{methodPath as E,isContextFunction as C}from"./declaration-ingress.js";import{localValue as o,isApi as a,unwrap as u,definitionOf as b}from"./model-bindings.js";const x=new Set(["resource.live","resource.load"]);function c(e,t){const n=o(e,t);if(n.type!==i.CallExpression)return!1;const r=E(e,n.callee);return r!==void 0&&x.has(r.method)&&C(e,r.fn)}function f(e,t){const n=o(e,t);return n.type===i.CallExpression&&a(e,n.callee,"@opetope/react","useResource",!0)}function l(e,t){const n=o(e,t);return n.type===i.CallExpression&&a(e,n.callee,"@opetope/react","useCommand",!0)}function v(e,t){const n=o(e,t);return n.type===i.CallExpression&&a(e,n.callee,"@opetope/navigation/react","defineSurface",!0)}function m(e,t){if(t.type!==i.MemberExpression||t.computed||t.property.type!==i.Identifier||t.property.name!=="state")return!1;const n=u(t.object);return c(e,n)||f(e,n)}function R(e,t){return t.type!==i.MemberExpression||t.computed||t.property.type!==i.Identifier||t.property.name!=="getSnapshot"?!1:m(e,u(t.object))}function d(e,t,n){const r=b(e,t);if(r?.type!==y.Scope.DefinitionType.Variable)return;const{init:s}=r.node,p=r.name.parent;if(!(s===null||p.type!==i.Property)&&!(S(p)!==n||p.parent!==r.node.id))return s}function h(e,t){if(t.type===i.Identifier){const r=d(e,t,"state");if(r!==void 0)return f(e,r)}const n=o(e,t);return n.type===i.CallExpression?R(e,n.callee):m(e,n)}function I(e,t){return h(e,t.object)}function j(e,t){if(t.type===i.Identifier){const r=d(e,t,"outcome");if(r!==void 0)return l(e,r)}const n=o(e,t);return n.type!==i.MemberExpression||n.computed||n.property.type!==i.Identifier||n.property.name!=="outcome"?!1:l(e,u(n.object))}export{j as isCommandOutcome,f as isResourceHook,c as isResourceValue,I as isStateActivity,v as isSurfaceValue};
2
2
  //# sourceMappingURL=retired-vocabulary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"retired-vocabulary.js","sources":["../src/retired-vocabulary.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils';\n\nimport { propertyName, within } from './ast';\nimport { isContextFunction, methodPath } from './declaration-ingress';\nimport { definitionOf, isApi, localValue, unwrap } from './model-bindings';\n\n/** D349: the two factories of the Resource family. Both answer the object whose verbs a migration renames. */\nconst RESOURCE_FACTORIES = new Set(['resource.live', 'resource.load']);\n/** D375: the one kind of `ResourceState` that lost `activity`; a `ready` one still carries the record whole. */\nconst LOADING = 'loading';\n\n/** A narrowing as it is written: the test that proves the kind, and the half of the code it protects. */\ntype Guard = { readonly body: TSESTree.Node; readonly test: TSESTree.Node };\n\n/**\n * A value this module proved is a Resource of this library: the `resource.load` or `resource.live` that declared it,\n * read past the name it was given. The shape decides first and the resolution second, so a call that cannot be a\n * declaration never pays for the context it would have been declared on (D323).\n */\nfunction isResourceValue(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n const value = localValue(source, node);\n\n if (value.type !== AST_NODE_TYPES.CallExpression) return false;\n\n const named = methodPath(source, value.callee);\n\n return named !== undefined && RESOURCE_FACTORIES.has(named.method) && isContextFunction(source, named.fn);\n}\n\n/**\n * `useResource(book)`: the record of hooks, under whatever local name this file gave the import. The module is\n * `@opetope/react` exactly — a host's own `./hooks` must not pass for ours, which is what `exact` asks for (D309).\n */\nfunction isResourceHook(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n const value = localValue(source, node);\n\n return (\n value.type === AST_NODE_TYPES.CallExpression && isApi(source, value.callee, '@opetope/react', 'useResource', true)\n );\n}\n\n/**\n * D411: `useCommand(save)` — the one consumer of a command, under whatever local name this file gave the import.\n * The module is `@opetope/react` exactly, for the reason `useResource` is asked exactly (D309).\n */\nfunction isCommandHook(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n const value = localValue(source, node);\n\n return (\n value.type === AST_NODE_TYPES.CallExpression && isApi(source, value.callee, '@opetope/react', 'useCommand', true)\n );\n}\n\n/**\n * D411, D415: the surface `defineSurface` answers, under whatever local name this file gave the import. The module\n * is `@opetope/navigation/react` exactly, for the reason `useResource` is asked exactly (D309): `policy` is a word\n * a host writes about its own objects all day, so the rule asks the symbol and never the spelling.\n */\nfunction isSurfaceValue(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n const value = localValue(source, node);\n\n return (\n value.type === AST_NODE_TYPES.CallExpression &&\n isApi(source, value.callee, '@opetope/navigation/react', 'defineSurface', true)\n );\n}\n\n/** `.state` read on a Resource of this library or on the record `useResource` answers. */\nfunction isStateMember(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n if (node.type !== AST_NODE_TYPES.MemberExpression || node.computed) return false;\n\n if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== 'state') return false;\n\n const object = unwrap(node.object);\n\n return isResourceValue(source, object) || isResourceHook(source, object);\n}\n\n/** `book.state.getSnapshot()`: the state as a model reads it. */\nfunction isSnapshotRead(source: TSESLint.SourceCode, callee: TSESTree.Node): boolean {\n if (callee.type !== AST_NODE_TYPES.MemberExpression || callee.computed) return false;\n\n if (callee.property.type !== AST_NODE_TYPES.Identifier || callee.property.name !== 'getSnapshot') return false;\n\n return isStateMember(source, unwrap(callee.object));\n}\n\n/**\n * `const { state } = useResource(book)`: the value a name was destructured out of, under the key it was taken by.\n * `localValue` answers the whole initializer for such a name, which is the record and not the member, so the key is\n * read here instead — the way a context member is read off the pattern that bound it.\n */\nfunction takenFrom(source: TSESLint.SourceCode, node: TSESTree.Identifier, key: string): TSESTree.Node | undefined {\n const definition = definitionOf(source, node);\n\n if (definition?.type !== TSESLint.Scope.DefinitionType.Variable) return undefined;\n\n const { init } = definition.node;\n const property = definition.name.parent;\n\n if (init === null || property.type !== AST_NODE_TYPES.Property) return undefined;\n\n if (propertyName(property) !== key || property.parent !== definition.node.id) return undefined;\n\n return init;\n}\n\n/** The `ResourceState` a name holds: the member itself, one value read out of it, or the key it was taken from. */\nfunction isResourceState(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n if (node.type === AST_NODE_TYPES.Identifier) {\n const taken = takenFrom(source, node, 'state');\n\n if (taken !== undefined) return isResourceHook(source, taken);\n }\n\n const value = localValue(source, node);\n\n return value.type === AST_NODE_TYPES.CallExpression\n ? isSnapshotRead(source, value.callee)\n : isStateMember(source, value);\n}\n\n/** `state.kind` read off the same expression the `activity` was read off, compared as the author wrote it. */\nfunction isKindOf(source: TSESLint.SourceCode, node: TSESTree.Node, text: string): boolean {\n if (node.type !== AST_NODE_TYPES.MemberExpression || node.computed) return false;\n\n if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== 'kind') return false;\n\n return source.getText(node.object) === text;\n}\n\nfunction isLoadingTest(source: TSESLint.SourceCode, kind: TSESTree.Node, word: TSESTree.Node, text: string): boolean {\n return word.type === AST_NODE_TYPES.Literal && word.value === LOADING && isKindOf(source, kind, text);\n}\n\n/** `state.kind === 'loading'` written about this very expression, through the `&&` chain a guard may be built of. */\nfunction narrows(source: TSESLint.SourceCode, test: TSESTree.Node, text: string): boolean {\n if (test.type === AST_NODE_TYPES.LogicalExpression && test.operator === '&&') {\n return narrows(source, test.left, text) || narrows(source, test.right, text);\n }\n\n if (test.type !== AST_NODE_TYPES.BinaryExpression || test.operator !== '===') return false;\n\n return isLoadingTest(source, test.left, test.right, text) || isLoadingTest(source, test.right, test.left, text);\n}\n\n/** The three shapes a narrowing is written in, each with the half of the code it protects. */\nfunction guardOf(node: TSESTree.Node): Guard | undefined {\n if (node.type === AST_NODE_TYPES.IfStatement) return { body: node.consequent, test: node.test };\n\n if (node.type === AST_NODE_TYPES.ConditionalExpression) return { body: node.consequent, test: node.test };\n\n if (node.type === AST_NODE_TYPES.LogicalExpression && node.operator === '&&') {\n return { body: node.right, test: node.left };\n }\n\n return undefined;\n}\n\n/**\n * D375: `activity` left the `loading` state and stayed on the `ready` one, so a read of it is retired only where a\n * narrowing proves which branch it is about. Both halves are asked: the expression is a `ResourceState` of this\n * library, and the read stands inside a guard written about that same expression.\n */\nfunction isLoadingActivity(source: TSESLint.SourceCode, node: TSESTree.MemberExpression): boolean {\n if (!isResourceState(source, node.object)) return false;\n\n const text = source.getText(node.object);\n\n return source.getAncestors(node).some(ancestor => {\n const guard = guardOf(ancestor);\n\n return guard !== undefined && within(node, guard.body) && narrows(source, guard.test, text);\n });\n}\n\n/**\n * D411: the settled answer a consumer keeps — `.outcome` read on a `useCommand`, or the name it was destructured\n * into. `status` is a common word, so the rule asks the symbol: nothing but this object is reported.\n */\nfunction isCommandOutcome(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n if (node.type === AST_NODE_TYPES.Identifier) {\n const taken = takenFrom(source, node, 'outcome');\n\n if (taken !== undefined) return isCommandHook(source, taken);\n }\n\n const value = localValue(source, node);\n\n if (value.type !== AST_NODE_TYPES.MemberExpression || value.computed) return false;\n\n if (value.property.type !== AST_NODE_TYPES.Identifier || value.property.name !== 'outcome') return false;\n\n return isCommandHook(source, unwrap(value.object));\n}\n\nexport { isCommandOutcome, isLoadingActivity, isResourceHook, isResourceValue, isSurfaceValue };\n"],"names":["RESOURCE_FACTORIES","LOADING","isResourceValue","source","node","value","localValue","AST_NODE_TYPES","named","methodPath","isContextFunction","isResourceHook","isApi","isCommandHook","isSurfaceValue","isStateMember","object","unwrap","isSnapshotRead","callee","takenFrom","key","definition","definitionOf","TSESLint","init","property","propertyName","isResourceState","taken","isKindOf","text","isLoadingTest","kind","word","narrows","test","guardOf","isLoadingActivity","ancestor","guard","within","isCommandOutcome"],"mappings":"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"}
1
+ {"version":3,"file":"retired-vocabulary.js","sources":["../src/retired-vocabulary.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils';\n\nimport { propertyName } from './ast';\nimport { isContextFunction, methodPath } from './declaration-ingress';\nimport { definitionOf, isApi, localValue, unwrap } from './model-bindings';\n\n/** D349: the two factories of the Resource family. Both answer the object whose verbs a migration renames. */\nconst RESOURCE_FACTORIES = new Set(['resource.live', 'resource.load']);\n/**\n * A value this module proved is a Resource of this library: the `resource.load` or `resource.live` that declared it,\n * read past the name it was given. The shape decides first and the resolution second, so a call that cannot be a\n * declaration never pays for the context it would have been declared on (D323).\n */\nfunction isResourceValue(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n const value = localValue(source, node);\n\n if (value.type !== AST_NODE_TYPES.CallExpression) return false;\n\n const named = methodPath(source, value.callee);\n\n return named !== undefined && RESOURCE_FACTORIES.has(named.method) && isContextFunction(source, named.fn);\n}\n\n/**\n * `useResource(book)`: the record of hooks, under whatever local name this file gave the import. The module is\n * `@opetope/react` exactly — a host's own `./hooks` must not pass for ours, which is what `exact` asks for (D309).\n */\nfunction isResourceHook(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n const value = localValue(source, node);\n\n return (\n value.type === AST_NODE_TYPES.CallExpression && isApi(source, value.callee, '@opetope/react', 'useResource', true)\n );\n}\n\n/**\n * D411: `useCommand(save)` — the one consumer of a command, under whatever local name this file gave the import.\n * The module is `@opetope/react` exactly, for the reason `useResource` is asked exactly (D309).\n */\nfunction isCommandHook(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n const value = localValue(source, node);\n\n return (\n value.type === AST_NODE_TYPES.CallExpression && isApi(source, value.callee, '@opetope/react', 'useCommand', true)\n );\n}\n\n/**\n * D411, D415: the surface `defineSurface` answers, under whatever local name this file gave the import. The module\n * is `@opetope/navigation/react` exactly, for the reason `useResource` is asked exactly (D309): `policy` is a word\n * a host writes about its own objects all day, so the rule asks the symbol and never the spelling.\n */\nfunction isSurfaceValue(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n const value = localValue(source, node);\n\n return (\n value.type === AST_NODE_TYPES.CallExpression &&\n isApi(source, value.callee, '@opetope/navigation/react', 'defineSurface', true)\n );\n}\n\n/** `.state` read on a Resource of this library or on the record `useResource` answers. */\nfunction isStateMember(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n if (node.type !== AST_NODE_TYPES.MemberExpression || node.computed) return false;\n\n if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== 'state') return false;\n\n const object = unwrap(node.object);\n\n return isResourceValue(source, object) || isResourceHook(source, object);\n}\n\n/** `book.state.getSnapshot()`: the state as a model reads it. */\nfunction isSnapshotRead(source: TSESLint.SourceCode, callee: TSESTree.Node): boolean {\n if (callee.type !== AST_NODE_TYPES.MemberExpression || callee.computed) return false;\n\n if (callee.property.type !== AST_NODE_TYPES.Identifier || callee.property.name !== 'getSnapshot') return false;\n\n return isStateMember(source, unwrap(callee.object));\n}\n\n/**\n * `const { state } = useResource(book)`: the value a name was destructured out of, under the key it was taken by.\n * `localValue` answers the whole initializer for such a name, which is the record and not the member, so the key is\n * read here instead — the way a context member is read off the pattern that bound it.\n */\nfunction takenFrom(source: TSESLint.SourceCode, node: TSESTree.Identifier, key: string): TSESTree.Node | undefined {\n const definition = definitionOf(source, node);\n\n if (definition?.type !== TSESLint.Scope.DefinitionType.Variable) return undefined;\n\n const { init } = definition.node;\n const property = definition.name.parent;\n\n if (init === null || property.type !== AST_NODE_TYPES.Property) return undefined;\n\n if (propertyName(property) !== key || property.parent !== definition.node.id) return undefined;\n\n return init;\n}\n\n/** The `ResourceState` a name holds: the member itself, one value read out of it, or the key it was taken from. */\nfunction isResourceState(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n if (node.type === AST_NODE_TYPES.Identifier) {\n const taken = takenFrom(source, node, 'state');\n\n if (taken !== undefined) return isResourceHook(source, taken);\n }\n\n const value = localValue(source, node);\n\n return value.type === AST_NODE_TYPES.CallExpression\n ? isSnapshotRead(source, value.callee)\n : isStateMember(source, value);\n}\n\n/**\n * D462: `activity` is gone from every member of `ResourceState`, so a read of it is retired wherever the expression\n * is one of ours — there is no branch left in which the field survives. D375 had retired it on `loading` alone, so\n * the rule had to prove which branch a read stood in; that machinery is gone with the half-retirement it served.\n */\nfunction isStateActivity(source: TSESLint.SourceCode, node: TSESTree.MemberExpression): boolean {\n return isResourceState(source, node.object);\n}\n\n/**\n * D411: the settled answer a consumer keeps — `.outcome` read on a `useCommand`, or the name it was destructured\n * into. `status` is a common word, so the rule asks the symbol: nothing but this object is reported.\n */\nfunction isCommandOutcome(source: TSESLint.SourceCode, node: TSESTree.Node): boolean {\n if (node.type === AST_NODE_TYPES.Identifier) {\n const taken = takenFrom(source, node, 'outcome');\n\n if (taken !== undefined) return isCommandHook(source, taken);\n }\n\n const value = localValue(source, node);\n\n if (value.type !== AST_NODE_TYPES.MemberExpression || value.computed) return false;\n\n if (value.property.type !== AST_NODE_TYPES.Identifier || value.property.name !== 'outcome') return false;\n\n return isCommandHook(source, unwrap(value.object));\n}\n\nexport { isCommandOutcome, isResourceHook, isResourceValue, isStateActivity, isSurfaceValue };\n"],"names":["RESOURCE_FACTORIES","isResourceValue","source","node","value","localValue","AST_NODE_TYPES","named","methodPath","isContextFunction","isResourceHook","isApi","isCommandHook","isSurfaceValue","isStateMember","object","unwrap","isSnapshotRead","callee","takenFrom","key","definition","definitionOf","TSESLint","init","property","propertyName","isResourceState","taken","isStateActivity","isCommandOutcome"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- type MessageIds = 'commandLane' | 'commandName' | 'commandOnce' | 'commandOutcomeStatus' | 'commandPolicy' | 'commandQueueBy' | 'conditionFrom' | 'contextCall' | 'contextCalls' | 'contributionWhen' | 'deliveryKey' | 'deliveryKind' | 'deliveryReject' | 'devtoolsResourceActivity' | 'effectOnDispose' | 'effectSkipInitial' | 'effectWhen' | 'eventBackpressure' | 'fromExternal' | 'loadingActivity' | 'navigatorPolicy' | 'resourceDisposer' | 'resourceInvalidate' | 'runtimeInternalEntry' | 'scopeKeyed' | 'useCommands';
1
+ type MessageIds = 'commandLane' | 'commandLatest' | 'commandName' | 'commandOnce' | 'commandOutcomeStatus' | 'commandPolicy' | 'commandQueueBy' | 'conditionFrom' | 'contextCall' | 'contextCalls' | 'contributionWhen' | 'deliveryKey' | 'deliveryKind' | 'deliveryReject' | 'effectOnDispose' | 'effectSkipInitial' | 'effectWhen' | 'eventBackpressure' | 'fromExternal' | 'navigatorPolicy' | 'resourceActivity' | 'resourceDisposer' | 'resourceInvalidate' | 'runtimeInternalEntry' | 'scopeKeyed' | 'stateActivity' | 'useCommands';
2
2
  declare const noRetiredVocabulary: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
3
3
  name: string;
4
4
  };
@@ -1,2 +1,2 @@
1
- import{AST_NODE_TYPES as s}from"@typescript-eslint/utils";import{propertyName as l,findProperty as E}from"../ast.js";import{methodPath as w,isContextFunction as O}from"../declaration-ingress.js";import{isFeatureSection as A,isApi as M,localValue as u}from"../model-bindings.js";import{isResourceValue as N,isResourceHook as T,isLoadingActivity as x,isSurfaceValue as S,isCommandOutcome as P}from"../retired-vocabulary.js";import{createRule as V}from"../rule.js";const d=new Map([["lane","commandLane"],["once","commandOnce"],["policy","commandPolicy"],["queueBy","commandQueueBy"]]),_=new Map([["onDispose","effectOnDispose"],["skipInitial","effectSkipInitial"],["when","effectWhen"]]),W=new Map([["backpressure","eventBackpressure"]]),B=new Map([["key","deliveryKey"],["kind","deliveryKind"]]),j=new Map,y=["backpressure","delivery"],L=new Map([["overflow",new Map([["reject","deliveryReject"]])]]),m=new Map([["when","contributionWhen"]]),F=new Map([["pipe",{at:[2],carries:[],words:m}],["register",{at:[2],carries:[],words:m}],["slot",{at:[2],carries:[],words:m}]]),q=new Map([["from","conditionFrom"]]),K=new Map([["call",{at:[1,2],carries:[],words:d}],["calls",{at:[2],carries:[],words:d}],["command",{at:[1,2],carries:[],words:d}],["effect",{at:[2],carries:[],words:_}],["event",{at:[3],carries:y,words:W}],["resource.live",{at:[0],carriedValues:L,carries:y,words:j}],["select",{at:[2],carries:[],words:d}]]),Y=new Map([["activity","loadingActivity"],["invalidate","resourceInvalidate"],["policy","navigatorPolicy"],["status","commandOutcomeStatus"]]),U=new Map([["call","contextCall"],["calls","contextCalls"],["scope.keyed","scopeKeyed"]]),z=new Map([["ApplicationConditionBinding",{messageId:"runtimeInternalEntry",module:"@opetope/runtime/internal",replacement:"@opetope/runtime"}],["ApplicationExecution",{messageId:"runtimeInternalEntry",module:"@opetope/runtime/internal",replacement:"@opetope/runtime"}],["ApplicationImportBinding",{messageId:"runtimeInternalEntry",module:"@opetope/runtime/internal",replacement:"@opetope/runtime"}],["Call",{messageId:"commandName",replacement:"Command"}],["CallError",{messageId:"commandName",replacement:"CommandError"}],["CallInputArgs",{messageId:"commandName",replacement:"CommandInputArgs"}],["CallTimeoutError",{messageId:"commandName",replacement:"CommandTimeoutError"}],["NavigatorPolicy",{messageId:"navigatorPolicy",replacement:"NavigatorCatalogue"}],["ResourceActivity",{messageId:"devtoolsResourceActivity",module:"@opetope/devtools",replacement:"ResourceNodeActivity"}],["ResourceDisposer",{messageId:"resourceDisposer",replacement:"Disposer"}],["RunCallOptions",{messageId:"commandName",replacement:"RunCommandOptions"}],["externalReadable",{messageId:"fromExternal",replacement:"fromExternal"}],["runCall",{messageId:"commandName",replacement:"runCommand"}],["useCommands",{messageId:"useCommands",replacement:"useModel"}]]);function H(r){return r.type===s.MemberExpression?r.property:r}function Q(r){return r.imported.type===s.Identifier?r.imported.name:r.imported.value}const G=V({create(r){const a=r.sourceCode,v=e=>{const t=w(a,e.callee);if(t===void 0)return;const n={modifiers:K.get(t.method),word:U.get(t.method)};if(!(n.modifiers===void 0&&n.word===void 0))return O(a,t.fn)?n:void 0},p=(e,t)=>{const n=e.arguments[t];if(n===void 0||n.type===s.SpreadElement)return;const o=u(a,n);return o.type===s.ObjectExpression?o:void 0},g=e=>{const t=w(a,e.callee),n=t===void 0?void 0:F.get(t.method);if(!(t===void 0||n===void 0))return A(a,t.fn,"provides",!0)?n:void 0},b=e=>{if(M(a,e.callee,"@opetope/runtime","defineCondition",!0))return p(e,1)},c=(e,t)=>{for(const n of e.properties){if(n.type!==s.Property)continue;const o=l(n),i=o===void 0?void 0:t.get(o);i!==void 0&&r.report({messageId:i,node:n.key})}},D=(e,t)=>{const n=l(e),o=n===void 0?void 0:t.get(n);if(o===void 0)return;const i=u(a,e.value);return i.type===s.Literal&&typeof i.value=="string"?o.get(i.value):void 0},I=(e,t)=>{for(const n of e.properties){if(n.type!==s.Property)continue;const o=D(n,t);o!==void 0&&r.report({messageId:o,node:n.value})}},C=(e,t,n)=>{const o=E(e,t),i=o===void 0?void 0:u(a,o.value);i?.type===s.ObjectExpression&&(c(i,B),n.carriedValues!==void 0&&I(i,n.carriedValues))},h=(e,t)=>{for(const n of t.at){const o=p(e,n);if(o!==void 0){c(o,t.words);for(const i of t.carries)C(o,i,t)}}},f=e=>N(a,e)||T(a,e),R=(e,t)=>t==="resourceInvalidate"?f(e.object):t==="loadingActivity"?x(a,e):t==="navigatorPolicy"?S(a,e.object):P(a,e.object),k=(e,t)=>{const n=Y.get(t);return n!==void 0&&R(e,n)?n:void 0};return{CallExpression(e){const t=g(e);t!==void 0&&h(e,t);const n=b(e);n!==void 0&&c(n,q);const o=v(e);o!==void 0&&(o.word!==void 0&&r.report({messageId:o.word,node:H(e.callee)}),o.modifiers!==void 0&&h(e,o.modifiers))},ImportDeclaration(e){if(e.source.value.startsWith("@opetope/"))for(const t of e.specifiers){if(t.type!==s.ImportSpecifier)continue;const n=Q(t),o=z.get(n);o!==void 0&&(o.module===void 0||o.module===e.source.value)&&r.report({data:{replacement:o.replacement,word:n},messageId:o.messageId,node:t.imported})}},MemberExpression(e){if(e.computed||e.property.type!==s.Identifier)return;const t=k(e,e.property.name);t!==void 0&&r.report({messageId:t,node:e.property})},Property(e){if(l(e)!=="invalidate"||e.parent.type!==s.ObjectPattern)return;const t=e.parent.parent;t.type!==s.VariableDeclarator||t.init===null||f(t.init)&&r.report({messageId:"resourceInvalidate",node:e.key})}}},meta:{docs:{description:"A word the D365\u2013D411 wave retired is named with the word that replaced it, and never rewritten."},messages:{commandLane:'`lane` is now a member of `concurrency`: write `concurrency: lane`, `concurrency: { by, lane }` for a keyed queue, or `concurrency: { lane, pending: "latest" }` where `policy: "latest"` stood beside it. Which of the three this record meant is in what it wrote together, so nothing here is rewritten for you (D387).',commandName:"`{{word}}` is now `{{replacement}}`: one word for a command, everywhere. The primitive was the last place the vocabulary still said `Call`, while the hook was already `useCommand` and the outcome `CommandOutcome`. There is no alias (D385).",commandOnce:"`once` is now `memoize`: it caches a successful result, it does not stop after one run. `addEventListener(type, handler, { once: true })` is what the platform means by the word, and it is not what this option ever did (D389).",commandOutcomeStatus:'`status` is now `kind` on a `CommandOutcome`: one word for the discriminant of a settled answer, the one `ResourceState`, `ResourceOperationOutcome`, `ResourceCommitOutcome`, `PaginationOutcome` and a screen result already carry. The three branches are unchanged \u2014 `{ kind: "ok", value }`, `{ kind: "failed", error }`, `{ kind: "cancelled", reason }` (D411).',commandPolicy:'`policy` is now `concurrency`: one word for the order the runs take, written as `queue`, `parallel`, `latest` or a lane. Where `queueBy` or `lane` stood beside it the three collapse into one value \u2014 `{ by }`, `{ by, lane }` or `{ lane, pending: "latest" }` \u2014 so the shape depends on which of them this record wrote, and that is why this rule names the word instead of rewriting it (D387).',commandQueueBy:"`queueBy` is now a member of `concurrency`: write `concurrency: { by: input => key }`, or `concurrency: { by, lane }` where a lane stood beside it (D387).",conditionFrom:"`from` of `defineCondition` is now `source`: write `defineCondition(id, { select, source })`. One word names the dependency a node reads \u2014 `resource.load({ source })` and `attach(source)` already say it, and this node's own refusals said `Condition source` about the field they called `from` (D410, D411).",contextCall:"`call` is now `command`: `ctx.command(run, options?)` in a model, `own.command(within, run, options?)` in a feature. The body takes one argument, its context, and reads the declared input off it as `input` \u2014 and the input is named by annotating that context, `({ input, update }: ModelCommandContext<Deposit>)` in a model and `({ input, source }: FeatureCommandContext<typeof within, Deposit>)` in a feature, because there is no other place to name it (D385, D386, D444).",contextCalls:'`ctx.calls` and `own.calls` are now `ctx.select` and `own.select`: declaring a body and selecting a command a dependency already declares are two mechanisms, so they are two words. `select(source, "name")` answers one command and `select(source, ["a", "b"])` a record of them (D388).',contributionWhen:"`when` of a contribution is now `enabled`: write `slot(target, value, { enabled })`, and the same at `pipe` and `register`. A truth the runtime reads while the node exists is `enabled`, at a contribution and at a Resource alike; `when` names the other mechanism \u2014 the declared `Condition`s of `defineFeature({ when })`, which the application resolves before anything exists. `scope.while` keeps its own `when` (D378, D411).",deliveryKey:'Inside a delivery record `key` is now `by`: `{ pending: "latest", by }` keeps one waiting place per key instead of one for the whole node (D374).',deliveryKind:'Inside a delivery record `kind` is now `pending`: `kind: "latest"` is `pending: "latest"`, and `kind: "queue"` is `pending: "all"` \u2014 the backlog only an event has. The discriminant moved because with one dimension shared by both nodes, the discriminant is that dimension (D374).',deliveryReject:'`overflow: "reject"` is now `overflow: "drop"`: one word at both nodes for \xABthe new one does not enter and `emit` answers `false`\xBB. `"flush-oldest"` is unchanged and still the default of a keyed delivery (D369, D411).',devtoolsResourceActivity:"`ResourceActivity` of `@opetope/devtools` is now `ResourceNodeActivity`: `@opetope/core` exports a `ResourceActivity` of its own \u2014 the union a `ready` state carries \u2014 and one name carried two unrelated types on two public entries. Import the core one under its own name (D411).",effectOnDispose:"`onDispose` is now `finalize`: an effect has two releases \u2014 the disposer a run returns, and the one the node itself gets once \u2014 and an `on*` prefix did not tell them apart. No word of the authoring vocabulary carries that prefix any more (D379).",effectSkipInitial:"`skipInitial` is now `initial`, and the polarity is inverted: `skipInitial: true` is `initial: false`, and `initial` defaults to `true`. Both words are booleans, so carrying the value across unchanged compiles and means the opposite \u2014 which is why this rule names it and leaves the rewrite to you (D379).",effectWhen:"`when` at an effect is now `filter` or `initial`, and which one depends on what the predicate asks. A predicate that selects values is `filter: (current, previous) => \u2026`; a predicate whose whole job is to refuse the first run \u2014 `(_current, previous) => previous !== undefined` \u2014 is `initial: false`. This rule does not guess between them. The word `when` is untouched at a feature and at `scope.while`; at a contribution it is now `enabled` (D379, D411).",eventBackpressure:'`backpressure` is now `delivery`: one word at both nodes that admit a producer. Write `delivery: "latest"` for one waiting place that the newest payload takes, or the record \u2014 `{ pending, by }`, `{ pending, capacity, overflow }` \u2014 for the rest (D374).',fromExternal:"`externalReadable` is now `fromExternal`: `from*` names where a `Readable` comes from, beside `fromMaybe`. The old name was built from its result, which every word of that module already answers (D380).",loadingActivity:"A `loading` state carries `failure`, not `activity`: read `state.failure` \u2014 `undefined` is \xABboth channels are still viable\xBB, and otherwise `channel` names the one that died terminally and `error` carries its failure. A `ready` state still carries `activity` whole, so this is one branch losing the field and not the field being renamed (D375).",navigatorPolicy:"`NavigatorPolicy` is now `NavigatorCatalogue`, and `surface.policy` is now `surface.catalogue`: this is four callbacks a navigator asks, and D291 made a policy data \u2014 a word when it has no parameters, a record when it has them (D411).",resourceDisposer:"`ResourceDisposer` is now `Disposer`: one name for `() => Awaitable<void>`, which three of them used to spell \u2014 `Disposer`, `ResourceDisposer` and `FeatureDisposer`. It travels on `@opetope/core/internal` beside `Awaitable` (D411).",resourceInvalidate:"`invalidate()` is now `reset()`: it clears the whole cache, drops the current data, opens a new epoch and restarts every configured channel. Everywhere else `invalidate` means \xABmark stale, keep the data\xBB, so the old name promised the opposite of what the verb does; it now names no operation of a Resource at all (D373).",runtimeInternalEntry:"`{{word}}` is published by `{{replacement}}`: import it from there. Three names were published by both entries and every consumer took the internal copy, so the copies are gone and the names are not (D411, D415).",scopeKeyed:"`scope.keyed(source, open, { key })` is now `scope.each(source, key, open)`: `each` says what the node does, one child per element, and the key is required \u2014 so it stands between the list it identifies and the child it opens. The trailing record is gone, which makes this a move and not only a rename (D378).",useCommands:"`useCommands` is gone: a record of command consumers comes from `useModel(Declaration, select)`, which has an owner and a lifetime. One command is still `useCommand` (D388)."},schema:[],type:"problem"},name:"no-retired-vocabulary"});export{G as noRetiredVocabulary};
1
+ import{AST_NODE_TYPES as s}from"@typescript-eslint/utils";import{propertyName as u,findProperty as O}from"../ast.js";import{methodPath as v,isContextFunction as M}from"../declaration-ingress.js";import{isFeatureSection as N,isApi as T,localValue as m}from"../model-bindings.js";import{isResourceValue as A,isResourceHook as S,isStateActivity as x,isSurfaceValue as P,isCommandOutcome as V}from"../retired-vocabulary.js";import{createRule as _}from"../rule.js";const d=new Map([["lane","commandLane"],["once","commandOnce"],["policy","commandPolicy"],["queueBy","commandQueueBy"]]),c=new Map([["concurrency",new Map([["latest","commandLatest"]])]]),W=new Map([["onDispose","effectOnDispose"],["skipInitial","effectSkipInitial"],["when","effectWhen"]]),B=new Map([["backpressure","eventBackpressure"]]),L=new Map([["key","deliveryKey"],["kind","deliveryKind"]]),j=new Map,g=["backpressure","delivery"],F=new Map([["overflow",new Map([["reject","deliveryReject"]])]]),p=new Map([["when","contributionWhen"]]),q=new Map([["pipe",{at:[2],carries:[],words:p}],["register",{at:[2],carries:[],words:p}],["slot",{at:[2],carries:[],words:p}]]),K=new Map([["from","conditionFrom"]]),U=new Map([["call",{at:[1,2],carries:[],values:c,words:d}],["calls",{at:[2],carries:[],values:c,words:d}],["command",{at:[1,2],carries:[],values:c,words:d}],["effect",{at:[2],carries:[],words:W}],["event",{at:[3],carries:g,words:B}],["resource.live",{at:[0],carriedValues:F,carries:g,words:j}],["select",{at:[2],carries:[],values:c,words:d}]]),Y=new Map([["activity","stateActivity"],["invalidate","resourceInvalidate"],["policy","navigatorPolicy"],["status","commandOutcomeStatus"]]),z=new Map([["call","contextCall"],["calls","contextCalls"],["scope.keyed","scopeKeyed"]]),H=new Map([["ApplicationConditionBinding",{messageId:"runtimeInternalEntry",module:"@opetope/runtime/internal",replacement:"@opetope/runtime"}],["ApplicationExecution",{messageId:"runtimeInternalEntry",module:"@opetope/runtime/internal",replacement:"@opetope/runtime"}],["ApplicationImportBinding",{messageId:"runtimeInternalEntry",module:"@opetope/runtime/internal",replacement:"@opetope/runtime"}],["Call",{messageId:"commandName",replacement:"Command"}],["CallError",{messageId:"commandName",replacement:"CommandError"}],["CallInputArgs",{messageId:"commandName",replacement:"CommandInputArgs"}],["CallTimeoutError",{messageId:"commandName",replacement:"CommandTimeoutError"}],["NavigatorPolicy",{messageId:"navigatorPolicy",replacement:"NavigatorCatalogue"}],["ResourceActivity",{messageId:"resourceActivity",replacement:"ResourceNodeActivity"}],["ResourceDisposer",{messageId:"resourceDisposer",replacement:"Disposer"}],["RunCallOptions",{messageId:"commandName",replacement:"RunCommandOptions"}],["externalReadable",{messageId:"fromExternal",replacement:"fromExternal"}],["runCall",{messageId:"commandName",replacement:"runCommand"}],["useCommands",{messageId:"useCommands",replacement:"useModel"}]]);function Q(a){return a.type===s.MemberExpression?a.property:a}function G(a){return a.imported.type===s.Identifier?a.imported.name:a.imported.value}const J=_({create(a){const r=a.sourceCode,b=e=>{const t=v(r,e.callee);if(t===void 0)return;const n={modifiers:U.get(t.method),word:z.get(t.method)};if(!(n.modifiers===void 0&&n.word===void 0))return M(r,t.fn)?n:void 0},h=(e,t)=>{const n=e.arguments[t];if(n===void 0||n.type===s.SpreadElement)return;const o=m(r,n);return o.type===s.ObjectExpression?o:void 0},D=e=>{const t=v(r,e.callee),n=t===void 0?void 0:q.get(t.method);if(!(t===void 0||n===void 0))return N(r,t.fn,"provides",!0)?n:void 0},I=e=>{if(T(r,e.callee,"@opetope/runtime","defineCondition",!0))return h(e,1)},l=(e,t)=>{for(const n of e.properties){if(n.type!==s.Property)continue;const o=u(n),i=o===void 0?void 0:t.get(o);i!==void 0&&a.report({messageId:i,node:n.key})}},C=(e,t)=>{const n=u(e),o=n===void 0?void 0:t.get(n);if(o===void 0)return;const i=m(r,e.value);return i.type===s.Literal&&typeof i.value=="string"?o.get(i.value):void 0},f=(e,t)=>{for(const n of e.properties){if(n.type!==s.Property)continue;const o=C(n,t);o!==void 0&&a.report({messageId:o,node:n.value})}},k=(e,t,n)=>{const o=O(e,t),i=o===void 0?void 0:m(r,o.value);i?.type===s.ObjectExpression&&(l(i,L),n.carriedValues!==void 0&&f(i,n.carriedValues))},w=(e,t)=>{for(const n of t.at){const o=h(e,n);if(o!==void 0){l(o,t.words),t.values!==void 0&&f(o,t.values);for(const i of t.carries)k(o,i,t)}}},y=e=>A(r,e)||S(r,e),R=(e,t)=>t==="resourceInvalidate"?y(e.object):t==="stateActivity"?x(r,e):t==="navigatorPolicy"?P(r,e.object):V(r,e.object),E=(e,t)=>{const n=Y.get(t);return n!==void 0&&R(e,n)?n:void 0};return{CallExpression(e){const t=D(e);t!==void 0&&w(e,t);const n=I(e);n!==void 0&&l(n,K);const o=b(e);o!==void 0&&(o.word!==void 0&&a.report({messageId:o.word,node:Q(e.callee)}),o.modifiers!==void 0&&w(e,o.modifiers))},ImportDeclaration(e){if(e.source.value.startsWith("@opetope/"))for(const t of e.specifiers){if(t.type!==s.ImportSpecifier)continue;const n=G(t),o=H.get(n);o!==void 0&&(o.module===void 0||o.module===e.source.value)&&a.report({data:{replacement:o.replacement,word:n},messageId:o.messageId,node:t.imported})}},MemberExpression(e){if(e.computed||e.property.type!==s.Identifier)return;const t=E(e,e.property.name);t!==void 0&&a.report({messageId:t,node:e.property})},Property(e){if(u(e)!=="invalidate"||e.parent.type!==s.ObjectPattern)return;const t=e.parent.parent;t.type!==s.VariableDeclarator||t.init===null||y(t.init)&&a.report({messageId:"resourceInvalidate",node:e.key})}}},meta:{docs:{description:"A word the D365\u2013D411 wave or a decision after it retired is named with its replacement, never rewritten."},messages:{commandLane:'`lane` is now a member of `concurrency`: write `concurrency: lane`, `concurrency: { by, lane }` for a keyed queue, or `concurrency: { lane, pending: "latest" }` where `policy: "latest"` stood beside it. Which of the three this record meant is in what it wrote together, so nothing here is rewritten for you (D387).',commandLatest:'`concurrency: "latest"` is now `concurrency: { pending: "latest" }`, and `{ lane, pending: "latest" }` where the queue is shared. The word named the input that wins and never named what it wins, so the place is written out: one waiting slot at the end of the lane, taken by a newer input while the body in flight is left to finish. Nothing else about the policy moved (D459).',commandName:"`{{word}}` is now `{{replacement}}`: one word for a command, everywhere. The primitive was the last place the vocabulary still said `Call`, while the hook was already `useCommand` and the outcome `CommandOutcome`. There is no alias (D385).",commandOnce:"`once` is now `memoize`: it caches a successful result, it does not stop after one run. `addEventListener(type, handler, { once: true })` is what the platform means by the word, and it is not what this option ever did (D389).",commandOutcomeStatus:'`status` is now `kind` on a `CommandOutcome`: one word for the discriminant of a settled answer, the one `ResourceState`, `ResourceOperationOutcome`, `ResourceCommitOutcome`, `PaginationOutcome` and a screen result already carry. The three branches are unchanged \u2014 `{ kind: "ok", value }`, `{ kind: "failed", error }`, `{ kind: "cancelled", reason }` (D411).',commandPolicy:'`policy` is now `concurrency`: one word for the order the runs take, written as `queue`, `parallel`, a lane or `{ pending: "latest" }`. Where `queueBy` or `lane` stood beside it the three collapse into one value \u2014 `{ by }`, `{ by, lane }` or `{ lane, pending: "latest" }` \u2014 so the shape depends on which of them this record wrote, and that is why this rule names the word instead of rewriting it (D387, D459).',commandQueueBy:"`queueBy` is now a member of `concurrency`: write `concurrency: { by: input => key }`, or `concurrency: { by, lane }` where a lane stood beside it (D387).",conditionFrom:"`from` of `defineCondition` is now `source`: write `defineCondition(id, { select, source })`. One word names the dependency a node reads \u2014 `resource.load({ source })` and `attach(source)` already say it, and this node's own refusals said `Condition source` about the field they called `from` (D410, D411).",contextCall:"`call` is now `command`: `ctx.command(run, options?)` in a model, `own.command(within, run, options?)` in a feature. The body takes one argument, its context, and reads the declared input off it as `input` \u2014 and `Input` is inferred from every position of the call except the body, so it is written in the cheapest that fits: the result type of a model factory names it in the literal it returns, an annotated option names it (`dedupe: (deposit: Deposit) => \u2026`), a constant names it (`const refill: Command<Refill, void> = ctx.command(\u2026)`), and the annotation of that context \u2014 `({ input, update }: ModelCommandContext<Deposit>)` in a model, `({ input, source }: FeatureCommandContext<typeof within, Deposit>)` in a feature \u2014 is what is left; a feature has the last two only. `command<Deposit>(\u2026)` is not a position: it pins `Output` to its default (D385, D386, D444, D455).",contextCalls:'`ctx.calls` and `own.calls` are now `ctx.select` and `own.select`: declaring a body and selecting a command a dependency already declares are two mechanisms, so they are two words. `select(source, "name")` answers one command and `select(source, ["a", "b"])` a record of them (D388).',contributionWhen:"`when` of a contribution is now `enabled`: write `slot(target, value, { enabled })`, and the same at `pipe` and `register`. A truth the runtime reads while the node exists is `enabled`, at a contribution and at a Resource alike; `when` names the other mechanism \u2014 the declared `Condition`s of `defineFeature({ when })`, which the application resolves before anything exists. `scope.while` keeps its own `when` (D378, D411).",deliveryKey:'Inside a delivery record `key` is now `by`: `{ pending: "latest", by }` keeps one waiting place per key instead of one for the whole node (D374).',deliveryKind:'Inside a delivery record `kind` is now `pending`: `kind: "latest"` is `pending: "latest"`, and `kind: "queue"` is `pending: "all"` \u2014 the backlog only an event has. The discriminant moved because with one dimension shared by both nodes, the discriminant is that dimension (D374).',deliveryReject:'`overflow: "reject"` is now `overflow: "drop"`: one word at both nodes for \xABthe new one does not enter and `emit` answers `false`\xBB. `"flush-oldest"` is unchanged and still the default of a keyed delivery (D369, D411).',effectOnDispose:"`onDispose` is now `finalize`: an effect has two releases \u2014 the disposer a run returns, and the one the node itself gets once \u2014 and an `on*` prefix did not tell them apart. No word of the authoring vocabulary carries that prefix any more (D379).",effectSkipInitial:"`skipInitial` is now `initial`, and the polarity is inverted: `skipInitial: true` is `initial: false`, and `initial` defaults to `true`. Both words are booleans, so carrying the value across unchanged compiles and means the opposite \u2014 which is why this rule names it and leaves the rewrite to you (D379).",effectWhen:"`when` at an effect is now `filter` or `initial`, and which one depends on what the predicate asks. A predicate that selects values is `filter: (current, previous) => \u2026`; a predicate whose whole job is to refuse the first run \u2014 `(_current, previous) => previous !== undefined` \u2014 is `initial: false`. This rule does not guess between them. The word `when` is untouched at a feature and at `scope.while`; at a contribution it is now `enabled` (D379, D411).",eventBackpressure:'`backpressure` is now `delivery`: one word at both nodes that admit a producer. Write `delivery: "latest"` for one waiting place that the newest payload takes, or the record \u2014 `{ pending, by }`, `{ pending, capacity, overflow }` \u2014 for the rest (D374).',fromExternal:"`externalReadable` is now `fromExternal`: `from*` names where a `Readable` comes from, beside `fromMaybe`. The old name was built from its result, which every word of that module already answers (D380).",navigatorPolicy:"`NavigatorPolicy` is now `NavigatorCatalogue`, and `surface.policy` is now `surface.catalogue`: this is four callbacks a navigator asks, and D291 made a policy data \u2014 a word when it has no parameters, a record when it has them (D411).",resourceActivity:"`ResourceActivity` is retired at both entries that spelled it. From `@opetope/devtools` it is `ResourceNodeActivity` (D411). From `@opetope/core` it is gone: a state answers what failed and what is working in two fields of its own, so read `state.failure` and `state.pending` instead of a union that flattened them (D462).",resourceDisposer:"`ResourceDisposer` is now `Disposer`: one name for `() => Awaitable<void>`, which three of them used to spell \u2014 `Disposer`, `ResourceDisposer` and `FeatureDisposer`. It travels on `@opetope/core/internal` beside `Awaitable` (D411).",resourceInvalidate:"`invalidate()` is now `reset()`: it clears the whole cache, drops the current data, opens a new epoch and restarts every configured channel. Everywhere else `invalidate` means \xABmark stale, keep the data\xBB, so the old name promised the opposite of what the verb does; it now names no operation of a Resource at all (D373).",runtimeInternalEntry:"`{{word}}` is published by `{{replacement}}`: import it from there. Three names were published by both entries and every consumer took the internal copy, so the copies are gone and the names are not (D411, D415).",scopeKeyed:"`scope.keyed(source, open, { key })` is now `scope.each(source, key, open)`: `each` says what the node does, one child per element, and the key is required \u2014 so it stands between the list it identifies and the child it opens. The trailing record is gone, which makes this a move and not only a rename (D378).",stateActivity:"No `ResourceState` carries `activity` any more: the union said what a channel was doing and what had failed in one word. Read `state.failure` \u2014 `undefined` is \xABnothing failed\xBB, and otherwise `channel` names the channel that died and `error` carries its failure \u2014 and `state.pending` for the channel with work in flight. Both are declared on every member, so neither needs a narrowing by `kind` first (D462).",useCommands:"`useCommands` is gone: a record of command consumers comes from `useModel(Declaration, select)`, which has an owner and a lifetime. One command is still `useCommand` (D388)."},schema:[],type:"problem"},name:"no-retired-vocabulary"});export{J as noRetiredVocabulary};
2
2
  //# sourceMappingURL=no-retired-vocabulary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"no-retired-vocabulary.js","sources":["../../src/rules/no-retired-vocabulary.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { AST_NODE_TYPES } from '@typescript-eslint/utils';\n\nimport { findProperty, propertyName } from '../ast';\nimport { isContextFunction, methodPath } from '../declaration-ingress';\nimport { isApi, isFeatureSection, localValue } from '../model-bindings';\nimport {\n isCommandOutcome,\n isLoadingActivity,\n isResourceHook,\n isResourceValue,\n isSurfaceValue,\n} from '../retired-vocabulary';\nimport { createRule } from '../rule';\n\ntype MessageIds =\n | 'commandLane'\n | 'commandName'\n | 'commandOnce'\n | 'commandOutcomeStatus'\n | 'commandPolicy'\n | 'commandQueueBy'\n | 'conditionFrom'\n | 'contextCall'\n | 'contextCalls'\n | 'contributionWhen'\n | 'deliveryKey'\n | 'deliveryKind'\n | 'deliveryReject'\n | 'devtoolsResourceActivity'\n | 'effectOnDispose'\n | 'effectSkipInitial'\n | 'effectWhen'\n | 'eventBackpressure'\n | 'fromExternal'\n | 'loadingActivity'\n | 'navigatorPolicy'\n | 'resourceDisposer'\n | 'resourceInvalidate'\n | 'runtimeInternalEntry'\n | 'scopeKeyed'\n | 'useCommands';\n\n/**\n * One name a package no longer exports, and the word that carries its meaning now. D411: `module` is written where\n * the name is retired at one entry and live at another — `ResourceActivity` is still what `@opetope/core` calls the\n * background work of a `ready` state, and `ApplicationConditionBinding` is still the name, on the entry an author\n * is meant to take it from.\n */\ntype Retired = { readonly messageId: MessageIds; readonly module?: string; readonly replacement: string };\n/**\n * Where one node keeps its modifiers, and which retired words live there. `at` holds every position the record is\n * written in across the two surfaces — `ctx.command(run, options)` and `own.command(within, run, options)` — and\n * nothing else at those positions is an object literal, so one list answers both. `carries` names the members whose\n * own record is read in turn: a delivery policy is a record inside a record.\n */\ntype Modifiers = {\n readonly at: readonly number[];\n readonly carries: readonly string[];\n /** D411: a word of a carried record whose **value** was retired, not its key: `overflow: 'reject'` is one. */\n readonly carriedValues?: ReadonlyMap<string, ReadonlyMap<string, MessageIds>>;\n readonly words: ReadonlyMap<string, MessageIds>;\n};\n\n/** D387, D389: the four words the options record of a command declaration and of a selection retired. */\nconst COMMAND_WORDS = new Map<string, MessageIds>([\n ['lane', 'commandLane'],\n ['once', 'commandOnce'],\n ['policy', 'commandPolicy'],\n ['queueBy', 'commandQueueBy'],\n]);\n/** D379: the three modifiers of an effect run. */\nconst EFFECT_WORDS = new Map<string, MessageIds>([\n ['onDispose', 'effectOnDispose'],\n ['skipInitial', 'effectSkipInitial'],\n ['when', 'effectWhen'],\n]);\nconst EVENT_WORDS = new Map<string, MessageIds>([['backpressure', 'eventBackpressure']]);\n/** D374: the two fields inside the record, whichever of the two words the record itself is still written under. */\nconst DELIVERY_WORDS = new Map<string, MessageIds>([\n ['key', 'deliveryKey'],\n ['kind', 'deliveryKind'],\n]);\nconst NO_WORDS = new Map<string, MessageIds>();\nconst DELIVERY = ['backpressure', 'delivery'];\n/** D411: the one field of a delivery whose value moved: a full keyed capacity answers `drop`, not `reject`. */\nconst LIVE_DELIVERY_VALUES = new Map<string, ReadonlyMap<string, MessageIds>>([\n ['overflow', new Map<string, MessageIds>([['reject', 'deliveryReject']])],\n]);\n/** D411: the words a contribution writes beside its value, on the `provides` section that declares it. */\nconst CONTRIBUTION_WORDS = new Map<string, MessageIds>([['when', 'contributionWhen']]);\nconst CONTRIBUTION_RECORDS = new Map<string, Modifiers>([\n ['pipe', { at: [2], carries: [], words: CONTRIBUTION_WORDS }],\n ['register', { at: [2], carries: [], words: CONTRIBUTION_WORDS }],\n ['slot', { at: [2], carries: [], words: CONTRIBUTION_WORDS }],\n]);\n/** D411: the record `defineCondition` takes second; the word it named its source by is the one that moved. */\nconst CONDITION_WORDS = new Map<string, MessageIds>([['from', 'conditionFrom']]);\n\nconst OPTION_RECORDS = new Map<string, Modifiers>([\n ['call', { at: [1, 2], carries: [], words: COMMAND_WORDS }],\n ['calls', { at: [2], carries: [], words: COMMAND_WORDS }],\n ['command', { at: [1, 2], carries: [], words: COMMAND_WORDS }],\n ['effect', { at: [2], carries: [], words: EFFECT_WORDS }],\n ['event', { at: [3], carries: DELIVERY, words: EVENT_WORDS }],\n ['resource.live', { at: [0], carriedValues: LIVE_DELIVERY_VALUES, carries: DELIVERY, words: NO_WORDS }],\n ['select', { at: [2], carries: [], words: COMMAND_WORDS }],\n]);\n\n/** D375, D411, D415: the members whose name is retired, each with the object it has to have been read on. */\nconst RETIRED_MEMBERS = new Map<string, MessageIds>([\n ['activity', 'loadingActivity'],\n ['invalidate', 'resourceInvalidate'],\n ['policy', 'navigatorPolicy'],\n ['status', 'commandOutcomeStatus'],\n]);\n\n/** D378, D385, D388: the methods themselves, named on a declaring context of this library. */\nconst RETIRED_METHODS = new Map<string, MessageIds>([\n ['call', 'contextCall'],\n ['calls', 'contextCalls'],\n ['scope.keyed', 'scopeKeyed'],\n]);\n\n/** D380, D385, D388: the names an `@opetope/*` entry no longer exports. The module itself is the proof. */\nconst RETIRED_IMPORTS = new Map<string, Retired>([\n [\n 'ApplicationConditionBinding',\n { messageId: 'runtimeInternalEntry', module: '@opetope/runtime/internal', replacement: '@opetope/runtime' },\n ],\n /** D411, D415: the entry retired three copies, and a table that held one left two migrations unnamed. */\n [\n 'ApplicationExecution',\n { messageId: 'runtimeInternalEntry', module: '@opetope/runtime/internal', replacement: '@opetope/runtime' },\n ],\n [\n 'ApplicationImportBinding',\n { messageId: 'runtimeInternalEntry', module: '@opetope/runtime/internal', replacement: '@opetope/runtime' },\n ],\n ['Call', { messageId: 'commandName', replacement: 'Command' }],\n ['CallError', { messageId: 'commandName', replacement: 'CommandError' }],\n ['CallInputArgs', { messageId: 'commandName', replacement: 'CommandInputArgs' }],\n ['CallTimeoutError', { messageId: 'commandName', replacement: 'CommandTimeoutError' }],\n ['NavigatorPolicy', { messageId: 'navigatorPolicy', replacement: 'NavigatorCatalogue' }],\n [\n 'ResourceActivity',\n { messageId: 'devtoolsResourceActivity', module: '@opetope/devtools', replacement: 'ResourceNodeActivity' },\n ],\n ['ResourceDisposer', { messageId: 'resourceDisposer', replacement: 'Disposer' }],\n ['RunCallOptions', { messageId: 'commandName', replacement: 'RunCommandOptions' }],\n ['externalReadable', { messageId: 'fromExternal', replacement: 'fromExternal' }],\n ['runCall', { messageId: 'commandName', replacement: 'runCommand' }],\n ['useCommands', { messageId: 'useCommands', replacement: 'useModel' }],\n]);\n\n/** What one call of a declaring context is, as far as this rule reads it: a retired word, retired modifiers, both. */\ntype Declared = { readonly modifiers: Modifiers | undefined; readonly word: MessageIds | undefined };\n\n/** The word a callee ends in: `keyed` of `own.scope.keyed`, or the plain name a destructured member is called by. */\nfunction calleeWord(callee: TSESTree.Node): TSESTree.Node {\n return callee.type === AST_NODE_TYPES.MemberExpression ? callee.property : callee;\n}\n\n/** The name an import carries in the module that exports it, past the local alias this file gave it. */\nfunction importedName(specifier: TSESTree.ImportSpecifier): string {\n return specifier.imported.type === AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value;\n}\n\nconst noRetiredVocabulary = createRule<[], MessageIds>({\n create(context) {\n const source = context.sourceCode;\n\n /**\n * The shape decides first and the context second: a call whose method this rule has nothing to say about never\n * pays for resolving the parameter it was written on (D309, D323).\n */\n const declaredCall = (node: TSESTree.CallExpression): Declared | undefined => {\n const named = methodPath(source, node.callee);\n\n if (named === undefined) return undefined;\n\n const declared: Declared = {\n modifiers: OPTION_RECORDS.get(named.method),\n word: RETIRED_METHODS.get(named.method),\n };\n\n if (declared.modifiers === undefined && declared.word === undefined) return undefined;\n\n return isContextFunction(source, named.fn) ? declared : undefined;\n };\n /** The record written at one of the positions this node takes its modifiers in, past the name it was given. */\n const recordAt = (node: TSESTree.CallExpression, position: number): TSESTree.ObjectExpression | undefined => {\n const argument = node.arguments[position];\n\n if (argument === undefined || argument.type === AST_NODE_TYPES.SpreadElement) return undefined;\n\n const value = localValue(source, argument);\n\n return value.type === AST_NODE_TYPES.ObjectExpression ? value : undefined;\n };\n /**\n * D411: a contribution is declared on `provides`, not on `own`, so the section that proves it is its own. The\n * shape decides first here too: nothing resolves a section for a method this rule has nothing to say about.\n */\n const contributionCall = (node: TSESTree.CallExpression): Modifiers | undefined => {\n const named = methodPath(source, node.callee);\n const modifiers = named === undefined ? undefined : CONTRIBUTION_RECORDS.get(named.method);\n\n if (named === undefined || modifiers === undefined) return undefined;\n\n return isFeatureSection(source, named.fn, 'provides', true) ? modifiers : undefined;\n };\n /** D411: `defineCondition(id, options)` is a name this package exports, so the import is what proves it. */\n const conditionRecord = (node: TSESTree.CallExpression): TSESTree.ObjectExpression | undefined => {\n if (!isApi(source, node.callee, '@opetope/runtime', 'defineCondition', true)) return undefined;\n\n return recordAt(node, 1);\n };\n const reportRecord = (record: TSESTree.ObjectExpression, words: ReadonlyMap<string, MessageIds>): void => {\n for (const property of record.properties) {\n if (property.type !== AST_NODE_TYPES.Property) continue;\n\n const name = propertyName(property);\n const messageId = name === undefined ? undefined : words.get(name);\n\n if (messageId !== undefined) context.report({ messageId, node: property.key });\n }\n };\n /** D411: the word this property was written with, where that word is a retired value of a known field. */\n const retiredValue = (\n property: TSESTree.Property,\n values: ReadonlyMap<string, ReadonlyMap<string, MessageIds>>,\n ): MessageIds | undefined => {\n const name = propertyName(property);\n const written = name === undefined ? undefined : values.get(name);\n\n if (written === undefined) return undefined;\n\n const value = localValue(source, property.value);\n\n return value.type === AST_NODE_TYPES.Literal && typeof value.value === 'string'\n ? written.get(value.value)\n : undefined;\n };\n /** D411: the value a field of a carried record was written with, where that value is the retired word. */\n const reportValues = (\n record: TSESTree.ObjectExpression,\n values: ReadonlyMap<string, ReadonlyMap<string, MessageIds>>,\n ): void => {\n for (const property of record.properties) {\n if (property.type !== AST_NODE_TYPES.Property) continue;\n\n const messageId = retiredValue(property, values);\n\n if (messageId !== undefined) context.report({ messageId, node: property.value });\n }\n };\n const reportCarried = (record: TSESTree.ObjectExpression, carrier: string, modifiers: Modifiers): void => {\n const property = findProperty(record, carrier);\n const carried = property === undefined ? undefined : localValue(source, property.value);\n\n if (carried?.type !== AST_NODE_TYPES.ObjectExpression) return;\n\n reportRecord(carried, DELIVERY_WORDS);\n\n if (modifiers.carriedValues !== undefined) reportValues(carried, modifiers.carriedValues);\n };\n const reportModifiers = (node: TSESTree.CallExpression, modifiers: Modifiers): void => {\n for (const position of modifiers.at) {\n const record = recordAt(node, position);\n\n if (record === undefined) continue;\n\n reportRecord(record, modifiers.words);\n\n for (const carrier of modifiers.carries) reportCarried(record, carrier, modifiers);\n }\n };\n /** Both objects that used to answer `invalidate`: the Resource itself, and the record `useResource` builds. */\n const holdsVerbs = (node: TSESTree.Node): boolean => isResourceValue(source, node) || isResourceHook(source, node);\n /** The object each retired member has to be read on, asked only once the name has already matched. */\n const memberOwner = (node: TSESTree.MemberExpression, messageId: MessageIds): boolean => {\n if (messageId === 'resourceInvalidate') return holdsVerbs(node.object);\n\n if (messageId === 'loadingActivity') return isLoadingActivity(source, node);\n\n if (messageId === 'navigatorPolicy') return isSurfaceValue(source, node.object);\n\n return isCommandOutcome(source, node.object);\n };\n /**\n * The four members this rule reads off a value it can resolve (D415 added `surface.policy`, which the message\n * of `NavigatorPolicy` already named and the rule did not report). The name decides first and the resolution\n * second, so a member this rule has nothing to say about never pays for the object it was read on (D309, D323).\n */\n const retiredMember = (node: TSESTree.MemberExpression, name: string): MessageIds | undefined => {\n const messageId = RETIRED_MEMBERS.get(name);\n\n return messageId !== undefined && memberOwner(node, messageId) ? messageId : undefined;\n };\n\n return {\n CallExpression(node): void {\n const contribution = contributionCall(node);\n\n if (contribution !== undefined) reportModifiers(node, contribution);\n\n const condition = conditionRecord(node);\n\n if (condition !== undefined) reportRecord(condition, CONDITION_WORDS);\n\n const declared = declaredCall(node);\n\n if (declared === undefined) return;\n\n if (declared.word !== undefined) context.report({ messageId: declared.word, node: calleeWord(node.callee) });\n\n if (declared.modifiers !== undefined) reportModifiers(node, declared.modifiers);\n },\n ImportDeclaration(node): void {\n if (!node.source.value.startsWith('@opetope/')) return;\n\n for (const specifier of node.specifiers) {\n if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) continue;\n\n const word = importedName(specifier);\n const retired = RETIRED_IMPORTS.get(word);\n\n if (retired !== undefined && (retired.module === undefined || retired.module === node.source.value)) {\n context.report({\n data: { replacement: retired.replacement, word },\n messageId: retired.messageId,\n node: specifier.imported,\n });\n }\n }\n },\n MemberExpression(node): void {\n if (node.computed || node.property.type !== AST_NODE_TYPES.Identifier) return;\n\n const messageId = retiredMember(node, node.property.name);\n\n if (messageId !== undefined) context.report({ messageId, node: node.property });\n },\n Property(node): void {\n if (propertyName(node) !== 'invalidate' || node.parent.type !== AST_NODE_TYPES.ObjectPattern) return;\n\n const declarator = node.parent.parent;\n\n if (declarator.type !== AST_NODE_TYPES.VariableDeclarator || declarator.init === null) return;\n\n if (holdsVerbs(declarator.init)) context.report({ messageId: 'resourceInvalidate', node: node.key });\n },\n };\n },\n meta: {\n docs: {\n description: 'A word the D365–D411 wave retired is named with the word that replaced it, and never rewritten.',\n },\n messages: {\n commandLane:\n '`lane` is now a member of `concurrency`: write `concurrency: lane`, `concurrency: { by, lane }` for a keyed queue, or `concurrency: { lane, pending: \"latest\" }` where `policy: \"latest\"` stood beside it. Which of the three this record meant is in what it wrote together, so nothing here is rewritten for you (D387).',\n commandName:\n '`{{word}}` is now `{{replacement}}`: one word for a command, everywhere. The primitive was the last place the vocabulary still said `Call`, while the hook was already `useCommand` and the outcome `CommandOutcome`. There is no alias (D385).',\n commandOnce:\n '`once` is now `memoize`: it caches a successful result, it does not stop after one run. `addEventListener(type, handler, { once: true })` is what the platform means by the word, and it is not what this option ever did (D389).',\n commandOutcomeStatus:\n '`status` is now `kind` on a `CommandOutcome`: one word for the discriminant of a settled answer, the one `ResourceState`, `ResourceOperationOutcome`, `ResourceCommitOutcome`, `PaginationOutcome` and a screen result already carry. The three branches are unchanged — `{ kind: \"ok\", value }`, `{ kind: \"failed\", error }`, `{ kind: \"cancelled\", reason }` (D411).',\n commandPolicy:\n '`policy` is now `concurrency`: one word for the order the runs take, written as `queue`, `parallel`, `latest` or a lane. Where `queueBy` or `lane` stood beside it the three collapse into one value — `{ by }`, `{ by, lane }` or `{ lane, pending: \"latest\" }` — so the shape depends on which of them this record wrote, and that is why this rule names the word instead of rewriting it (D387).',\n commandQueueBy:\n '`queueBy` is now a member of `concurrency`: write `concurrency: { by: input => key }`, or `concurrency: { by, lane }` where a lane stood beside it (D387).',\n conditionFrom:\n \"`from` of `defineCondition` is now `source`: write `defineCondition(id, { select, source })`. One word names the dependency a node reads — `resource.load({ source })` and `attach(source)` already say it, and this node's own refusals said `Condition source` about the field they called `from` (D410, D411).\",\n contextCall:\n '`call` is now `command`: `ctx.command(run, options?)` in a model, `own.command(within, run, options?)` in a feature. The body takes one argument, its context, and reads the declared input off it as `input` — and the input is named by annotating that context, `({ input, update }: ModelCommandContext<Deposit>)` in a model and `({ input, source }: FeatureCommandContext<typeof within, Deposit>)` in a feature, because there is no other place to name it (D385, D386, D444).',\n contextCalls:\n '`ctx.calls` and `own.calls` are now `ctx.select` and `own.select`: declaring a body and selecting a command a dependency already declares are two mechanisms, so they are two words. `select(source, \"name\")` answers one command and `select(source, [\"a\", \"b\"])` a record of them (D388).',\n contributionWhen:\n '`when` of a contribution is now `enabled`: write `slot(target, value, { enabled })`, and the same at `pipe` and `register`. A truth the runtime reads while the node exists is `enabled`, at a contribution and at a Resource alike; `when` names the other mechanism — the declared `Condition`s of `defineFeature({ when })`, which the application resolves before anything exists. `scope.while` keeps its own `when` (D378, D411).',\n deliveryKey:\n 'Inside a delivery record `key` is now `by`: `{ pending: \"latest\", by }` keeps one waiting place per key instead of one for the whole node (D374).',\n deliveryKind:\n 'Inside a delivery record `kind` is now `pending`: `kind: \"latest\"` is `pending: \"latest\"`, and `kind: \"queue\"` is `pending: \"all\"` — the backlog only an event has. The discriminant moved because with one dimension shared by both nodes, the discriminant is that dimension (D374).',\n deliveryReject:\n '`overflow: \"reject\"` is now `overflow: \"drop\"`: one word at both nodes for «the new one does not enter and `emit` answers `false`». `\"flush-oldest\"` is unchanged and still the default of a keyed delivery (D369, D411).',\n devtoolsResourceActivity:\n '`ResourceActivity` of `@opetope/devtools` is now `ResourceNodeActivity`: `@opetope/core` exports a `ResourceActivity` of its own — the union a `ready` state carries — and one name carried two unrelated types on two public entries. Import the core one under its own name (D411).',\n effectOnDispose:\n '`onDispose` is now `finalize`: an effect has two releases — the disposer a run returns, and the one the node itself gets once — and an `on*` prefix did not tell them apart. No word of the authoring vocabulary carries that prefix any more (D379).',\n effectSkipInitial:\n '`skipInitial` is now `initial`, and the polarity is inverted: `skipInitial: true` is `initial: false`, and `initial` defaults to `true`. Both words are booleans, so carrying the value across unchanged compiles and means the opposite — which is why this rule names it and leaves the rewrite to you (D379).',\n effectWhen:\n '`when` at an effect is now `filter` or `initial`, and which one depends on what the predicate asks. A predicate that selects values is `filter: (current, previous) => …`; a predicate whose whole job is to refuse the first run — `(_current, previous) => previous !== undefined` — is `initial: false`. This rule does not guess between them. The word `when` is untouched at a feature and at `scope.while`; at a contribution it is now `enabled` (D379, D411).',\n eventBackpressure:\n '`backpressure` is now `delivery`: one word at both nodes that admit a producer. Write `delivery: \"latest\"` for one waiting place that the newest payload takes, or the record — `{ pending, by }`, `{ pending, capacity, overflow }` — for the rest (D374).',\n fromExternal:\n '`externalReadable` is now `fromExternal`: `from*` names where a `Readable` comes from, beside `fromMaybe`. The old name was built from its result, which every word of that module already answers (D380).',\n loadingActivity:\n 'A `loading` state carries `failure`, not `activity`: read `state.failure` — `undefined` is «both channels are still viable», and otherwise `channel` names the one that died terminally and `error` carries its failure. A `ready` state still carries `activity` whole, so this is one branch losing the field and not the field being renamed (D375).',\n navigatorPolicy:\n '`NavigatorPolicy` is now `NavigatorCatalogue`, and `surface.policy` is now `surface.catalogue`: this is four callbacks a navigator asks, and D291 made a policy data — a word when it has no parameters, a record when it has them (D411).',\n resourceDisposer:\n '`ResourceDisposer` is now `Disposer`: one name for `() => Awaitable<void>`, which three of them used to spell — `Disposer`, `ResourceDisposer` and `FeatureDisposer`. It travels on `@opetope/core/internal` beside `Awaitable` (D411).',\n resourceInvalidate:\n '`invalidate()` is now `reset()`: it clears the whole cache, drops the current data, opens a new epoch and restarts every configured channel. Everywhere else `invalidate` means «mark stale, keep the data», so the old name promised the opposite of what the verb does; it now names no operation of a Resource at all (D373).',\n runtimeInternalEntry:\n '`{{word}}` is published by `{{replacement}}`: import it from there. Three names were published by both entries and every consumer took the internal copy, so the copies are gone and the names are not (D411, D415).',\n scopeKeyed:\n '`scope.keyed(source, open, { key })` is now `scope.each(source, key, open)`: `each` says what the node does, one child per element, and the key is required — so it stands between the list it identifies and the child it opens. The trailing record is gone, which makes this a move and not only a rename (D378).',\n useCommands:\n '`useCommands` is gone: a record of command consumers comes from `useModel(Declaration, select)`, which has an owner and a lifetime. One command is still `useCommand` (D388).',\n },\n schema: [],\n type: 'problem',\n },\n name: 'no-retired-vocabulary',\n});\n\nexport { noRetiredVocabulary };\n"],"names":["COMMAND_WORDS","EFFECT_WORDS","EVENT_WORDS","DELIVERY_WORDS","NO_WORDS","DELIVERY","LIVE_DELIVERY_VALUES","CONTRIBUTION_WORDS","CONTRIBUTION_RECORDS","CONDITION_WORDS","OPTION_RECORDS","RETIRED_MEMBERS","RETIRED_METHODS","RETIRED_IMPORTS","calleeWord","callee","AST_NODE_TYPES","importedName","specifier","noRetiredVocabulary","createRule","context","source","declaredCall","node","named","methodPath","declared","isContextFunction","recordAt","position","argument","value","localValue","contributionCall","modifiers","isFeatureSection","conditionRecord","isApi","reportRecord","record","words","property","name","propertyName","messageId","retiredValue","values","written","reportValues","reportCarried","carrier","findProperty","carried","reportModifiers","holdsVerbs","isResourceValue","isResourceHook","memberOwner","isLoadingActivity","isSurfaceValue","isCommandOutcome","retiredMember","contribution","condition","word","retired","declarator"],"mappings":"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"}
1
+ {"version":3,"file":"no-retired-vocabulary.js","sources":["../../src/rules/no-retired-vocabulary.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { AST_NODE_TYPES } from '@typescript-eslint/utils';\n\nimport { findProperty, propertyName } from '../ast';\nimport { isContextFunction, methodPath } from '../declaration-ingress';\nimport { isApi, isFeatureSection, localValue } from '../model-bindings';\nimport {\n isCommandOutcome,\n isResourceHook,\n isResourceValue,\n isStateActivity,\n isSurfaceValue,\n} from '../retired-vocabulary';\nimport { createRule } from '../rule';\n\ntype MessageIds =\n | 'commandLane'\n | 'commandLatest'\n | 'commandName'\n | 'commandOnce'\n | 'commandOutcomeStatus'\n | 'commandPolicy'\n | 'commandQueueBy'\n | 'conditionFrom'\n | 'contextCall'\n | 'contextCalls'\n | 'contributionWhen'\n | 'deliveryKey'\n | 'deliveryKind'\n | 'deliveryReject'\n | 'effectOnDispose'\n | 'effectSkipInitial'\n | 'effectWhen'\n | 'eventBackpressure'\n | 'fromExternal'\n | 'navigatorPolicy'\n | 'resourceActivity'\n | 'resourceDisposer'\n | 'resourceInvalidate'\n | 'runtimeInternalEntry'\n | 'scopeKeyed'\n | 'stateActivity'\n | 'useCommands';\n\n/**\n * One name a package no longer exports, and the word that carries its meaning now. D411: `module` is written where\n * the name is retired at one entry and live at another — `ApplicationConditionBinding` is still the name, on the\n * entry an author is meant to take it from. D462 took the scope off `ResourceActivity`: the name is now retired at\n * both entries it was ever written from, so asking the module would only let one of them through.\n */\ntype Retired = { readonly messageId: MessageIds; readonly module?: string; readonly replacement: string };\n/**\n * Where one node keeps its modifiers, and which retired words live there. `at` holds every position the record is\n * written in across the two surfaces — `ctx.command(run, options)` and `own.command(within, run, options)` — and\n * nothing else at those positions is an object literal, so one list answers both. `carries` names the members whose\n * own record is read in turn: a delivery policy is a record inside a record.\n */\ntype Modifiers = {\n readonly at: readonly number[];\n readonly carries: readonly string[];\n /** D411: a word of a carried record whose **value** was retired, not its key: `overflow: 'reject'` is one. */\n readonly carriedValues?: ReadonlyMap<string, ReadonlyMap<string, MessageIds>>;\n /** D459: the same fact one record higher — a word retired as the **value** of a field of this record itself. */\n readonly values?: ReadonlyMap<string, ReadonlyMap<string, MessageIds>>;\n readonly words: ReadonlyMap<string, MessageIds>;\n};\n\n/** D387, D389: the four words the options record of a command declaration and of a selection retired. */\nconst COMMAND_WORDS = new Map<string, MessageIds>([\n ['lane', 'commandLane'],\n ['once', 'commandOnce'],\n ['policy', 'commandPolicy'],\n ['queueBy', 'commandQueueBy'],\n]);\n/** D459: the one value of that record that moved — the waiting place is written as the record that names it. */\nconst COMMAND_VALUES = new Map<string, ReadonlyMap<string, MessageIds>>([\n ['concurrency', new Map<string, MessageIds>([['latest', 'commandLatest']])],\n]);\n/** D379: the three modifiers of an effect run. */\nconst EFFECT_WORDS = new Map<string, MessageIds>([\n ['onDispose', 'effectOnDispose'],\n ['skipInitial', 'effectSkipInitial'],\n ['when', 'effectWhen'],\n]);\nconst EVENT_WORDS = new Map<string, MessageIds>([['backpressure', 'eventBackpressure']]);\n/** D374: the two fields inside the record, whichever of the two words the record itself is still written under. */\nconst DELIVERY_WORDS = new Map<string, MessageIds>([\n ['key', 'deliveryKey'],\n ['kind', 'deliveryKind'],\n]);\nconst NO_WORDS = new Map<string, MessageIds>();\nconst DELIVERY = ['backpressure', 'delivery'];\n/** D411: the one field of a delivery whose value moved: a full keyed capacity answers `drop`, not `reject`. */\nconst LIVE_DELIVERY_VALUES = new Map<string, ReadonlyMap<string, MessageIds>>([\n ['overflow', new Map<string, MessageIds>([['reject', 'deliveryReject']])],\n]);\n/** D411: the words a contribution writes beside its value, on the `provides` section that declares it. */\nconst CONTRIBUTION_WORDS = new Map<string, MessageIds>([['when', 'contributionWhen']]);\nconst CONTRIBUTION_RECORDS = new Map<string, Modifiers>([\n ['pipe', { at: [2], carries: [], words: CONTRIBUTION_WORDS }],\n ['register', { at: [2], carries: [], words: CONTRIBUTION_WORDS }],\n ['slot', { at: [2], carries: [], words: CONTRIBUTION_WORDS }],\n]);\n/** D411: the record `defineCondition` takes second; the word it named its source by is the one that moved. */\nconst CONDITION_WORDS = new Map<string, MessageIds>([['from', 'conditionFrom']]);\n\nconst OPTION_RECORDS = new Map<string, Modifiers>([\n ['call', { at: [1, 2], carries: [], values: COMMAND_VALUES, words: COMMAND_WORDS }],\n ['calls', { at: [2], carries: [], values: COMMAND_VALUES, words: COMMAND_WORDS }],\n ['command', { at: [1, 2], carries: [], values: COMMAND_VALUES, words: COMMAND_WORDS }],\n ['effect', { at: [2], carries: [], words: EFFECT_WORDS }],\n ['event', { at: [3], carries: DELIVERY, words: EVENT_WORDS }],\n ['resource.live', { at: [0], carriedValues: LIVE_DELIVERY_VALUES, carries: DELIVERY, words: NO_WORDS }],\n ['select', { at: [2], carries: [], values: COMMAND_VALUES, words: COMMAND_WORDS }],\n]);\n\n/** D411, D415, D462: the members whose name is retired, each with the object it has to have been read on. */\nconst RETIRED_MEMBERS = new Map<string, MessageIds>([\n ['activity', 'stateActivity'],\n ['invalidate', 'resourceInvalidate'],\n ['policy', 'navigatorPolicy'],\n ['status', 'commandOutcomeStatus'],\n]);\n\n/** D378, D385, D388: the methods themselves, named on a declaring context of this library. */\nconst RETIRED_METHODS = new Map<string, MessageIds>([\n ['call', 'contextCall'],\n ['calls', 'contextCalls'],\n ['scope.keyed', 'scopeKeyed'],\n]);\n\n/** D380, D385, D388: the names an `@opetope/*` entry no longer exports. The module itself is the proof. */\nconst RETIRED_IMPORTS = new Map<string, Retired>([\n [\n 'ApplicationConditionBinding',\n { messageId: 'runtimeInternalEntry', module: '@opetope/runtime/internal', replacement: '@opetope/runtime' },\n ],\n /** D411, D415: the entry retired three copies, and a table that held one left two migrations unnamed. */\n [\n 'ApplicationExecution',\n { messageId: 'runtimeInternalEntry', module: '@opetope/runtime/internal', replacement: '@opetope/runtime' },\n ],\n [\n 'ApplicationImportBinding',\n { messageId: 'runtimeInternalEntry', module: '@opetope/runtime/internal', replacement: '@opetope/runtime' },\n ],\n ['Call', { messageId: 'commandName', replacement: 'Command' }],\n ['CallError', { messageId: 'commandName', replacement: 'CommandError' }],\n ['CallInputArgs', { messageId: 'commandName', replacement: 'CommandInputArgs' }],\n ['CallTimeoutError', { messageId: 'commandName', replacement: 'CommandTimeoutError' }],\n ['NavigatorPolicy', { messageId: 'navigatorPolicy', replacement: 'NavigatorCatalogue' }],\n ['ResourceActivity', { messageId: 'resourceActivity', replacement: 'ResourceNodeActivity' }],\n ['ResourceDisposer', { messageId: 'resourceDisposer', replacement: 'Disposer' }],\n ['RunCallOptions', { messageId: 'commandName', replacement: 'RunCommandOptions' }],\n ['externalReadable', { messageId: 'fromExternal', replacement: 'fromExternal' }],\n ['runCall', { messageId: 'commandName', replacement: 'runCommand' }],\n ['useCommands', { messageId: 'useCommands', replacement: 'useModel' }],\n]);\n\n/** What one call of a declaring context is, as far as this rule reads it: a retired word, retired modifiers, both. */\ntype Declared = { readonly modifiers: Modifiers | undefined; readonly word: MessageIds | undefined };\n\n/** The word a callee ends in: `keyed` of `own.scope.keyed`, or the plain name a destructured member is called by. */\nfunction calleeWord(callee: TSESTree.Node): TSESTree.Node {\n return callee.type === AST_NODE_TYPES.MemberExpression ? callee.property : callee;\n}\n\n/** The name an import carries in the module that exports it, past the local alias this file gave it. */\nfunction importedName(specifier: TSESTree.ImportSpecifier): string {\n return specifier.imported.type === AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value;\n}\n\nconst noRetiredVocabulary = createRule<[], MessageIds>({\n create(context) {\n const source = context.sourceCode;\n\n /**\n * The shape decides first and the context second: a call whose method this rule has nothing to say about never\n * pays for resolving the parameter it was written on (D309, D323).\n */\n const declaredCall = (node: TSESTree.CallExpression): Declared | undefined => {\n const named = methodPath(source, node.callee);\n\n if (named === undefined) return undefined;\n\n const declared: Declared = {\n modifiers: OPTION_RECORDS.get(named.method),\n word: RETIRED_METHODS.get(named.method),\n };\n\n if (declared.modifiers === undefined && declared.word === undefined) return undefined;\n\n return isContextFunction(source, named.fn) ? declared : undefined;\n };\n /** The record written at one of the positions this node takes its modifiers in, past the name it was given. */\n const recordAt = (node: TSESTree.CallExpression, position: number): TSESTree.ObjectExpression | undefined => {\n const argument = node.arguments[position];\n\n if (argument === undefined || argument.type === AST_NODE_TYPES.SpreadElement) return undefined;\n\n const value = localValue(source, argument);\n\n return value.type === AST_NODE_TYPES.ObjectExpression ? value : undefined;\n };\n /**\n * D411: a contribution is declared on `provides`, not on `own`, so the section that proves it is its own. The\n * shape decides first here too: nothing resolves a section for a method this rule has nothing to say about.\n */\n const contributionCall = (node: TSESTree.CallExpression): Modifiers | undefined => {\n const named = methodPath(source, node.callee);\n const modifiers = named === undefined ? undefined : CONTRIBUTION_RECORDS.get(named.method);\n\n if (named === undefined || modifiers === undefined) return undefined;\n\n return isFeatureSection(source, named.fn, 'provides', true) ? modifiers : undefined;\n };\n /** D411: `defineCondition(id, options)` is a name this package exports, so the import is what proves it. */\n const conditionRecord = (node: TSESTree.CallExpression): TSESTree.ObjectExpression | undefined => {\n if (!isApi(source, node.callee, '@opetope/runtime', 'defineCondition', true)) return undefined;\n\n return recordAt(node, 1);\n };\n const reportRecord = (record: TSESTree.ObjectExpression, words: ReadonlyMap<string, MessageIds>): void => {\n for (const property of record.properties) {\n if (property.type !== AST_NODE_TYPES.Property) continue;\n\n const name = propertyName(property);\n const messageId = name === undefined ? undefined : words.get(name);\n\n if (messageId !== undefined) context.report({ messageId, node: property.key });\n }\n };\n /** D411: the word this property was written with, where that word is a retired value of a known field. */\n const retiredValue = (\n property: TSESTree.Property,\n values: ReadonlyMap<string, ReadonlyMap<string, MessageIds>>,\n ): MessageIds | undefined => {\n const name = propertyName(property);\n const written = name === undefined ? undefined : values.get(name);\n\n if (written === undefined) return undefined;\n\n const value = localValue(source, property.value);\n\n return value.type === AST_NODE_TYPES.Literal && typeof value.value === 'string'\n ? written.get(value.value)\n : undefined;\n };\n /** D411: the value a field of a carried record was written with, where that value is the retired word. */\n const reportValues = (\n record: TSESTree.ObjectExpression,\n values: ReadonlyMap<string, ReadonlyMap<string, MessageIds>>,\n ): void => {\n for (const property of record.properties) {\n if (property.type !== AST_NODE_TYPES.Property) continue;\n\n const messageId = retiredValue(property, values);\n\n if (messageId !== undefined) context.report({ messageId, node: property.value });\n }\n };\n const reportCarried = (record: TSESTree.ObjectExpression, carrier: string, modifiers: Modifiers): void => {\n const property = findProperty(record, carrier);\n const carried = property === undefined ? undefined : localValue(source, property.value);\n\n if (carried?.type !== AST_NODE_TYPES.ObjectExpression) return;\n\n reportRecord(carried, DELIVERY_WORDS);\n\n if (modifiers.carriedValues !== undefined) reportValues(carried, modifiers.carriedValues);\n };\n const reportModifiers = (node: TSESTree.CallExpression, modifiers: Modifiers): void => {\n for (const position of modifiers.at) {\n const record = recordAt(node, position);\n\n if (record === undefined) continue;\n\n reportRecord(record, modifiers.words);\n\n if (modifiers.values !== undefined) reportValues(record, modifiers.values);\n\n for (const carrier of modifiers.carries) reportCarried(record, carrier, modifiers);\n }\n };\n /** Both objects that used to answer `invalidate`: the Resource itself, and the record `useResource` builds. */\n const holdsVerbs = (node: TSESTree.Node): boolean => isResourceValue(source, node) || isResourceHook(source, node);\n /** The object each retired member has to be read on, asked only once the name has already matched. */\n const memberOwner = (node: TSESTree.MemberExpression, messageId: MessageIds): boolean => {\n if (messageId === 'resourceInvalidate') return holdsVerbs(node.object);\n\n if (messageId === 'stateActivity') return isStateActivity(source, node);\n\n if (messageId === 'navigatorPolicy') return isSurfaceValue(source, node.object);\n\n return isCommandOutcome(source, node.object);\n };\n /**\n * The four members this rule reads off a value it can resolve (D415 added `surface.policy`, which the message\n * of `NavigatorPolicy` already named and the rule did not report). The name decides first and the resolution\n * second, so a member this rule has nothing to say about never pays for the object it was read on (D309, D323).\n */\n const retiredMember = (node: TSESTree.MemberExpression, name: string): MessageIds | undefined => {\n const messageId = RETIRED_MEMBERS.get(name);\n\n return messageId !== undefined && memberOwner(node, messageId) ? messageId : undefined;\n };\n\n return {\n CallExpression(node): void {\n const contribution = contributionCall(node);\n\n if (contribution !== undefined) reportModifiers(node, contribution);\n\n const condition = conditionRecord(node);\n\n if (condition !== undefined) reportRecord(condition, CONDITION_WORDS);\n\n const declared = declaredCall(node);\n\n if (declared === undefined) return;\n\n if (declared.word !== undefined) context.report({ messageId: declared.word, node: calleeWord(node.callee) });\n\n if (declared.modifiers !== undefined) reportModifiers(node, declared.modifiers);\n },\n ImportDeclaration(node): void {\n if (!node.source.value.startsWith('@opetope/')) return;\n\n for (const specifier of node.specifiers) {\n if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) continue;\n\n const word = importedName(specifier);\n const retired = RETIRED_IMPORTS.get(word);\n\n if (retired !== undefined && (retired.module === undefined || retired.module === node.source.value)) {\n context.report({\n data: { replacement: retired.replacement, word },\n messageId: retired.messageId,\n node: specifier.imported,\n });\n }\n }\n },\n MemberExpression(node): void {\n if (node.computed || node.property.type !== AST_NODE_TYPES.Identifier) return;\n\n const messageId = retiredMember(node, node.property.name);\n\n if (messageId !== undefined) context.report({ messageId, node: node.property });\n },\n Property(node): void {\n if (propertyName(node) !== 'invalidate' || node.parent.type !== AST_NODE_TYPES.ObjectPattern) return;\n\n const declarator = node.parent.parent;\n\n if (declarator.type !== AST_NODE_TYPES.VariableDeclarator || declarator.init === null) return;\n\n if (holdsVerbs(declarator.init)) context.report({ messageId: 'resourceInvalidate', node: node.key });\n },\n };\n },\n meta: {\n docs: {\n description:\n 'A word the D365–D411 wave or a decision after it retired is named with its replacement, never rewritten.',\n },\n messages: {\n commandLane:\n '`lane` is now a member of `concurrency`: write `concurrency: lane`, `concurrency: { by, lane }` for a keyed queue, or `concurrency: { lane, pending: \"latest\" }` where `policy: \"latest\"` stood beside it. Which of the three this record meant is in what it wrote together, so nothing here is rewritten for you (D387).',\n commandLatest:\n '`concurrency: \"latest\"` is now `concurrency: { pending: \"latest\" }`, and `{ lane, pending: \"latest\" }` where the queue is shared. The word named the input that wins and never named what it wins, so the place is written out: one waiting slot at the end of the lane, taken by a newer input while the body in flight is left to finish. Nothing else about the policy moved (D459).',\n commandName:\n '`{{word}}` is now `{{replacement}}`: one word for a command, everywhere. The primitive was the last place the vocabulary still said `Call`, while the hook was already `useCommand` and the outcome `CommandOutcome`. There is no alias (D385).',\n commandOnce:\n '`once` is now `memoize`: it caches a successful result, it does not stop after one run. `addEventListener(type, handler, { once: true })` is what the platform means by the word, and it is not what this option ever did (D389).',\n commandOutcomeStatus:\n '`status` is now `kind` on a `CommandOutcome`: one word for the discriminant of a settled answer, the one `ResourceState`, `ResourceOperationOutcome`, `ResourceCommitOutcome`, `PaginationOutcome` and a screen result already carry. The three branches are unchanged — `{ kind: \"ok\", value }`, `{ kind: \"failed\", error }`, `{ kind: \"cancelled\", reason }` (D411).',\n commandPolicy:\n '`policy` is now `concurrency`: one word for the order the runs take, written as `queue`, `parallel`, a lane or `{ pending: \"latest\" }`. Where `queueBy` or `lane` stood beside it the three collapse into one value — `{ by }`, `{ by, lane }` or `{ lane, pending: \"latest\" }` — so the shape depends on which of them this record wrote, and that is why this rule names the word instead of rewriting it (D387, D459).',\n commandQueueBy:\n '`queueBy` is now a member of `concurrency`: write `concurrency: { by: input => key }`, or `concurrency: { by, lane }` where a lane stood beside it (D387).',\n conditionFrom:\n \"`from` of `defineCondition` is now `source`: write `defineCondition(id, { select, source })`. One word names the dependency a node reads — `resource.load({ source })` and `attach(source)` already say it, and this node's own refusals said `Condition source` about the field they called `from` (D410, D411).\",\n contextCall:\n '`call` is now `command`: `ctx.command(run, options?)` in a model, `own.command(within, run, options?)` in a feature. The body takes one argument, its context, and reads the declared input off it as `input` — and `Input` is inferred from every position of the call except the body, so it is written in the cheapest that fits: the result type of a model factory names it in the literal it returns, an annotated option names it (`dedupe: (deposit: Deposit) => …`), a constant names it (`const refill: Command<Refill, void> = ctx.command(…)`), and the annotation of that context — `({ input, update }: ModelCommandContext<Deposit>)` in a model, `({ input, source }: FeatureCommandContext<typeof within, Deposit>)` in a feature — is what is left; a feature has the last two only. `command<Deposit>(…)` is not a position: it pins `Output` to its default (D385, D386, D444, D455).',\n contextCalls:\n '`ctx.calls` and `own.calls` are now `ctx.select` and `own.select`: declaring a body and selecting a command a dependency already declares are two mechanisms, so they are two words. `select(source, \"name\")` answers one command and `select(source, [\"a\", \"b\"])` a record of them (D388).',\n contributionWhen:\n '`when` of a contribution is now `enabled`: write `slot(target, value, { enabled })`, and the same at `pipe` and `register`. A truth the runtime reads while the node exists is `enabled`, at a contribution and at a Resource alike; `when` names the other mechanism — the declared `Condition`s of `defineFeature({ when })`, which the application resolves before anything exists. `scope.while` keeps its own `when` (D378, D411).',\n deliveryKey:\n 'Inside a delivery record `key` is now `by`: `{ pending: \"latest\", by }` keeps one waiting place per key instead of one for the whole node (D374).',\n deliveryKind:\n 'Inside a delivery record `kind` is now `pending`: `kind: \"latest\"` is `pending: \"latest\"`, and `kind: \"queue\"` is `pending: \"all\"` — the backlog only an event has. The discriminant moved because with one dimension shared by both nodes, the discriminant is that dimension (D374).',\n deliveryReject:\n '`overflow: \"reject\"` is now `overflow: \"drop\"`: one word at both nodes for «the new one does not enter and `emit` answers `false`». `\"flush-oldest\"` is unchanged and still the default of a keyed delivery (D369, D411).',\n effectOnDispose:\n '`onDispose` is now `finalize`: an effect has two releases — the disposer a run returns, and the one the node itself gets once — and an `on*` prefix did not tell them apart. No word of the authoring vocabulary carries that prefix any more (D379).',\n effectSkipInitial:\n '`skipInitial` is now `initial`, and the polarity is inverted: `skipInitial: true` is `initial: false`, and `initial` defaults to `true`. Both words are booleans, so carrying the value across unchanged compiles and means the opposite — which is why this rule names it and leaves the rewrite to you (D379).',\n effectWhen:\n '`when` at an effect is now `filter` or `initial`, and which one depends on what the predicate asks. A predicate that selects values is `filter: (current, previous) => …`; a predicate whose whole job is to refuse the first run — `(_current, previous) => previous !== undefined` — is `initial: false`. This rule does not guess between them. The word `when` is untouched at a feature and at `scope.while`; at a contribution it is now `enabled` (D379, D411).',\n eventBackpressure:\n '`backpressure` is now `delivery`: one word at both nodes that admit a producer. Write `delivery: \"latest\"` for one waiting place that the newest payload takes, or the record — `{ pending, by }`, `{ pending, capacity, overflow }` — for the rest (D374).',\n fromExternal:\n '`externalReadable` is now `fromExternal`: `from*` names where a `Readable` comes from, beside `fromMaybe`. The old name was built from its result, which every word of that module already answers (D380).',\n navigatorPolicy:\n '`NavigatorPolicy` is now `NavigatorCatalogue`, and `surface.policy` is now `surface.catalogue`: this is four callbacks a navigator asks, and D291 made a policy data — a word when it has no parameters, a record when it has them (D411).',\n resourceActivity:\n '`ResourceActivity` is retired at both entries that spelled it. From `@opetope/devtools` it is `ResourceNodeActivity` (D411). From `@opetope/core` it is gone: a state answers what failed and what is working in two fields of its own, so read `state.failure` and `state.pending` instead of a union that flattened them (D462).',\n resourceDisposer:\n '`ResourceDisposer` is now `Disposer`: one name for `() => Awaitable<void>`, which three of them used to spell — `Disposer`, `ResourceDisposer` and `FeatureDisposer`. It travels on `@opetope/core/internal` beside `Awaitable` (D411).',\n resourceInvalidate:\n '`invalidate()` is now `reset()`: it clears the whole cache, drops the current data, opens a new epoch and restarts every configured channel. Everywhere else `invalidate` means «mark stale, keep the data», so the old name promised the opposite of what the verb does; it now names no operation of a Resource at all (D373).',\n runtimeInternalEntry:\n '`{{word}}` is published by `{{replacement}}`: import it from there. Three names were published by both entries and every consumer took the internal copy, so the copies are gone and the names are not (D411, D415).',\n scopeKeyed:\n '`scope.keyed(source, open, { key })` is now `scope.each(source, key, open)`: `each` says what the node does, one child per element, and the key is required — so it stands between the list it identifies and the child it opens. The trailing record is gone, which makes this a move and not only a rename (D378).',\n stateActivity:\n 'No `ResourceState` carries `activity` any more: the union said what a channel was doing and what had failed in one word. Read `state.failure` — `undefined` is «nothing failed», and otherwise `channel` names the channel that died and `error` carries its failure — and `state.pending` for the channel with work in flight. Both are declared on every member, so neither needs a narrowing by `kind` first (D462).',\n useCommands:\n '`useCommands` is gone: a record of command consumers comes from `useModel(Declaration, select)`, which has an owner and a lifetime. One command is still `useCommand` (D388).',\n },\n schema: [],\n type: 'problem',\n },\n name: 'no-retired-vocabulary',\n});\n\nexport { noRetiredVocabulary };\n"],"names":["COMMAND_WORDS","COMMAND_VALUES","EFFECT_WORDS","EVENT_WORDS","DELIVERY_WORDS","NO_WORDS","DELIVERY","LIVE_DELIVERY_VALUES","CONTRIBUTION_WORDS","CONTRIBUTION_RECORDS","CONDITION_WORDS","OPTION_RECORDS","RETIRED_MEMBERS","RETIRED_METHODS","RETIRED_IMPORTS","calleeWord","callee","AST_NODE_TYPES","importedName","specifier","noRetiredVocabulary","createRule","context","source","declaredCall","node","named","methodPath","declared","isContextFunction","recordAt","position","argument","value","localValue","contributionCall","modifiers","isFeatureSection","conditionRecord","isApi","reportRecord","record","words","property","name","propertyName","messageId","retiredValue","values","written","reportValues","reportCarried","carrier","findProperty","carried","reportModifiers","holdsVerbs","isResourceValue","isResourceHook","memberOwner","isStateActivity","isSurfaceValue","isCommandOutcome","retiredMember","contribution","condition","word","retired","declarator"],"mappings":"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EAAapB,CAAI,IAAM,cAAgBA,EAAK,OAAO,OAASR,EAAe,cAAe,OAE9F,MAAMmD,EAAa3C,EAAK,OAAO,OAE3B2C,EAAW,OAASnD,EAAe,oBAAsBmD,EAAW,OAAS,MAE7EZ,EAAWY,EAAW,IAAI,GAAG9C,EAAQ,OAAO,CAAE,UAAW,qBAAsB,KAAMG,EAAK,IAAK,CACrG,EAEJ,EACA,KAAM,CACJ,KAAM,CACJ,YACE,+GACH,EACD,SAAU,CACR,YACE,6TACF,cACE,0XACF,YACE,kPACF,YACE,oOACF,qBACE,8WACF,cACE,saACF,eACE,6JACF,cACE,yTACF,YACE,04BACF,aACE,8RACF,iBACE,+aACF,YACE,oJACF,aACE,8RACF,eACE,kOACF,gBACE,kQACF,kBACE,wTACF,WACE,wdACF,kBACE,wQACF,aACE,6MACF,gBACE,kPACF,iBACE,qUACF,iBACE,+OACF,mBACE,yUACF,qBACE,uNACF,WACE,4TACF,cACE,0aACF,YACE,+KACH,EACD,OAAQ,CAAA,EACR,KAAM,SACP,EACD,KAAM,uBACP,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opetope/lint",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "engines": {
5
5
  "node": ">=20.19.0"
6
6
  },
@@ -9,7 +9,6 @@
9
9
  "dist",
10
10
  "oxlintrc.json",
11
11
  "README.md",
12
- "README.ru.md",
13
12
  "LICENSE",
14
13
  "CHANGELOG.md"
15
14
  ],