@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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 @codeschoolinabox
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,86 @@
1
+ # @study-lenses/create-package
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@study-lenses/create-package.svg)](https://www.npmjs.com/package/@study-lenses/create-package)
4
+ [![CI](https://github.com/codeschoolinabox/sl-create-package/actions/workflows/ci.yml/badge.svg)](https://github.com/codeschoolinabox/sl-create-package/actions/workflows/ci.yml)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
6
+
7
+ > CLI scaffolder that generates new `@study-lenses` packages from the standard template,
8
+ > replacing all placeholders with user-provided values.
9
+
10
+ ## Pedagogical Purpose
11
+
12
+ **Neutral infrastructure:** This package generates the boilerplate for new `@study-lenses`
13
+ packages. It makes no pedagogical decisions — those belong in the packages it creates.
14
+
15
+ ## Who Is This For
16
+
17
+ **Primary — Educational tool developers:** Creating new `@study-lenses` packages. Instead
18
+ of forking `sl-starter` and manually finding/replacing ~15 placeholders across 8+ files,
19
+ run one command and get a correct package on first try.
20
+
21
+ ## Install
22
+
23
+ Not installed as a dependency. Run directly:
24
+
25
+ ```bash
26
+ npm create @study-lenses
27
+ # or
28
+ npx @study-lenses/create-package
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ```bash
34
+ npm create @study-lenses
35
+ # Package name (e.g., utils-normalize): utils-normalize
36
+ # Description: Config normalization utilities
37
+ # Author (@codeschoolinabox):
38
+ #
39
+ # Creating @study-lenses/utils-normalize in /path/to/sl-utils-normalize...
40
+ # Done!
41
+ ```
42
+
43
+ The CLI asks three questions, then generates `sl-{name}/` with all files from the
44
+ standard template, all placeholders replaced, git initialized, and dependencies installed.
45
+
46
+ ## Design Principles
47
+
48
+ ### What this package provides
49
+
50
+ - Generates a complete `@study-lenses` package directory from the standard template
51
+ - Replaces all placeholder tokens (CHANGEME, @study-lenses/CHANGEME, OWNER/REPO, OWNER, REPO, PACKAGE_DESCRIPTION, [YEAR], [NAME])
52
+ - Initializes git and runs `npm install`
53
+ - Validates package name against npm naming rules
54
+
55
+ ### What this package does NOT do
56
+
57
+ - No `--update` mode (re-generating templates in existing packages is deferred)
58
+ - No interactive file selection (all template files are always generated)
59
+ - No custom template support (uses the single standard template)
60
+
61
+ ## API Reference
62
+
63
+ Generated from TSDoc comments in source. Run `npm run docs` locally, or see the
64
+ [hosted API docs](https://codeschoolinabox.github.io/sl-create-package/).
65
+
66
+ ## Architecture
67
+
68
+ The CLI is a three-step pipeline:
69
+
70
+ 1. **Collect Input** (`collect-input.ts`) — collects package name, description, author via readline
71
+ 2. **Derive** (`derive-variables.ts`) — computes all template variables from the three answers
72
+ 3. **Generate** (`generate.ts`) — walks `templates/` directory, replaces tokens, writes files
73
+
74
+ Templates are shipped as real files in the `templates/` directory (not embedded strings).
75
+ Token replacement uses `String.prototype.replaceAll()` in a specific order to avoid
76
+ substring collisions (e.g., `@study-lenses/CHANGEME` before bare `CHANGEME`).
77
+
78
+ See [DEV.md](./DEV.md) for full architecture, conventions, and the TDD workflow.
79
+
80
+ ## Contributing
81
+
82
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) and [DEV.md](./DEV.md).
83
+
84
+ ## License
85
+
86
+ MIT © 2026 @codeschoolinabox
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@study-lenses/create-package",
3
+ "version": "0.1.0",
4
+ "description": "Scaffold new @study-lenses packages from the standard template",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-package": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "test": "vitest run",
12
+ "test:watch": "vitest",
13
+ "test:ui": "vitest --ui",
14
+ "lint": "eslint src/",
15
+ "lint:fix": "eslint src/ --fix",
16
+ "format": "prettier --write \"**/*.{ts,js,json,md}\"",
17
+ "format:check": "prettier --check \"**/*.{ts,js,json,md}\"",
18
+ "type-check": "tsc --noEmit",
19
+ "validate": "npm run lint && npm run type-check && npm run test",
20
+ "docs": "typedoc",
21
+ "prepare": "husky"
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "templates",
26
+ "README.md",
27
+ "LICENSE",
28
+ "package.json"
29
+ ],
30
+ "engines": {
31
+ "node": ">=22.0.0"
32
+ },
33
+ "keywords": [
34
+ "study-lenses",
35
+ "scaffolder",
36
+ "create",
37
+ "template"
38
+ ],
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/codeschoolinabox/sl-create-package"
42
+ },
43
+ "author": "@codeschoolinabox",
44
+ "license": "MIT",
45
+ "publishConfig": {
46
+ "access": "public",
47
+ "registry": "https://registry.npmjs.org/"
48
+ },
49
+ "lint-staged": {
50
+ "*.{ts,js}": [
51
+ "eslint --fix",
52
+ "prettier --write"
53
+ ],
54
+ "*.{json,md,yml,yaml}": [
55
+ "prettier --write"
56
+ ]
57
+ },
58
+ "devDependencies": {
59
+ "@types/node": "^22.0.0",
60
+ "@vitest/ui": "^2.0.0",
61
+ "eslint": "^9.39.2",
62
+ "eslint-config-prettier": "^10.1.8",
63
+ "eslint-import-resolver-typescript": "^4.4.4",
64
+ "eslint-plugin-boundaries": "^5.4.0",
65
+ "eslint-plugin-functional": "^9.0.2",
66
+ "eslint-plugin-import": "^2.32.0",
67
+ "eslint-plugin-security": "^3.0.1",
68
+ "eslint-plugin-sonarjs": "^3.0.6",
69
+ "eslint-plugin-unicorn": "^62.0.0",
70
+ "husky": "^9.1.7",
71
+ "lint-staged": "^16.0.0",
72
+ "prettier": "^3.0.0",
73
+ "ts-api-utils": "^2.4.0",
74
+ "typedoc": "^0.28.0",
75
+ "typescript": "^5.0.0",
76
+ "typescript-eslint": "^8.53.1",
77
+ "vitest": "^2.0.0"
78
+ }
79
+ }
@@ -0,0 +1,15 @@
1
+ # EditorConfig - consistent formatting across all editors
2
+ # https://editorconfig.org
3
+
4
+ root = true
5
+
6
+ [*]
7
+ charset = utf-8
8
+ end_of_line = lf
9
+ indent_style = space
10
+ indent_size = 2
11
+ insert_final_newline = true
12
+ trim_trailing_whitespace = true
13
+
14
+ [*.md]
15
+ trim_trailing_whitespace = false
@@ -0,0 +1,91 @@
1
+ name: Bug Report
2
+ description: Report a bug
3
+ title: "[Bug]: "
4
+ labels: ["bug"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thank you for reporting a bug. Please fill out the sections below
10
+ so we can reproduce and fix the issue.
11
+
12
+ - type: textarea
13
+ id: description
14
+ attributes:
15
+ label: Description
16
+ description: A clear description of what the bug is.
17
+ placeholder: What happened?
18
+ validations:
19
+ required: true
20
+
21
+ - type: textarea
22
+ id: reproduction
23
+ attributes:
24
+ label: Steps to Reproduce
25
+ description: |
26
+ Minimal code example that demonstrates the bug.
27
+ Include the exact code, configuration, and function calls.
28
+ placeholder: |
29
+ ```javascript
30
+ import { trace } from '@study-lenses/CHANGEME';
31
+
32
+ const result = trace(...);
33
+ // Expected: [...]
34
+ // Actual: [...]
35
+ ```
36
+ validations:
37
+ required: true
38
+
39
+ - type: textarea
40
+ id: expected
41
+ attributes:
42
+ label: Expected Behavior
43
+ description: What did you expect to happen?
44
+ validations:
45
+ required: true
46
+
47
+ - type: textarea
48
+ id: actual
49
+ attributes:
50
+ label: Actual Behavior
51
+ description: What actually happened? Include error messages if any.
52
+ validations:
53
+ required: true
54
+
55
+ - type: input
56
+ id: node-version
57
+ attributes:
58
+ label: Node.js Version
59
+ description: "Run `node --version` and paste the output."
60
+ placeholder: "v22.0.0"
61
+ validations:
62
+ required: true
63
+
64
+ - type: dropdown
65
+ id: os
66
+ attributes:
67
+ label: Operating System
68
+ options:
69
+ - macOS
70
+ - Linux
71
+ - Windows
72
+ - Other
73
+ validations:
74
+ required: true
75
+
76
+ - type: input
77
+ id: package-version
78
+ attributes:
79
+ label: Package Version
80
+ description: "The version from your package.json or `npm ls @study-lenses/CHANGEME`."
81
+ placeholder: "1.0.0"
82
+ validations:
83
+ required: true
84
+
85
+ - type: textarea
86
+ id: additional
87
+ attributes:
88
+ label: Additional Context
89
+ description: Any other context, screenshots, or information.
90
+ validations:
91
+ required: false
@@ -0,0 +1,68 @@
1
+ name: Feature Request
2
+ description: Suggest a new feature or improvement
3
+ title: "[Feature]: "
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thank you for suggesting an improvement.
10
+
11
+ - type: textarea
12
+ id: problem
13
+ attributes:
14
+ label: Problem Statement
15
+ description: |
16
+ What problem does this feature solve? Describe the limitation or
17
+ pain point you are experiencing.
18
+ placeholder: "I'm trying to [...] but currently [...]"
19
+ validations:
20
+ required: true
21
+
22
+ - type: textarea
23
+ id: solution
24
+ attributes:
25
+ label: Proposed Solution
26
+ description: |
27
+ How do you think this should work? Include API examples if possible.
28
+ placeholder: |
29
+ ```javascript
30
+ // Example of how the feature would be used:
31
+ const result = doThing({ newOption: true });
32
+ ```
33
+ validations:
34
+ required: true
35
+
36
+ - type: textarea
37
+ id: alternatives
38
+ attributes:
39
+ label: Alternatives Considered
40
+ description: |
41
+ What other approaches did you consider? Why is this approach better?
42
+ validations:
43
+ required: false
44
+
45
+ - type: dropdown
46
+ id: scope
47
+ attributes:
48
+ label: Feature Scope
49
+ description: Which part of this package does this affect?
50
+ options:
51
+ - API
52
+ - Core logic
53
+ - Configuration
54
+ - Types / TypeScript
55
+ - Testing
56
+ - Documentation
57
+ - Other
58
+ validations:
59
+ required: true
60
+
61
+ - type: textarea
62
+ id: additional
63
+ attributes:
64
+ label: Additional Context
65
+ description: |
66
+ Any other context, examples from other tools, research references, etc.
67
+ validations:
68
+ required: false
@@ -0,0 +1,27 @@
1
+ ## Summary
2
+
3
+ <!-- What does this PR do? 1-3 bullet points. -->
4
+
5
+ ## Changes
6
+
7
+ <!-- Key files changed and why. -->
8
+
9
+ ## Code Review Checklist
10
+
11
+ ### Automated (ESLint + TypeScript)
12
+
13
+ - [ ] `npm run validate` passes with no errors
14
+
15
+ ### Manual Review
16
+
17
+ - [ ] Named function/const, then `export default` at bottom
18
+ - [ ] Direct imports from source files (no barrel imports), always with `.js` extension
19
+ - [ ] Named `function` declarations (arrows only for inline single-expression callbacks)
20
+ - [ ] No `this` keyword, no mutable closures
21
+ - [ ] Default empty object `= {}` on all destructured parameters
22
+ - [ ] Verb-first naming; predicates prefixed with `is`/`has`/`can`/`should`
23
+ - [ ] Tests in `tests/` subdirectory (not alongside source files), `.test.ts` suffix
24
+ - [ ] One assertion per `it`; nested `describe` for grouping
25
+ - [ ] JSDoc on public functions; inline comments explain "why" not "what"
26
+ - [ ] Every modified directory has `README.md`
27
+ - [ ] No future-proofing or "nice-to-haves" beyond what was requested
@@ -0,0 +1,9 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: npm
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ groups:
8
+ dev-dependencies:
9
+ dependency-type: development
@@ -0,0 +1,19 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ workflow_dispatch:
6
+ push:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ validate:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-node@v4
15
+ with:
16
+ node-version: '22'
17
+ cache: 'npm'
18
+ - run: npm ci
19
+ - run: npm run validate
@@ -0,0 +1,25 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ docs:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-node@v4
16
+ with:
17
+ node-version: '22'
18
+ cache: 'npm'
19
+ - run: npm ci
20
+ - run: npm run docs
21
+ - name: Deploy to GitHub Pages
22
+ uses: peaceiris/actions-gh-pages@v4
23
+ with:
24
+ github_token: ${{ secrets.GITHUB_TOKEN }}
25
+ publish_dir: ./docs
@@ -0,0 +1,23 @@
1
+ name: Publish
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ release:
6
+ types: [created]
7
+
8
+ permissions:
9
+ id-token: write
10
+ contents: read
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-node@v4
18
+ with:
19
+ node-version: '22'
20
+ cache: 'npm'
21
+ - run: npm ci
22
+ - run: npm run build
23
+ - run: npm publish --provenance
@@ -0,0 +1 @@
1
+ npx lint-staged
@@ -0,0 +1,15 @@
1
+ {
2
+ "semi": true,
3
+ "trailingComma": "all",
4
+ "singleQuote": true,
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "useTabs": false,
8
+ "quoteProps": "as-needed",
9
+ "bracketSpacing": true,
10
+ "bracketSameLine": false,
11
+ "arrowParens": "always",
12
+ "endOfLine": "lf",
13
+ "embeddedLanguageFormatting": "auto",
14
+ "singleAttributePerLine": false
15
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "recommendations": [
3
+ "dbaeumer.vscode-eslint",
4
+ "esbenp.prettier-vscode",
5
+ "editorconfig.editorconfig",
6
+ "vitest.explorer",
7
+ "streetsidesoftware.code-spell-checker",
8
+ "yoavbls.pretty-ts-errors"
9
+ ],
10
+ "unwantedRecommendations": []
11
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "Debug Current Test File",
6
+ "type": "node",
7
+ "request": "launch",
8
+ "runtimeExecutable": "npm",
9
+ "runtimeArgs": ["run", "test", "--", "--reporter=verbose", "${relativeFile}"],
10
+ "console": "integratedTerminal",
11
+ "internalConsoleOptions": "neverOpen",
12
+ "skipFiles": ["<node_internals>/**", "**/node_modules/**"]
13
+ },
14
+ {
15
+ "name": "Debug All Tests",
16
+ "type": "node",
17
+ "request": "launch",
18
+ "runtimeExecutable": "npm",
19
+ "runtimeArgs": ["run", "test"],
20
+ "console": "integratedTerminal",
21
+ "internalConsoleOptions": "neverOpen",
22
+ "skipFiles": ["<node_internals>/**", "**/node_modules/**"]
23
+ },
24
+ {
25
+ "name": "Debug Current Script",
26
+ "type": "node",
27
+ "request": "launch",
28
+ "program": "${file}",
29
+ "console": "integratedTerminal",
30
+ "internalConsoleOptions": "neverOpen",
31
+ "skipFiles": ["<node_internals>/**", "**/node_modules/**"]
32
+ }
33
+ ]
34
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
4
+ "editor.codeActionsOnSave": {
5
+ "source.fixAll.eslint": "explicit"
6
+ },
7
+ "editor.rulers": [100],
8
+ "editor.wordWrap": "bounded",
9
+ "editor.wordWrapColumn": 100,
10
+ "editor.tabSize": 2,
11
+ "editor.insertSpaces": true,
12
+ "files.eol": "\n",
13
+ "files.trimTrailingWhitespace": true,
14
+ "files.insertFinalNewline": true,
15
+
16
+ "typescript.preferences.importModuleSpecifierEnding": "js",
17
+ "typescript.suggest.includeAutomaticOptionalChainCompletions": true,
18
+ "typescript.updateImportsOnFileMove.enabled": "always",
19
+
20
+ "eslint.validate": ["javascript", "typescript"],
21
+ "eslint.useFlatConfig": true,
22
+
23
+ "search.exclude": {
24
+ "**/dist": true,
25
+ "**/coverage": true,
26
+ "**/docs": true
27
+ }
28
+ }