digital-products 2.0.1

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 (110) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/CHANGELOG.md +9 -0
  3. package/README.md +535 -0
  4. package/dist/api.d.ts +99 -0
  5. package/dist/api.d.ts.map +1 -0
  6. package/dist/api.js +129 -0
  7. package/dist/api.js.map +1 -0
  8. package/dist/app.d.ts +79 -0
  9. package/dist/app.d.ts.map +1 -0
  10. package/dist/app.js +107 -0
  11. package/dist/app.js.map +1 -0
  12. package/dist/content.d.ts +58 -0
  13. package/dist/content.d.ts.map +1 -0
  14. package/dist/content.js +78 -0
  15. package/dist/content.js.map +1 -0
  16. package/dist/data.d.ts +67 -0
  17. package/dist/data.d.ts.map +1 -0
  18. package/dist/data.js +107 -0
  19. package/dist/data.js.map +1 -0
  20. package/dist/dataset.d.ts +32 -0
  21. package/dist/dataset.d.ts.map +1 -0
  22. package/dist/dataset.js +50 -0
  23. package/dist/dataset.js.map +1 -0
  24. package/dist/entities/ai.d.ts +53 -0
  25. package/dist/entities/ai.d.ts.map +1 -0
  26. package/dist/entities/ai.js +859 -0
  27. package/dist/entities/ai.js.map +1 -0
  28. package/dist/entities/content.d.ts +52 -0
  29. package/dist/entities/content.d.ts.map +1 -0
  30. package/dist/entities/content.js +784 -0
  31. package/dist/entities/content.js.map +1 -0
  32. package/dist/entities/index.d.ts +112 -0
  33. package/dist/entities/index.d.ts.map +1 -0
  34. package/dist/entities/index.js +89 -0
  35. package/dist/entities/index.js.map +1 -0
  36. package/dist/entities/interfaces.d.ts +67 -0
  37. package/dist/entities/interfaces.d.ts.map +1 -0
  38. package/dist/entities/interfaces.js +930 -0
  39. package/dist/entities/interfaces.js.map +1 -0
  40. package/dist/entities/lifecycle.d.ts +51 -0
  41. package/dist/entities/lifecycle.d.ts.map +1 -0
  42. package/dist/entities/lifecycle.js +804 -0
  43. package/dist/entities/lifecycle.js.map +1 -0
  44. package/dist/entities/products.d.ts +53 -0
  45. package/dist/entities/products.d.ts.map +1 -0
  46. package/dist/entities/products.js +798 -0
  47. package/dist/entities/products.js.map +1 -0
  48. package/dist/entities/web.d.ts +44 -0
  49. package/dist/entities/web.d.ts.map +1 -0
  50. package/dist/entities/web.js +658 -0
  51. package/dist/entities/web.js.map +1 -0
  52. package/dist/index.d.ts +29 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +36 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/mcp.d.ts +101 -0
  57. package/dist/mcp.d.ts.map +1 -0
  58. package/dist/mcp.js +140 -0
  59. package/dist/mcp.js.map +1 -0
  60. package/dist/product.d.ts +37 -0
  61. package/dist/product.d.ts.map +1 -0
  62. package/dist/product.js +54 -0
  63. package/dist/product.js.map +1 -0
  64. package/dist/registry.d.ts +9 -0
  65. package/dist/registry.d.ts.map +1 -0
  66. package/dist/registry.js +32 -0
  67. package/dist/registry.js.map +1 -0
  68. package/dist/sdk.d.ts +99 -0
  69. package/dist/sdk.d.ts.map +1 -0
  70. package/dist/sdk.js +128 -0
  71. package/dist/sdk.js.map +1 -0
  72. package/dist/site.d.ts +85 -0
  73. package/dist/site.d.ts.map +1 -0
  74. package/dist/site.js +113 -0
  75. package/dist/site.js.map +1 -0
  76. package/dist/types.d.ts +528 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/dist/types.js +5 -0
  79. package/dist/types.js.map +1 -0
  80. package/example.ts +236 -0
  81. package/package.json +35 -0
  82. package/src/api.ts +140 -0
  83. package/src/app.ts +117 -0
  84. package/src/content.ts +82 -0
  85. package/src/data.ts +129 -0
  86. package/src/dataset.ts +53 -0
  87. package/src/entities/ai.ts +932 -0
  88. package/src/entities/content.ts +851 -0
  89. package/src/entities/index.ts +156 -0
  90. package/src/entities/interfaces.ts +1017 -0
  91. package/src/entities/lifecycle.ts +872 -0
  92. package/src/entities/products.ts +867 -0
  93. package/src/entities/web.ts +719 -0
  94. package/src/index.ts +55 -0
  95. package/src/mcp.ts +163 -0
  96. package/src/product.ts +59 -0
  97. package/src/registry.ts +41 -0
  98. package/src/sdk.ts +148 -0
  99. package/src/site.ts +127 -0
  100. package/src/types.ts +558 -0
  101. package/test/api.test.ts +247 -0
  102. package/test/app.test.ts +220 -0
  103. package/test/content.test.ts +171 -0
  104. package/test/data.test.ts +201 -0
  105. package/test/dataset.test.ts +181 -0
  106. package/test/mcp.test.ts +230 -0
  107. package/test/product.test.ts +200 -0
  108. package/test/sdk.test.ts +236 -0
  109. package/test/site.test.ts +245 -0
  110. package/tsconfig.json +9 -0
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Tests for Data functionality
3
+ *
4
+ * Covers data definitions and helper functions.
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach } from 'vitest'
8
+ import { Data, Index, Relationship, Validate, registry } from '../src/index.js'
9
+
10
+ describe('Data', () => {
11
+ beforeEach(() => {
12
+ registry.clear()
13
+ })
14
+
15
+ describe('Data creation', () => {
16
+ it('creates data with basic config', () => {
17
+ const data = Data({
18
+ id: 'users',
19
+ name: 'Users',
20
+ description: 'User data store',
21
+ version: '1.0.0',
22
+ schema: {
23
+ id: 'User ID',
24
+ name: 'User name',
25
+ email: 'User email',
26
+ },
27
+ })
28
+
29
+ expect(data.id).toBe('users')
30
+ expect(data.name).toBe('Users')
31
+ expect(data.type).toBe('data')
32
+ })
33
+
34
+ it('defaults provider to fs', () => {
35
+ const data = Data({
36
+ id: 'default-provider',
37
+ name: 'Default Provider',
38
+ description: 'Uses default provider',
39
+ version: '1.0.0',
40
+ schema: {},
41
+ })
42
+
43
+ expect(data.provider).toBe('fs')
44
+ })
45
+
46
+ it('supports custom providers', () => {
47
+ const data = Data({
48
+ id: 'postgres-data',
49
+ name: 'Postgres Data',
50
+ description: 'Postgres storage',
51
+ version: '1.0.0',
52
+ schema: {},
53
+ provider: 'postgres',
54
+ })
55
+
56
+ expect(data.provider).toBe('postgres')
57
+ })
58
+
59
+ it('creates data with indexes', () => {
60
+ const data = Data({
61
+ id: 'indexed-data',
62
+ name: 'Indexed Data',
63
+ description: 'Data with indexes',
64
+ version: '1.0.0',
65
+ schema: {
66
+ id: 'ID',
67
+ email: 'Email',
68
+ name: 'Name',
69
+ },
70
+ indexes: [
71
+ Index('email_idx', ['email'], { unique: true }),
72
+ Index('name_idx', ['name']),
73
+ ],
74
+ })
75
+
76
+ expect(data.indexes).toHaveLength(2)
77
+ expect(data.indexes?.[0]?.name).toBe('email_idx')
78
+ expect(data.indexes?.[0]?.unique).toBe(true)
79
+ })
80
+
81
+ it('creates data with relationships', () => {
82
+ const data = Data({
83
+ id: 'related-data',
84
+ name: 'Related Data',
85
+ description: 'Data with relationships',
86
+ version: '1.0.0',
87
+ schema: {},
88
+ relationships: [
89
+ Relationship('one-to-many', 'userId', 'posts', 'author'),
90
+ ],
91
+ })
92
+
93
+ expect(data.relationships).toHaveLength(1)
94
+ expect(data.relationships?.[0]?.type).toBe('one-to-many')
95
+ })
96
+
97
+ it('creates data with validation', () => {
98
+ const data = Data({
99
+ id: 'validated-data',
100
+ name: 'Validated Data',
101
+ description: 'Data with validation',
102
+ version: '1.0.0',
103
+ schema: {},
104
+ validation: [
105
+ Validate('email', 'email', 'Must be a valid email'),
106
+ Validate('name', 'required', 'Name is required'),
107
+ ],
108
+ })
109
+
110
+ expect(data.validation).toHaveLength(2)
111
+ expect(data.validation?.[0]?.field).toBe('email')
112
+ })
113
+
114
+ it('registers data automatically', () => {
115
+ Data({
116
+ id: 'auto-registered',
117
+ name: 'Auto Registered',
118
+ description: 'Automatically registered',
119
+ version: '1.0.0',
120
+ schema: {},
121
+ })
122
+
123
+ expect(registry.get('auto-registered')).toBeDefined()
124
+ })
125
+ })
126
+
127
+ describe('Index helper', () => {
128
+ it('creates a basic index', () => {
129
+ const index = Index('my_idx', ['field1', 'field2'])
130
+
131
+ expect(index.name).toBe('my_idx')
132
+ expect(index.fields).toEqual(['field1', 'field2'])
133
+ })
134
+
135
+ it('creates a unique index', () => {
136
+ const index = Index('unique_idx', ['email'], { unique: true })
137
+
138
+ expect(index.unique).toBe(true)
139
+ })
140
+
141
+ it('creates a vector index', () => {
142
+ const index = Index('vector_idx', ['embedding'], { type: 'vector' })
143
+
144
+ expect(index.type).toBe('vector')
145
+ })
146
+ })
147
+
148
+ describe('Relationship helper', () => {
149
+ it('creates a one-to-many relationship', () => {
150
+ const rel = Relationship('one-to-many', 'userId', 'posts', 'author')
151
+
152
+ expect(rel.type).toBe('one-to-many')
153
+ expect(rel.from).toBe('userId')
154
+ expect(rel.to).toBe('posts')
155
+ expect(rel.field).toBe('author')
156
+ })
157
+
158
+ it('creates a many-to-many relationship', () => {
159
+ const rel = Relationship('many-to-many', 'postId', 'tags', 'posts')
160
+
161
+ expect(rel.type).toBe('many-to-many')
162
+ })
163
+
164
+ it('creates a one-to-one relationship', () => {
165
+ const rel = Relationship('one-to-one', 'userId', 'profile', 'user')
166
+
167
+ expect(rel.type).toBe('one-to-one')
168
+ })
169
+ })
170
+
171
+ describe('Validate helper', () => {
172
+ it('creates a validation rule with message', () => {
173
+ const rule = Validate('email', 'email', 'Must be a valid email')
174
+
175
+ expect(rule.field).toBe('email')
176
+ expect(rule.rule).toBe('email')
177
+ expect(rule.message).toBe('Must be a valid email')
178
+ })
179
+
180
+ it('creates a validation rule with params', () => {
181
+ const rule = Validate('age', 'min', { value: 18 }, 'Must be 18 or older')
182
+
183
+ expect(rule.field).toBe('age')
184
+ expect(rule.rule).toBe('min')
185
+ expect(rule.params).toEqual({ value: 18 })
186
+ expect(rule.message).toBe('Must be 18 or older')
187
+ })
188
+
189
+ it('creates a required validation rule', () => {
190
+ const rule = Validate('name', 'required', 'Name is required')
191
+
192
+ expect(rule.rule).toBe('required')
193
+ })
194
+
195
+ it('creates a unique validation rule', () => {
196
+ const rule = Validate('username', 'unique', 'Username already taken')
197
+
198
+ expect(rule.rule).toBe('unique')
199
+ })
200
+ })
201
+ })
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Tests for Dataset functionality
3
+ *
4
+ * Covers dataset creation.
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach } from 'vitest'
8
+ import { Dataset, registry } from '../src/index.js'
9
+
10
+ describe('Dataset', () => {
11
+ beforeEach(() => {
12
+ registry.clear()
13
+ })
14
+
15
+ describe('Dataset creation', () => {
16
+ it('creates a dataset with basic config', () => {
17
+ const dataset = Dataset({
18
+ id: 'movies',
19
+ name: 'Movie Database',
20
+ description: 'Movie information dataset',
21
+ version: '2024.1',
22
+ })
23
+
24
+ expect(dataset.id).toBe('movies')
25
+ expect(dataset.name).toBe('Movie Database')
26
+ expect(dataset.type).toBe('dataset')
27
+ })
28
+
29
+ it('defaults format to json', () => {
30
+ const dataset = Dataset({
31
+ id: 'default-format',
32
+ name: 'Default Format',
33
+ description: 'Uses default format',
34
+ version: '1.0.0',
35
+ })
36
+
37
+ expect(dataset.format).toBe('json')
38
+ })
39
+
40
+ it('supports parquet format', () => {
41
+ const dataset = Dataset({
42
+ id: 'parquet-dataset',
43
+ name: 'Parquet Dataset',
44
+ description: 'Parquet format',
45
+ version: '1.0.0',
46
+ format: 'parquet',
47
+ })
48
+
49
+ expect(dataset.format).toBe('parquet')
50
+ })
51
+
52
+ it('supports csv format', () => {
53
+ const dataset = Dataset({
54
+ id: 'csv-dataset',
55
+ name: 'CSV Dataset',
56
+ description: 'CSV format',
57
+ version: '1.0.0',
58
+ format: 'csv',
59
+ })
60
+
61
+ expect(dataset.format).toBe('csv')
62
+ })
63
+
64
+ it('creates a dataset with schema', () => {
65
+ const dataset = Dataset({
66
+ id: 'schema-dataset',
67
+ name: 'Schema Dataset',
68
+ description: 'Dataset with schema',
69
+ version: '1.0.0',
70
+ schema: {
71
+ id: 'Movie ID',
72
+ title: 'Movie title',
73
+ year: 'Release year (number)',
74
+ rating: 'Average rating (number)',
75
+ },
76
+ })
77
+
78
+ expect(dataset.schema?.id).toBe('Movie ID')
79
+ expect(dataset.schema?.title).toBe('Movie title')
80
+ })
81
+
82
+ it('creates a dataset with source', () => {
83
+ const dataset = Dataset({
84
+ id: 'source-dataset',
85
+ name: 'Source Dataset',
86
+ description: 'Dataset with source',
87
+ version: '1.0.0',
88
+ source: 's3://datasets/movies.parquet',
89
+ })
90
+
91
+ expect(dataset.source).toBe('s3://datasets/movies.parquet')
92
+ })
93
+
94
+ it('creates a dataset with size', () => {
95
+ const dataset = Dataset({
96
+ id: 'sized-dataset',
97
+ name: 'Sized Dataset',
98
+ description: 'Dataset with size',
99
+ version: '1.0.0',
100
+ size: 1000000,
101
+ })
102
+
103
+ expect(dataset.size).toBe(1000000)
104
+ })
105
+
106
+ it('creates a dataset with license', () => {
107
+ const dataset = Dataset({
108
+ id: 'licensed-dataset',
109
+ name: 'Licensed Dataset',
110
+ description: 'Dataset with license',
111
+ version: '1.0.0',
112
+ license: 'CC-BY-4.0',
113
+ })
114
+
115
+ expect(dataset.license).toBe('CC-BY-4.0')
116
+ })
117
+
118
+ it('defaults updateFrequency to static', () => {
119
+ const dataset = Dataset({
120
+ id: 'static-dataset',
121
+ name: 'Static Dataset',
122
+ description: 'Static dataset',
123
+ version: '1.0.0',
124
+ })
125
+
126
+ expect(dataset.updateFrequency).toBe('static')
127
+ })
128
+
129
+ it('supports daily updateFrequency', () => {
130
+ const dataset = Dataset({
131
+ id: 'daily-dataset',
132
+ name: 'Daily Dataset',
133
+ description: 'Updated daily',
134
+ version: '1.0.0',
135
+ updateFrequency: 'daily',
136
+ })
137
+
138
+ expect(dataset.updateFrequency).toBe('daily')
139
+ })
140
+
141
+ it('registers dataset automatically', () => {
142
+ Dataset({
143
+ id: 'auto-registered',
144
+ name: 'Auto Registered',
145
+ description: 'Automatically registered',
146
+ version: '1.0.0',
147
+ })
148
+
149
+ expect(registry.get('auto-registered')).toBeDefined()
150
+ })
151
+
152
+ it('creates a complete dataset definition', () => {
153
+ const dataset = Dataset({
154
+ id: 'complete-dataset',
155
+ name: 'Complete Dataset',
156
+ description: 'Comprehensive movie information dataset',
157
+ version: '2024.1',
158
+ format: 'parquet',
159
+ schema: {
160
+ id: 'Movie ID',
161
+ title: 'Movie title',
162
+ year: 'Release year (number)',
163
+ genres: ['Array of genre names'],
164
+ rating: 'Average rating (number)',
165
+ votes: 'Number of votes (number)',
166
+ },
167
+ source: 's3://datasets/movies.parquet',
168
+ size: 1000000,
169
+ license: 'CC-BY-4.0',
170
+ updateFrequency: 'daily',
171
+ tags: ['movies', 'entertainment'],
172
+ metadata: { curator: 'Data Team' },
173
+ })
174
+
175
+ expect(dataset.id).toBe('complete-dataset')
176
+ expect(dataset.format).toBe('parquet')
177
+ expect(dataset.license).toBe('CC-BY-4.0')
178
+ expect(dataset.tags).toContain('movies')
179
+ })
180
+ })
181
+ })
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Tests for MCP functionality
3
+ *
4
+ * Covers MCP server creation and helper functions.
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach } from 'vitest'
8
+ import { MCP, Tool, Resource, Prompt, MCPConfig, registry } from '../src/index.js'
9
+
10
+ describe('MCP', () => {
11
+ beforeEach(() => {
12
+ registry.clear()
13
+ })
14
+
15
+ describe('MCP creation', () => {
16
+ it('creates an MCP with basic config', () => {
17
+ const mcp = MCP({
18
+ id: 'my-mcp',
19
+ name: 'My MCP Server',
20
+ description: 'Custom MCP server',
21
+ version: '1.0.0',
22
+ })
23
+
24
+ expect(mcp.id).toBe('my-mcp')
25
+ expect(mcp.name).toBe('My MCP Server')
26
+ expect(mcp.type).toBe('mcp')
27
+ })
28
+
29
+ it('creates an MCP with transport', () => {
30
+ const mcp = MCP({
31
+ id: 'stdio-mcp',
32
+ name: 'Stdio MCP',
33
+ description: 'MCP with stdio',
34
+ version: '1.0.0',
35
+ transport: 'stdio',
36
+ })
37
+
38
+ expect(mcp.transport).toBe('stdio')
39
+ })
40
+
41
+ it('creates an MCP with tools', () => {
42
+ const mcp = MCP({
43
+ id: 'tool-mcp',
44
+ name: 'Tool MCP',
45
+ description: 'MCP with tools',
46
+ version: '1.0.0',
47
+ tools: [
48
+ Tool('searchFiles', 'Search for files', {
49
+ query: 'Search query',
50
+ path: 'Directory to search',
51
+ }),
52
+ Tool('readFile', 'Read file contents', {
53
+ path: 'File path to read',
54
+ }),
55
+ ],
56
+ })
57
+
58
+ expect(mcp.tools).toHaveLength(2)
59
+ expect(mcp.tools?.[0]?.name).toBe('searchFiles')
60
+ })
61
+
62
+ it('creates an MCP with resources', () => {
63
+ const mcp = MCP({
64
+ id: 'resource-mcp',
65
+ name: 'Resource MCP',
66
+ description: 'MCP with resources',
67
+ version: '1.0.0',
68
+ resources: [
69
+ Resource('file://', 'Project Files', 'Access to project files'),
70
+ ],
71
+ })
72
+
73
+ expect(mcp.resources).toHaveLength(1)
74
+ expect(mcp.resources?.[0]?.uri).toBe('file://')
75
+ })
76
+
77
+ it('creates an MCP with prompts', () => {
78
+ const mcp = MCP({
79
+ id: 'prompt-mcp',
80
+ name: 'Prompt MCP',
81
+ description: 'MCP with prompts',
82
+ version: '1.0.0',
83
+ prompts: [
84
+ Prompt('codeReview', 'Review code', 'Review the following code:\n\n{{code}}'),
85
+ ],
86
+ })
87
+
88
+ expect(mcp.prompts).toHaveLength(1)
89
+ expect(mcp.prompts?.[0]?.name).toBe('codeReview')
90
+ })
91
+
92
+ it('creates an MCP with config', () => {
93
+ const mcp = MCP({
94
+ id: 'config-mcp',
95
+ name: 'Config MCP',
96
+ description: 'MCP with config',
97
+ version: '1.0.0',
98
+ config: {
99
+ port: 3000,
100
+ host: 'localhost',
101
+ },
102
+ })
103
+
104
+ expect(mcp.config?.port).toBe(3000)
105
+ })
106
+
107
+ it('registers MCP automatically', () => {
108
+ MCP({
109
+ id: 'auto-registered',
110
+ name: 'Auto Registered',
111
+ description: 'Automatically registered',
112
+ version: '1.0.0',
113
+ })
114
+
115
+ expect(registry.get('auto-registered')).toBeDefined()
116
+ })
117
+ })
118
+
119
+ describe('Tool helper', () => {
120
+ it('creates a basic tool', () => {
121
+ const tool = Tool('myTool', 'My tool description', {
122
+ param1: 'First parameter',
123
+ param2: 'Second parameter',
124
+ })
125
+
126
+ expect(tool.name).toBe('myTool')
127
+ expect(tool.description).toBe('My tool description')
128
+ expect(tool.inputSchema).toHaveProperty('param1')
129
+ })
130
+
131
+ it('creates a tool with handler', () => {
132
+ const handler = async (input: unknown) => ({ result: 'done' })
133
+ const tool = Tool('handlerTool', 'Tool with handler', {
134
+ input: 'Input value',
135
+ }, handler)
136
+
137
+ expect(tool.handler).toBe(handler)
138
+ })
139
+
140
+ it('creates a tool with complex schema', () => {
141
+ const tool = Tool('complexTool', 'Tool with complex schema', {
142
+ query: 'Search query (required)',
143
+ options: {
144
+ limit: 'Maximum results (number)',
145
+ offset: 'Result offset (number)',
146
+ },
147
+ })
148
+
149
+ expect(tool.inputSchema?.query).toBe('Search query (required)')
150
+ expect(tool.inputSchema?.options).toHaveProperty('limit')
151
+ })
152
+ })
153
+
154
+ describe('Resource helper', () => {
155
+ it('creates a basic resource', () => {
156
+ const resource = Resource(
157
+ 'file://project',
158
+ 'Project Files',
159
+ 'Access to all project files'
160
+ )
161
+
162
+ expect(resource.uri).toBe('file://project')
163
+ expect(resource.name).toBe('Project Files')
164
+ expect(resource.description).toBe('Access to all project files')
165
+ })
166
+
167
+ it('creates a resource with mimeType', () => {
168
+ const resource = Resource(
169
+ 'file://config.json',
170
+ 'Config',
171
+ 'Configuration file',
172
+ 'application/json'
173
+ )
174
+
175
+ expect(resource.mimeType).toBe('application/json')
176
+ })
177
+ })
178
+
179
+ describe('Prompt helper', () => {
180
+ it('creates a basic prompt', () => {
181
+ const prompt = Prompt(
182
+ 'summarize',
183
+ 'Summarize text',
184
+ 'Summarize the following:\n\n{{text}}'
185
+ )
186
+
187
+ expect(prompt.name).toBe('summarize')
188
+ expect(prompt.description).toBe('Summarize text')
189
+ expect(prompt.template).toContain('{{text}}')
190
+ })
191
+
192
+ it('creates a prompt with arguments', () => {
193
+ const prompt = Prompt(
194
+ 'translate',
195
+ 'Translate text',
196
+ 'Translate {{text}} to {{language}}',
197
+ {
198
+ text: 'Text to translate',
199
+ language: 'Target language',
200
+ }
201
+ )
202
+
203
+ expect(prompt.arguments).toHaveProperty('text')
204
+ expect(prompt.arguments).toHaveProperty('language')
205
+ })
206
+ })
207
+
208
+ describe('MCPConfig helper', () => {
209
+ it('creates MCP config', () => {
210
+ const config = MCPConfig({
211
+ port: 3000,
212
+ host: 'localhost',
213
+ })
214
+
215
+ expect(config.port).toBe(3000)
216
+ expect(config.host).toBe('localhost')
217
+ })
218
+
219
+ it('creates MCP config with auth', () => {
220
+ const config = MCPConfig({
221
+ auth: {
222
+ type: 'bearer',
223
+ token: 'secret-token',
224
+ },
225
+ })
226
+
227
+ expect(config.auth?.type).toBe('bearer')
228
+ })
229
+ })
230
+ })