@manifesto-ai/core 0.2.0 → 0.3.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 CHANGED
@@ -20,14 +20,19 @@ import {
20
20
  createRuntime,
21
21
  defineDerived,
22
22
  defineAction,
23
+ defineSource,
23
24
  sequence,
24
25
  setState,
25
- apiCall,
26
+ setValue,
26
27
  z
27
28
  } from '@manifesto-ai/core';
28
29
 
29
30
  // Define a domain
30
- const todosDomain = defineDomain('todos', {
31
+ const todosDomain = defineDomain({
32
+ id: 'todos',
33
+ name: 'Todos',
34
+ description: 'Todo list management domain',
35
+
31
36
  dataSchema: z.object({
32
37
  items: z.array(z.object({
33
38
  id: z.string(),
@@ -37,44 +42,61 @@ const todosDomain = defineDomain('todos', {
37
42
  }),
38
43
 
39
44
  stateSchema: z.object({
40
- filter: z.enum(['all', 'active', 'completed']).default('all'),
41
- isLoading: z.boolean().default(false)
45
+ filter: z.enum(['all', 'active', 'completed']),
46
+ isLoading: z.boolean()
42
47
  }),
43
48
 
44
- derived: {
45
- 'derived.activeCount': defineDerived(
46
- { $size: { $filter: ['data.items', { $eq: ['$item.completed', false] }] } },
47
- z.number()
48
- ),
49
- 'derived.filteredItems': defineDerived(
50
- {
51
- $if: [
52
- { $eq: [{ $get: 'state.filter' }, 'all'] },
53
- { $get: 'data.items' },
54
- { $filter: ['data.items', {
55
- $eq: ['$item.completed', { $eq: [{ $get: 'state.filter' }, 'completed'] }]
56
- }] }
57
- ]
58
- },
59
- z.array(z.object({ id: z.string(), title: z.string(), completed: z.boolean() }))
60
- )
49
+ initialState: {
50
+ filter: 'all',
51
+ isLoading: false
61
52
  },
62
53
 
63
- actions: {
64
- addTodo: defineAction({
65
- precondition: { $gt: [{ $size: { $get: 'input.title' } }, 0] },
66
- effect: setValue('data.items', {
67
- $concat: [
68
- { $get: 'data.items' },
69
- [{ id: { $get: 'input.id' }, title: { $get: 'input.title' }, completed: false }]
70
- ]
54
+ paths: {
55
+ sources: {
56
+ // Auto-prefixed: 'items' becomes 'data.items'
57
+ items: defineSource({
58
+ schema: z.array(z.object({
59
+ id: z.string(),
60
+ title: z.string(),
61
+ completed: z.boolean()
62
+ })),
63
+ defaultValue: [],
64
+ semantic: { type: 'list', description: 'Todo items' }
65
+ })
66
+ },
67
+ derived: {
68
+ // Auto-prefixed: 'activeCount' becomes 'derived.activeCount'
69
+ activeCount: defineDerived({
70
+ deps: ['data.items'],
71
+ expr: ['length', ['filter', ['get', 'data.items'], ['!', '$.completed']]],
72
+ semantic: { type: 'count', description: 'Number of active todos' }
71
73
  })
74
+ }
75
+ },
76
+
77
+ actions: {
78
+ // Set filter action
79
+ setFilter: defineAction({
80
+ deps: ['state.filter'],
81
+ input: z.object({ filter: z.enum(['all', 'active', 'completed']) }),
82
+ effect: setState('state.filter', ['get', 'input.filter'], 'Set filter'),
83
+ semantic: { type: 'action', verb: 'set', description: 'Set todo filter' }
84
+ }),
85
+
86
+ // Clear completed todos
87
+ clearCompleted: defineAction({
88
+ deps: ['data.items'],
89
+ effect: setValue('data.items',
90
+ ['filter', ['get', 'data.items'], ['!', '$.completed']],
91
+ 'Clear completed todos'
92
+ ),
93
+ semantic: { type: 'action', verb: 'clear', description: 'Remove completed todos' }
72
94
  })
73
95
  }
74
96
  });
75
97
 
76
98
  // Create runtime
77
- const runtime = createRuntime(todosDomain);
99
+ const runtime = createRuntime({ domain: todosDomain });
78
100
 
79
101
  // Use the runtime
80
102
  runtime.set('data.items', [
@@ -88,91 +110,130 @@ console.log(runtime.get('derived.activeCount')); // 1
88
110
 
89
111
  ### Domain Definition
90
112
 
91
- #### `defineDomain(name, config)`
113
+ > **Note:** Keys in `sources`, `derived`, and `async` are auto-prefixed (`data.`, `derived.`, `async.` respectively). Keys with existing prefixes are preserved for backward compatibility. Both `activeCount` and `'derived.activeCount'` are valid.
114
+
115
+ #### `defineDomain(options)`
92
116
 
93
117
  Creates a domain definition.
94
118
 
95
119
  ```typescript
96
- const domain = defineDomain('myDomain', {
120
+ const domain = defineDomain({
121
+ id: 'myDomain',
122
+ name: 'My Domain',
123
+ description: 'Domain description for AI understanding',
97
124
  dataSchema: z.object({ ... }), // Required: Source data schema
98
- stateSchema: z.object({ ... }), // Optional: UI state schema
99
- derived: { ... }, // Optional: Computed values
100
- async: { ... }, // Optional: Async data sources
101
- actions: { ... } // Optional: Domain actions
125
+ stateSchema: z.object({ ... }), // Required: UI state schema
126
+ initialState: { ... }, // Required: Initial state values
127
+ paths: {
128
+ sources: { ... }, // Optional: Source definitions
129
+ derived: { ... }, // Optional: Computed values
130
+ async: { ... }, // Optional: Async data sources
131
+ },
132
+ actions: { ... }, // Optional: Domain actions
133
+ meta: { ... } // Optional: Domain metadata
102
134
  });
103
135
  ```
104
136
 
105
- #### `defineSource(schema, meta?)`
137
+ #### `defineSource(options)`
106
138
 
107
- Defines a source field with optional metadata.
139
+ Defines a source field with semantic metadata.
108
140
 
109
141
  ```typescript
110
142
  const sources = {
111
- 'data.user': defineSource(
112
- z.object({ name: z.string(), email: z.string() }),
113
- { description: 'Current user information' }
114
- )
143
+ // Auto-prefixed: 'user' becomes 'data.user'
144
+ user: defineSource({
145
+ schema: z.object({ name: z.string(), email: z.string() }),
146
+ defaultValue: { name: '', email: '' },
147
+ semantic: {
148
+ type: 'entity',
149
+ description: 'Current user information'
150
+ }
151
+ })
115
152
  };
116
153
  ```
117
154
 
118
- #### `defineDerived(expression, schema, meta?)`
155
+ #### `defineDerived(options)`
119
156
 
120
- Defines a computed value.
157
+ Defines a computed value with explicit dependencies.
121
158
 
122
159
  ```typescript
123
160
  const derived = {
124
- 'derived.fullName': defineDerived(
125
- { $concat: [{ $get: 'data.firstName' }, ' ', { $get: 'data.lastName' }] },
126
- z.string(),
127
- { description: 'User full name' }
128
- )
161
+ // Auto-prefixed: 'fullName' becomes 'derived.fullName'
162
+ fullName: defineDerived({
163
+ deps: ['data.firstName', 'data.lastName'],
164
+ expr: ['concat', ['get', 'data.firstName'], ' ', ['get', 'data.lastName']],
165
+ semantic: {
166
+ type: 'computed',
167
+ description: 'User full name'
168
+ }
169
+ })
129
170
  };
130
171
  ```
131
172
 
132
- #### `defineAsync(config, schema, meta?)`
173
+ #### `defineAsync(options)`
133
174
 
134
- Defines an async data source.
175
+ Defines an async data source with result paths.
135
176
 
136
177
  ```typescript
137
178
  const async = {
138
- 'async.userData': defineAsync(
139
- {
140
- fetch: { method: 'GET', url: '/api/user' },
141
- dependencies: ['data.userId']
179
+ // Auto-prefixed: 'userData' becomes 'async.userData'
180
+ userData: defineAsync({
181
+ deps: ['data.userId'],
182
+ condition: ['!=', ['get', 'data.userId'], null],
183
+ debounce: 300,
184
+ effect: {
185
+ _tag: 'ApiCall',
186
+ method: 'GET',
187
+ endpoint: '/api/user',
188
+ description: 'Fetch user data'
142
189
  },
143
- z.object({ name: z.string() })
144
- )
190
+ resultPath: 'state.userData',
191
+ loadingPath: 'state.userLoading',
192
+ errorPath: 'state.userError',
193
+ semantic: {
194
+ type: 'async',
195
+ description: 'User data from API'
196
+ }
197
+ })
145
198
  };
146
199
  ```
147
200
 
148
- #### `defineAction(config)`
201
+ #### `defineAction(options)`
149
202
 
150
203
  Defines a domain action with preconditions and effects.
151
204
 
152
205
  ```typescript
153
206
  const actions = {
154
207
  submit: defineAction({
155
- precondition: { $and: [
156
- { $gt: [{ $get: 'derived.total' }, 0] },
157
- { $not: { $get: 'state.isSubmitting' } }
158
- ]},
208
+ deps: ['derived.total', 'state.isSubmitting'],
209
+ preconditions: [
210
+ { path: 'derived.hasItems', expect: 'true', reason: 'Cart must have items' },
211
+ { path: 'state.isSubmitting', expect: 'false', reason: 'Already submitting' }
212
+ ],
159
213
  effect: sequence([
160
214
  setState('state.isSubmitting', true),
161
215
  apiCall({ method: 'POST', url: '/api/submit' }),
162
216
  setState('state.isSubmitting', false)
163
- ])
217
+ ]),
218
+ semantic: {
219
+ type: 'action',
220
+ verb: 'submit',
221
+ description: 'Submit the order',
222
+ risk: 'medium'
223
+ }
164
224
  })
165
225
  };
166
226
  ```
167
227
 
168
228
  ### Runtime
169
229
 
170
- #### `createRuntime(domain, options?)`
230
+ #### `createRuntime(options)`
171
231
 
172
232
  Creates a runtime instance for a domain.
173
233
 
174
234
  ```typescript
175
- const runtime = createRuntime(domain, {
235
+ const runtime = createRuntime({
236
+ domain: myDomain,
176
237
  initialData: { count: 0 },
177
238
  initialState: { isLoading: false }
178
239
  });
@@ -215,77 +276,148 @@ const explanation = runtime.explain('derived.total');
215
276
 
216
277
  ### Expression DSL
217
278
 
218
- Manifesto uses a JSON-based DSL for declarative expressions.
279
+ Manifesto uses a JSON-based DSL for declarative expressions. All expressions use **array format**: `['operator', ...args]`.
280
+
281
+ #### Path Reference
282
+
283
+ ```typescript
284
+ ['get', 'data.user.name'] // Get value at path
285
+ ['get', 'state.isLoading'] // Get state value
286
+ ['get', 'derived.total'] // Get derived value
287
+
288
+ // In predicates (filter, map, etc.)
289
+ '$.price' // Current item's price field
290
+ '$.completed' // Current item's completed field
291
+ '$' // Current item itself
292
+ ```
219
293
 
220
294
  #### Comparison Operators
221
295
 
222
296
  ```typescript
223
- { $eq: [a, b] } // a === b
224
- { $ne: [a, b] } // a !== b
225
- { $gt: [a, b] } // a > b
226
- { $gte: [a, b] } // a >= b
227
- { $lt: [a, b] } // a < b
228
- { $lte: [a, b] } // a <= b
297
+ ['==', a, b] // a === b
298
+ ['!=', a, b] // a !== b
299
+ ['>', a, b] // a > b
300
+ ['>=', a, b] // a >= b
301
+ ['<', a, b] // a < b
302
+ ['<=', a, b] // a <= b
229
303
  ```
230
304
 
231
305
  #### Logical Operators
232
306
 
233
307
  ```typescript
234
- { $and: [expr1, expr2, ...] } // All true
235
- { $or: [expr1, expr2, ...] } // Any true
236
- { $not: expr } // Negation
308
+ ['all', expr1, expr2, ...] // All expressions must be true (AND)
309
+ ['any', expr1, expr2, ...] // Any expression is true (OR)
310
+ ['!', expr] // Negation (NOT)
237
311
  ```
238
312
 
239
313
  #### Arithmetic Operators
240
314
 
241
315
  ```typescript
242
- { $add: [a, b] } // a + b
243
- { $subtract: [a, b] } // a - b
244
- { $multiply: [a, b] } // a * b
245
- { $divide: [a, b] } // a / b
246
- { $modulo: [a, b] } // a % b
316
+ ['+', a, b] // a + b
317
+ ['-', a, b] // a - b
318
+ ['*', a, b] // a * b
247
319
  ```
248
320
 
249
321
  #### String Functions
250
322
 
251
323
  ```typescript
252
- { $concat: [str1, str2, ...] } // Concatenate strings
253
- { $upper: str } // Uppercase
254
- { $lower: str } // Lowercase
255
- { $trim: str } // Trim whitespace
256
- { $split: [str, delimiter] } // Split string
257
- { $includes: [str, search] } // Contains substring
324
+ ['concat', str1, str2, ...] // Concatenate strings
325
+ ['join', array, delimiter] // Join array elements
326
+ ['includes', str, search] // Contains substring
327
+ ['slice', str, start, end] // Substring
258
328
  ```
259
329
 
260
330
  #### Array Functions
261
331
 
262
332
  ```typescript
263
- { $size: array } // Array length
264
- { $first: array } // First element
265
- { $last: array } // Last element
266
- { $filter: [array, predicate] } // Filter elements
267
- { $map: [array, transform] } // Transform elements
268
- { $find: [array, predicate] } // Find first match
269
- { $some: [array, predicate] } // Any match
270
- { $every: [array, predicate] } // All match
271
- { $sum: array } // Sum numbers
272
- { $reduce: [array, reducer, initial] } // Reduce array
333
+ ['length', array] // Array length
334
+ ['at', array, index] // Element at index (0 = first, -1 = last)
335
+ ['filter', array, predicate] // Filter elements
336
+ ['map', array, transform] // Transform elements
337
+ ['some', array, predicate] // Any element matches
338
+ ['every', array, predicate] // All elements match
339
+ ['concat', array1, array2] // Concatenate arrays
340
+ ['includes', array, element] // Array contains element
341
+ ['sort', array, key] // Sort by key
342
+ ['slice', array, start, end] // Slice array
343
+ ['indexOf', array, element] // Find index of element
273
344
  ```
274
345
 
346
+ > **Note:** There is no `find` operator. Use `['at', ['filter', array, predicate], 0]` instead.
347
+
275
348
  #### Conditional
276
349
 
277
350
  ```typescript
278
- { $if: [condition, thenValue, elseValue] }
351
+ // Case expression (if-else chain) - each condition-value pair is a tuple
352
+ ['case',
353
+ [condition1, value1],
354
+ [condition2, value2],
355
+ defaultValue
356
+ ]
357
+
358
+ // Example: return 'large', 'medium', or 'small' based on total
359
+ ['case',
360
+ [['>', ['get', 'derived.total'], 100], 'large'],
361
+ [['>', ['get', 'derived.total'], 50], 'medium'],
362
+ 'small'
363
+ ]
364
+
365
+ // Match expression (pattern matching)
366
+ ['match', value,
367
+ [pattern1, result1],
368
+ [pattern2, result2],
369
+ defaultResult
370
+ ]
371
+
372
+ // Coalesce (first non-null value)
373
+ ['coalesce', value1, value2, value3]
279
374
  ```
280
375
 
281
- #### Path Reference
376
+ #### Object Operations
377
+
378
+ ```typescript
379
+ ['pick', object, ['key1', 'key2']] // Pick specific keys
380
+ ['omit', object, ['key1', 'key2']] // Omit specific keys
381
+ ```
382
+
383
+ #### Examples
282
384
 
283
385
  ```typescript
284
- { $get: 'data.user.name' } // Get value at path
285
- '$item.price' // Current item in iteration
286
- '$index' // Current index in iteration
386
+ // Filter active todos
387
+ ['filter', ['get', 'data.items'], ['!', '$.completed']]
388
+
389
+ // Count completed items
390
+ ['length', ['filter', ['get', 'data.items'], '$.completed']]
391
+
392
+ // Find first item by id (no find operator, use filter + at)
393
+ ['at', ['filter', ['get', 'data.items'], ['==', '$.id', ['get', 'input.id']]], 0]
394
+
395
+ // Concatenate first and last name
396
+ ['concat', ['get', 'data.firstName'], ' ', ['get', 'data.lastName']]
397
+
398
+ // Conditional value (each condition-value pair is a tuple)
399
+ ['case',
400
+ [['>', ['get', 'derived.total'], 100], 'large'],
401
+ [['>', ['get', 'derived.total'], 50], 'medium'],
402
+ 'small'
403
+ ]
287
404
  ```
288
405
 
406
+ #### Known Limitations
407
+
408
+ 1. **No object literal construction**: You cannot create new objects with dynamic values directly in expressions.
409
+ ```typescript
410
+ // ❌ This does NOT work
411
+ ['concat', ['get', 'data.items'], [{ id: ['get', 'input.id'], name: 'New' }]]
412
+
413
+ // ✅ Use pick/omit for existing objects, or handle in effect handlers
414
+ ['pick', '$', ['id', 'name']]
415
+ ```
416
+
417
+ 2. **No empty object literal**: `{}` is not a valid expression. Use `['coalesce']` or handle in application code.
418
+
419
+ 3. **No `find` operator**: Use `['at', ['filter', array, predicate], 0]` instead.
420
+
289
421
  ### Effect System
290
422
 
291
423
  Effects describe side effects as data.
@@ -295,7 +427,7 @@ Effects describe side effects as data.
295
427
  ```typescript
296
428
  // Set a value
297
429
  setValue('data.count', 10)
298
- setValue('data.count', { $add: [{ $get: 'data.count' }, 1] })
430
+ setValue('data.count', ['+', ['get', 'data.count'], 1])
299
431
 
300
432
  // Set state
301
433
  setState('state.isLoading', true)
@@ -304,7 +436,7 @@ setState('state.isLoading', true)
304
436
  apiCall({
305
437
  method: 'POST',
306
438
  url: '/api/orders',
307
- body: { $get: 'data.order' },
439
+ body: ['get', 'data.order'],
308
440
  headers: { 'Content-Type': 'application/json' }
309
441
  })
310
442
 
@@ -336,7 +468,7 @@ parallel([
336
468
 
337
469
  // Conditional execution
338
470
  conditional(
339
- { $get: 'state.isPremium' },
471
+ ['get', 'state.isPremium'],
340
472
  apiCall({ method: 'GET', url: '/api/premium' }),
341
473
  apiCall({ method: 'GET', url: '/api/basic' })
342
474
  )
@@ -344,7 +476,7 @@ conditional(
344
476
  // Error handling
345
477
  catchEffect(
346
478
  apiCall({ method: 'POST', url: '/api/submit' }),
347
- setState('state.error', { $get: 'error.message' })
479
+ setState('state.error', ['get', 'error.message'])
348
480
  )
349
481
  ```
350
482
 
@@ -1 +1 @@
1
- {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/domain/define.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/domain/define.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,17 @@
1
+ /**
2
+ * Adds namespace prefix to keys if not already present.
3
+ * Supports nested paths (e.g., 'user.name' → 'data.user.name').
4
+ */
5
+ function prefixKeys(record, prefix) {
6
+ if (!record)
7
+ return {};
8
+ const result = {};
9
+ for (const [key, value] of Object.entries(record)) {
10
+ const prefixedKey = key.startsWith(`${prefix}.`) ? key : `${prefix}.${key}`;
11
+ result[prefixedKey] = value;
12
+ }
13
+ return result;
14
+ }
1
15
  /**
2
16
  * 도메인 정의 헬퍼 함수
3
17
  */
@@ -10,9 +24,9 @@ export function defineDomain(options) {
10
24
  stateSchema: options.stateSchema,
11
25
  initialState: options.initialState,
12
26
  paths: {
13
- sources: options.paths?.sources ?? {},
14
- derived: options.paths?.derived ?? {},
15
- async: options.paths?.async ?? {},
27
+ sources: prefixKeys(options.paths?.sources, 'data'),
28
+ derived: prefixKeys(options.paths?.derived, 'derived'),
29
+ async: prefixKeys(options.paths?.async, 'async'),
16
30
  },
17
31
  actions: options.actions ?? {},
18
32
  meta: options.meta,
@@ -1 +1 @@
1
- {"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/domain/define.ts"],"names":[],"mappings":"AAiCA;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,OAA2C;IAE3C,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,KAAK,EAAE;YACL,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE;YACrC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE;YACrC,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;SAClC;QACD,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;QAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,CAAC;AACJ,CAAC;AAYD,MAAM,UAAU,YAAY,CAAC,OAA4B;IACvD,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI;YACd,GAAG,OAAO,CAAC,QAAQ;SACpB;KACF,CAAC;AACJ,CAAC;AAWD,MAAM,UAAU,aAAa,CAAC,OAA6B;IACzD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,KAAK;YACf,GAAG,OAAO,CAAC,QAAQ;SACpB;KACF,CAAC;AACJ,CAAC;AAgBD,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,KAAK;YACf,GAAG,OAAO,CAAC,QAAQ;SACpB;KACF,CAAC;AACJ,CAAC;AAaD,MAAM,UAAU,YAAY,CAAC,OAA4B;IACvD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,KAAK;YACjB,GAAG,OAAO,CAAC,QAAQ;SACpB;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAI3B;IACC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CACvB,IAAkB,EAClB,OAAwD;IAExD,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,MAAM;QACjC,MAAM,EAAE,OAAO,EAAE,MAAM;KACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/domain/define.ts"],"names":[],"mappings":"AAiCA;;;GAGG;AACH,SAAS,UAAU,CACjB,MAAqC,EACrC,MAAc;IAEd,IAAI,CAAC,MAAM;QAAE,OAAO,EAAuB,CAAC;IAE5C,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,MAAM,WAAW,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC;QAC5E,MAAM,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;IAC9B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,OAA2C;IAE3C,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,KAAK,EAAE;YACL,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;YACnD,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC;YACtD,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC;SACjD;QACD,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;QAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,CAAC;AACJ,CAAC;AAYD,MAAM,UAAU,YAAY,CAAC,OAA4B;IACvD,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI;YACd,GAAG,OAAO,CAAC,QAAQ;SACpB;KACF,CAAC;AACJ,CAAC;AAWD,MAAM,UAAU,aAAa,CAAC,OAA6B;IACzD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,KAAK;YACf,GAAG,OAAO,CAAC,QAAQ;SACpB;KACF,CAAC;AACJ,CAAC;AAgBD,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,KAAK;YACf,GAAG,OAAO,CAAC,QAAQ;SACpB;KACF,CAAC;AACJ,CAAC;AAaD,MAAM,UAAU,YAAY,CAAC,OAA4B;IACvD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,KAAK;YACjB,GAAG,OAAO,CAAC,QAAQ;SACpB;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAI3B;IACC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CACvB,IAAkB,EAClB,OAAwD;IAExD,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,MAAM;QACjC,MAAM,EAAE,OAAO,EAAE,MAAM;KACxB,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manifesto-ai/core",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "AI Native Semantic Layer for SaaS Business Logic",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,14 +17,6 @@
17
17
  "README.md",
18
18
  "LICENSE"
19
19
  ],
20
- "scripts": {
21
- "build": "tsc",
22
- "test": "vitest run",
23
- "test:watch": "vitest",
24
- "test:coverage": "vitest run --coverage",
25
- "typecheck": "tsc --noEmit",
26
- "clean": "rm -rf dist"
27
- },
28
20
  "keywords": [
29
21
  "manifesto",
30
22
  "ai",
@@ -54,5 +46,13 @@
54
46
  "@vitest/coverage-v8": "^2.1.9",
55
47
  "typescript": "^5.7.2",
56
48
  "vitest": "^2.1.9"
49
+ },
50
+ "scripts": {
51
+ "build": "tsc",
52
+ "test": "vitest run",
53
+ "test:watch": "vitest",
54
+ "test:coverage": "vitest run --coverage",
55
+ "typecheck": "tsc --noEmit",
56
+ "clean": "rm -rf dist"
57
57
  }
58
- }
58
+ }