@elevasis/core 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +9 -2
  3. package/dist/organization-model/index.d.ts +1 -1
  4. package/dist/organization-model/index.js +9 -2
  5. package/dist/test-utils/index.d.ts +480 -389
  6. package/dist/test-utils/index.js +28 -2
  7. package/package.json +1 -1
  8. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +2324 -0
  9. package/src/auth/multi-tenancy/credentials/__tests__/encryption.test.ts +217 -216
  10. package/src/auth/multi-tenancy/credentials/server/encryption.ts +5 -19
  11. package/src/auth/multi-tenancy/credentials/server/kek-loader.ts +3 -13
  12. package/src/auth/multi-tenancy/permissions.ts +12 -5
  13. package/src/business/acquisition/activity-events.test.ts +250 -0
  14. package/src/business/acquisition/activity-events.ts +84 -0
  15. package/src/business/acquisition/api-schemas.test.ts +1180 -0
  16. package/src/business/acquisition/api-schemas.ts +456 -235
  17. package/src/business/acquisition/crm-state-actions.test.ts +160 -0
  18. package/src/business/acquisition/derive-actions.test.ts +518 -0
  19. package/src/business/acquisition/derive-actions.ts +103 -0
  20. package/src/business/acquisition/index.ts +51 -11
  21. package/src/business/acquisition/stateful.ts +30 -0
  22. package/src/business/acquisition/types.ts +44 -77
  23. package/src/execution/engine/index.ts +4 -1
  24. package/src/execution/engine/tools/integration/server/adapters/apify/__tests__/apify-run-actor.integration.test.ts +1 -2
  25. package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +363 -361
  26. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.test.ts +162 -186
  27. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.test.ts +316 -338
  28. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +204 -210
  29. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.test.ts +88 -0
  30. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +141 -134
  31. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +76 -75
  32. package/src/execution/engine/tools/integration/service.test.ts +34 -9
  33. package/src/execution/engine/tools/integration/service.ts +6 -3
  34. package/src/execution/engine/tools/lead-service-types.ts +90 -30
  35. package/src/execution/engine/tools/platform/acquisition/types.ts +266 -260
  36. package/src/execution/engine/tools/registry.ts +5 -4
  37. package/src/execution/engine/tools/tool-maps.ts +43 -21
  38. package/src/execution/engine/workflow/types.ts +11 -0
  39. package/src/organization-model/contracts.ts +4 -4
  40. package/src/organization-model/domains/navigation.ts +62 -62
  41. package/src/organization-model/domains/sales.ts +272 -0
  42. package/src/organization-model/organization-graph.mdx +2 -2
  43. package/src/organization-model/published.ts +21 -21
  44. package/src/organization-model/resolve.ts +21 -8
  45. package/src/platform/constants/versions.ts +1 -1
  46. package/src/reference/_generated/contracts.md +2324 -0
  47. package/src/scaffold-registry/index.ts +10 -9
  48. package/src/scaffold-registry/schema.ts +68 -62
  49. package/src/supabase/database.types.ts +2958 -2884
  50. package/src/test-utils/rls/RLSTestContext.ts +585 -553
@@ -1,186 +1,162 @@
1
- /**
2
- * Tests for Attio getRecord fetch implementation
3
- */
4
-
5
- import { describe, it, expect, vi, beforeEach } from 'vitest'
6
- import { getRecord } from './index.js'
7
- import { ToolingError } from '../../../../../../types.js'
8
-
9
- // Mock fetch globally
10
- const mockFetch = vi.fn()
11
- global.fetch = mockFetch as typeof fetch
12
-
13
- describe('getRecord', () => {
14
- beforeEach(() => {
15
- vi.clearAllMocks()
16
- })
17
-
18
- it('should fetch a record successfully', async () => {
19
- const mockResponse = {
20
- data: {
21
- id: {
22
- workspace_id: 'workspace-123',
23
- object_id: 'object-456',
24
- record_id: 'record-789'
25
- },
26
- created_at: '2024-01-01T12:00:00Z',
27
- web_url: 'https://app.attio.com/workspace/record-789',
28
- values: {
29
- name: [{ first_name: 'John', last_name: 'Doe' }],
30
- email: [{ email_address: 'john@example.com' }]
31
- }
32
- }
33
- }
34
-
35
- mockFetch.mockResolvedValue({
36
- ok: true,
37
- json: async () => mockResponse
38
- })
39
-
40
- const result = await getRecord(
41
- { apiKey: 'test-key' },
42
- { object: 'people', recordId: 'record-789' }
43
- )
44
-
45
- expect(result).toEqual({
46
- id: 'record-789',
47
- values: mockResponse.data.values,
48
- createdAt: '2024-01-01T12:00:00Z',
49
- webUrl: 'https://app.attio.com/workspace/record-789'
50
- })
51
-
52
- expect(mockFetch).toHaveBeenCalledWith(
53
- 'https://api.attio.com/v2/objects/people/records/record-789',
54
- expect.objectContaining({
55
- method: 'GET',
56
- headers: {
57
- 'Authorization': 'Bearer test-key',
58
- 'Accept': 'application/json'
59
- }
60
- })
61
- )
62
- })
63
-
64
- it('should throw credentials_invalid when API key is missing', async () => {
65
- await expect(
66
- getRecord(
67
- { apiKey: '' },
68
- { object: 'people', recordId: 'record-123' }
69
- )
70
- ).rejects.toThrow(ToolingError)
71
-
72
- await expect(
73
- getRecord(
74
- { apiKey: '' },
75
- { object: 'people', recordId: 'record-123' }
76
- )
77
- ).rejects.toThrow('Missing Attio API key')
78
- })
79
-
80
- it('should throw validation_error when parameters are missing', async () => {
81
- await expect(
82
- getRecord(
83
- { apiKey: 'test-key' },
84
- { object: '', recordId: 'record-123' }
85
- )
86
- ).rejects.toThrow(ToolingError)
87
-
88
- await expect(
89
- getRecord(
90
- { apiKey: 'test-key' },
91
- { object: 'people', recordId: '' }
92
- )
93
- ).rejects.toThrow('Missing required parameters')
94
- })
95
-
96
- it('should handle 404 not found errors', async () => {
97
- mockFetch.mockResolvedValue({
98
- ok: false,
99
- status: 404,
100
- statusText: 'Not Found',
101
- text: async () => JSON.stringify({
102
- status_code: 404,
103
- type: 'invalid_request_error',
104
- code: 'not_found',
105
- message: 'Record not found'
106
- })
107
- })
108
-
109
- await expect(
110
- getRecord(
111
- { apiKey: 'test-key' },
112
- { object: 'people', recordId: 'nonexistent' }
113
- )
114
- ).rejects.toThrow(ToolingError)
115
-
116
- try {
117
- await getRecord(
118
- { apiKey: 'test-key' },
119
- { object: 'people', recordId: 'nonexistent' }
120
- )
121
- } catch (error) {
122
- expect((error as ToolingError).errorType).toBe('validation_error')
123
- expect((error as ToolingError).message).toContain('Record not found')
124
- }
125
- })
126
-
127
- it('should handle 401 authentication errors', async () => {
128
- mockFetch.mockResolvedValue({
129
- ok: false,
130
- status: 401,
131
- statusText: 'Unauthorized',
132
- text: async () => JSON.stringify({
133
- status_code: 401,
134
- type: 'authentication_error',
135
- code: 'unauthorized',
136
- message: 'Invalid API key'
137
- })
138
- })
139
-
140
- try {
141
- await getRecord(
142
- { apiKey: 'invalid-key' },
143
- { object: 'people', recordId: 'record-123' }
144
- )
145
- } catch (error) {
146
- expect((error as ToolingError).errorType).toBe('credentials_invalid')
147
- expect((error as ToolingError).message).toContain('Invalid API key')
148
- }
149
- })
150
-
151
- it('should work with different object types', async () => {
152
- const mockResponse = {
153
- data: {
154
- id: {
155
- workspace_id: 'workspace-123',
156
- object_id: 'object-456',
157
- record_id: 'company-789'
158
- },
159
- created_at: '2024-01-01T12:00:00Z',
160
- web_url: 'https://app.attio.com/workspace/company-789',
161
- values: {
162
- name: 'Acme Corp',
163
- domains: [{ domain: 'acme.com' }]
164
- }
165
- }
166
- }
167
-
168
- mockFetch.mockResolvedValue({
169
- ok: true,
170
- json: async () => mockResponse
171
- })
172
-
173
- const result = await getRecord(
174
- { apiKey: 'test-key' },
175
- { object: 'companies', recordId: 'company-789' }
176
- )
177
-
178
- expect(result.id).toBe('company-789')
179
- expect(result.values.name).toBe('Acme Corp')
180
-
181
- expect(mockFetch).toHaveBeenCalledWith(
182
- 'https://api.attio.com/v2/objects/companies/records/company-789',
183
- expect.anything()
184
- )
185
- })
186
- })
1
+ /**
2
+ * Tests for Attio getRecord fetch implementation
3
+ */
4
+
5
+ import { describe as _describe, it, expect, vi, beforeEach } from 'vitest'
6
+
7
+ // Attio integration not in use; suite skipped per project decision (2026-04-29).
8
+ const describe = _describe.skip
9
+ import { getRecord } from './index.js'
10
+ import { ToolingError } from '../../../../../../types.js'
11
+
12
+ // Mock fetch globally
13
+ const mockFetch = vi.fn()
14
+ global.fetch = mockFetch as typeof fetch
15
+
16
+ describe('getRecord', () => {
17
+ beforeEach(() => {
18
+ vi.clearAllMocks()
19
+ })
20
+
21
+ it('should fetch a record successfully', async () => {
22
+ const mockResponse = {
23
+ data: {
24
+ id: {
25
+ workspace_id: 'workspace-123',
26
+ object_id: 'object-456',
27
+ record_id: 'record-789'
28
+ },
29
+ created_at: '2024-01-01T12:00:00Z',
30
+ web_url: 'https://app.attio.com/workspace/record-789',
31
+ values: {
32
+ name: [{ first_name: 'John', last_name: 'Doe' }],
33
+ email: [{ email_address: 'john@example.com' }]
34
+ }
35
+ }
36
+ }
37
+
38
+ mockFetch.mockResolvedValue({
39
+ ok: true,
40
+ json: async () => mockResponse
41
+ })
42
+
43
+ const result = await getRecord({ apiKey: 'test-key' }, { object: 'people', recordId: 'record-789' })
44
+
45
+ expect(result).toEqual({
46
+ id: 'record-789',
47
+ values: mockResponse.data.values,
48
+ createdAt: '2024-01-01T12:00:00Z',
49
+ webUrl: 'https://app.attio.com/workspace/record-789'
50
+ })
51
+
52
+ expect(mockFetch).toHaveBeenCalledWith(
53
+ 'https://api.attio.com/v2/objects/people/records/record-789',
54
+ expect.objectContaining({
55
+ method: 'GET',
56
+ headers: {
57
+ Authorization: 'Bearer test-key',
58
+ Accept: 'application/json'
59
+ }
60
+ })
61
+ )
62
+ })
63
+
64
+ it('should throw credentials_invalid when API key is missing', async () => {
65
+ await expect(getRecord({ apiKey: '' }, { object: 'people', recordId: 'record-123' })).rejects.toThrow(ToolingError)
66
+
67
+ await expect(getRecord({ apiKey: '' }, { object: 'people', recordId: 'record-123' })).rejects.toThrow(
68
+ 'Missing Attio API key'
69
+ )
70
+ })
71
+
72
+ it('should throw validation_error when parameters are missing', async () => {
73
+ await expect(getRecord({ apiKey: 'test-key' }, { object: '', recordId: 'record-123' })).rejects.toThrow(
74
+ ToolingError
75
+ )
76
+
77
+ await expect(getRecord({ apiKey: 'test-key' }, { object: 'people', recordId: '' })).rejects.toThrow(
78
+ 'Missing required parameters'
79
+ )
80
+ })
81
+
82
+ it('should handle 404 not found errors', async () => {
83
+ mockFetch.mockResolvedValue({
84
+ ok: false,
85
+ status: 404,
86
+ statusText: 'Not Found',
87
+ text: async () =>
88
+ JSON.stringify({
89
+ status_code: 404,
90
+ type: 'invalid_request_error',
91
+ code: 'not_found',
92
+ message: 'Record not found'
93
+ })
94
+ })
95
+
96
+ await expect(getRecord({ apiKey: 'test-key' }, { object: 'people', recordId: 'nonexistent' })).rejects.toThrow(
97
+ ToolingError
98
+ )
99
+
100
+ try {
101
+ await getRecord({ apiKey: 'test-key' }, { object: 'people', recordId: 'nonexistent' })
102
+ } catch (error) {
103
+ expect((error as ToolingError).errorType).toBe('validation_error')
104
+ expect((error as ToolingError).message).toContain('Record not found')
105
+ }
106
+ })
107
+
108
+ it('should handle 401 authentication errors', async () => {
109
+ mockFetch.mockResolvedValue({
110
+ ok: false,
111
+ status: 401,
112
+ statusText: 'Unauthorized',
113
+ text: async () =>
114
+ JSON.stringify({
115
+ status_code: 401,
116
+ type: 'authentication_error',
117
+ code: 'unauthorized',
118
+ message: 'Invalid API key'
119
+ })
120
+ })
121
+
122
+ try {
123
+ await getRecord({ apiKey: 'invalid-key' }, { object: 'people', recordId: 'record-123' })
124
+ } catch (error) {
125
+ expect((error as ToolingError).errorType).toBe('credentials_invalid')
126
+ expect((error as ToolingError).message).toContain('Invalid API key')
127
+ }
128
+ })
129
+
130
+ it('should work with different object types', async () => {
131
+ const mockResponse = {
132
+ data: {
133
+ id: {
134
+ workspace_id: 'workspace-123',
135
+ object_id: 'object-456',
136
+ record_id: 'company-789'
137
+ },
138
+ created_at: '2024-01-01T12:00:00Z',
139
+ web_url: 'https://app.attio.com/workspace/company-789',
140
+ values: {
141
+ name: 'Acme Corp',
142
+ domains: [{ domain: 'acme.com' }]
143
+ }
144
+ }
145
+ }
146
+
147
+ mockFetch.mockResolvedValue({
148
+ ok: true,
149
+ json: async () => mockResponse
150
+ })
151
+
152
+ const result = await getRecord({ apiKey: 'test-key' }, { object: 'companies', recordId: 'company-789' })
153
+
154
+ expect(result.id).toBe('company-789')
155
+ expect(result.values.name).toBe('Acme Corp')
156
+
157
+ expect(mockFetch).toHaveBeenCalledWith(
158
+ 'https://api.attio.com/v2/objects/companies/records/company-789',
159
+ expect.anything()
160
+ )
161
+ })
162
+ })