speckeeper 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/README.md +273 -0
- package/bin/speckeeper.js +10 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1110 -0
- package/dist/cli.js.map +1 -0
- package/dist/dsl/index.d.ts +2 -0
- package/dist/dsl/index.js +3 -0
- package/dist/dsl/index.js.map +1 -0
- package/dist/index.d.ts +1377 -0
- package/dist/index.js +1364 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/init/design/_models/component.ts +70 -0
- package/dist/templates/init/design/_models/entity.ts +82 -0
- package/dist/templates/init/design/_models/index.ts +33 -0
- package/dist/templates/init/design/_models/requirement.ts +95 -0
- package/dist/templates/init/design/_models/term.ts +58 -0
- package/dist/templates/init/design/_models/usecase.ts +99 -0
- package/dist/templates/init/design/index.ts +8 -0
- package/dist/templates/init/design/requirements.ts +20 -0
- package/dist/templates/init/package.json.template +17 -0
- package/dist/templates/init/speckeeper.config.ts +11 -0
- package/dist/templates/init/tsconfig.json +14 -0
- package/package.json +80 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Term Model Definition
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { Model, RelationSchema } from 'speckeeper';
|
|
6
|
+
import type { LintRule, Exporter, ModelLevel } from 'speckeeper';
|
|
7
|
+
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// Schema Definition
|
|
10
|
+
// =============================================================================
|
|
11
|
+
|
|
12
|
+
export const TermSchema = z.object({
|
|
13
|
+
id: z.string(),
|
|
14
|
+
term: z.string(),
|
|
15
|
+
definition: z.string(),
|
|
16
|
+
category: z.enum(['business', 'technical', 'acronym', 'process', 'role']),
|
|
17
|
+
abbreviation: z.string().optional(),
|
|
18
|
+
expandedForm: z.string().optional(),
|
|
19
|
+
relations: z.array(RelationSchema).optional(),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// Type Export
|
|
24
|
+
// =============================================================================
|
|
25
|
+
|
|
26
|
+
export type Term = z.input<typeof TermSchema>;
|
|
27
|
+
|
|
28
|
+
// =============================================================================
|
|
29
|
+
// Model Class
|
|
30
|
+
// =============================================================================
|
|
31
|
+
|
|
32
|
+
class TermModel extends Model<typeof TermSchema> {
|
|
33
|
+
readonly id = 'term';
|
|
34
|
+
readonly name = 'Term';
|
|
35
|
+
readonly idPrefix = 'TERM';
|
|
36
|
+
readonly schema = TermSchema;
|
|
37
|
+
readonly description = 'Defines terms (glossary)';
|
|
38
|
+
protected modelLevel: ModelLevel = 'L0';
|
|
39
|
+
|
|
40
|
+
protected lintRules: LintRule<Term>[] = [
|
|
41
|
+
{
|
|
42
|
+
id: 'term-has-definition',
|
|
43
|
+
severity: 'error',
|
|
44
|
+
message: 'Term must have a definition',
|
|
45
|
+
check: (spec) => !spec.definition || spec.definition.trim() === '',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'term-acronym-has-expanded-form',
|
|
49
|
+
severity: 'warning',
|
|
50
|
+
message: 'Acronym terms should have an expanded form',
|
|
51
|
+
check: (spec) => spec.category === 'acronym' && !spec.expandedForm,
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
protected exporters: Exporter<Term>[] = [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { TermModel };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UseCase Model Definition
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { Model, RelationSchema } from 'speckeeper';
|
|
6
|
+
import type { LintRule, Exporter, ModelLevel } from 'speckeeper';
|
|
7
|
+
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// Schema Definition
|
|
10
|
+
// =============================================================================
|
|
11
|
+
|
|
12
|
+
export const ActorSchema = z.object({
|
|
13
|
+
id: z.string(),
|
|
14
|
+
name: z.string(),
|
|
15
|
+
description: z.string().optional(),
|
|
16
|
+
type: z.enum(['human', 'system', 'external']),
|
|
17
|
+
relations: z.array(RelationSchema).optional(),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const UseCaseStepSchema = z.object({
|
|
21
|
+
stepNumber: z.number(),
|
|
22
|
+
type: z.enum(['user_action', 'system_response', 'alternative']),
|
|
23
|
+
description: z.string(),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const UseCaseSchema = z.object({
|
|
27
|
+
id: z.string(),
|
|
28
|
+
name: z.string(),
|
|
29
|
+
description: z.string(),
|
|
30
|
+
actor: z.string(),
|
|
31
|
+
preconditions: z.array(z.string()).optional().default([]),
|
|
32
|
+
postconditions: z.array(z.string()).optional().default([]),
|
|
33
|
+
mainFlow: z.array(UseCaseStepSchema),
|
|
34
|
+
relations: z.array(RelationSchema).optional(),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// =============================================================================
|
|
38
|
+
// Type Export
|
|
39
|
+
// =============================================================================
|
|
40
|
+
|
|
41
|
+
export type Actor = z.input<typeof ActorSchema>;
|
|
42
|
+
export type UseCaseStep = z.infer<typeof UseCaseStepSchema>;
|
|
43
|
+
export type UseCase = z.input<typeof UseCaseSchema>;
|
|
44
|
+
|
|
45
|
+
// =============================================================================
|
|
46
|
+
// Actor Model Class
|
|
47
|
+
// =============================================================================
|
|
48
|
+
|
|
49
|
+
class ActorModel extends Model<typeof ActorSchema> {
|
|
50
|
+
readonly id = 'actor';
|
|
51
|
+
readonly name = 'Actor';
|
|
52
|
+
readonly idPrefix = 'ACT';
|
|
53
|
+
readonly schema = ActorSchema;
|
|
54
|
+
readonly description = 'Defines actors';
|
|
55
|
+
protected modelLevel: ModelLevel = 'L0';
|
|
56
|
+
|
|
57
|
+
protected lintRules: LintRule<Actor>[] = [
|
|
58
|
+
{
|
|
59
|
+
id: 'actor-has-description',
|
|
60
|
+
severity: 'warning',
|
|
61
|
+
message: 'Actor should have a description',
|
|
62
|
+
check: (spec) => !spec.description || spec.description.trim() === '',
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
protected exporters: Exporter<Actor>[] = [];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// =============================================================================
|
|
70
|
+
// UseCase Model Class
|
|
71
|
+
// =============================================================================
|
|
72
|
+
|
|
73
|
+
class UseCaseModel extends Model<typeof UseCaseSchema> {
|
|
74
|
+
readonly id = 'usecase';
|
|
75
|
+
readonly name = 'UseCase';
|
|
76
|
+
readonly idPrefix = 'UC';
|
|
77
|
+
readonly schema = UseCaseSchema;
|
|
78
|
+
readonly description = 'Defines use cases (business flows)';
|
|
79
|
+
protected modelLevel: ModelLevel = 'L0';
|
|
80
|
+
|
|
81
|
+
protected lintRules: LintRule<UseCase>[] = [
|
|
82
|
+
{
|
|
83
|
+
id: 'usecase-has-main-flow',
|
|
84
|
+
severity: 'error',
|
|
85
|
+
message: 'UseCase must have a main flow',
|
|
86
|
+
check: (spec) => !spec.mainFlow || spec.mainFlow.length === 0,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: 'usecase-has-actor',
|
|
90
|
+
severity: 'error',
|
|
91
|
+
message: 'UseCase must have an actor',
|
|
92
|
+
check: (spec) => !spec.actor || spec.actor.trim() === '',
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
protected exporters: Exporter<UseCase>[] = [];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { ActorModel, UseCaseModel };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Requirements
|
|
3
|
+
*/
|
|
4
|
+
import type { Requirement } from './_models/requirement.ts';
|
|
5
|
+
|
|
6
|
+
export const requirements: Requirement[] = [
|
|
7
|
+
{
|
|
8
|
+
id: 'FR-001',
|
|
9
|
+
name: 'User Authentication',
|
|
10
|
+
type: 'functional',
|
|
11
|
+
priority: 'must',
|
|
12
|
+
description: 'Users can authenticate using email and password',
|
|
13
|
+
acceptanceCriteria: [
|
|
14
|
+
{ id: 'FR-001-01', description: 'Valid credentials grant access', verificationMethod: 'test' },
|
|
15
|
+
{ id: 'FR-001-02', description: 'Invalid credentials show error message', verificationMethod: 'test' },
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
console.log(`Requirements loaded: ${requirements.length} items`);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"typecheck": "tsc --noEmit",
|
|
7
|
+
"lint": "speckeeper lint",
|
|
8
|
+
"check": "speckeeper check"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"speckeeper": "^0.1.0",
|
|
12
|
+
"zod": "^3.22.4"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"typescript": "^5.3.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"allowImportingTsExtensions": true,
|
|
7
|
+
"noEmit": true,
|
|
8
|
+
"strict": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["design/**/*", "speckeeper.config.ts"]
|
|
14
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "speckeeper",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript-first specification validation framework with external SSOT integration",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./dsl": {
|
|
15
|
+
"import": "./dist/dsl/index.js",
|
|
16
|
+
"types": "./dist/dsl/index.d.ts"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"speckeeper": "./bin/speckeeper.js"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20.0.0"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"bin"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup",
|
|
31
|
+
"build:docs": "npm run build && embedoc build",
|
|
32
|
+
"dev": "tsup --watch",
|
|
33
|
+
"lint": "eslint",
|
|
34
|
+
"lint:design": "eslint design/",
|
|
35
|
+
"test": "vitest",
|
|
36
|
+
"test:run": "vitest run",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"prepublishOnly": "npm run build",
|
|
39
|
+
"docs": "embedoc build",
|
|
40
|
+
"docs:watch": "embedoc watch",
|
|
41
|
+
"ci": "npm run ci:validate && npm run ci:generate && npm run ci:verify",
|
|
42
|
+
"ci:validate": "npm run typecheck && npm run lint && npm run lint:design && npm run build && npx speckeeper lint && npm run test:run",
|
|
43
|
+
"ci:generate": "embedoc build",
|
|
44
|
+
"ci:verify": "npx speckeeper check external-ssot && npx speckeeper check test && npx speckeeper check test --coverage"
|
|
45
|
+
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"requirements",
|
|
48
|
+
"design",
|
|
49
|
+
"documentation",
|
|
50
|
+
"markdown",
|
|
51
|
+
"mermaid",
|
|
52
|
+
"typescript",
|
|
53
|
+
"dsl",
|
|
54
|
+
"architecture",
|
|
55
|
+
"c4-model"
|
|
56
|
+
],
|
|
57
|
+
"author": "",
|
|
58
|
+
"license": "MIT",
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"chalk": "^5.3.0",
|
|
61
|
+
"commander": "^12.1.0",
|
|
62
|
+
"embedoc": "^0.10.1",
|
|
63
|
+
"glob": "^10.3.10",
|
|
64
|
+
"tsx": "^4.21.0",
|
|
65
|
+
"yaml": "^2.3.4",
|
|
66
|
+
"zod": "^3.22.4"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@eslint/js": "^9.39.2",
|
|
70
|
+
"@types/node": "^20.11.0",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
72
|
+
"@typescript-eslint/parser": "^8.54.0",
|
|
73
|
+
"@vitest/coverage-v8": "^1.6.1",
|
|
74
|
+
"eslint": "^9.39.2",
|
|
75
|
+
"tsup": "^8.0.1",
|
|
76
|
+
"typescript": "^5.3.3",
|
|
77
|
+
"typescript-eslint": "^8.54.0",
|
|
78
|
+
"vitest": "^1.2.0"
|
|
79
|
+
}
|
|
80
|
+
}
|