@sha3/code-standards 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 (59) hide show
  1. package/AGENTS.md +19 -0
  2. package/README.md +368 -0
  3. package/ai/adapters/codex.md +5 -0
  4. package/ai/adapters/copilot.md +5 -0
  5. package/ai/adapters/cursor.md +5 -0
  6. package/ai/adapters/windsurf.md +6 -0
  7. package/ai/constitution.md +9 -0
  8. package/bin/code-standards.mjs +1010 -0
  9. package/eslint/base.mjs +36 -0
  10. package/eslint/node.mjs +14 -0
  11. package/eslint/test.mjs +19 -0
  12. package/index.mjs +19 -0
  13. package/package.json +64 -0
  14. package/prettier/index.cjs +10 -0
  15. package/profiles/default.profile.json +38 -0
  16. package/profiles/schema.json +159 -0
  17. package/resources/ai/AGENTS.md +16 -0
  18. package/resources/ai/adapters/codex.md +5 -0
  19. package/resources/ai/adapters/copilot.md +5 -0
  20. package/resources/ai/adapters/cursor.md +5 -0
  21. package/resources/ai/adapters/windsurf.md +5 -0
  22. package/resources/ai/templates/adapters/codex.template.md +6 -0
  23. package/resources/ai/templates/adapters/copilot.template.md +6 -0
  24. package/resources/ai/templates/adapters/cursor.template.md +6 -0
  25. package/resources/ai/templates/adapters/windsurf.template.md +6 -0
  26. package/resources/ai/templates/agents.project.template.md +33 -0
  27. package/resources/ai/templates/rules/architecture.md +26 -0
  28. package/resources/ai/templates/rules/async.md +23 -0
  29. package/resources/ai/templates/rules/class-first.md +96 -0
  30. package/resources/ai/templates/rules/control-flow.md +19 -0
  31. package/resources/ai/templates/rules/errors.md +22 -0
  32. package/resources/ai/templates/rules/functions.md +27 -0
  33. package/resources/ai/templates/rules/readme.md +25 -0
  34. package/resources/ai/templates/rules/returns.md +33 -0
  35. package/resources/ai/templates/rules/testing.md +26 -0
  36. package/standards/architecture.md +24 -0
  37. package/standards/changelog-policy.md +12 -0
  38. package/standards/manifest.json +47 -0
  39. package/standards/readme.md +25 -0
  40. package/standards/schema.json +122 -0
  41. package/standards/style.md +48 -0
  42. package/standards/testing.md +18 -0
  43. package/standards/tooling.md +32 -0
  44. package/templates/node-lib/eslint.config.mjs +4 -0
  45. package/templates/node-lib/package.json +30 -0
  46. package/templates/node-lib/prettier.config.cjs +9 -0
  47. package/templates/node-lib/src/index.ts +3 -0
  48. package/templates/node-lib/test/smoke.test.ts +8 -0
  49. package/templates/node-lib/tsconfig.build.json +7 -0
  50. package/templates/node-lib/tsconfig.json +7 -0
  51. package/templates/node-service/eslint.config.mjs +4 -0
  52. package/templates/node-service/package.json +25 -0
  53. package/templates/node-service/prettier.config.cjs +9 -0
  54. package/templates/node-service/src/index.ts +17 -0
  55. package/templates/node-service/test/smoke.test.ts +37 -0
  56. package/templates/node-service/tsconfig.json +7 -0
  57. package/tsconfig/base.json +16 -0
  58. package/tsconfig/node-lib.json +12 -0
  59. package/tsconfig/node-service.json +10 -0
@@ -0,0 +1,27 @@
1
+ ### Function Structure (MUST)
2
+
3
+ - Functions and methods SHOULD stay under 30 lines.
4
+ - Functions MUST implement one responsibility.
5
+ - Long functions MUST be split into private helper methods.
6
+ - Types MUST be preferred over interfaces for local modeling unless a public contract requires an interface.
7
+
8
+ Good example:
9
+
10
+ ```ts
11
+ private normalize(input: PaymentInput): PaymentDraft {
12
+ const amount: number = normalizeAmount(input.amount);
13
+ const currency: CurrencyCode = normalizeCurrency(input.currency);
14
+ const metadata: PaymentMetadata = sanitizeMetadata(input.metadata);
15
+ return { amount, currency, metadata };
16
+ }
17
+ ```
18
+
19
+ Bad example:
20
+
21
+ ```ts
22
+ private normalize(input: any): any {
23
+ // huge branchy function with parsing, IO, validation and persistence mixed together
24
+ // ... 80+ lines omitted
25
+ return input;
26
+ }
27
+ ```
@@ -0,0 +1,25 @@
1
+ ### README Quality Standard (MUST)
2
+
3
+ When creating or updating `README.md`, output MUST be top-tier and production-quality.
4
+
5
+ Mandatory requirements:
6
+
7
+ - README MUST clearly explain: what the project does, why it exists, and how to use it in under 60 seconds.
8
+ - README MUST include practical copy/paste examples that are runnable.
9
+ - README MUST include a fast path (`TL;DR` or `Quick Start`) and an in-depth reference section.
10
+ - README MUST include a section for AI usage (how to instruct assistants to follow local standards).
11
+ - README MUST avoid vague marketing language and focus on actionable guidance.
12
+ - README MUST be visually structured with clean headings, concise lists, and code blocks.
13
+ - README MUST be updated whenever behavior, commands, or setup steps change.
14
+
15
+ Good example characteristics:
16
+
17
+ - Starts with immediate value and one-command quick start.
18
+ - Shows exact commands and expected flow.
19
+ - Includes troubleshooting or FAQ for common confusion points.
20
+
21
+ Bad example characteristics:
22
+
23
+ - Only describes high-level ideas.
24
+ - Missing runnable commands.
25
+ - Forces reader to guess execution order.
@@ -0,0 +1,33 @@
1
+ ### Return Policy (MUST)
2
+
3
+ - Every function or method MUST have a single `return` statement.
4
+ - Early returns are not allowed.
5
+ - Conditional paths MUST assign to a local result variable and return once.
6
+
7
+ Good example:
8
+
9
+ ```ts
10
+ public toStatusLabel(status: InvoiceStatus): string {
11
+ let label: string;
12
+
13
+ if (status === "paid") {
14
+ label = "Paid";
15
+ } else if (status === "void") {
16
+ label = "Void";
17
+ } else {
18
+ label = "Pending";
19
+ }
20
+
21
+ return label;
22
+ }
23
+ ```
24
+
25
+ Bad example:
26
+
27
+ ```ts
28
+ public toStatusLabel(status: InvoiceStatus): string {
29
+ if (status === "paid") return "Paid";
30
+ if (status === "void") return "Void";
31
+ return "Pending";
32
+ }
33
+ ```
@@ -0,0 +1,26 @@
1
+ ### Testing and Comments (MUST)
2
+
3
+ - Any behavior change MUST include or update tests.
4
+ - Tests MUST validate behavior, not implementation details.
5
+ - Comments MUST be explicit and extensive when logic is non-trivial.
6
+ - Async workflows MUST use `async/await` style only.
7
+
8
+ Good example:
9
+
10
+ ```ts
11
+ // Business rule: invoices older than 30 days are escalated for manual review.
12
+ public evaluateEscalation(invoice: Invoice, now: Date): EscalationDecision {
13
+ const ageInDays: number = daysBetween(invoice.issuedAt, now);
14
+ const decision: EscalationDecision =
15
+ ageInDays > 30 ? "manual-review" : "no-escalation";
16
+ return decision;
17
+ }
18
+ ```
19
+
20
+ Bad example:
21
+
22
+ ```ts
23
+ public evaluateEscalation(invoice: any, now: Date): any {
24
+ return Promise.resolve(invoice).then((it) => (Date.now() - it.issuedAt > 0 ? "x" : "y"));
25
+ }
26
+ ```
@@ -0,0 +1,24 @@
1
+ # Architecture Guide
2
+
3
+ Architecture strictness is **moderate**.
4
+
5
+ ## Project Templates
6
+
7
+ Two templates are supported:
8
+
9
+ - `node-lib`
10
+ - `node-service`
11
+
12
+ ## Default Layout
13
+
14
+ Both templates SHOULD keep this baseline structure:
15
+
16
+ - `src/` for implementation.
17
+ - `test/` for automated tests.
18
+ - `eslint.config.mjs`, `prettier.config.cjs`, and `tsconfig.json` at root.
19
+
20
+ ## Boundary Rules
21
+
22
+ - Keep feature modules cohesive.
23
+ - Avoid cyclic dependencies.
24
+ - Keep configuration centralized at project root.
@@ -0,0 +1,12 @@
1
+ # Changelog Policy
2
+
3
+ ## Versioning
4
+
5
+ Use semantic versioning for the published `@sha3/code-standards` package.
6
+
7
+ ## Rules
8
+
9
+ - Every release MUST include a concise changelog entry.
10
+ - Breaking changes MUST document migration steps.
11
+ - `npm run release:check` MUST pass before publishing.
12
+ - Use `npm run release:publish` to publish from repository root.
@@ -0,0 +1,47 @@
1
+ {
2
+ "meta": {
3
+ "version": "v1",
4
+ "scope": "@sha3",
5
+ "packageManager": "npm",
6
+ "moduleSystem": "esm"
7
+ },
8
+ "language": {
9
+ "runtime": "node",
10
+ "typescript": true,
11
+ "target": "ES2022"
12
+ },
13
+ "formatting": {
14
+ "prettier": true,
15
+ "lineLength": 100,
16
+ "semi": true,
17
+ "singleQuote": false
18
+ },
19
+ "naming": {
20
+ "files": "kebab-case",
21
+ "directories": "kebab-case",
22
+ "typescript": {
23
+ "types": "PascalCase",
24
+ "interfaces": "PascalCase",
25
+ "constants": "SCREAMING_SNAKE_CASE"
26
+ }
27
+ },
28
+ "architecture": {
29
+ "strictness": "moderate",
30
+ "templates": ["node-lib", "node-service"]
31
+ },
32
+ "testing": {
33
+ "runner": "node-test-runner",
34
+ "coverage": false,
35
+ "testLocation": "test/"
36
+ },
37
+ "tooling": {
38
+ "eslintConfig": "@sha3/code-standards/eslint/node",
39
+ "prettierConfig": "@sha3/code-standards/prettier",
40
+ "tsconfigPackage": "@sha3/code-standards/tsconfig/node-lib.json",
41
+ "enforcement": "local-strict"
42
+ },
43
+ "ai": {
44
+ "enabledByDefault": true,
45
+ "assistants": ["codex", "cursor", "copilot", "windsurf"]
46
+ }
47
+ }
@@ -0,0 +1,25 @@
1
+ # README Guide
2
+
3
+ ## Goal
4
+
5
+ Every repository README MUST be clear, actionable, and visually structured.
6
+
7
+ ## Mandatory Sections
8
+
9
+ - Title and one-line value proposition.
10
+ - TL;DR or Quick Start with copy/paste commands.
11
+ - What it does and why it exists.
12
+ - Setup and usage examples.
13
+ - AI workflow section when the repository uses AI coding contracts.
14
+ - Troubleshooting or FAQ.
15
+
16
+ ## Writing Rules
17
+
18
+ - Use concrete commands and expected execution order.
19
+ - Avoid vague claims without implementation detail.
20
+ - Keep headings and lists scannable.
21
+ - Update README with every behavior or command change.
22
+
23
+ ## Quality Bar
24
+
25
+ A top-tier README lets a new engineer understand and run the project in under 5 minutes without asking additional questions.
@@ -0,0 +1,122 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://sha3.dev/code-standards/schema.json",
4
+ "title": "Code Standards Manifest",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "meta",
9
+ "language",
10
+ "formatting",
11
+ "naming",
12
+ "architecture",
13
+ "testing",
14
+ "tooling",
15
+ "ai"
16
+ ],
17
+ "properties": {
18
+ "meta": {
19
+ "type": "object",
20
+ "additionalProperties": false,
21
+ "required": ["version", "scope", "packageManager", "moduleSystem"],
22
+ "properties": {
23
+ "version": { "type": "string", "pattern": "^v[0-9]+$" },
24
+ "scope": { "type": "string", "const": "@sha3" },
25
+ "packageManager": { "type": "string", "const": "npm" },
26
+ "moduleSystem": { "type": "string", "enum": ["esm"] }
27
+ }
28
+ },
29
+ "language": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "required": ["runtime", "typescript", "target"],
33
+ "properties": {
34
+ "runtime": { "type": "string", "const": "node" },
35
+ "typescript": { "type": "boolean" },
36
+ "target": { "type": "string" }
37
+ }
38
+ },
39
+ "formatting": {
40
+ "type": "object",
41
+ "additionalProperties": false,
42
+ "required": ["prettier", "lineLength", "semi", "singleQuote"],
43
+ "properties": {
44
+ "prettier": { "type": "boolean" },
45
+ "lineLength": { "type": "integer", "minimum": 80, "maximum": 140 },
46
+ "semi": { "type": "boolean" },
47
+ "singleQuote": { "type": "boolean" }
48
+ }
49
+ },
50
+ "naming": {
51
+ "type": "object",
52
+ "additionalProperties": false,
53
+ "required": ["files", "directories", "typescript"],
54
+ "properties": {
55
+ "files": { "type": "string", "enum": ["kebab-case"] },
56
+ "directories": { "type": "string", "enum": ["kebab-case"] },
57
+ "typescript": {
58
+ "type": "object",
59
+ "additionalProperties": false,
60
+ "required": ["types", "interfaces", "constants"],
61
+ "properties": {
62
+ "types": { "type": "string", "enum": ["PascalCase"] },
63
+ "interfaces": { "type": "string", "enum": ["PascalCase"] },
64
+ "constants": { "type": "string", "enum": ["SCREAMING_SNAKE_CASE"] }
65
+ }
66
+ }
67
+ }
68
+ },
69
+ "architecture": {
70
+ "type": "object",
71
+ "additionalProperties": false,
72
+ "required": ["strictness", "templates"],
73
+ "properties": {
74
+ "strictness": { "type": "string", "enum": ["moderate"] },
75
+ "templates": {
76
+ "type": "array",
77
+ "items": { "type": "string", "enum": ["node-lib", "node-service"] },
78
+ "minItems": 2,
79
+ "uniqueItems": true
80
+ }
81
+ }
82
+ },
83
+ "testing": {
84
+ "type": "object",
85
+ "additionalProperties": false,
86
+ "required": ["runner", "coverage", "testLocation"],
87
+ "properties": {
88
+ "runner": { "type": "string", "const": "node-test-runner" },
89
+ "coverage": { "type": "boolean" },
90
+ "testLocation": { "type": "string", "enum": ["test/"] }
91
+ }
92
+ },
93
+ "tooling": {
94
+ "type": "object",
95
+ "additionalProperties": false,
96
+ "required": ["eslintConfig", "prettierConfig", "tsconfigPackage", "enforcement"],
97
+ "properties": {
98
+ "eslintConfig": { "type": "string", "const": "@sha3/code-standards/eslint/node" },
99
+ "prettierConfig": { "type": "string", "const": "@sha3/code-standards/prettier" },
100
+ "tsconfigPackage": {
101
+ "type": "string",
102
+ "const": "@sha3/code-standards/tsconfig/node-lib.json"
103
+ },
104
+ "enforcement": { "type": "string", "enum": ["local-strict"] }
105
+ }
106
+ },
107
+ "ai": {
108
+ "type": "object",
109
+ "additionalProperties": false,
110
+ "required": ["enabledByDefault", "assistants"],
111
+ "properties": {
112
+ "enabledByDefault": { "type": "boolean" },
113
+ "assistants": {
114
+ "type": "array",
115
+ "items": { "type": "string", "enum": ["codex", "cursor", "copilot", "windsurf"] },
116
+ "minItems": 4,
117
+ "uniqueItems": true
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
@@ -0,0 +1,48 @@
1
+ # Style Guide
2
+
3
+ All code MUST follow the canonical rules in `standards/manifest.json`.
4
+
5
+ ## Formatting
6
+
7
+ - Use Prettier for formatting.
8
+ - Use a max line length of 100.
9
+ - Use semicolons.
10
+ - Use double quotes for strings.
11
+
12
+ ## TypeScript
13
+
14
+ - Use strict TypeScript mode.
15
+ - Avoid `any` unless there is no viable alternative.
16
+ - Prefer explicit return types for exported functions.
17
+ - Use type-only imports when possible.
18
+ - Always use braces in control flow (`if`, `else`, `for`, `while`, `do`).
19
+
20
+ ## Naming
21
+
22
+ - Use `kebab-case` for files and directories.
23
+ - Use `PascalCase` for types and interfaces.
24
+ - Use `SCREAMING_SNAKE_CASE` for constants.
25
+
26
+ ## Class File Comment Blocks
27
+
28
+ Class-oriented files MUST use `/** @section ... */` markers in this exact order:
29
+
30
+ 1. `imports:externals`
31
+ 2. `imports:internals`
32
+ 3. `consts`
33
+ 4. `types`
34
+ 5. `private:attributes`
35
+ 6. `private:properties`
36
+ 7. `public:properties`
37
+ 8. `constructor`
38
+ 9. `static:properties`
39
+ 10. `factory`
40
+ 11. `private:methods`
41
+ 12. `public:methods`
42
+ 13. `static:methods`
43
+
44
+ All section blocks MUST be present even when empty. Empty sections MUST include:
45
+
46
+ ```ts
47
+ // empty
48
+ ```
@@ -0,0 +1,18 @@
1
+ # Testing Guide
2
+
3
+ Projects MUST use the Node test runner.
4
+
5
+ ## Location
6
+
7
+ - Store tests under `test/`.
8
+ - Use `*.test.ts` or `*.test.js` naming.
9
+
10
+ ## Commands
11
+
12
+ - `npm run test` MUST execute all automated tests.
13
+ - `npm run check` MUST include test execution.
14
+
15
+ ## Assertions
16
+
17
+ - Prefer `node:assert/strict`.
18
+ - Keep tests deterministic and isolated.
@@ -0,0 +1,32 @@
1
+ # Tooling Guide
2
+
3
+ All new projects MUST use this package and its subpath exports:
4
+
5
+ - `@sha3/code-standards/eslint/node`
6
+ - `@sha3/code-standards/eslint/test`
7
+ - `@sha3/code-standards/prettier`
8
+ - `@sha3/code-standards/tsconfig/node-lib.json` or `node-service.json`
9
+
10
+ ## Behavioral Policy
11
+
12
+ In addition to tooling, each generated project MUST include profile-driven AI instructions:
13
+
14
+ - `AGENTS.md` generated from the active style profile
15
+ - `ai/codex.md`, `ai/cursor.md`, `ai/copilot.md`, `ai/windsurf.md`
16
+
17
+ The generated instructions are blocking rules and MUST be treated as the top local AI coding contract.
18
+
19
+ ## Enforcement
20
+
21
+ Enforcement is local and strict.
22
+
23
+ Required scripts:
24
+
25
+ - `npm run check`
26
+ - `npm run fix`
27
+ - `npm run lint`
28
+ - `npm run format:check`
29
+ - `npm run typecheck`
30
+ - `npm run test`
31
+
32
+ No remote CI is required for v1.
@@ -0,0 +1,4 @@
1
+ import nodeConfig from "@sha3/code-standards/eslint/node";
2
+ import testConfig from "@sha3/code-standards/eslint/test";
3
+
4
+ export default [...nodeConfig, ...testConfig];
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "{{packageName}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc -p tsconfig.build.json",
13
+ "check": "npm run lint && npm run format:check && npm run typecheck && npm run test",
14
+ "fix": "npm run lint:fix && npm run format:write",
15
+ "lint": "eslint .",
16
+ "lint:fix": "eslint . --fix",
17
+ "format:check": "prettier --check .",
18
+ "format:write": "prettier --write .",
19
+ "typecheck": "tsc --noEmit",
20
+ "test": "node --import tsx --test"
21
+ },
22
+ "devDependencies": {
23
+ "@sha3/code-standards": "^0.1.0",
24
+ "@types/node": "^22.13.10",
25
+ "eslint": "^9.20.1",
26
+ "prettier": "^3.5.3",
27
+ "tsx": "^4.19.3",
28
+ "typescript": "^5.8.2"
29
+ }
30
+ }
@@ -0,0 +1,9 @@
1
+ let config;
2
+
3
+ try {
4
+ config = require("@sha3/code-standards/prettier");
5
+ } catch {
6
+ config = require("../../prettier/index.cjs");
7
+ }
8
+
9
+ module.exports = config;
@@ -0,0 +1,3 @@
1
+ export function greet(name: string): string {
2
+ return `Hello, ${name}`;
3
+ }
@@ -0,0 +1,8 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { greet } from "../src/index.js";
5
+
6
+ test("greet returns a deterministic message", () => {
7
+ assert.equal(greet("world"), "Hello, world");
8
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": false
5
+ },
6
+ "exclude": ["test/**/*.ts"]
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "@sha3/code-standards/tsconfig/node-lib.json",
3
+ "compilerOptions": {
4
+ "types": ["node"]
5
+ },
6
+ "include": ["src/**/*.ts", "test/**/*.ts"]
7
+ }
@@ -0,0 +1,4 @@
1
+ import nodeConfig from "@sha3/code-standards/eslint/node";
2
+ import testConfig from "@sha3/code-standards/eslint/test";
3
+
4
+ export default [...nodeConfig, ...testConfig];
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "{{packageName}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "start": "node --import tsx src/index.ts",
8
+ "check": "npm run lint && npm run format:check && npm run typecheck && npm run test",
9
+ "fix": "npm run lint:fix && npm run format:write",
10
+ "lint": "eslint .",
11
+ "lint:fix": "eslint . --fix",
12
+ "format:check": "prettier --check .",
13
+ "format:write": "prettier --write .",
14
+ "typecheck": "tsc --noEmit",
15
+ "test": "node --import tsx --test"
16
+ },
17
+ "devDependencies": {
18
+ "@sha3/code-standards": "^0.1.0",
19
+ "@types/node": "^22.13.10",
20
+ "eslint": "^9.20.1",
21
+ "prettier": "^3.5.3",
22
+ "tsx": "^4.19.3",
23
+ "typescript": "^5.8.2"
24
+ }
25
+ }
@@ -0,0 +1,9 @@
1
+ let config;
2
+
3
+ try {
4
+ config = require("@sha3/code-standards/prettier");
5
+ } catch {
6
+ config = require("../../prettier/index.cjs");
7
+ }
8
+
9
+ module.exports = config;
@@ -0,0 +1,17 @@
1
+ import { createServer } from "node:http";
2
+
3
+ export function buildServer() {
4
+ return createServer((_, response) => {
5
+ response.statusCode = 200;
6
+ response.setHeader("content-type", "application/json");
7
+ response.end(JSON.stringify({ ok: true }));
8
+ });
9
+ }
10
+
11
+ if (process.env.NODE_ENV !== "test") {
12
+ const port = Number(process.env.PORT ?? "3000");
13
+ const server = buildServer();
14
+ server.listen(port, () => {
15
+ console.log(`service listening on http://localhost:${port}`);
16
+ });
17
+ }
@@ -0,0 +1,37 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { buildServer } from "../src/index.js";
5
+
6
+ test("service responds with ok payload", async () => {
7
+ const server = buildServer();
8
+
9
+ await new Promise<void>((resolve) => {
10
+ server.listen(0, () => {
11
+ resolve();
12
+ });
13
+ });
14
+
15
+ const address = server.address();
16
+
17
+ if (!address || typeof address === "string") {
18
+ throw new Error("failed to bind test server");
19
+ }
20
+
21
+ const response = await fetch(`http://127.0.0.1:${address.port}`);
22
+ const json = await response.json();
23
+
24
+ assert.equal(response.status, 200);
25
+ assert.deepEqual(json, { ok: true });
26
+
27
+ await new Promise<void>((resolve, reject) => {
28
+ server.close((error) => {
29
+ if (error) {
30
+ reject(error);
31
+ return;
32
+ }
33
+
34
+ resolve();
35
+ });
36
+ });
37
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "@sha3/code-standards/tsconfig/node-service.json",
3
+ "compilerOptions": {
4
+ "types": ["node"]
5
+ },
6
+ "include": ["src/**/*.ts", "test/**/*.ts"]
7
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "target": "ES2022",
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "strict": true,
8
+ "noUncheckedIndexedAccess": true,
9
+ "exactOptionalPropertyTypes": true,
10
+ "useUnknownInCatchVariables": true,
11
+ "isolatedModules": true,
12
+ "esModuleInterop": false,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "skipLibCheck": true
15
+ }
16
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "./base.json",
4
+ "compilerOptions": {
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "sourceMap": true,
8
+ "outDir": "dist",
9
+ "rootDir": "src"
10
+ },
11
+ "include": ["src/**/*.ts", "test/**/*.ts"]
12
+ }