@timothyrusso/eslint-plugin-arch 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/dist/configs/recommended.d.ts +33 -0
  4. package/dist/configs/recommended.d.ts.map +1 -0
  5. package/dist/configs/recommended.js +103 -0
  6. package/dist/configs/recommended.js.map +1 -0
  7. package/dist/createRule.d.ts +6 -0
  8. package/dist/createRule.d.ts.map +1 -0
  9. package/dist/createRule.js +4 -0
  10. package/dist/createRule.js.map +1 -0
  11. package/dist/index.d.ts +19 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +13 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/kitConfig.d.ts +26 -0
  16. package/dist/kitConfig.d.ts.map +1 -0
  17. package/dist/kitConfig.js +2 -0
  18. package/dist/kitConfig.js.map +1 -0
  19. package/dist/paths.d.ts +13 -0
  20. package/dist/paths.d.ts.map +1 -0
  21. package/dist/paths.js +47 -0
  22. package/dist/paths.js.map +1 -0
  23. package/dist/plugin.d.ts +10 -0
  24. package/dist/plugin.d.ts.map +1 -0
  25. package/dist/plugin.js +13 -0
  26. package/dist/plugin.js.map +1 -0
  27. package/dist/rules/index.d.ts +43 -0
  28. package/dist/rules/index.d.ts.map +1 -0
  29. package/dist/rules/index.js +24 -0
  30. package/dist/rules/index.js.map +1 -0
  31. package/dist/rules/noDashes.d.ts +8 -0
  32. package/dist/rules/noDashes.d.ts.map +1 -0
  33. package/dist/rules/noDashes.js +59 -0
  34. package/dist/rules/noDashes.js.map +1 -0
  35. package/dist/rules/noEffectInViews.d.ts +9 -0
  36. package/dist/rules/noEffectInViews.d.ts.map +1 -0
  37. package/dist/rules/noEffectInViews.js +43 -0
  38. package/dist/rules/noEffectInViews.js.map +1 -0
  39. package/dist/rules/noEffectRunInFacades.d.ts +9 -0
  40. package/dist/rules/noEffectRunInFacades.d.ts.map +1 -0
  41. package/dist/rules/noEffectRunInFacades.js +50 -0
  42. package/dist/rules/noEffectRunInFacades.js.map +1 -0
  43. package/dist/rules/noInlineComments.d.ts +8 -0
  44. package/dist/rules/noInlineComments.d.ts.map +1 -0
  45. package/dist/rules/noInlineComments.js +128 -0
  46. package/dist/rules/noInlineComments.js.map +1 -0
  47. package/dist/rules/noJsxCommentText.d.ts +9 -0
  48. package/dist/rules/noJsxCommentText.d.ts.map +1 -0
  49. package/dist/rules/noJsxCommentText.js +31 -0
  50. package/dist/rules/noJsxCommentText.js.map +1 -0
  51. package/dist/rules/noLiteralGutter.d.ts +17 -0
  52. package/dist/rules/noLiteralGutter.d.ts.map +1 -0
  53. package/dist/rules/noLiteralGutter.js +155 -0
  54. package/dist/rules/noLiteralGutter.js.map +1 -0
  55. package/dist/rules/noRelativeImports.d.ts +13 -0
  56. package/dist/rules/noRelativeImports.d.ts.map +1 -0
  57. package/dist/rules/noRelativeImports.js +51 -0
  58. package/dist/rules/noRelativeImports.js.map +1 -0
  59. package/dist/rules/preferViewmodel.d.ts +12 -0
  60. package/dist/rules/preferViewmodel.d.ts.map +1 -0
  61. package/dist/rules/preferViewmodel.js +93 -0
  62. package/dist/rules/preferViewmodel.js.map +1 -0
  63. package/dist/rules/stableRowHandlers.d.ts +10 -0
  64. package/dist/rules/stableRowHandlers.d.ts.map +1 -0
  65. package/dist/rules/stableRowHandlers.js +162 -0
  66. package/dist/rules/stableRowHandlers.js.map +1 -0
  67. package/dist/rules/viewmodelReturnShape.d.ts +5 -0
  68. package/dist/rules/viewmodelReturnShape.d.ts.map +1 -0
  69. package/dist/rules/viewmodelReturnShape.js +150 -0
  70. package/dist/rules/viewmodelReturnShape.js.map +1 -0
  71. package/package.json +46 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Timothy Russo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # @timothyrusso/eslint-plugin-arch
2
+
3
+ ESLint rules for the kit's architecture: the ViewModel contract, comments, dashes, layout tokens,
4
+ stable row handlers and Effect placement. Flat config only, ESLint 9.15 or later.
5
+
6
+ ## Use
7
+
8
+ ```sh
9
+ npm install -D @timothyrusso/eslint-plugin-arch @timothyrusso/config-presets eslint typescript
10
+ ```
11
+
12
+ `eslint.config.js` at the app root:
13
+
14
+ ```js
15
+ import arch from '@timothyrusso/eslint-plugin-arch';
16
+ import { loadKitConfig } from '@timothyrusso/config-presets';
17
+
18
+ export default [
19
+ { ignores: ['node_modules/**', 'dist/**', '.expo/**'] },
20
+ ...arch.configs.recommended(loadKitConfig()),
21
+ ];
22
+ ```
23
+
24
+ `configs.recommended(kitConfig)` reads `appRoot`, `featuresRoot` and the `lint` section of
25
+ `kit.config.json` (a raw parsed file works too: every field takes the schema default). It
26
+ registers the plugin as `arch`, parses every JS and TS file with `@typescript-eslint/parser`, and
27
+ turns rules on as follows:
28
+
29
+ | Rule | On when |
30
+ | --- | --- |
31
+ | `arch/viewmodel-return-shape` | always |
32
+ | `arch/prefer-viewmodel` | always, `allow` = `lint.allowedHooksInViews` (default empty) |
33
+ | `arch/no-inline-comments` | always |
34
+ | `arch/no-jsx-comment-text` | always |
35
+ | `arch/stable-row-handlers` | always |
36
+ | `arch/no-effect-in-views` | always |
37
+ | `arch/no-effect-run-in-facades` | always |
38
+ | `arch/no-relative-imports` | always, allowed only in root-level `*.config.{js,cjs,mjs,ts}` files (`DEFAULT_RELATIVE_IMPORT_ALLOW`) |
39
+ | `no-restricted-syntax` (`enum`, `as Error`) | always |
40
+ | `arch/no-dashes` | `lint.dashes` is not `allow` |
41
+ | `arch/no-literal-gutter` | `lint.layoutTokens` is set; only in `appRoot` and `<featuresRoot>/core/design-system` |
42
+ | `no-restricted-imports` (`ActivityIndicator`) | `lint.singleSpinner`; off inside the design system |
43
+
44
+ Override any of them in a later config block, for example a wider allowlist for relative imports
45
+ (an override replaces the default list, so spread it back in):
46
+
47
+ ```js
48
+ import arch, { DEFAULT_RELATIVE_IMPORT_ALLOW } from '@timothyrusso/eslint-plugin-arch';
49
+
50
+ {
51
+ files: ['**/*.ts'],
52
+ rules: { 'arch/no-relative-imports': ['error', { allow: [...DEFAULT_RELATIVE_IMPORT_ALLOW, 'scripts'] }] },
53
+ }
54
+ ```
55
+
56
+ The package also exports `rules` (for `RuleTester`), `RESTRICTED_SYNTAX`, `SOURCE_FILES`,
57
+ `DEFAULT_RELATIVE_IMPORT_ALLOW` and the
58
+ `LintKitConfig` type.
59
+
60
+ Checks that need more than one file (i18n parity, unused catalog keys, hooks, watch bounds) are
61
+ node scripts in `@timothyrusso/config-presets`, because ESLint sees one file at a time.
62
+
63
+ ## Rules
64
+
65
+ ### viewmodel-return-shape
66
+
67
+ A hook in a `*.logic.ts` file returns an object literal whose keys are a non-empty subset of
68
+ `{ state, derived, effects }`, or returns nothing. Spreads and computed keys are rejected because
69
+ they cannot be checked. Returns inside nested functions belong to those functions.
70
+
71
+ ### prefer-viewmodel
72
+
73
+ A `.tsx` that imports its sibling `.logic` module (same basename) calls only that ViewModel hook,
74
+ at most once. Any other hook call, including `React.useState` and another view's ViewModel, is
75
+ reported unless its name is in `allow`. A `.tsx` without a `.logic` import is presentational and
76
+ exempt, and so are test files.
77
+
78
+ ### no-inline-comments
79
+
80
+ Only `// NOTE:` and `// HACK:` codetags (a codetag may wrap onto the `//` lines directly under
81
+ it), tool directives (`eslint-disable`, `biome-ignore`, `@ts-expect-error`, triple-slash
82
+ references), a shebang, and TSDoc `/** */` blocks. A TSDoc block must lead a top-level
83
+ declaration, a class or interface member, an `export` statement, or the first import (a file
84
+ overview).
85
+
86
+ ### no-dashes
87
+
88
+ No em dash (U+2014) anywhere in the file. No en dash (U+2013) in string literals, template text,
89
+ JSX text or comments. A numeric range takes a hyphen (`8-12`).
90
+
91
+ ### no-literal-gutter
92
+
93
+ A horizontal padding or margin (`paddingHorizontal`, `paddingLeft`, `paddingRight`,
94
+ `paddingStart`, `paddingEnd` and the `margin` equivalents, as a style key or a JSX prop, plus the
95
+ `px`, `mx`, `pl`, `pr`, `ml`, `mr` layout props) is never a literal number other than 0, and never
96
+ the non-gutter token of the spacing scale (`spacing.xl` by default). Use the gutter token for a
97
+ screen edge and a smaller step inside a component. Arithmetic on a token passes.
98
+
99
+ Options: `gutterToken` and `spacingImport` (from `lint.layoutTokens`: the spacing object is
100
+ whatever the file imports from `spacingImport`), `allowlistFile` (one path or glob per line,
101
+ relative to the ESLint working directory, `#` starts a comment; a missing file allows nothing),
102
+ and `nonGutterTokens` (default `['xl']`).
103
+
104
+ ### no-jsx-comment-text
105
+
106
+ JSX text that starts with `//` or `/*`. Inside JSX those characters are text, which type-checks
107
+ and then fails at runtime in React Native. A comment inside `{}` passes.
108
+
109
+ ### stable-row-handlers
110
+
111
+ In a file that renders a `FlashList` or `FlatList`, a function passed as a prop to a row component
112
+ (the outermost element `renderItem` returns) or to a `memo` component is a `useCallback` result
113
+ or a module-level function. An inline arrow, a function expression, a `.bind()` call or a function
114
+ declared inside the component is reported. Props and ViewModel members (`effects.select`) pass,
115
+ since their stability is decided elsewhere.
116
+
117
+ ### no-effect-in-views
118
+
119
+ A `.tsx` never imports `effect`, a subpath of it or an `@effect/*` package, including type-only
120
+ imports, re-exports, `import()` and `require()`. The `effect-only-in-inner-layers` rule of
121
+ `@timothyrusso/arch-rules` catches the same import across the graph; this one puts the message on
122
+ the line.
123
+
124
+ ### no-effect-run-in-facades
125
+
126
+ In a file under `facades/`: no `.runPromise`, `.runSync`, `.runFork`, `.runCallback` (or their
127
+ `Exit` variants) on anything, and no `ManagedRuntime` import. The dependency-cruiser rule
128
+ `facades-run-through-boundary` sees modules, not the names imported from them; this rule sees
129
+ names. Facades hand Effects to `useEffectQuery` and `useEffectMutation`.
130
+
131
+ ### no-relative-imports
132
+
133
+ `./` and `../` in imports, re-exports, `import()`, `require()` and `import('...')` types, unless
134
+ the file is in one of the `allow` globs (relative to the ESLint working directory; `*` stays in
135
+ one folder, `**` spans folders, `{a,b}` matches either, a folder covers everything under it). The
136
+ recommended config allows root-level `*.config.{js,cjs,mjs,ts}` files, which import their
137
+ neighbours (`./kit.config.json`) by nature.
138
+
139
+ ## Develop
140
+
141
+ Tests are Jest with `@typescript-eslint/rule-tester`, one file per rule in
142
+ `src/__tests__/rules/`. `src/__tests__/recommended.test.ts` lints the Expo-shaped fixture app in
143
+ `src/__tests__/fixtures/app` through ESLint's `ESLint` class with `configs.recommended` and its
144
+ `kit.config.json`: the clean files report nothing, and every file with `broken` in its path
145
+ reports exactly its deliberate violations. The fixture app is excluded from Biome, the kit's own
146
+ ESLint run, `tsc` and dependency-cruiser.
@@ -0,0 +1,33 @@
1
+ import type { Linter } from 'eslint';
2
+ import type { LintKitConfig } from '../kitConfig.js';
3
+ /** The namespace the recommended config registers the plugin under: rules read `arch/<rule>`. */
4
+ export declare const PLUGIN_NAMESPACE = "arch";
5
+ /** Every file the recommended config lints. */
6
+ export declare const SOURCE_FILES = "**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}";
7
+ /**
8
+ * Where `no-relative-imports` allows relative imports by default: root-level config files, such as
9
+ * `eslint.config.js` importing `./kit.config.json` or `metro.config.js`.
10
+ */
11
+ export declare const DEFAULT_RELATIVE_IMPORT_ALLOW: readonly ["*.config.{js,cjs,mjs,ts}"];
12
+ /** `no-restricted-syntax` entries: no TypeScript `enum`, no `as Error`. */
13
+ export declare const RESTRICTED_SYNTAX: readonly [{
14
+ readonly selector: "TSEnumDeclaration";
15
+ readonly message: "Use a union of string literals or an `as const` object, not `enum`.";
16
+ }, {
17
+ readonly selector: "TSAsExpression > TSTypeReference.typeAnnotation > Identifier[name='Error']";
18
+ readonly message: "Do not cast to Error: narrow with `instanceof` or convert with a helper.";
19
+ }];
20
+ /**
21
+ * The kit's flat config for an app, driven by its `kit.config.json`. Spread it into
22
+ * `eslint.config.js`; override a rule in a later block.
23
+ *
24
+ * - Always: the ViewModel rules (`prefer-viewmodel` allows `lint.allowedHooksInViews`),
25
+ * `no-inline-comments`, `no-jsx-comment-text`, `stable-row-handlers`, `no-effect-in-views`,
26
+ * `no-effect-run-in-facades`, `no-relative-imports` (allowed in root-level config files) and `no-restricted-syntax` for `enum` and
27
+ * `as Error`.
28
+ * - `lint.dashes` is not `allow`: `no-dashes`.
29
+ * - `lint.layoutTokens`: `no-literal-gutter` in `appRoot` and `<featuresRoot>/core/design-system`.
30
+ * - `lint.singleSpinner`: `no-restricted-imports` for `ActivityIndicator`, outside the design system.
31
+ */
32
+ export declare function recommended(kitConfig?: LintKitConfig): Linter.Config[];
33
+ //# sourceMappingURL=recommended.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommended.d.ts","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIrD,iGAAiG;AACjG,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAIvC,+CAA+C;AAC/C,eAAO,MAAM,YAAY,yCAAuB,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,uCAAwC,CAAC;AAEnF,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB;;;;;;EASpB,CAAC;AAOX;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,SAAS,GAAE,aAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,CAkE1E"}
@@ -0,0 +1,103 @@
1
+ import * as tsParser from '@typescript-eslint/parser';
2
+ import { plugin } from '../plugin.js';
3
+ /** The namespace the recommended config registers the plugin under: rules read `arch/<rule>`. */
4
+ export const PLUGIN_NAMESPACE = 'arch';
5
+ const EXTENSIONS = '{js,jsx,mjs,cjs,ts,tsx,mts,cts}';
6
+ /** Every file the recommended config lints. */
7
+ export const SOURCE_FILES = `**/*.${EXTENSIONS}`;
8
+ /**
9
+ * Where `no-relative-imports` allows relative imports by default: root-level config files, such as
10
+ * `eslint.config.js` importing `./kit.config.json` or `metro.config.js`.
11
+ */
12
+ export const DEFAULT_RELATIVE_IMPORT_ALLOW = ['*.config.{js,cjs,mjs,ts}'];
13
+ /** `no-restricted-syntax` entries: no TypeScript `enum`, no `as Error`. */
14
+ export const RESTRICTED_SYNTAX = [
15
+ {
16
+ selector: 'TSEnumDeclaration',
17
+ message: 'Use a union of string literals or an `as const` object, not `enum`.',
18
+ },
19
+ {
20
+ selector: "TSAsExpression > TSTypeReference.typeAnnotation > Identifier[name='Error']",
21
+ message: 'Do not cast to Error: narrow with `instanceof` or convert with a helper.',
22
+ },
23
+ ];
24
+ /** The folder of the design system, which owns the spinner and the spacing scale. */
25
+ function designSystemRoot(featuresRoot) {
26
+ return `${featuresRoot}/core/design-system`;
27
+ }
28
+ /**
29
+ * The kit's flat config for an app, driven by its `kit.config.json`. Spread it into
30
+ * `eslint.config.js`; override a rule in a later block.
31
+ *
32
+ * - Always: the ViewModel rules (`prefer-viewmodel` allows `lint.allowedHooksInViews`),
33
+ * `no-inline-comments`, `no-jsx-comment-text`, `stable-row-handlers`, `no-effect-in-views`,
34
+ * `no-effect-run-in-facades`, `no-relative-imports` (allowed in root-level config files) and `no-restricted-syntax` for `enum` and
35
+ * `as Error`.
36
+ * - `lint.dashes` is not `allow`: `no-dashes`.
37
+ * - `lint.layoutTokens`: `no-literal-gutter` in `appRoot` and `<featuresRoot>/core/design-system`.
38
+ * - `lint.singleSpinner`: `no-restricted-imports` for `ActivityIndicator`, outside the design system.
39
+ */
40
+ export function recommended(kitConfig = {}) {
41
+ const appRoot = kitConfig.appRoot ?? 'app';
42
+ const featuresRoot = kitConfig.featuresRoot ?? 'features';
43
+ const lint = kitConfig.lint ?? {};
44
+ const designSystem = designSystemRoot(featuresRoot);
45
+ const prefix = (rule) => `${PLUGIN_NAMESPACE}/${rule}`;
46
+ const rules = {
47
+ [prefix('viewmodel-return-shape')]: 'error',
48
+ [prefix('prefer-viewmodel')]: ['error', { allow: [...(lint.allowedHooksInViews ?? [])] }],
49
+ [prefix('no-inline-comments')]: 'error',
50
+ [prefix('no-jsx-comment-text')]: 'error',
51
+ [prefix('stable-row-handlers')]: 'error',
52
+ [prefix('no-effect-in-views')]: 'error',
53
+ [prefix('no-effect-run-in-facades')]: 'error',
54
+ [prefix('no-relative-imports')]: ['error', { allow: [...DEFAULT_RELATIVE_IMPORT_ALLOW] }],
55
+ 'no-restricted-syntax': ['error', ...RESTRICTED_SYNTAX],
56
+ };
57
+ if (lint.dashes !== 'allow')
58
+ rules[prefix('no-dashes')] = 'error';
59
+ if (lint.singleSpinner) {
60
+ rules['no-restricted-imports'] = [
61
+ 'error',
62
+ {
63
+ paths: [
64
+ {
65
+ name: 'react-native',
66
+ importNames: ['ActivityIndicator'],
67
+ message: `Use the design system spinner from ${designSystem}.`,
68
+ },
69
+ ],
70
+ },
71
+ ];
72
+ }
73
+ const configs = [
74
+ {
75
+ name: `${PLUGIN_NAMESPACE}/recommended`,
76
+ files: [SOURCE_FILES],
77
+ plugins: { [PLUGIN_NAMESPACE]: plugin },
78
+ languageOptions: {
79
+ parser: tsParser,
80
+ sourceType: 'module',
81
+ parserOptions: { ecmaFeatures: { jsx: true } },
82
+ },
83
+ rules,
84
+ },
85
+ ];
86
+ if (lint.singleSpinner) {
87
+ configs.push({
88
+ name: `${PLUGIN_NAMESPACE}/recommended/design-system-spinner`,
89
+ files: [`${designSystem}/**/*.${EXTENSIONS}`],
90
+ rules: { 'no-restricted-imports': 'off' },
91
+ });
92
+ }
93
+ if (lint.layoutTokens) {
94
+ const { gutterToken, spacingImport, allowlistFile } = lint.layoutTokens;
95
+ configs.push({
96
+ name: `${PLUGIN_NAMESPACE}/recommended/layout`,
97
+ files: [`${appRoot}/**/*.{ts,tsx}`, `${designSystem}/**/*.{ts,tsx}`],
98
+ rules: { [prefix('no-literal-gutter')]: ['error', { gutterToken, spacingImport, allowlistFile }] },
99
+ });
100
+ }
101
+ return configs;
102
+ }
103
+ //# sourceMappingURL=recommended.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommended.js","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ /** Every rule links to its section of the package README. */
3
+ export declare const createRule: <Options extends readonly unknown[], MessageIds extends string>({ meta, name, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<Options, MessageIds, unknown>>) => ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener> & {
4
+ name: string;
5
+ };
6
+ //# sourceMappingURL=createRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createRule.d.ts","sourceRoot":"","sources":["../src/createRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,6DAA6D;AAC7D,eAAO,MAAM,UAAU;;CAEtB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ /** Every rule links to its section of the package README. */
3
+ export const createRule = ESLintUtils.RuleCreator(name => `https://github.com/timothyrusso/agentic-kit/tree/main/packages/eslint-plugin-arch#${name}`);
4
+ //# sourceMappingURL=createRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createRule.js","sourceRoot":"","sources":["../src/createRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CAC/C,IAAI,CAAC,EAAE,CAAC,qFAAqF,IAAI,EAAE,CACpG,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @timothyrusso/eslint-plugin-arch. ESLint rules for the agentic-kit architecture: ViewModel contract, comments, dashes, layout, stable row handlers, Effect in views.
3
+ */
4
+ import { recommended } from './configs/recommended.js';
5
+ export { DEFAULT_RELATIVE_IMPORT_ALLOW, PLUGIN_NAMESPACE, RESTRICTED_SYNTAX, recommended, SOURCE_FILES, } from './configs/recommended.js';
6
+ export type { LintKitConfig } from './kitConfig.js';
7
+ export { rules } from './rules/index.js';
8
+ /** `configs.recommended(kitConfig)` builds the flat config for an app. */
9
+ export declare const configs: {
10
+ recommended: typeof recommended;
11
+ };
12
+ /** The plugin, with `configs`. The recommended config registers this same object. */
13
+ declare const eslintPluginArch: import("@eslint/core", { with: { "resolution-mode": "require" } }).Plugin & {
14
+ configs: {
15
+ recommended: typeof recommended;
16
+ };
17
+ };
18
+ export default eslintPluginArch;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,0EAA0E;AAC1E,eAAO,MAAM,OAAO;;CAAkB,CAAC;AAEvC,qFAAqF;AACrF,QAAA,MAAM,gBAAgB;;;;CAAqC,CAAC;AAE5D,eAAe,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @timothyrusso/eslint-plugin-arch. ESLint rules for the agentic-kit architecture: ViewModel contract, comments, dashes, layout, stable row handlers, Effect in views.
3
+ */
4
+ import { recommended } from './configs/recommended.js';
5
+ import { plugin } from './plugin.js';
6
+ export { DEFAULT_RELATIVE_IMPORT_ALLOW, PLUGIN_NAMESPACE, RESTRICTED_SYNTAX, recommended, SOURCE_FILES, } from './configs/recommended.js';
7
+ export { rules } from './rules/index.js';
8
+ /** `configs.recommended(kitConfig)` builds the flat config for an app. */
9
+ export const configs = { recommended };
10
+ /** The plugin, with `configs`. The recommended config registers this same object. */
11
+ const eslintPluginArch = Object.assign(plugin, { configs });
12
+ export default eslintPluginArch;
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,YAAY,GACb,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,0EAA0E;AAC1E,MAAM,CAAC,MAAM,OAAO,GAAG,EAAE,WAAW,EAAE,CAAC;AAEvC,qFAAqF;AACrF,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AAE5D,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The fields of `kit.config.json` the recommended config reads. A `KitConfig` from
3
+ * `@timothyrusso/config-presets` satisfies it, and so does the raw parsed file: every field is
4
+ * optional and takes the schema default.
5
+ */
6
+ export interface LintKitConfig {
7
+ /** expo-router app folder. Defaults to `app`. */
8
+ readonly appRoot?: string;
9
+ /** Folder that holds the feature modules. Defaults to `features`. */
10
+ readonly featuresRoot?: string;
11
+ readonly lint?: {
12
+ /** Hooks a view may call besides its own ViewModel hook. */
13
+ readonly allowedHooksInViews?: readonly string[];
14
+ /** `forbid` (the default) turns on `no-dashes`. */
15
+ readonly dashes?: 'forbid' | 'allow';
16
+ /** Turns on `no-literal-gutter` for the app folder and the design system. */
17
+ readonly layoutTokens?: {
18
+ readonly gutterToken: string;
19
+ readonly spacingImport: string;
20
+ readonly allowlistFile: string;
21
+ };
22
+ /** Forbids `ActivityIndicator` in favour of the design system spinner. */
23
+ readonly singleSpinner?: boolean;
24
+ };
25
+ }
26
+ //# sourceMappingURL=kitConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kitConfig.d.ts","sourceRoot":"","sources":["../src/kitConfig.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE;QACd,4DAA4D;QAC5D,QAAQ,CAAC,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACjD,mDAAmD;QACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;QACrC,6EAA6E;QAC7E,QAAQ,CAAC,YAAY,CAAC,EAAE;YACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;YAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;YAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;SAChC,CAAC;QACF,0EAA0E;QAC1E,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;KAClC,CAAC;CACH"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=kitConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kitConfig.js","sourceRoot":"","sources":["../src/kitConfig.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ /** A file path relative to `cwd`, with forward slashes, for matching against config folders. */
2
+ export declare function relativePath(cwd: string, filename: string): string;
3
+ /**
4
+ * Turns a small glob into a regular expression that matches a relative path and everything under
5
+ * it: `**` spans folders, `*` stays inside one segment, `{a,b}` is either. `packages/*` matches
6
+ * `packages/a/src/b.ts`.
7
+ */
8
+ export declare function globToRegExp(glob: string): RegExp;
9
+ /** Whether `path` sits in one of the folders or files the globs name. */
10
+ export declare function matchesAny(path: string, globs: readonly string[]): boolean;
11
+ /** Whether a file is a test, which the ViewModel rules skip. */
12
+ export declare function isTestFile(filename: string): boolean;
13
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAEA,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqBjD;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAE1E;AAED,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEpD"}
package/dist/paths.js ADDED
@@ -0,0 +1,47 @@
1
+ import { isAbsolute, relative, sep } from 'node:path';
2
+ /** A file path relative to `cwd`, with forward slashes, for matching against config folders. */
3
+ export function relativePath(cwd, filename) {
4
+ const rel = isAbsolute(filename) ? relative(cwd, filename) : filename;
5
+ return rel.split(sep).join('/');
6
+ }
7
+ /**
8
+ * Turns a small glob into a regular expression that matches a relative path and everything under
9
+ * it: `**` spans folders, `*` stays inside one segment, `{a,b}` is either. `packages/*` matches
10
+ * `packages/a/src/b.ts`.
11
+ */
12
+ export function globToRegExp(glob) {
13
+ const trimmed = glob.replace(/^\.\//, '').replace(/\/+$/, '');
14
+ let source = '';
15
+ for (let i = 0; i < trimmed.length; i += 1) {
16
+ const ch = trimmed.charAt(i);
17
+ if (ch === '*' && trimmed.charAt(i + 1) === '*') {
18
+ source += '.*';
19
+ i += 1;
20
+ }
21
+ else if (ch === '*') {
22
+ source += '[^/]*';
23
+ }
24
+ else if (ch === '{') {
25
+ source += '(?:';
26
+ }
27
+ else if (ch === '}') {
28
+ source += ')';
29
+ }
30
+ else if (ch === ',') {
31
+ source += '|';
32
+ }
33
+ else {
34
+ source += ch.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
35
+ }
36
+ }
37
+ return new RegExp(`^${source}(?:/|$)`);
38
+ }
39
+ /** Whether `path` sits in one of the folders or files the globs name. */
40
+ export function matchesAny(path, globs) {
41
+ return globs.some(glob => globToRegExp(glob).test(path));
42
+ }
43
+ /** Whether a file is a test, which the ViewModel rules skip. */
44
+ export function isTestFile(filename) {
45
+ return filename.includes('.test.') || filename.includes('.spec.');
46
+ }
47
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEtD,gGAAgG;AAChG,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,QAAgB;IACxD,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACtE,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC9D,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC7B,IAAI,EAAE,KAAK,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAChD,MAAM,IAAI,IAAI,CAAC;YACf,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,MAAM,IAAI,OAAO,CAAC;QACpB,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC;QAClB,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,CAAC;QAChB,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,EAAE,CAAC,OAAO,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,IAAI,MAAM,SAAS,CAAC,CAAC;AACzC,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAwB;IAC/D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,OAAO,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ESLint } from 'eslint';
2
+ /**
3
+ * The plugin object, without `configs`: the recommended config registers this same instance.
4
+ *
5
+ * NOTE: the rules are typed with `@typescript-eslint/utils`, whose `RuleContext` declares members
6
+ * ESLint's own `Rule` type leaves out, so the two types do not unify. They are the same objects at
7
+ * runtime; the cast is the one place the plugin crosses from one type to the other.
8
+ */
9
+ export declare const plugin: ESLint.Plugin;
10
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGrC;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAG3B,CAAC"}
package/dist/plugin.js ADDED
@@ -0,0 +1,13 @@
1
+ import { rules } from './rules/index.js';
2
+ /**
3
+ * The plugin object, without `configs`: the recommended config registers this same instance.
4
+ *
5
+ * NOTE: the rules are typed with `@typescript-eslint/utils`, whose `RuleContext` declares members
6
+ * ESLint's own `Rule` type leaves out, so the two types do not unify. They are the same objects at
7
+ * runtime; the cast is the one place the plugin crosses from one type to the other.
8
+ */
9
+ export const plugin = {
10
+ meta: { name: '@timothyrusso/eslint-plugin-arch' },
11
+ rules: rules,
12
+ };
13
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,MAAM,GAAkB;IACnC,IAAI,EAAE,EAAE,IAAI,EAAE,kCAAkC,EAAE;IAClD,KAAK,EAAE,KAAuD;CAC/D,CAAC"}
@@ -0,0 +1,43 @@
1
+ /** Every rule the plugin ships, by rule id. */
2
+ export declare const rules: {
3
+ 'no-dashes': import("@typescript-eslint/utils/ts-eslint").RuleModule<"emDash" | "enDash", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
4
+ name: string;
5
+ };
6
+ 'no-effect-in-views': import("@typescript-eslint/utils/ts-eslint").RuleModule<"effectImport", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
7
+ name: string;
8
+ };
9
+ 'no-effect-run-in-facades': import("@typescript-eslint/utils/ts-eslint").RuleModule<"run" | "runtime", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
10
+ name: string;
11
+ };
12
+ 'no-inline-comments': import("@typescript-eslint/utils/ts-eslint").RuleModule<"noComment" | "misplacedDoc", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
13
+ name: string;
14
+ };
15
+ 'no-jsx-comment-text': import("@typescript-eslint/utils/ts-eslint").RuleModule<"commentText", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
16
+ name: string;
17
+ };
18
+ 'no-literal-gutter': import("@typescript-eslint/utils/ts-eslint").RuleModule<"literal" | "token", [{
19
+ gutterToken: string;
20
+ spacingImport: string;
21
+ allowlistFile?: string;
22
+ nonGutterTokens?: string[];
23
+ }], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
24
+ name: string;
25
+ };
26
+ 'no-relative-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"relative", [{
27
+ allow?: string[];
28
+ }], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
29
+ name: string;
30
+ };
31
+ 'prefer-viewmodel': import("@typescript-eslint/utils/ts-eslint").RuleModule<"foreignHook" | "calledTwice", [{
32
+ allow?: string[];
33
+ }], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
34
+ name: string;
35
+ };
36
+ 'stable-row-handlers': import("@typescript-eslint/utils/ts-eslint").RuleModule<"inline" | "unstable", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
37
+ name: string;
38
+ };
39
+ 'viewmodel-return-shape': import("@typescript-eslint/utils/ts-eslint").RuleModule<"notObject" | "wrongShape", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
40
+ name: string;
41
+ };
42
+ };
43
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAWA,+CAA+C;AAC/C,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAWjB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { noDashes } from './noDashes.js';
2
+ import { noEffectInViews } from './noEffectInViews.js';
3
+ import { noEffectRunInFacades } from './noEffectRunInFacades.js';
4
+ import { noInlineComments } from './noInlineComments.js';
5
+ import { noJsxCommentText } from './noJsxCommentText.js';
6
+ import { noLiteralGutter } from './noLiteralGutter.js';
7
+ import { noRelativeImports } from './noRelativeImports.js';
8
+ import { preferViewmodel } from './preferViewmodel.js';
9
+ import { stableRowHandlers } from './stableRowHandlers.js';
10
+ import { viewmodelReturnShape } from './viewmodelReturnShape.js';
11
+ /** Every rule the plugin ships, by rule id. */
12
+ export const rules = {
13
+ 'no-dashes': noDashes,
14
+ 'no-effect-in-views': noEffectInViews,
15
+ 'no-effect-run-in-facades': noEffectRunInFacades,
16
+ 'no-inline-comments': noInlineComments,
17
+ 'no-jsx-comment-text': noJsxCommentText,
18
+ 'no-literal-gutter': noLiteralGutter,
19
+ 'no-relative-imports': noRelativeImports,
20
+ 'prefer-viewmodel': preferViewmodel,
21
+ 'stable-row-handlers': stableRowHandlers,
22
+ 'viewmodel-return-shape': viewmodelReturnShape,
23
+ };
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,+CAA+C;AAC/C,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,WAAW,EAAE,QAAQ;IACrB,oBAAoB,EAAE,eAAe;IACrC,0BAA0B,EAAE,oBAAoB;IAChD,oBAAoB,EAAE,gBAAgB;IACtC,qBAAqB,EAAE,gBAAgB;IACvC,mBAAmB,EAAE,eAAe;IACpC,qBAAqB,EAAE,iBAAiB;IACxC,kBAAkB,EAAE,eAAe;IACnC,qBAAqB,EAAE,iBAAiB;IACxC,wBAAwB,EAAE,oBAAoB;CAC/C,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * No em dash anywhere in a file, and no en dash in prose: string literals, template text, JSX
3
+ * text and comments. A numeric range takes a plain hyphen (`8-12`).
4
+ */
5
+ export declare const noDashes: import("@typescript-eslint/utils/ts-eslint").RuleModule<"emDash" | "enDash", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
6
+ name: string;
7
+ };
8
+ //# sourceMappingURL=noDashes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noDashes.d.ts","sourceRoot":"","sources":["../../src/rules/noDashes.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,eAAO,MAAM,QAAQ;;CA8CnB,CAAC"}