@guinetik/primitives-ts 0.5.1 → 0.6.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 +68 -0
- package/dist/chat.types.spec.d.ts +6 -0
- package/dist/chat.types.spec.d.ts.map +1 -0
- package/dist/chat.types.spec.js +85 -0
- package/dist/file.types.d.ts +93 -0
- package/dist/file.types.d.ts.map +1 -0
- package/dist/file.types.js +9 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/system.types.d.ts +31 -0
- package/dist/system.types.d.ts.map +1 -1
- package/dist/type-guards.d.ts +34 -0
- package/dist/type-guards.d.ts.map +1 -0
- package/dist/type-guards.js +92 -0
- package/dist/type-guards.spec.d.ts +5 -0
- package/dist/type-guards.spec.d.ts.map +1 -0
- package/dist/type-guards.spec.js +222 -0
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -72,9 +72,77 @@ const metrics: SystemMetrics = {
|
|
|
72
72
|
# Build the package
|
|
73
73
|
npm run build
|
|
74
74
|
|
|
75
|
+
# Run tests
|
|
76
|
+
npm test
|
|
77
|
+
|
|
78
|
+
# Run tests in watch mode
|
|
79
|
+
npm run test:watch
|
|
80
|
+
|
|
81
|
+
# Generate coverage report
|
|
82
|
+
npm run test:cov
|
|
83
|
+
|
|
75
84
|
# The build output will be in the dist/ folder
|
|
76
85
|
```
|
|
77
86
|
|
|
87
|
+
## Testing
|
|
88
|
+
|
|
89
|
+
This package includes unit tests using Jest with TypeScript support.
|
|
90
|
+
|
|
91
|
+
### Test Coverage
|
|
92
|
+
|
|
93
|
+
Tests cover:
|
|
94
|
+
- **Type Guards** - Runtime validation for chat types, models, and request objects
|
|
95
|
+
- **Enum Validation** - ClaudeModel enum consistency and format checks
|
|
96
|
+
- **Constants** - Model tier values and chat role validation
|
|
97
|
+
- **Edge Cases** - Null/undefined handling, invalid types, and boundary conditions
|
|
98
|
+
|
|
99
|
+
### Running Tests
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Run all tests once
|
|
103
|
+
npm test
|
|
104
|
+
|
|
105
|
+
# Watch mode for test-driven development
|
|
106
|
+
npm run test:watch
|
|
107
|
+
|
|
108
|
+
# Generate HTML coverage report (outputs to coverage/ folder)
|
|
109
|
+
npm run test:cov
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Type Guards
|
|
113
|
+
|
|
114
|
+
The package exports runtime type guards for validating data structures:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import {
|
|
118
|
+
isChatMessage,
|
|
119
|
+
isChatSession,
|
|
120
|
+
isModel,
|
|
121
|
+
isSendMessageRequest
|
|
122
|
+
} from '@guinetik/primitives-ts';
|
|
123
|
+
|
|
124
|
+
// Validate incoming data
|
|
125
|
+
if (isChatMessage(data)) {
|
|
126
|
+
// TypeScript knows data is ChatMessage here
|
|
127
|
+
console.log(data.content);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Validate API requests
|
|
131
|
+
if (isSendMessageRequest(req.body)) {
|
|
132
|
+
// Safe to use req.body as SendMessageRequest
|
|
133
|
+
const { message, model } = req.body;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Available type guards:
|
|
138
|
+
- `isChatRole(value)` - Validates 'user' | 'assistant'
|
|
139
|
+
- `isChatMessage(obj)` - Validates ChatMessage interface
|
|
140
|
+
- `isChatSession(obj)` - Validates ChatSession interface
|
|
141
|
+
- `isModel(obj)` - Validates Model interface
|
|
142
|
+
- `isClaudeModel(value)` - Validates ClaudeModel enum values
|
|
143
|
+
- `isSendMessageRequest(obj)` - Validates SendMessageRequest interface
|
|
144
|
+
- `isCreateSessionRequest(obj)` - Validates CreateSessionRequest interface
|
|
145
|
+
|
|
78
146
|
## Publishing Workflow
|
|
79
147
|
|
|
80
148
|
### ⚠️ IMPORTANT: Never Link Locally
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat.types.spec.d.ts","sourceRoot":"","sources":["../src/chat.types.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Chat Types Tests
|
|
4
|
+
* Validation tests for enums and constants
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const chat_types_1 = require("./chat.types");
|
|
8
|
+
describe('Chat Types', () => {
|
|
9
|
+
describe('ClaudeModel Enum', () => {
|
|
10
|
+
it('should have valid model IDs starting with "claude-"', () => {
|
|
11
|
+
const allModels = Object.values(chat_types_1.ClaudeModel);
|
|
12
|
+
allModels.forEach((modelId) => {
|
|
13
|
+
expect(modelId).toMatch(/^claude-/);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
it('should have exactly 4 defined models', () => {
|
|
17
|
+
const modelCount = Object.keys(chat_types_1.ClaudeModel).length;
|
|
18
|
+
expect(modelCount).toBe(4);
|
|
19
|
+
});
|
|
20
|
+
it('should have HAIKU_3_5 with correct ID', () => {
|
|
21
|
+
expect(chat_types_1.ClaudeModel.HAIKU_3_5).toBe('claude-3-5-haiku-20241022');
|
|
22
|
+
});
|
|
23
|
+
it('should have SONNET_3_5 with correct ID', () => {
|
|
24
|
+
expect(chat_types_1.ClaudeModel.SONNET_3_5).toBe('claude-3-5-sonnet-20241022');
|
|
25
|
+
});
|
|
26
|
+
it('should have SONNET_3_7 with correct ID', () => {
|
|
27
|
+
expect(chat_types_1.ClaudeModel.SONNET_3_7).toBe('claude-3-5-sonnet-20250219');
|
|
28
|
+
});
|
|
29
|
+
it('should have OPUS_3 with correct ID', () => {
|
|
30
|
+
expect(chat_types_1.ClaudeModel.OPUS_3).toBe('claude-3-opus-20240229');
|
|
31
|
+
});
|
|
32
|
+
it('should not have duplicate model IDs', () => {
|
|
33
|
+
const modelIds = Object.values(chat_types_1.ClaudeModel);
|
|
34
|
+
const uniqueIds = new Set(modelIds);
|
|
35
|
+
expect(modelIds.length).toBe(uniqueIds.size);
|
|
36
|
+
});
|
|
37
|
+
it('should have model IDs with valid date format', () => {
|
|
38
|
+
const allModels = Object.values(chat_types_1.ClaudeModel);
|
|
39
|
+
const datePattern = /\d{8}$/; // YYYYMMDD at the end
|
|
40
|
+
allModels.forEach((modelId) => {
|
|
41
|
+
expect(modelId).toMatch(datePattern);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
it('should be accessible by enum key', () => {
|
|
45
|
+
expect(chat_types_1.ClaudeModel['HAIKU_3_5']).toBeDefined();
|
|
46
|
+
expect(chat_types_1.ClaudeModel['SONNET_3_5']).toBeDefined();
|
|
47
|
+
expect(chat_types_1.ClaudeModel['SONNET_3_7']).toBeDefined();
|
|
48
|
+
expect(chat_types_1.ClaudeModel['OPUS_3']).toBeDefined();
|
|
49
|
+
});
|
|
50
|
+
it('should support iteration over enum values', () => {
|
|
51
|
+
const models = [];
|
|
52
|
+
for (const model of Object.values(chat_types_1.ClaudeModel)) {
|
|
53
|
+
models.push(model);
|
|
54
|
+
}
|
|
55
|
+
expect(models).toHaveLength(4);
|
|
56
|
+
expect(models).toContain('claude-3-5-haiku-20241022');
|
|
57
|
+
expect(models).toContain('claude-3-5-sonnet-20241022');
|
|
58
|
+
expect(models).toContain('claude-3-5-sonnet-20250219');
|
|
59
|
+
expect(models).toContain('claude-3-opus-20240229');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('Model Tier Values', () => {
|
|
63
|
+
const validTiers = ['fast', 'balanced', 'powerful', 'expert'];
|
|
64
|
+
it('should recognize all valid tier values', () => {
|
|
65
|
+
validTiers.forEach((tier) => {
|
|
66
|
+
expect(['fast', 'balanced', 'powerful', 'expert']).toContain(tier);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
it('should have exactly 4 tier options', () => {
|
|
70
|
+
expect(validTiers).toHaveLength(4);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe('ChatRole Type', () => {
|
|
74
|
+
const validRoles = ['user', 'assistant'];
|
|
75
|
+
it('should have exactly 2 valid roles', () => {
|
|
76
|
+
expect(validRoles).toHaveLength(2);
|
|
77
|
+
});
|
|
78
|
+
it('should include "user" role', () => {
|
|
79
|
+
expect(validRoles).toContain('user');
|
|
80
|
+
});
|
|
81
|
+
it('should include "assistant" role', () => {
|
|
82
|
+
expect(validRoles).toContain('assistant');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File upload and management types
|
|
3
|
+
*
|
|
4
|
+
* Shared types for file upload, storage, and management across the application.
|
|
5
|
+
*
|
|
6
|
+
* @module file.types
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Metadata for an uploaded file
|
|
10
|
+
*
|
|
11
|
+
* Represents a file stored in the system with all its metadata.
|
|
12
|
+
* Used by both API endpoints and frontend components.
|
|
13
|
+
*/
|
|
14
|
+
export interface FileMetadata {
|
|
15
|
+
/**
|
|
16
|
+
* Optional unique identifier for the file
|
|
17
|
+
*/
|
|
18
|
+
id?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Name of the file including extension
|
|
21
|
+
* @example "example.pdf"
|
|
22
|
+
*/
|
|
23
|
+
filename: string;
|
|
24
|
+
/**
|
|
25
|
+
* Size of the file in bytes
|
|
26
|
+
*/
|
|
27
|
+
size: number;
|
|
28
|
+
/**
|
|
29
|
+
* MIME type of the file
|
|
30
|
+
* @example "image/png", "application/pdf", "video/mp4"
|
|
31
|
+
*/
|
|
32
|
+
mimeType: string;
|
|
33
|
+
/**
|
|
34
|
+
* ISO 8601 timestamp of when the file was uploaded
|
|
35
|
+
* @example "2024-01-15T10:30:00.000Z"
|
|
36
|
+
*/
|
|
37
|
+
uploadedAt: string;
|
|
38
|
+
/**
|
|
39
|
+
* Public URL where the file can be accessed
|
|
40
|
+
* @example "https://example.com/uploads/example.pdf"
|
|
41
|
+
*/
|
|
42
|
+
url: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Request body for renaming a file
|
|
46
|
+
*/
|
|
47
|
+
export interface RenameFileRequest {
|
|
48
|
+
/**
|
|
49
|
+
* New filename (including extension)
|
|
50
|
+
*/
|
|
51
|
+
newFilename: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Response from file upload operation
|
|
55
|
+
*/
|
|
56
|
+
export interface FileUploadResponse {
|
|
57
|
+
/**
|
|
58
|
+
* Array of uploaded file metadata
|
|
59
|
+
*/
|
|
60
|
+
files: FileMetadata[];
|
|
61
|
+
/**
|
|
62
|
+
* Number of files successfully uploaded
|
|
63
|
+
*/
|
|
64
|
+
count: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* File upload status tracking (frontend only)
|
|
68
|
+
*
|
|
69
|
+
* Used to track the progress of individual file uploads in the UI.
|
|
70
|
+
*/
|
|
71
|
+
export interface FileUploadProgress {
|
|
72
|
+
/**
|
|
73
|
+
* Unique identifier for this upload
|
|
74
|
+
*/
|
|
75
|
+
id: string;
|
|
76
|
+
/**
|
|
77
|
+
* The file being uploaded
|
|
78
|
+
*/
|
|
79
|
+
file: File;
|
|
80
|
+
/**
|
|
81
|
+
* Upload progress percentage (0-100)
|
|
82
|
+
*/
|
|
83
|
+
progress: number;
|
|
84
|
+
/**
|
|
85
|
+
* Current status of the upload
|
|
86
|
+
*/
|
|
87
|
+
status: 'uploading' | 'success' | 'error';
|
|
88
|
+
/**
|
|
89
|
+
* Error message if status is 'error'
|
|
90
|
+
*/
|
|
91
|
+
error?: string;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=file.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.types.d.ts","sourceRoot":"","sources":["../src/file.types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,KAAK,EAAE,YAAY,EAAE,CAAC;IAEtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,IAAI,EAAE,IAAI,CAAC;IAEX;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;IAE1C;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,9 @@ export * from './totp.types';
|
|
|
16
16
|
export * from './deployment-history.types';
|
|
17
17
|
export * from './github.types';
|
|
18
18
|
export * from './chat.types';
|
|
19
|
+
export * from './type-guards';
|
|
19
20
|
export * from './agent.types';
|
|
21
|
+
export * from './file.types';
|
|
20
22
|
export type { Security, SecurityChallengeOptions, SecurityChallengeResult } from './security.interface';
|
|
21
23
|
export { SecurityLevel } from './security.interface';
|
|
22
24
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,cAAc,cAAc,CAAC;AAG7B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,2BAA2B,CAAC;AAG1C,cAAc,cAAc,CAAC;AAG7B,cAAc,4BAA4B,CAAC;AAG3C,cAAc,gBAAgB,CAAC;AAG/B,cAAc,cAAc,CAAC;AAG7B,cAAc,eAAe,CAAC;AAG9B,YAAY,EAAE,QAAQ,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACxG,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,cAAc,cAAc,CAAC;AAG7B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,2BAA2B,CAAC;AAG1C,cAAc,cAAc,CAAC;AAG7B,cAAc,4BAA4B,CAAC;AAG3C,cAAc,gBAAgB,CAAC;AAG/B,cAAc,cAAc,CAAC;AAG7B,cAAc,eAAe,CAAC;AAG9B,cAAc,eAAe,CAAC;AAG9B,cAAc,cAAc,CAAC;AAG7B,YAAY,EAAE,QAAQ,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACxG,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -42,7 +42,11 @@ __exportStar(require("./deployment-history.types"), exports);
|
|
|
42
42
|
__exportStar(require("./github.types"), exports);
|
|
43
43
|
// Chat system types
|
|
44
44
|
__exportStar(require("./chat.types"), exports);
|
|
45
|
+
// Type guards for runtime validation
|
|
46
|
+
__exportStar(require("./type-guards"), exports);
|
|
45
47
|
// Agent monitoring types
|
|
46
48
|
__exportStar(require("./agent.types"), exports);
|
|
49
|
+
// File upload and management types
|
|
50
|
+
__exportStar(require("./file.types"), exports);
|
|
47
51
|
var security_interface_1 = require("./security.interface");
|
|
48
52
|
Object.defineProperty(exports, "SecurityLevel", { enumerable: true, get: function () { return security_interface_1.SecurityLevel; } });
|
package/dist/system.types.d.ts
CHANGED
|
@@ -58,6 +58,35 @@ export type ContainerStatus = 'running' | 'stopped' | 'restarting' | 'error';
|
|
|
58
58
|
* Container health status types
|
|
59
59
|
*/
|
|
60
60
|
export type ContainerHealth = 'healthy' | 'unhealthy' | 'starting' | 'none';
|
|
61
|
+
/**
|
|
62
|
+
* Agent working status types
|
|
63
|
+
*/
|
|
64
|
+
export type AgentWorkingStatus = 'idle' | 'working' | 'reviewing' | 'deploying';
|
|
65
|
+
/**
|
|
66
|
+
* Agent type definitions
|
|
67
|
+
*/
|
|
68
|
+
export type AgentType = 'dev' | 'tl' | 'designer' | 'infosec';
|
|
69
|
+
/**
|
|
70
|
+
* Agent information for containers
|
|
71
|
+
*/
|
|
72
|
+
export interface AgentContainerInfo {
|
|
73
|
+
/** Agent type (dev, tl, designer, infosec) */
|
|
74
|
+
type: AgentType;
|
|
75
|
+
/** Agent display name (Daniel, Mr. Smith, Monica, Elliot) */
|
|
76
|
+
name: string;
|
|
77
|
+
/** Claude model being used */
|
|
78
|
+
model: string;
|
|
79
|
+
/** Current working status */
|
|
80
|
+
workingStatus: AgentWorkingStatus;
|
|
81
|
+
/** Current task ID if working */
|
|
82
|
+
currentTaskId?: string;
|
|
83
|
+
/** Current task description if working */
|
|
84
|
+
currentTaskDescription?: string;
|
|
85
|
+
/** Last activity timestamp */
|
|
86
|
+
lastActivity?: Date;
|
|
87
|
+
/** Current git branch if on feature branch */
|
|
88
|
+
currentBranch?: string;
|
|
89
|
+
}
|
|
61
90
|
/**
|
|
62
91
|
* Docker container information
|
|
63
92
|
*/
|
|
@@ -82,6 +111,8 @@ export interface Container {
|
|
|
82
111
|
image: string;
|
|
83
112
|
/** Container health status */
|
|
84
113
|
health: ContainerHealth;
|
|
114
|
+
/** Agent information (only present for agent containers) */
|
|
115
|
+
agentInfo?: AgentContainerInfo;
|
|
85
116
|
}
|
|
86
117
|
/**
|
|
87
118
|
* Log level types
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system.types.d.ts","sourceRoot":"","sources":["../src/system.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IAEd,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IAEd,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IAEb,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IAEd,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IAEb,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IAEd,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,GAAG,EAAE,OAAO,CAAC;IAEb,yBAAyB;IACzB,MAAM,EAAE,UAAU,CAAC;IAEnB,uBAAuB;IACvB,IAAI,EAAE,QAAQ,CAAC;IAEf,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IAEf,4CAA4C;IAC5C,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,OAAO,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IAEb,mBAAmB;IACnB,EAAE,EAAE,MAAM,CAAC;IAEX,uBAAuB;IACvB,MAAM,EAAE,eAAe,CAAC;IAExB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IAEf,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IAEZ,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;IAEf,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IAEb,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IAErB,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IAEd,8BAA8B;IAC9B,MAAM,EAAE,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"system.types.d.ts","sourceRoot":"","sources":["../src/system.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type Guards
|
|
3
|
+
* Runtime type checking for primitives
|
|
4
|
+
*/
|
|
5
|
+
import { ChatMessage, ChatSession, ChatRole, Model, ClaudeModel, SendMessageRequest, CreateSessionRequest } from './chat.types';
|
|
6
|
+
/**
|
|
7
|
+
* Type guard for ChatRole
|
|
8
|
+
*/
|
|
9
|
+
export declare function isChatRole(value: any): value is ChatRole;
|
|
10
|
+
/**
|
|
11
|
+
* Type guard for ChatMessage
|
|
12
|
+
*/
|
|
13
|
+
export declare function isChatMessage(obj: any): obj is ChatMessage;
|
|
14
|
+
/**
|
|
15
|
+
* Type guard for ChatSession
|
|
16
|
+
*/
|
|
17
|
+
export declare function isChatSession(obj: any): obj is ChatSession;
|
|
18
|
+
/**
|
|
19
|
+
* Type guard for Model
|
|
20
|
+
*/
|
|
21
|
+
export declare function isModel(obj: any): obj is Model;
|
|
22
|
+
/**
|
|
23
|
+
* Type guard for ClaudeModel enum values
|
|
24
|
+
*/
|
|
25
|
+
export declare function isClaudeModel(value: any): value is ClaudeModel;
|
|
26
|
+
/**
|
|
27
|
+
* Type guard for SendMessageRequest
|
|
28
|
+
*/
|
|
29
|
+
export declare function isSendMessageRequest(obj: any): obj is SendMessageRequest;
|
|
30
|
+
/**
|
|
31
|
+
* Type guard for CreateSessionRequest
|
|
32
|
+
*/
|
|
33
|
+
export declare function isCreateSessionRequest(obj: any): obj is CreateSessionRequest;
|
|
34
|
+
//# sourceMappingURL=type-guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-guards.d.ts","sourceRoot":"","sources":["../src/type-guards.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,WAAW,EACX,WAAW,EACX,QAAQ,EACR,KAAK,EACL,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAEtB;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,QAAQ,CAExD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,WAAW,CAY1D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,WAAW,CAY1D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,KAAK,CAe9C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,WAAW,CAE9D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,kBAAkB,CASxE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,oBAAoB,CAQ5E"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Type Guards
|
|
4
|
+
* Runtime type checking for primitives
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.isChatRole = isChatRole;
|
|
8
|
+
exports.isChatMessage = isChatMessage;
|
|
9
|
+
exports.isChatSession = isChatSession;
|
|
10
|
+
exports.isModel = isModel;
|
|
11
|
+
exports.isClaudeModel = isClaudeModel;
|
|
12
|
+
exports.isSendMessageRequest = isSendMessageRequest;
|
|
13
|
+
exports.isCreateSessionRequest = isCreateSessionRequest;
|
|
14
|
+
const chat_types_1 = require("./chat.types");
|
|
15
|
+
/**
|
|
16
|
+
* Type guard for ChatRole
|
|
17
|
+
*/
|
|
18
|
+
function isChatRole(value) {
|
|
19
|
+
return value === 'user' || value === 'assistant';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Type guard for ChatMessage
|
|
23
|
+
*/
|
|
24
|
+
function isChatMessage(obj) {
|
|
25
|
+
return (obj !== null &&
|
|
26
|
+
obj !== undefined &&
|
|
27
|
+
typeof obj === 'object' &&
|
|
28
|
+
typeof obj.id === 'string' &&
|
|
29
|
+
typeof obj.sessionId === 'string' &&
|
|
30
|
+
isChatRole(obj.role) &&
|
|
31
|
+
typeof obj.content === 'string' &&
|
|
32
|
+
obj.timestamp instanceof Date &&
|
|
33
|
+
(obj.model === undefined || typeof obj.model === 'string'));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Type guard for ChatSession
|
|
37
|
+
*/
|
|
38
|
+
function isChatSession(obj) {
|
|
39
|
+
return (obj !== null &&
|
|
40
|
+
obj !== undefined &&
|
|
41
|
+
typeof obj === 'object' &&
|
|
42
|
+
typeof obj.id === 'string' &&
|
|
43
|
+
typeof obj.userId === 'string' &&
|
|
44
|
+
typeof obj.model === 'string' &&
|
|
45
|
+
obj.createdAt instanceof Date &&
|
|
46
|
+
obj.updatedAt instanceof Date &&
|
|
47
|
+
(obj.title === undefined || typeof obj.title === 'string'));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Type guard for Model
|
|
51
|
+
*/
|
|
52
|
+
function isModel(obj) {
|
|
53
|
+
return (obj !== null &&
|
|
54
|
+
obj !== undefined &&
|
|
55
|
+
typeof obj === 'object' &&
|
|
56
|
+
obj.type === 'model' &&
|
|
57
|
+
typeof obj.id === 'string' &&
|
|
58
|
+
typeof obj.display_name === 'string' &&
|
|
59
|
+
typeof obj.created_at === 'string' &&
|
|
60
|
+
(obj.tier === undefined ||
|
|
61
|
+
obj.tier === 'fast' ||
|
|
62
|
+
obj.tier === 'balanced' ||
|
|
63
|
+
obj.tier === 'powerful' ||
|
|
64
|
+
obj.tier === 'expert'));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Type guard for ClaudeModel enum values
|
|
68
|
+
*/
|
|
69
|
+
function isClaudeModel(value) {
|
|
70
|
+
return Object.values(chat_types_1.ClaudeModel).includes(value);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Type guard for SendMessageRequest
|
|
74
|
+
*/
|
|
75
|
+
function isSendMessageRequest(obj) {
|
|
76
|
+
return (obj !== null &&
|
|
77
|
+
obj !== undefined &&
|
|
78
|
+
typeof obj === 'object' &&
|
|
79
|
+
(obj.sessionId === undefined || typeof obj.sessionId === 'string') &&
|
|
80
|
+
typeof obj.message === 'string' &&
|
|
81
|
+
typeof obj.model === 'string');
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Type guard for CreateSessionRequest
|
|
85
|
+
*/
|
|
86
|
+
function isCreateSessionRequest(obj) {
|
|
87
|
+
return (obj !== null &&
|
|
88
|
+
obj !== undefined &&
|
|
89
|
+
typeof obj === 'object' &&
|
|
90
|
+
typeof obj.model === 'string' &&
|
|
91
|
+
(obj.title === undefined || typeof obj.title === 'string'));
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-guards.spec.d.ts","sourceRoot":"","sources":["../src/type-guards.spec.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Type Guards Tests
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const type_guards_1 = require("./type-guards");
|
|
7
|
+
const chat_types_1 = require("./chat.types");
|
|
8
|
+
describe('Type Guards', () => {
|
|
9
|
+
describe('isChatRole', () => {
|
|
10
|
+
it('should return true for valid chat roles', () => {
|
|
11
|
+
expect((0, type_guards_1.isChatRole)('user')).toBe(true);
|
|
12
|
+
expect((0, type_guards_1.isChatRole)('assistant')).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
it('should return false for invalid values', () => {
|
|
15
|
+
expect((0, type_guards_1.isChatRole)('admin')).toBe(false);
|
|
16
|
+
expect((0, type_guards_1.isChatRole)('system')).toBe(false);
|
|
17
|
+
expect((0, type_guards_1.isChatRole)('')).toBe(false);
|
|
18
|
+
expect((0, type_guards_1.isChatRole)(null)).toBe(false);
|
|
19
|
+
expect((0, type_guards_1.isChatRole)(undefined)).toBe(false);
|
|
20
|
+
expect((0, type_guards_1.isChatRole)(123)).toBe(false);
|
|
21
|
+
expect((0, type_guards_1.isChatRole)({})).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe('isChatMessage', () => {
|
|
25
|
+
const validMessage = {
|
|
26
|
+
id: 'msg_123',
|
|
27
|
+
sessionId: 'session_456',
|
|
28
|
+
role: 'user',
|
|
29
|
+
content: 'Hello, world!',
|
|
30
|
+
timestamp: new Date(),
|
|
31
|
+
};
|
|
32
|
+
it('should return true for valid ChatMessage', () => {
|
|
33
|
+
expect((0, type_guards_1.isChatMessage)(validMessage)).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it('should return true for ChatMessage with optional model', () => {
|
|
36
|
+
const messageWithModel = {
|
|
37
|
+
...validMessage,
|
|
38
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
39
|
+
};
|
|
40
|
+
expect((0, type_guards_1.isChatMessage)(messageWithModel)).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
it('should return false for missing required fields', () => {
|
|
43
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, id: undefined })).toBe(false);
|
|
44
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, sessionId: undefined })).toBe(false);
|
|
45
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, role: undefined })).toBe(false);
|
|
46
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, content: undefined })).toBe(false);
|
|
47
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, timestamp: undefined })).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
it('should return false for invalid field types', () => {
|
|
50
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, id: 123 })).toBe(false);
|
|
51
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, sessionId: 123 })).toBe(false);
|
|
52
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, role: 'invalid' })).toBe(false);
|
|
53
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, content: 123 })).toBe(false);
|
|
54
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, timestamp: '2025-01-01' })).toBe(false);
|
|
55
|
+
expect((0, type_guards_1.isChatMessage)({ ...validMessage, model: 123 })).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
it('should return false for null and undefined', () => {
|
|
58
|
+
expect((0, type_guards_1.isChatMessage)(null)).toBe(false);
|
|
59
|
+
expect((0, type_guards_1.isChatMessage)(undefined)).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
it('should return false for non-object values', () => {
|
|
62
|
+
expect((0, type_guards_1.isChatMessage)('message')).toBe(false);
|
|
63
|
+
expect((0, type_guards_1.isChatMessage)(123)).toBe(false);
|
|
64
|
+
expect((0, type_guards_1.isChatMessage)(true)).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('isChatSession', () => {
|
|
68
|
+
const validSession = {
|
|
69
|
+
id: 'session_123',
|
|
70
|
+
userId: 'user_456',
|
|
71
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
72
|
+
createdAt: new Date(),
|
|
73
|
+
updatedAt: new Date(),
|
|
74
|
+
};
|
|
75
|
+
it('should return true for valid ChatSession', () => {
|
|
76
|
+
expect((0, type_guards_1.isChatSession)(validSession)).toBe(true);
|
|
77
|
+
});
|
|
78
|
+
it('should return true for ChatSession with optional title', () => {
|
|
79
|
+
const sessionWithTitle = {
|
|
80
|
+
...validSession,
|
|
81
|
+
title: 'My Chat Session',
|
|
82
|
+
};
|
|
83
|
+
expect((0, type_guards_1.isChatSession)(sessionWithTitle)).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
it('should return false for missing required fields', () => {
|
|
86
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, id: undefined })).toBe(false);
|
|
87
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, userId: undefined })).toBe(false);
|
|
88
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, model: undefined })).toBe(false);
|
|
89
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, createdAt: undefined })).toBe(false);
|
|
90
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, updatedAt: undefined })).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
it('should return false for invalid field types', () => {
|
|
93
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, id: 123 })).toBe(false);
|
|
94
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, userId: 123 })).toBe(false);
|
|
95
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, model: 123 })).toBe(false);
|
|
96
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, createdAt: '2025-01-01' })).toBe(false);
|
|
97
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, updatedAt: '2025-01-01' })).toBe(false);
|
|
98
|
+
expect((0, type_guards_1.isChatSession)({ ...validSession, title: 123 })).toBe(false);
|
|
99
|
+
});
|
|
100
|
+
it('should return false for null and undefined', () => {
|
|
101
|
+
expect((0, type_guards_1.isChatSession)(null)).toBe(false);
|
|
102
|
+
expect((0, type_guards_1.isChatSession)(undefined)).toBe(false);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('isModel', () => {
|
|
106
|
+
const validModel = {
|
|
107
|
+
type: 'model',
|
|
108
|
+
id: 'claude-sonnet-4-5-20250929',
|
|
109
|
+
display_name: 'Claude Sonnet 4.5',
|
|
110
|
+
created_at: '2025-09-29T00:00:00Z',
|
|
111
|
+
};
|
|
112
|
+
it('should return true for valid Model', () => {
|
|
113
|
+
expect((0, type_guards_1.isModel)(validModel)).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
it('should return true for Model with optional tier', () => {
|
|
116
|
+
expect((0, type_guards_1.isModel)({ ...validModel, tier: 'fast' })).toBe(true);
|
|
117
|
+
expect((0, type_guards_1.isModel)({ ...validModel, tier: 'balanced' })).toBe(true);
|
|
118
|
+
expect((0, type_guards_1.isModel)({ ...validModel, tier: 'powerful' })).toBe(true);
|
|
119
|
+
expect((0, type_guards_1.isModel)({ ...validModel, tier: 'expert' })).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
it('should return false for missing required fields', () => {
|
|
122
|
+
expect((0, type_guards_1.isModel)({ ...validModel, type: undefined })).toBe(false);
|
|
123
|
+
expect((0, type_guards_1.isModel)({ ...validModel, id: undefined })).toBe(false);
|
|
124
|
+
expect((0, type_guards_1.isModel)({ ...validModel, display_name: undefined })).toBe(false);
|
|
125
|
+
expect((0, type_guards_1.isModel)({ ...validModel, created_at: undefined })).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
it('should return false for invalid type value', () => {
|
|
128
|
+
expect((0, type_guards_1.isModel)({ ...validModel, type: 'invalid' })).toBe(false);
|
|
129
|
+
expect((0, type_guards_1.isModel)({ ...validModel, type: 'user' })).toBe(false);
|
|
130
|
+
});
|
|
131
|
+
it('should return false for invalid tier value', () => {
|
|
132
|
+
expect((0, type_guards_1.isModel)({ ...validModel, tier: 'invalid' })).toBe(false);
|
|
133
|
+
expect((0, type_guards_1.isModel)({ ...validModel, tier: 'super-fast' })).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
it('should return false for null and undefined', () => {
|
|
136
|
+
expect((0, type_guards_1.isModel)(null)).toBe(false);
|
|
137
|
+
expect((0, type_guards_1.isModel)(undefined)).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('isClaudeModel', () => {
|
|
141
|
+
it('should return true for valid ClaudeModel enum values', () => {
|
|
142
|
+
expect((0, type_guards_1.isClaudeModel)(chat_types_1.ClaudeModel.HAIKU_3_5)).toBe(true);
|
|
143
|
+
expect((0, type_guards_1.isClaudeModel)(chat_types_1.ClaudeModel.SONNET_3_5)).toBe(true);
|
|
144
|
+
expect((0, type_guards_1.isClaudeModel)(chat_types_1.ClaudeModel.SONNET_3_7)).toBe(true);
|
|
145
|
+
expect((0, type_guards_1.isClaudeModel)(chat_types_1.ClaudeModel.OPUS_3)).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
it('should return true for valid model ID strings', () => {
|
|
148
|
+
expect((0, type_guards_1.isClaudeModel)('claude-3-5-haiku-20241022')).toBe(true);
|
|
149
|
+
expect((0, type_guards_1.isClaudeModel)('claude-3-5-sonnet-20241022')).toBe(true);
|
|
150
|
+
expect((0, type_guards_1.isClaudeModel)('claude-3-5-sonnet-20250219')).toBe(true);
|
|
151
|
+
expect((0, type_guards_1.isClaudeModel)('claude-3-opus-20240229')).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
it('should return false for invalid model IDs', () => {
|
|
154
|
+
expect((0, type_guards_1.isClaudeModel)('claude-4-sonnet')).toBe(false);
|
|
155
|
+
expect((0, type_guards_1.isClaudeModel)('gpt-4')).toBe(false);
|
|
156
|
+
expect((0, type_guards_1.isClaudeModel)('invalid-model')).toBe(false);
|
|
157
|
+
expect((0, type_guards_1.isClaudeModel)('')).toBe(false);
|
|
158
|
+
});
|
|
159
|
+
it('should return false for non-string values', () => {
|
|
160
|
+
expect((0, type_guards_1.isClaudeModel)(null)).toBe(false);
|
|
161
|
+
expect((0, type_guards_1.isClaudeModel)(undefined)).toBe(false);
|
|
162
|
+
expect((0, type_guards_1.isClaudeModel)(123)).toBe(false);
|
|
163
|
+
expect((0, type_guards_1.isClaudeModel)({})).toBe(false);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
describe('isSendMessageRequest', () => {
|
|
167
|
+
const validRequest = {
|
|
168
|
+
message: 'Hello, Claude!',
|
|
169
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
170
|
+
};
|
|
171
|
+
it('should return true for valid SendMessageRequest', () => {
|
|
172
|
+
expect((0, type_guards_1.isSendMessageRequest)(validRequest)).toBe(true);
|
|
173
|
+
});
|
|
174
|
+
it('should return true with optional sessionId', () => {
|
|
175
|
+
const requestWithSession = {
|
|
176
|
+
...validRequest,
|
|
177
|
+
sessionId: 'session_123',
|
|
178
|
+
};
|
|
179
|
+
expect((0, type_guards_1.isSendMessageRequest)(requestWithSession)).toBe(true);
|
|
180
|
+
});
|
|
181
|
+
it('should return false for missing required fields', () => {
|
|
182
|
+
expect((0, type_guards_1.isSendMessageRequest)({ ...validRequest, message: undefined })).toBe(false);
|
|
183
|
+
expect((0, type_guards_1.isSendMessageRequest)({ ...validRequest, model: undefined })).toBe(false);
|
|
184
|
+
});
|
|
185
|
+
it('should return false for invalid field types', () => {
|
|
186
|
+
expect((0, type_guards_1.isSendMessageRequest)({ ...validRequest, message: 123 })).toBe(false);
|
|
187
|
+
expect((0, type_guards_1.isSendMessageRequest)({ ...validRequest, model: 123 })).toBe(false);
|
|
188
|
+
expect((0, type_guards_1.isSendMessageRequest)({ ...validRequest, sessionId: 123 })).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
it('should return false for null and undefined', () => {
|
|
191
|
+
expect((0, type_guards_1.isSendMessageRequest)(null)).toBe(false);
|
|
192
|
+
expect((0, type_guards_1.isSendMessageRequest)(undefined)).toBe(false);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
describe('isCreateSessionRequest', () => {
|
|
196
|
+
const validRequest = {
|
|
197
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
198
|
+
};
|
|
199
|
+
it('should return true for valid CreateSessionRequest', () => {
|
|
200
|
+
expect((0, type_guards_1.isCreateSessionRequest)(validRequest)).toBe(true);
|
|
201
|
+
});
|
|
202
|
+
it('should return true with optional title', () => {
|
|
203
|
+
const requestWithTitle = {
|
|
204
|
+
...validRequest,
|
|
205
|
+
title: 'My Session',
|
|
206
|
+
};
|
|
207
|
+
expect((0, type_guards_1.isCreateSessionRequest)(requestWithTitle)).toBe(true);
|
|
208
|
+
});
|
|
209
|
+
it('should return false for missing required fields', () => {
|
|
210
|
+
expect((0, type_guards_1.isCreateSessionRequest)({ ...validRequest, model: undefined })).toBe(false);
|
|
211
|
+
expect((0, type_guards_1.isCreateSessionRequest)({})).toBe(false);
|
|
212
|
+
});
|
|
213
|
+
it('should return false for invalid field types', () => {
|
|
214
|
+
expect((0, type_guards_1.isCreateSessionRequest)({ ...validRequest, model: 123 })).toBe(false);
|
|
215
|
+
expect((0, type_guards_1.isCreateSessionRequest)({ ...validRequest, title: 123 })).toBe(false);
|
|
216
|
+
});
|
|
217
|
+
it('should return false for null and undefined', () => {
|
|
218
|
+
expect((0, type_guards_1.isCreateSessionRequest)(null)).toBe(false);
|
|
219
|
+
expect((0, type_guards_1.isCreateSessionRequest)(undefined)).toBe(false);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guinetik/primitives-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Shared TypeScript primitives for Guinetik projects",
|
|
5
5
|
"author": "Guinetik",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "tsc",
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"test:watch": "jest --watch",
|
|
16
|
+
"test:cov": "jest --coverage",
|
|
17
|
+
"pre-commit": "npm run test && npm run build",
|
|
14
18
|
"prepublishOnly": "npm run build"
|
|
15
19
|
},
|
|
16
20
|
"keywords": [
|
|
@@ -20,6 +24,9 @@
|
|
|
20
24
|
"guinetik"
|
|
21
25
|
],
|
|
22
26
|
"devDependencies": {
|
|
27
|
+
"@types/jest": "^30.0.0",
|
|
28
|
+
"jest": "^30.2.0",
|
|
29
|
+
"ts-jest": "^29.4.5",
|
|
23
30
|
"typescript": "^5.9.3"
|
|
24
31
|
},
|
|
25
32
|
"repository": {
|