@study-lenses/create-package 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.
- package/LICENSE +21 -0
- package/README.md +86 -0
- package/package.json +79 -0
- package/templates/.editorconfig +15 -0
- package/templates/.github/ISSUE_TEMPLATE/bug-report.yml +91 -0
- package/templates/.github/ISSUE_TEMPLATE/feature-request.yml +68 -0
- package/templates/.github/PULL_REQUEST_TEMPLATE.md +27 -0
- package/templates/.github/dependabot.yml +9 -0
- package/templates/.github/workflows/ci.yml +19 -0
- package/templates/.github/workflows/docs.yml +25 -0
- package/templates/.github/workflows/publish.yml +23 -0
- package/templates/.husky/pre-commit +1 -0
- package/templates/.prettierrc.json +15 -0
- package/templates/.vscode/extensions.json +11 -0
- package/templates/.vscode/launch.json +34 -0
- package/templates/.vscode/settings.json +28 -0
- package/templates/AGENTS.md +575 -0
- package/templates/CLAUDE.md +3 -0
- package/templates/CODE-OF-CONDUCT.md +39 -0
- package/templates/CONTRIBUTING.md +53 -0
- package/templates/DEV.md +1200 -0
- package/templates/DOCS.md +19 -0
- package/templates/LICENSE +21 -0
- package/templates/README.md +89 -0
- package/templates/eslint.config.js +308 -0
- package/templates/gitignore +70 -0
- package/templates/package.json +78 -0
- package/templates/src/DOCS.md +16 -0
- package/templates/src/README.md +15 -0
- package/templates/src/index.ts +1 -0
- package/templates/tsconfig.json +57 -0
- package/templates/tsconfig.lint.json +5 -0
- package/templates/typedoc.json +15 -0
- package/templates/vitest.config.ts +8 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @study-lenses/CHANGEME — Architecture & Decisions
|
|
2
|
+
|
|
3
|
+
## Why this package exists
|
|
4
|
+
|
|
5
|
+
TODO: one paragraph — what problem does this package solve and why does it exist as a
|
|
6
|
+
separate package rather than inline code?
|
|
7
|
+
|
|
8
|
+
## Architecture
|
|
9
|
+
|
|
10
|
+
TODO: describe the internal pipeline or data flow. Diagrams welcome.
|
|
11
|
+
|
|
12
|
+
## Key decisions
|
|
13
|
+
|
|
14
|
+
TODO: explain the non-obvious choices made in this package — what was considered and why
|
|
15
|
+
the current approach was chosen over alternatives.
|
|
16
|
+
|
|
17
|
+
## What this package deliberately does NOT do
|
|
18
|
+
|
|
19
|
+
TODO: scope boundaries. What did you intentionally leave out, and why?
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [YEAR] [NAME]
|
|
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.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# @study-lenses/CHANGEME
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@study-lenses/CHANGEME)
|
|
4
|
+
[](https://github.com/OWNER/REPO/actions/workflows/ci.yml)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
7
|
+
> TODO: One sentence — what does this package do and who is it for?
|
|
8
|
+
|
|
9
|
+
## Pedagogical Purpose
|
|
10
|
+
|
|
11
|
+
<!-- What role does this package play in the Study Lenses learning ecosystem? -->
|
|
12
|
+
<!-- Is it neutral infrastructure (provides data, makes no pedagogical decisions)? -->
|
|
13
|
+
<!-- Or does it implement a specific pedagogical approach? If so, which one and why? -->
|
|
14
|
+
<!-- See embody's README §Design Principles for a worked example. -->
|
|
15
|
+
|
|
16
|
+
TODO: describe the package's educational function. Choose one framing (delete the other):
|
|
17
|
+
|
|
18
|
+
**Neutral infrastructure:** This package provides `[X]` for educational tool developers.
|
|
19
|
+
It makes no pedagogical decisions — those belong in the tools that consume it.
|
|
20
|
+
|
|
21
|
+
**Pedagogically opinionated:** This package implements `[approach/theory]` because
|
|
22
|
+
`[rationale]`. It is intended to be used as `[context]`.
|
|
23
|
+
|
|
24
|
+
## Who Is This For
|
|
25
|
+
|
|
26
|
+
<!-- Study Lenses packages typically serve one or more of these three audiences. -->
|
|
27
|
+
<!-- Delete tiers that don't apply. Adapt descriptions to your specific package. -->
|
|
28
|
+
|
|
29
|
+
**Primary — Educational tool developers:** Building Study Lenses, custom analysis tools,
|
|
30
|
+
LMS integrations, or other learning environments on top of this package.
|
|
31
|
+
|
|
32
|
+
**Secondary — CS instructors:** Using this package directly to build course-specific
|
|
33
|
+
tools, debugging aids, or assessment instruments.
|
|
34
|
+
|
|
35
|
+
**Tertiary — CER researchers:** Using this package for data collection, intervention
|
|
36
|
+
measurement, or misconception detection across student populations.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @study-lenses/CHANGEME
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// TODO: Simplest possible usage — one import, one call, one meaningful output
|
|
48
|
+
import { ... } from '@study-lenses/CHANGEME';
|
|
49
|
+
|
|
50
|
+
const result = ...;
|
|
51
|
+
console.log(result);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Design Principles
|
|
55
|
+
|
|
56
|
+
<!-- What does this package do, and — just as importantly — what does it NOT do? -->
|
|
57
|
+
<!-- The infrastructure/intelligence boundary is central to Study Lenses design: -->
|
|
58
|
+
<!-- infrastructure packages provide raw data / capabilities -->
|
|
59
|
+
<!-- tool packages interpret that data and make pedagogical decisions -->
|
|
60
|
+
|
|
61
|
+
### What this package provides
|
|
62
|
+
|
|
63
|
+
TODO
|
|
64
|
+
|
|
65
|
+
### What this package does NOT do
|
|
66
|
+
|
|
67
|
+
TODO
|
|
68
|
+
|
|
69
|
+
## API Reference
|
|
70
|
+
|
|
71
|
+
Generated from TSDoc comments in source. Run `npm run docs` locally, or see the
|
|
72
|
+
[hosted API docs](https://OWNER.github.io/REPO/).
|
|
73
|
+
|
|
74
|
+
## Architecture
|
|
75
|
+
|
|
76
|
+
<!-- Contributor-facing. Describe the internal pipeline or data flow. -->
|
|
77
|
+
<!-- Pipeline diagrams belong here. Detailed conventions are in DEV.md. -->
|
|
78
|
+
|
|
79
|
+
TODO: brief description of the internal pipeline or data flow.
|
|
80
|
+
|
|
81
|
+
See [DEV.md](./DEV.md) for full architecture, conventions, and the TDD workflow.
|
|
82
|
+
|
|
83
|
+
## Contributing
|
|
84
|
+
|
|
85
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) and [DEV.md](./DEV.md).
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
MIT © [YEAR] [NAME]
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import tseslint from 'typescript-eslint';
|
|
2
|
+
import eslintPluginBoundaries from 'eslint-plugin-boundaries';
|
|
3
|
+
import eslintPluginImport from 'eslint-plugin-import';
|
|
4
|
+
import eslintPluginFunctional from 'eslint-plugin-functional';
|
|
5
|
+
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
|
|
6
|
+
import eslintPluginSonarJS from 'eslint-plugin-sonarjs';
|
|
7
|
+
import eslintPluginSecurity from 'eslint-plugin-security';
|
|
8
|
+
import eslintConfigPrettier from 'eslint-config-prettier';
|
|
9
|
+
|
|
10
|
+
export default tseslint.config(
|
|
11
|
+
// --- Global ignores ---
|
|
12
|
+
{
|
|
13
|
+
ignores: [
|
|
14
|
+
'dist/',
|
|
15
|
+
'node_modules/',
|
|
16
|
+
'**/*.d.ts',
|
|
17
|
+
'docs/', // TypeDoc-generated, not linted
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
// --- Base TypeScript configs ---
|
|
22
|
+
...tseslint.configs.recommended,
|
|
23
|
+
...tseslint.configs.recommendedTypeChecked,
|
|
24
|
+
|
|
25
|
+
// --- Prettier (must come after other configs to override formatting rules) ---
|
|
26
|
+
eslintConfigPrettier,
|
|
27
|
+
|
|
28
|
+
// --- All source files ---
|
|
29
|
+
{
|
|
30
|
+
files: ['src/**/*.ts'],
|
|
31
|
+
plugins: {
|
|
32
|
+
boundaries: eslintPluginBoundaries,
|
|
33
|
+
import: eslintPluginImport,
|
|
34
|
+
functional: eslintPluginFunctional,
|
|
35
|
+
unicorn: eslintPluginUnicorn,
|
|
36
|
+
sonarjs: eslintPluginSonarJS,
|
|
37
|
+
security: eslintPluginSecurity,
|
|
38
|
+
},
|
|
39
|
+
languageOptions: {
|
|
40
|
+
parserOptions: {
|
|
41
|
+
project: './tsconfig.lint.json',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
settings: {
|
|
45
|
+
// --- TypeScript import resolution (required for boundaries plugin) ---
|
|
46
|
+
'import/resolver': {
|
|
47
|
+
typescript: {
|
|
48
|
+
alwaysTryTypes: true,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
// --- Module boundaries ---
|
|
52
|
+
'boundaries/ignore': ['**/tests/**/*.ts'],
|
|
53
|
+
'boundaries/elements': [
|
|
54
|
+
{ type: 'src', pattern: 'src/**', mode: 'file' },
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
rules: {
|
|
58
|
+
// --- Module boundaries ---
|
|
59
|
+
// TODO: All src files can import from other src files. Expand elements and rules per package.
|
|
60
|
+
'boundaries/element-types': [
|
|
61
|
+
'error',
|
|
62
|
+
{
|
|
63
|
+
default: 'disallow',
|
|
64
|
+
rules: [
|
|
65
|
+
{ from: 'src', allow: ['src'] },
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
'boundaries/no-unknown': ['error'],
|
|
70
|
+
'boundaries/no-unknown-files': ['error'],
|
|
71
|
+
|
|
72
|
+
// --- TypeScript ---
|
|
73
|
+
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
74
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
75
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
76
|
+
// `any` types: Warn during development, review in PR
|
|
77
|
+
// Acceptable uses (see DEV.md § When `any` is OK):
|
|
78
|
+
// - Dynamic runtime values (JSON.parse, eval results)
|
|
79
|
+
// - Untyped library boundaries
|
|
80
|
+
// - Generic utilities (e.g. deep-clone, deep-merge)
|
|
81
|
+
// - Test fixtures (intentionally breaking types)
|
|
82
|
+
// - Stub implementations (temporary mock data)
|
|
83
|
+
// All `any` usage must be justified in code review.
|
|
84
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
85
|
+
'@typescript-eslint/no-unsafe-assignment': 'warn',
|
|
86
|
+
'@typescript-eslint/no-unsafe-call': 'warn',
|
|
87
|
+
'@typescript-eslint/no-unsafe-member-access': 'warn',
|
|
88
|
+
'@typescript-eslint/no-unsafe-return': 'warn',
|
|
89
|
+
'@typescript-eslint/prefer-readonly': 'error',
|
|
90
|
+
'@typescript-eslint/prefer-readonly-parameter-types': 'off',
|
|
91
|
+
'@typescript-eslint/restrict-template-expressions': 'warn',
|
|
92
|
+
'@typescript-eslint/prefer-nullish-coalescing': 'off',
|
|
93
|
+
'@typescript-eslint/prefer-optional-chain': 'error',
|
|
94
|
+
'@typescript-eslint/no-non-null-assertion': 'warn',
|
|
95
|
+
'@typescript-eslint/consistent-type-definitions': ['error', 'type'],
|
|
96
|
+
'@typescript-eslint/no-shadow': 'error',
|
|
97
|
+
|
|
98
|
+
// --- Import rules ---
|
|
99
|
+
// TypeScript handles module resolution (.js imports → .ts files)
|
|
100
|
+
// We just forbid .ts extensions which would break at runtime
|
|
101
|
+
'import/extensions': 'off',
|
|
102
|
+
'import/order': [
|
|
103
|
+
'error',
|
|
104
|
+
{
|
|
105
|
+
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
|
|
106
|
+
'newlines-between': 'always',
|
|
107
|
+
alphabetize: { order: 'asc' },
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
'import/no-named-export': 'error',
|
|
111
|
+
'import/prefer-default-export': 'off',
|
|
112
|
+
|
|
113
|
+
// --- Functional programming (eslint-plugin-functional) ---
|
|
114
|
+
// ERRORS: Core conventions
|
|
115
|
+
'functional/no-this-expressions': 'error',
|
|
116
|
+
'functional/no-classes': 'error',
|
|
117
|
+
// WARNINGS: Encourage immutability without blocking
|
|
118
|
+
'functional/immutable-data': [
|
|
119
|
+
'warn',
|
|
120
|
+
{
|
|
121
|
+
ignoreAccessorPattern: ['module.exports'],
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
'functional/prefer-readonly-type': 'warn',
|
|
125
|
+
// OFF: Too strict for pedagogical codebase
|
|
126
|
+
'functional/no-let': 'off',
|
|
127
|
+
'functional/no-loop-statements': 'off',
|
|
128
|
+
'functional/no-mixed-types': 'off',
|
|
129
|
+
|
|
130
|
+
// --- Naming and style ---
|
|
131
|
+
'func-names': ['error', 'always'],
|
|
132
|
+
'unicorn/filename-case': ['error', { case: 'kebabCase' }],
|
|
133
|
+
|
|
134
|
+
// --- General rules ---
|
|
135
|
+
'no-console': 'off',
|
|
136
|
+
'no-debugger': 'error',
|
|
137
|
+
'prefer-const': 'error',
|
|
138
|
+
'no-var': 'error',
|
|
139
|
+
'object-shorthand': 'error',
|
|
140
|
+
'prefer-template': 'error',
|
|
141
|
+
'no-param-reassign': 'error',
|
|
142
|
+
'no-shadow': 'off',
|
|
143
|
+
'prefer-destructuring': [
|
|
144
|
+
'error',
|
|
145
|
+
{
|
|
146
|
+
array: false,
|
|
147
|
+
object: true,
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
'no-invalid-this': 'error',
|
|
151
|
+
'arrow-body-style': ['error', 'never'],
|
|
152
|
+
|
|
153
|
+
// --- Unicorn (recommended + additions) ---
|
|
154
|
+
...eslintPluginUnicorn.configs.recommended.rules,
|
|
155
|
+
'unicorn/consistent-destructuring': 'error',
|
|
156
|
+
'unicorn/prefer-switch': 'off', // Conflicts with switch ban
|
|
157
|
+
'unicorn/switch-case-braces': 'off', // Conflicts with switch ban
|
|
158
|
+
'unicorn/prefer-ternary': 'off',
|
|
159
|
+
'prevent-abbreviations': 'off',
|
|
160
|
+
'unicorn/no-null': 'off',
|
|
161
|
+
|
|
162
|
+
// --- SonarJS (recommended + additions + overrides) ---
|
|
163
|
+
...eslintPluginSonarJS.configs.recommended.rules,
|
|
164
|
+
// Override levels
|
|
165
|
+
'sonarjs/no-duplicate-string': 'error',
|
|
166
|
+
'sonarjs/no-identical-functions': 'error',
|
|
167
|
+
'sonarjs/cognitive-complexity': ['warn', 15],
|
|
168
|
+
'sonarjs/prefer-object-literal': 'error',
|
|
169
|
+
// Disable conflicts/irrelevant
|
|
170
|
+
'sonarjs/prefer-immediate-return': 'off',
|
|
171
|
+
'sonarjs/max-switch-cases': 'off',
|
|
172
|
+
'sonarjs/no-small-switch': 'off',
|
|
173
|
+
'sonarjs/prefer-single-boolean-return': 'off',
|
|
174
|
+
'sonarjs/enforce-trailing-comma': 'off',
|
|
175
|
+
// Add rules not in recommended
|
|
176
|
+
'sonarjs/bool-param-default': 'error',
|
|
177
|
+
'sonarjs/destructuring-assignment-syntax': 'error',
|
|
178
|
+
'sonarjs/values-not-convertible-to-numbers': 'error',
|
|
179
|
+
'sonarjs/useless-string-operation': 'error',
|
|
180
|
+
'sonarjs/strings-comparison': 'error',
|
|
181
|
+
'sonarjs/non-number-in-arithmetic-expression': 'error',
|
|
182
|
+
'sonarjs/no-unused-function-argument': 'error',
|
|
183
|
+
'sonarjs/no-nested-incdec': 'error',
|
|
184
|
+
'sonarjs/no-incorrect-string-concat': 'error',
|
|
185
|
+
'sonarjs/no-inconsistent-returns': 'error',
|
|
186
|
+
'sonarjs/no-function-declaration-in-block': 'error',
|
|
187
|
+
'sonarjs/no-for-in-iterable': 'error',
|
|
188
|
+
'sonarjs/no-collapsible-if': 'error',
|
|
189
|
+
'sonarjs/no-built-in-override': 'error',
|
|
190
|
+
'sonarjs/nested-control-flow': 'error',
|
|
191
|
+
'sonarjs/expression-complexity': 'error',
|
|
192
|
+
'sonarjs/no-inverted-boolean-check': 'error',
|
|
193
|
+
|
|
194
|
+
// --- Naming conventions ---
|
|
195
|
+
camelcase: [
|
|
196
|
+
'error',
|
|
197
|
+
{
|
|
198
|
+
properties: 'never',
|
|
199
|
+
ignoreDestructuring: true,
|
|
200
|
+
ignoreImports: true,
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
|
|
204
|
+
// --- Banned syntax patterns ---
|
|
205
|
+
'no-restricted-syntax': [
|
|
206
|
+
'error',
|
|
207
|
+
{
|
|
208
|
+
selector: 'SwitchStatement',
|
|
209
|
+
message: 'Switch statements are not allowed. Use if-else or lookup objects.',
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
selector: 'ImportDeclaration[source.value=/\\.ts$/]',
|
|
213
|
+
message: 'Do not use .ts extension in imports. Use .js for TypeScript ESM.',
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
|
|
217
|
+
// --- Security (warn only - educational codebase) ---
|
|
218
|
+
'security/detect-object-injection': 'off',
|
|
219
|
+
'security/detect-non-literal-require': 'warn',
|
|
220
|
+
'security/detect-eval-with-expression': 'warn',
|
|
221
|
+
|
|
222
|
+
// --- LLM Guardrails (limit code bloat) ---
|
|
223
|
+
'spaced-comment': ['error', 'always', { exceptions: ['-', '=', '*', '/'] }],
|
|
224
|
+
'max-len': [
|
|
225
|
+
'error',
|
|
226
|
+
{
|
|
227
|
+
code: 100,
|
|
228
|
+
comments: Infinity, // Disable comment checking - use editor word wrap
|
|
229
|
+
ignoreUrls: true,
|
|
230
|
+
ignoreStrings: true,
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
// --- Plain JS files (disable type-checked rules, no TS project) ---
|
|
237
|
+
{
|
|
238
|
+
files: ['**/*.js'],
|
|
239
|
+
...tseslint.configs.disableTypeChecked,
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
// --- Public API (named exports allowed) ---
|
|
243
|
+
{
|
|
244
|
+
files: ['src/index.ts'],
|
|
245
|
+
rules: {
|
|
246
|
+
'import/no-named-export': 'off',
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
// --- Type definition files (named exports allowed) ---
|
|
251
|
+
{
|
|
252
|
+
files: ['**/types.ts', '**/*.types.ts', '**/types/*.ts'],
|
|
253
|
+
rules: {
|
|
254
|
+
'import/no-named-export': 'off',
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
// --- Test files ---
|
|
259
|
+
{
|
|
260
|
+
files: ['**/*.test.ts', '**/*.test.js', '**/tests/**/*.ts'],
|
|
261
|
+
languageOptions: {
|
|
262
|
+
globals: {
|
|
263
|
+
describe: 'readonly',
|
|
264
|
+
it: 'readonly',
|
|
265
|
+
test: 'readonly',
|
|
266
|
+
expect: 'readonly',
|
|
267
|
+
beforeEach: 'readonly',
|
|
268
|
+
afterEach: 'readonly',
|
|
269
|
+
beforeAll: 'readonly',
|
|
270
|
+
afterAll: 'readonly',
|
|
271
|
+
vi: 'readonly',
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
rules: {
|
|
275
|
+
'import/no-named-export': 'off',
|
|
276
|
+
'functional/immutable-data': 'off',
|
|
277
|
+
'functional/prefer-readonly-type': 'off',
|
|
278
|
+
'arrow-body-style': 'off', // Test callbacks use standard arrow pattern
|
|
279
|
+
'sonarjs/no-duplicate-string': 'off', // Tests repeat literals for readability
|
|
280
|
+
'unicorn/consistent-function-scoping': 'off', // Arrow callbacks are idiomatic in tests
|
|
281
|
+
// Test fixtures are often loosely typed — strict safety checks not needed
|
|
282
|
+
'@typescript-eslint/no-unsafe-call': 'off',
|
|
283
|
+
'@typescript-eslint/no-unsafe-member-access': 'off',
|
|
284
|
+
'@typescript-eslint/no-unsafe-assignment': 'off',
|
|
285
|
+
'@typescript-eslint/no-unsafe-return': 'off',
|
|
286
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
// --- Example files ---
|
|
291
|
+
{
|
|
292
|
+
files: ['examples/**/*.js'],
|
|
293
|
+
rules: {
|
|
294
|
+
'no-console': 'off',
|
|
295
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
|
|
299
|
+
// --- Error types (class/this allowed per JS Error convention) ---
|
|
300
|
+
{
|
|
301
|
+
files: ['src/errors/**/*.ts'],
|
|
302
|
+
rules: {
|
|
303
|
+
'functional/no-classes': 'off',
|
|
304
|
+
'functional/no-this-expressions': 'off',
|
|
305
|
+
'no-invalid-this': 'off',
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
npm-debug.log*
|
|
4
|
+
yarn-debug.log*
|
|
5
|
+
yarn-error.log*
|
|
6
|
+
pnpm-debug.log*
|
|
7
|
+
lerna-debug.log*
|
|
8
|
+
|
|
9
|
+
# Build outputs
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
out/
|
|
13
|
+
*.tsbuildinfo
|
|
14
|
+
|
|
15
|
+
# Generated docs (regenerated by CI on push to main)
|
|
16
|
+
docs/
|
|
17
|
+
|
|
18
|
+
# Testing
|
|
19
|
+
coverage/
|
|
20
|
+
*.lcov
|
|
21
|
+
.nyc_output/
|
|
22
|
+
|
|
23
|
+
# IDE
|
|
24
|
+
.idea/
|
|
25
|
+
*.swp
|
|
26
|
+
*.swo
|
|
27
|
+
*~
|
|
28
|
+
.DS_Store
|
|
29
|
+
|
|
30
|
+
# Environment
|
|
31
|
+
.env
|
|
32
|
+
.env.local
|
|
33
|
+
.env.*.local
|
|
34
|
+
|
|
35
|
+
# Debug
|
|
36
|
+
npm-debug.log*
|
|
37
|
+
yarn-debug.log*
|
|
38
|
+
yarn-error.log*
|
|
39
|
+
|
|
40
|
+
# Temporary files
|
|
41
|
+
*.tmp
|
|
42
|
+
*.temp
|
|
43
|
+
.tmp/
|
|
44
|
+
.temp/
|
|
45
|
+
|
|
46
|
+
# OS files
|
|
47
|
+
Thumbs.db
|
|
48
|
+
Desktop.ini
|
|
49
|
+
|
|
50
|
+
# Optional npm cache directory
|
|
51
|
+
.npm
|
|
52
|
+
|
|
53
|
+
# Optional eslint cache
|
|
54
|
+
.eslintcache
|
|
55
|
+
|
|
56
|
+
# Optional stylelint cache
|
|
57
|
+
.stylelintcache
|
|
58
|
+
|
|
59
|
+
# Logs
|
|
60
|
+
logs/
|
|
61
|
+
*.log
|
|
62
|
+
|
|
63
|
+
# Runtime data
|
|
64
|
+
pids
|
|
65
|
+
*.pid
|
|
66
|
+
*.seed
|
|
67
|
+
*.pid.lock
|
|
68
|
+
|
|
69
|
+
# Planning files (local, not shipped)
|
|
70
|
+
.plann/
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@study-lenses/CHANGEME",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "PACKAGE_DESCRIPTION",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest",
|
|
18
|
+
"test:ui": "vitest --ui",
|
|
19
|
+
"lint": "eslint src/",
|
|
20
|
+
"lint:fix": "eslint src/ --fix",
|
|
21
|
+
"format": "prettier --write \"**/*.{ts,js,json,md}\"",
|
|
22
|
+
"format:check": "prettier --check \"**/*.{ts,js,json,md}\"",
|
|
23
|
+
"type-check": "tsc --noEmit",
|
|
24
|
+
"validate": "npm run lint && npm run type-check && npm run test",
|
|
25
|
+
"docs": "typedoc",
|
|
26
|
+
"prepare": "husky"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"package.json"
|
|
33
|
+
],
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=22.0.0"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [],
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/OWNER/REPO"
|
|
41
|
+
},
|
|
42
|
+
"author": "[NAME]",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public",
|
|
46
|
+
"registry": "https://registry.npmjs.org/"
|
|
47
|
+
},
|
|
48
|
+
"lint-staged": {
|
|
49
|
+
"*.{ts,js}": [
|
|
50
|
+
"eslint --fix",
|
|
51
|
+
"prettier --write"
|
|
52
|
+
],
|
|
53
|
+
"*.{json,md,yml,yaml}": [
|
|
54
|
+
"prettier --write"
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/node": "^22.0.0",
|
|
59
|
+
"@vitest/ui": "^2.0.0",
|
|
60
|
+
"eslint": "^9.39.2",
|
|
61
|
+
"eslint-config-prettier": "^10.1.8",
|
|
62
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
63
|
+
"eslint-plugin-boundaries": "^5.4.0",
|
|
64
|
+
"eslint-plugin-functional": "^9.0.2",
|
|
65
|
+
"eslint-plugin-import": "^2.32.0",
|
|
66
|
+
"eslint-plugin-security": "^3.0.1",
|
|
67
|
+
"eslint-plugin-sonarjs": "^3.0.6",
|
|
68
|
+
"eslint-plugin-unicorn": "^62.0.0",
|
|
69
|
+
"husky": "^9.1.7",
|
|
70
|
+
"lint-staged": "^16.0.0",
|
|
71
|
+
"prettier": "^3.0.0",
|
|
72
|
+
"ts-api-utils": "^2.4.0",
|
|
73
|
+
"typedoc": "^0.28.0",
|
|
74
|
+
"typescript": "^5.0.0",
|
|
75
|
+
"typescript-eslint": "^8.53.1",
|
|
76
|
+
"vitest": "^2.0.0"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# src — Architecture & Decisions
|
|
2
|
+
|
|
3
|
+
TODO: explain the module structure — why these directories exist and how they relate.
|
|
4
|
+
|
|
5
|
+
## Module boundaries
|
|
6
|
+
|
|
7
|
+
The ESLint `boundaries` plugin enforces a DAG between modules. See `eslint.config.js`
|
|
8
|
+
for the full dependency graph. In short:
|
|
9
|
+
|
|
10
|
+
- TODO: describe boundary rules for your specific modules
|
|
11
|
+
|
|
12
|
+
## Why no barrel files?
|
|
13
|
+
|
|
14
|
+
Importing directly from source files (no `index.ts` re-exports except at package entry)
|
|
15
|
+
keeps the dependency graph explicit and prevents accidental coupling. The `boundaries`
|
|
16
|
+
plugin enforces this.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# src/
|
|
2
|
+
|
|
3
|
+
TODO: one paragraph — what does this package's source do?
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
| Module | Purpose |
|
|
8
|
+
| ------ | -------- |
|
|
9
|
+
| TODO | CHANGEME |
|
|
10
|
+
|
|
11
|
+
## Conventions
|
|
12
|
+
|
|
13
|
+
- One default export per file; no barrel imports
|
|
14
|
+
- Types in `types.ts` per module
|
|
15
|
+
- Tests in `tests/` subdirectory
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default null;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Language and Environment
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"lib": ["ES2022"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleResolution": "node",
|
|
8
|
+
|
|
9
|
+
// Output
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"rootDir": "./src",
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"removeComments": false,
|
|
16
|
+
"importHelpers": false,
|
|
17
|
+
|
|
18
|
+
// Type Checking
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noImplicitAny": true,
|
|
21
|
+
"strictNullChecks": true,
|
|
22
|
+
"strictFunctionTypes": true,
|
|
23
|
+
"strictBindCallApply": true,
|
|
24
|
+
"strictPropertyInitialization": true,
|
|
25
|
+
"noImplicitThis": true,
|
|
26
|
+
"useUnknownInCatchVariables": true,
|
|
27
|
+
"alwaysStrict": true,
|
|
28
|
+
"noUnusedLocals": true,
|
|
29
|
+
"noUnusedParameters": true,
|
|
30
|
+
"exactOptionalPropertyTypes": true,
|
|
31
|
+
"noImplicitReturns": true,
|
|
32
|
+
"noFallthroughCasesInSwitch": true,
|
|
33
|
+
"noUncheckedIndexedAccess": false,
|
|
34
|
+
"noImplicitOverride": true,
|
|
35
|
+
"noPropertyAccessFromIndexSignature": false,
|
|
36
|
+
|
|
37
|
+
// Module Resolution
|
|
38
|
+
"esModuleInterop": true,
|
|
39
|
+
"allowSyntheticDefaultImports": true,
|
|
40
|
+
"forceConsistentCasingInFileNames": true,
|
|
41
|
+
"allowImportingTsExtensions": false,
|
|
42
|
+
"resolveJsonModule": true,
|
|
43
|
+
"isolatedModules": true,
|
|
44
|
+
"verbatimModuleSyntax": false,
|
|
45
|
+
|
|
46
|
+
// Emit
|
|
47
|
+
"skipLibCheck": true,
|
|
48
|
+
"preserveConstEnums": true,
|
|
49
|
+
"preserveValueImports": false,
|
|
50
|
+
"downlevelIteration": true,
|
|
51
|
+
|
|
52
|
+
// Completeness
|
|
53
|
+
"skipDefaultLibCheck": true
|
|
54
|
+
},
|
|
55
|
+
"include": ["src/**/*.ts"],
|
|
56
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.js", ".plann/**/*", "docs/**/*"]
|
|
57
|
+
}
|