@sha3/code-standards 0.1.5 → 0.1.7
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/README.md +4 -1
- package/bin/code-standards.mjs +3 -1
- package/package.json +1 -1
- package/resources/ai/templates/examples/demo/src/billing/billing-service.ts +3 -3
- package/resources/ai/templates/examples/demo/src/config.ts +7 -3
- package/resources/ai/templates/examples/demo/src/invoices/invoice-service.ts +2 -2
- package/resources/ai/templates/rules/architecture.md +1 -0
- package/resources/ai/templates/rules/readme.md +6 -0
- package/standards/architecture.md +1 -0
- package/standards/readme.md +7 -0
- package/standards/style.md +1 -0
- package/templates/node-lib/README.md +83 -0
- package/templates/node-lib/src/config.ts +5 -1
- package/templates/node-lib/src/index.ts +2 -2
- package/templates/node-service/README.md +70 -0
- package/templates/node-service/src/config.ts +7 -3
- package/templates/node-service/src/index.ts +4 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
# @sha3/code-standards
|
|
3
|
+
# 📏 @sha3/code-standards
|
|
4
4
|
|
|
5
5
|
**Scaffold TypeScript projects + enforce how AI writes code.**
|
|
6
6
|
|
|
@@ -117,10 +117,13 @@ After `init`, your new repo contains:
|
|
|
117
117
|
- `ai/examples/rules/*.ts` (good/bad examples per rule)
|
|
118
118
|
- `ai/examples/demo/src/*` (feature-folder demo with classes and section blocks)
|
|
119
119
|
- `src/config.ts` for centralized hardcoded configuration values
|
|
120
|
+
- `README.md` generated with an icon emoji and complete integration docs (API + config + integration contract for other LLMs)
|
|
120
121
|
- `.gitignore` preconfigured for Node/TypeScript output
|
|
121
122
|
- lint/format/typecheck/test-ready project template
|
|
122
123
|
- `package.json.codeStandards` metadata used by `refresh` (`template`, `profilePath`, `withAiAdapters`, `lastRefreshWith`)
|
|
123
124
|
|
|
125
|
+
`config.ts` convention: export a single default object and import it as `import CONFIG from "./config.js"`.
|
|
126
|
+
|
|
124
127
|
That means the next step is **not** configuring tools. The next step is telling your assistant to obey `AGENTS.md` before coding.
|
|
125
128
|
|
|
126
129
|
Generated project code is TypeScript-only: implementation and tests live in `.ts` files.
|
package/bin/code-standards.mjs
CHANGED
|
@@ -537,8 +537,10 @@ function getRelativeProfilePath(profilePath, targetPath) {
|
|
|
537
537
|
const resolvedProfilePath = path.resolve(targetPath, profilePath);
|
|
538
538
|
const relativePath = path.relative(targetPath, resolvedProfilePath);
|
|
539
539
|
|
|
540
|
+
// If the profile is outside the project directory, return null instead of absolute path
|
|
541
|
+
// to avoid storing machine-specific paths in package.json
|
|
540
542
|
if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
|
|
541
|
-
return
|
|
543
|
+
return null;
|
|
542
544
|
}
|
|
543
545
|
|
|
544
546
|
return relativePath;
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @section imports:internals
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import CONFIG from "../config.js";
|
|
12
12
|
import type { InvoiceService } from "../invoices/invoice-service.js";
|
|
13
13
|
import type { InvoiceSummary } from "../invoices/invoice-types.js";
|
|
14
14
|
|
|
@@ -83,7 +83,7 @@ export class BillingService {
|
|
|
83
83
|
*/
|
|
84
84
|
|
|
85
85
|
private formatCurrency(amount: number): string {
|
|
86
|
-
const formattedAmount = `${BILLING_CURRENCY_SYMBOL}${amount.toFixed(2)}`;
|
|
86
|
+
const formattedAmount = `${CONFIG.BILLING_CURRENCY_SYMBOL}${amount.toFixed(2)}`;
|
|
87
87
|
return formattedAmount;
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -104,7 +104,7 @@ export class BillingService {
|
|
|
104
104
|
invoiceCount: summary.count,
|
|
105
105
|
totalAmount: summary.totalAmount,
|
|
106
106
|
formattedTotal: this.formatCurrency(summary.totalAmount),
|
|
107
|
-
statusServiceUrl: STATUS_SERVICE_URL
|
|
107
|
+
statusServiceUrl: CONFIG.STATUS_SERVICE_URL
|
|
108
108
|
};
|
|
109
109
|
return snapshot;
|
|
110
110
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const CONFIG = {
|
|
2
|
+
MINIMUM_INVOICE_AMOUNT: 0,
|
|
3
|
+
BILLING_CURRENCY_SYMBOL: "$",
|
|
4
|
+
STATUS_SERVICE_URL: "https://status.example.com/health"
|
|
5
|
+
} as const;
|
|
6
|
+
|
|
7
|
+
export default CONFIG;
|
|
@@ -8,7 +8,7 @@ import { randomUUID } from "node:crypto";
|
|
|
8
8
|
* @section imports:internals
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import CONFIG from "../config.js";
|
|
12
12
|
import { InvalidInvoiceCommandError } from "./invoice-errors.js";
|
|
13
13
|
import type { CreateInvoiceCommand, Invoice, InvoiceSummary } from "./invoice-types.js";
|
|
14
14
|
|
|
@@ -81,7 +81,7 @@ export class InvoiceService {
|
|
|
81
81
|
throw InvalidInvoiceCommandError.forReason("customerId is required");
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
if (command.amount <= MINIMUM_INVOICE_AMOUNT) {
|
|
84
|
+
if (command.amount <= CONFIG.MINIMUM_INVOICE_AMOUNT) {
|
|
85
85
|
throw InvalidInvoiceCommandError.forReason("amount must be greater than zero");
|
|
86
86
|
}
|
|
87
87
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
- Each feature MUST keep its own domain model, application services, and infrastructure adapters grouped by feature.
|
|
5
5
|
- Cross-feature imports MUST happen through explicit public entry points.
|
|
6
6
|
- Hardcoded, non-parameterized configuration MUST be centralized in `src/config.ts` (for example, external service URLs).
|
|
7
|
+
- `src/config.ts` MUST export a single default object and it MUST always be imported as `import CONFIG from ".../config.js"`.
|
|
7
8
|
|
|
8
9
|
Good example:
|
|
9
10
|
|
|
@@ -7,6 +7,11 @@ Mandatory requirements:
|
|
|
7
7
|
- README MUST clearly explain: what the project does, why it exists, and how to use it in under 60 seconds.
|
|
8
8
|
- README MUST include practical copy/paste examples that are runnable.
|
|
9
9
|
- README MUST include a fast path (`TL;DR` or `Quick Start`) and an in-depth reference section.
|
|
10
|
+
- For libraries, README MUST be complete integration documentation for external teams and LLM agents.
|
|
11
|
+
- README MUST include a public API reference section with exported members and behavior expectations.
|
|
12
|
+
- README MUST include a dedicated integration section that shows how to install/import/use from another project.
|
|
13
|
+
- README MUST include a configuration reference section (`src/config.ts`) with meaning of each constant.
|
|
14
|
+
- README MUST include compatibility constraints (runtime, ESM/CJS expectations, TypeScript assumptions).
|
|
10
15
|
- README MUST include a section for AI usage (how to instruct assistants to follow local standards).
|
|
11
16
|
- README MUST avoid vague marketing language and focus on actionable guidance.
|
|
12
17
|
- README MUST be visually structured with clean headings, concise lists, and code blocks.
|
|
@@ -16,6 +21,7 @@ Good example characteristics:
|
|
|
16
21
|
|
|
17
22
|
- Starts with immediate value and one-command quick start.
|
|
18
23
|
- Shows exact commands and expected flow.
|
|
24
|
+
- Includes public API and integration contract without forcing reader to inspect source files.
|
|
19
25
|
- Includes troubleshooting or FAQ for common confusion points.
|
|
20
26
|
|
|
21
27
|
Bad example characteristics:
|
|
@@ -23,3 +23,4 @@ Both templates SHOULD keep this baseline structure:
|
|
|
23
23
|
- Keep feature modules cohesive.
|
|
24
24
|
- Avoid cyclic dependencies.
|
|
25
25
|
- Keep hardcoded application configuration centralized in `src/config.ts`.
|
|
26
|
+
- `src/config.ts` MUST export a default object (for example `CONFIG`) and consumers MUST import it as `import CONFIG from "./config.js"`.
|
package/standards/readme.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
## Goal
|
|
4
4
|
|
|
5
5
|
Every repository README MUST be clear, actionable, and visually structured.
|
|
6
|
+
For libraries, README MUST be complete integration documentation because other LLMs will use it as source-of-truth.
|
|
6
7
|
|
|
7
8
|
## Mandatory Sections
|
|
8
9
|
|
|
@@ -10,6 +11,11 @@ Every repository README MUST be clear, actionable, and visually structured.
|
|
|
10
11
|
- TL;DR or Quick Start with copy/paste commands.
|
|
11
12
|
- What it does and why it exists.
|
|
12
13
|
- Setup and usage examples.
|
|
14
|
+
- Installation requirements and exact install command.
|
|
15
|
+
- Public API reference (exports, expected inputs/outputs, and behavior notes).
|
|
16
|
+
- Integration guide (how to consume the library from another project).
|
|
17
|
+
- Configuration reference (`src/config.ts` constants and impact).
|
|
18
|
+
- Compatibility and constraints (runtime, module format, TypeScript expectations).
|
|
13
19
|
- AI workflow section when the repository uses AI coding contracts.
|
|
14
20
|
- Troubleshooting or FAQ.
|
|
15
21
|
|
|
@@ -23,3 +29,4 @@ Every repository README MUST be clear, actionable, and visually structured.
|
|
|
23
29
|
## Quality Bar
|
|
24
30
|
|
|
25
31
|
A top-tier README lets a new engineer understand and run the project in under 5 minutes without asking additional questions.
|
|
32
|
+
For libraries, a top-tier README also lets another LLM integrate the library in a different codebase without opening source files.
|
package/standards/style.md
CHANGED
|
@@ -20,6 +20,7 @@ All code MUST follow the canonical rules in `standards/manifest.json`.
|
|
|
20
20
|
- Use type-only imports when possible.
|
|
21
21
|
- If a function/method needs many inputs, define a named `<FunctionName>Options` type and pass a single `options` parameter.
|
|
22
22
|
- Always use braces in control flow (`if`, `else`, `for`, `while`, `do`).
|
|
23
|
+
- `src/config.ts` MUST export a default object and it MUST always be imported as `import CONFIG from ".../config.js"`.
|
|
23
24
|
|
|
24
25
|
## Naming
|
|
25
26
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# 📚 {{packageName}}
|
|
2
|
+
|
|
3
|
+
Reusable TypeScript library with a clear integration contract for external projects and LLM agents.
|
|
4
|
+
|
|
5
|
+
## TL;DR
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run check
|
|
10
|
+
npm run build
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install <library-name>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Compatibility
|
|
20
|
+
|
|
21
|
+
- Node.js 20+
|
|
22
|
+
- ESM (`"type": "module"`)
|
|
23
|
+
- Strict TypeScript
|
|
24
|
+
|
|
25
|
+
## Public API
|
|
26
|
+
|
|
27
|
+
### `greet(name: string): string`
|
|
28
|
+
|
|
29
|
+
Returns a greeting using the configured prefix.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { greet } from "<library-name>";
|
|
33
|
+
|
|
34
|
+
const greeting = greet("world");
|
|
35
|
+
console.log(greeting);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Integration Guide (External Projects)
|
|
39
|
+
|
|
40
|
+
1. Install the library with `npm install <library-name>`.
|
|
41
|
+
2. Import only from the public entrypoint (`<library-name>`).
|
|
42
|
+
3. Do not import internal paths (`src/*`, private `dist/*` files, or private modules).
|
|
43
|
+
4. If you integrate with an LLM, treat this section as the integration contract.
|
|
44
|
+
|
|
45
|
+
## Configuration (`src/config.ts`)
|
|
46
|
+
|
|
47
|
+
Hardcoded configuration is centralized in `src/config.ts`.
|
|
48
|
+
|
|
49
|
+
- `CONFIG.GREETING_PREFIX`: prefix used by `greet`.
|
|
50
|
+
|
|
51
|
+
## Contract for LLM Integrators
|
|
52
|
+
|
|
53
|
+
- This README is the source of truth for external integration.
|
|
54
|
+
- The stable API is the one documented in `Public API`.
|
|
55
|
+
- If API shape or observable behavior changes, update this README in the same change.
|
|
56
|
+
|
|
57
|
+
## Scripts
|
|
58
|
+
|
|
59
|
+
- `npm run check`: lint + format check + typecheck + tests
|
|
60
|
+
- `npm run fix`: lint/prettier autofix
|
|
61
|
+
- `npm run build`: compile to `dist/`
|
|
62
|
+
- `npm run test`: tests con Node test runner
|
|
63
|
+
|
|
64
|
+
## Structure
|
|
65
|
+
|
|
66
|
+
- `src/`: implementation
|
|
67
|
+
- `src/config.ts`: centralized configuration
|
|
68
|
+
- `test/`: tests
|
|
69
|
+
- `dist/`: build output
|
|
70
|
+
|
|
71
|
+
## Troubleshooting
|
|
72
|
+
|
|
73
|
+
### Import errors (ESM)
|
|
74
|
+
|
|
75
|
+
Ensure the consumer project uses Node.js-compatible ESM.
|
|
76
|
+
|
|
77
|
+
### Type errors
|
|
78
|
+
|
|
79
|
+
Run `npm run typecheck` in the consumer project and verify TypeScript version compatibility.
|
|
80
|
+
|
|
81
|
+
## AI Workflow
|
|
82
|
+
|
|
83
|
+
If you work with assistants, treat `AGENTS.md` and `ai/*.md` as blocking rules.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# 🚀 {{packageName}}
|
|
2
|
+
|
|
3
|
+
TypeScript service template ready for local execution and feature-based evolution.
|
|
4
|
+
|
|
5
|
+
## TL;DR
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run check
|
|
10
|
+
npm run start
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Run
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm run start
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The service starts on `http://localhost:3000` by default.
|
|
20
|
+
|
|
21
|
+
## Compatibility
|
|
22
|
+
|
|
23
|
+
- Node.js 20+
|
|
24
|
+
- ESM (`"type": "module"`)
|
|
25
|
+
- Strict TypeScript
|
|
26
|
+
|
|
27
|
+
## API HTTP
|
|
28
|
+
|
|
29
|
+
### `GET /`
|
|
30
|
+
|
|
31
|
+
- Response: `200 OK`
|
|
32
|
+
- `content-type`: `application/json`
|
|
33
|
+
- body: `{ "ok": true, "statusSource": "<url>" }`
|
|
34
|
+
|
|
35
|
+
## Integration Guide (External Projects)
|
|
36
|
+
|
|
37
|
+
1. Start the service with `npm run start`.
|
|
38
|
+
2. Consume the root endpoint for health/status.
|
|
39
|
+
3. Integrate through the HTTP contract, not through internal files.
|
|
40
|
+
|
|
41
|
+
## Configuration (`src/config.ts`)
|
|
42
|
+
|
|
43
|
+
Hardcoded configuration is centralized:
|
|
44
|
+
|
|
45
|
+
- `CONFIG.RESPONSE_CONTENT_TYPE`
|
|
46
|
+
- `CONFIG.DEFAULT_PORT`
|
|
47
|
+
- `CONFIG.EXTERNAL_STATUS_URL`
|
|
48
|
+
|
|
49
|
+
## Contract for LLM Integrators
|
|
50
|
+
|
|
51
|
+
- This README defines the expected HTTP contract.
|
|
52
|
+
- Payload/status/header changes require a README update in the same change.
|
|
53
|
+
- For integration, use documented endpoints and do not assume internal details.
|
|
54
|
+
|
|
55
|
+
## Scripts
|
|
56
|
+
|
|
57
|
+
- `npm run start`: start the service with `tsx`
|
|
58
|
+
- `npm run check`: lint + format check + typecheck + tests
|
|
59
|
+
- `npm run fix`: apply lint/prettier autofix
|
|
60
|
+
- `npm run test`: run tests with Node test runner
|
|
61
|
+
|
|
62
|
+
## Structure
|
|
63
|
+
|
|
64
|
+
- `src/`: implementation
|
|
65
|
+
- `src/config.ts`: centralized hardcoded configuration
|
|
66
|
+
- `test/`: tests
|
|
67
|
+
|
|
68
|
+
## AI Workflow
|
|
69
|
+
|
|
70
|
+
If you work with assistants, treat `AGENTS.md` and `ai/*.md` as blocking rules.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const CONFIG = {
|
|
2
|
+
RESPONSE_CONTENT_TYPE: "application/json",
|
|
3
|
+
DEFAULT_PORT: 3000,
|
|
4
|
+
EXTERNAL_STATUS_URL: "https://status.example.com/health"
|
|
5
|
+
} as const;
|
|
6
|
+
|
|
7
|
+
export default CONFIG;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { createServer } from "node:http";
|
|
2
|
-
import
|
|
2
|
+
import CONFIG from "./config.js";
|
|
3
3
|
|
|
4
4
|
export function buildServer() {
|
|
5
5
|
return createServer((_, response) => {
|
|
6
6
|
response.statusCode = 200;
|
|
7
|
-
response.setHeader("content-type", RESPONSE_CONTENT_TYPE);
|
|
8
|
-
response.end(JSON.stringify({ ok: true, statusSource: EXTERNAL_STATUS_URL }));
|
|
7
|
+
response.setHeader("content-type", CONFIG.RESPONSE_CONTENT_TYPE);
|
|
8
|
+
response.end(JSON.stringify({ ok: true, statusSource: CONFIG.EXTERNAL_STATUS_URL }));
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
if (process.env.NODE_ENV !== "test") {
|
|
13
|
-
const port = Number(process.env.PORT ?? String(DEFAULT_PORT));
|
|
13
|
+
const port = Number(process.env.PORT ?? String(CONFIG.DEFAULT_PORT));
|
|
14
14
|
const server = buildServer();
|
|
15
15
|
server.listen(port, () => {
|
|
16
16
|
console.log(`service listening on http://localhost:${port}`);
|