@elevasis/core 0.41.0 → 0.42.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.
package/dist/index.d.ts CHANGED
@@ -3777,10 +3777,10 @@ type DeepPartial<T> = T extends Array<infer U> ? Array<DeepPartial<U>> : T exten
3777
3777
 
3778
3778
  declare const KNOWLEDGE_FEATURE_ID: "knowledge";
3779
3779
  declare const KNOWLEDGE_SYSTEM_ID: "knowledge";
3780
- declare const PROJECTS_SYSTEM_ID: "projects";
3780
+ declare const PROJECTS_SYSTEM_ID: "platform.projects";
3781
3781
  /** @deprecated Use PROJECTS_SYSTEM_ID. Scheduled for removal after one publish cycle. */
3782
- declare const PROJECTS_FEATURE_ID: "projects";
3783
- declare const PROJECTS_INDEX_SURFACE_ID: "projects.index";
3782
+ declare const PROJECTS_FEATURE_ID: "platform.projects";
3783
+ declare const PROJECTS_INDEX_SURFACE_ID: "platform.projects.index";
3784
3784
  declare const PROJECTS_VIEW_ACTION_ID: "delivery.projects.view";
3785
3785
  declare const SALES_FEATURE_ID: "crm";
3786
3786
  declare const PROSPECTING_FEATURE_ID: "lead-gen";
package/dist/index.js CHANGED
@@ -2648,9 +2648,9 @@ var LinkSchema = z.object({
2648
2648
  // src/organization-model/contracts.ts
2649
2649
  var KNOWLEDGE_FEATURE_ID = "knowledge";
2650
2650
  var KNOWLEDGE_SYSTEM_ID = "knowledge";
2651
- var PROJECTS_SYSTEM_ID = "projects";
2651
+ var PROJECTS_SYSTEM_ID = "platform.projects";
2652
2652
  var PROJECTS_FEATURE_ID = PROJECTS_SYSTEM_ID;
2653
- var PROJECTS_INDEX_SURFACE_ID = "projects.index";
2653
+ var PROJECTS_INDEX_SURFACE_ID = "platform.projects.index";
2654
2654
  var PROJECTS_VIEW_ACTION_ID = "delivery.projects.view";
2655
2655
  var SALES_FEATURE_ID = "crm";
2656
2656
  var PROSPECTING_FEATURE_ID = "lead-gen";
@@ -3777,10 +3777,10 @@ type DeepPartial<T> = T extends Array<infer U> ? Array<DeepPartial<U>> : T exten
3777
3777
 
3778
3778
  declare const KNOWLEDGE_FEATURE_ID: "knowledge";
3779
3779
  declare const KNOWLEDGE_SYSTEM_ID: "knowledge";
3780
- declare const PROJECTS_SYSTEM_ID: "projects";
3780
+ declare const PROJECTS_SYSTEM_ID: "platform.projects";
3781
3781
  /** @deprecated Use PROJECTS_SYSTEM_ID. Scheduled for removal after one publish cycle. */
3782
- declare const PROJECTS_FEATURE_ID: "projects";
3783
- declare const PROJECTS_INDEX_SURFACE_ID: "projects.index";
3782
+ declare const PROJECTS_FEATURE_ID: "platform.projects";
3783
+ declare const PROJECTS_INDEX_SURFACE_ID: "platform.projects.index";
3784
3784
  declare const PROJECTS_VIEW_ACTION_ID: "delivery.projects.view";
3785
3785
  declare const SALES_FEATURE_ID: "crm";
3786
3786
  declare const PROSPECTING_FEATURE_ID: "lead-gen";
@@ -2648,9 +2648,9 @@ var LinkSchema = z.object({
2648
2648
  // src/organization-model/contracts.ts
2649
2649
  var KNOWLEDGE_FEATURE_ID = "knowledge";
2650
2650
  var KNOWLEDGE_SYSTEM_ID = "knowledge";
2651
- var PROJECTS_SYSTEM_ID = "projects";
2651
+ var PROJECTS_SYSTEM_ID = "platform.projects";
2652
2652
  var PROJECTS_FEATURE_ID = PROJECTS_SYSTEM_ID;
2653
- var PROJECTS_INDEX_SURFACE_ID = "projects.index";
2653
+ var PROJECTS_INDEX_SURFACE_ID = "platform.projects.index";
2654
2654
  var PROJECTS_VIEW_ACTION_ID = "delivery.projects.view";
2655
2655
  var SALES_FEATURE_ID = "crm";
2656
2656
  var PROSPECTING_FEATURE_ID = "lead-gen";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/core",
3
- "version": "0.41.0",
3
+ "version": "0.42.1",
4
4
  "license": "MIT",
5
5
  "description": "Minimal shared constants across Elevasis monorepo",
6
6
  "sideEffects": false,
@@ -6,7 +6,15 @@ export const accessTestOrganizationModel = {
6
6
  id: 'platform',
7
7
  label: 'Platform',
8
8
  lifecycle: 'active',
9
- order: 10
9
+ order: 10,
10
+ systems: {
11
+ projects: {
12
+ id: 'projects',
13
+ label: 'Projects',
14
+ lifecycle: 'active',
15
+ order: 10
16
+ }
17
+ }
10
18
  },
11
19
  sales: {
12
20
  id: 'sales',
@@ -28,12 +36,6 @@ export const accessTestOrganizationModel = {
28
36
  }
29
37
  }
30
38
  },
31
- projects: {
32
- id: 'projects',
33
- label: 'Projects',
34
- lifecycle: 'active',
35
- order: 30
36
- },
37
39
  clients: {
38
40
  id: 'clients',
39
41
  label: 'Clients',
@@ -114,7 +114,6 @@ describe('client API schemas', () => {
114
114
  source: 'word_of_mouth',
115
115
  metadata: {
116
116
  externalProjectSlug: 'developer-workspace-slug',
117
- workspacePath: 'client-workspace',
118
117
  campaignSlug: 'byron-for-irvine'
119
118
  }
120
119
  }).success
@@ -159,20 +159,15 @@ export class GmailAdapter implements BaseIntegrationAdapter {
159
159
  requestBody: {
160
160
  raw: encodedMessage
161
161
  }
162
- })
163
-
164
- if (context?.logger) {
165
- console.log('[GmailAdapter] Email sent:', {
166
- organizationId: context.organizationId,
167
- executionId: context.executionId,
168
- to: params.to,
169
- subject: params.subject,
170
- messageId: response.data.id,
171
- threadId: response.data.threadId
172
- })
173
- }
174
-
175
- return {
162
+ })
163
+
164
+ if (context?.logger) {
165
+ context.logger.info(
166
+ `[GmailAdapter] Email sent: organizationId=${context.organizationId} executionId=${context.executionId} messageId=${response.data.id} threadId=${response.data.threadId} to=${params.to}`
167
+ )
168
+ }
169
+
170
+ return {
176
171
  messageId: response.data.id!,
177
172
  threadId: response.data.threadId!
178
173
  }
@@ -26,7 +26,6 @@ export {
26
26
  export type { CredentialSchema, CredentialField } from './schemas'
27
27
 
28
28
  export { buildCredentialValue, extractFormValues } from './utils'
29
-
30
- // API validation schemas
31
- export * from './api-schemas'
32
- export { CredentialSchemas } from './api-schemas'
29
+
30
+ // API validation schemas
31
+ export * from './api-schemas'
@@ -1,27 +1,27 @@
1
- export const KNOWLEDGE_FEATURE_ID = 'knowledge' as const
2
- export const KNOWLEDGE_SYSTEM_ID = 'knowledge' as const
3
-
4
- export const PROJECTS_SYSTEM_ID = 'projects' as const
5
- /** @deprecated Use PROJECTS_SYSTEM_ID. Scheduled for removal after one publish cycle. */
6
- export const PROJECTS_FEATURE_ID = PROJECTS_SYSTEM_ID
7
- export const PROJECTS_INDEX_SURFACE_ID = 'projects.index' as const
8
- export const PROJECTS_VIEW_ACTION_ID = 'delivery.projects.view' as const
9
-
10
- export const SALES_FEATURE_ID = 'crm' as const
11
- export const PROSPECTING_FEATURE_ID = 'lead-gen' as const
12
- export const MONITORING_FEATURE_ID = 'monitoring' as const
13
- export const SETTINGS_FEATURE_ID = 'settings' as const
14
- export const SEO_FEATURE_ID = 'seo' as const
15
- export const SALES_SYSTEM_ID = 'sales.crm' as const
16
- export const PROSPECTING_SYSTEM_ID = 'sales.lead-gen' as const
17
- export const OPERATIONS_SYSTEM_ID = 'operations' as const
18
- /** @deprecated Use OPERATIONS_SYSTEM_ID. Scheduled for removal after one publish cycle. */
19
- export const OPERATIONS_FEATURE_ID = OPERATIONS_SYSTEM_ID
20
- export const MONITORING_SYSTEM_ID = 'monitoring' as const
21
- export const SETTINGS_SYSTEM_ID = 'settings' as const
22
- export const SEO_SYSTEM_ID = 'seo' as const
23
-
24
- export const SALES_PIPELINE_SURFACE_ID = 'crm.pipeline' as const
25
- export const PROSPECTING_LISTS_SURFACE_ID = 'lead-gen.lists' as const
26
- export const OPERATIONS_COMMAND_VIEW_SURFACE_ID = 'knowledge.command-view' as const
27
- export const SETTINGS_ROLES_SURFACE_ID = 'settings.roles' as const
1
+ export const KNOWLEDGE_FEATURE_ID = 'knowledge' as const
2
+ export const KNOWLEDGE_SYSTEM_ID = 'knowledge' as const
3
+
4
+ export const PROJECTS_SYSTEM_ID = 'platform.projects' as const
5
+ /** @deprecated Use PROJECTS_SYSTEM_ID. Scheduled for removal after one publish cycle. */
6
+ export const PROJECTS_FEATURE_ID = PROJECTS_SYSTEM_ID
7
+ export const PROJECTS_INDEX_SURFACE_ID = 'platform.projects.index' as const
8
+ export const PROJECTS_VIEW_ACTION_ID = 'delivery.projects.view' as const
9
+
10
+ export const SALES_FEATURE_ID = 'crm' as const
11
+ export const PROSPECTING_FEATURE_ID = 'lead-gen' as const
12
+ export const MONITORING_FEATURE_ID = 'monitoring' as const
13
+ export const SETTINGS_FEATURE_ID = 'settings' as const
14
+ export const SEO_FEATURE_ID = 'seo' as const
15
+ export const SALES_SYSTEM_ID = 'sales.crm' as const
16
+ export const PROSPECTING_SYSTEM_ID = 'sales.lead-gen' as const
17
+ export const OPERATIONS_SYSTEM_ID = 'operations' as const
18
+ /** @deprecated Use OPERATIONS_SYSTEM_ID. Scheduled for removal after one publish cycle. */
19
+ export const OPERATIONS_FEATURE_ID = OPERATIONS_SYSTEM_ID
20
+ export const MONITORING_SYSTEM_ID = 'monitoring' as const
21
+ export const SETTINGS_SYSTEM_ID = 'settings' as const
22
+ export const SEO_SYSTEM_ID = 'seo' as const
23
+
24
+ export const SALES_PIPELINE_SURFACE_ID = 'crm.pipeline' as const
25
+ export const PROSPECTING_LISTS_SURFACE_ID = 'lead-gen.lists' as const
26
+ export const OPERATIONS_COMMAND_VIEW_SURFACE_ID = 'knowledge.command-view' as const
27
+ export const SETTINGS_ROLES_SURFACE_ID = 'settings.roles' as const
@@ -1,3 +1,3 @@
1
1
  export const VERSION = {
2
- CURRENT: '1.12.17'
2
+ CURRENT: '1.12.19'
3
3
  }
@@ -6,19 +6,19 @@ import { type ScaffoldRegistry, type ScaffoldRegistryEntry, ScaffoldRegistrySche
6
6
 
7
7
  const MODULE_DIR = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/, '$1'))
8
8
 
9
- export {
10
- ExternalSyncCategorySchema,
11
- ExternalSyncDeletePolicySchema,
12
- ExternalSyncOwnerSchema,
13
- ExternalSyncStrategySchema,
14
- ScaffoldEntryKindSchema,
9
+ export {
10
+ ExternalSyncCategorySchema,
11
+ ExternalSyncDeletePolicySchema,
12
+ ExternalSyncOwnerSchema,
13
+ ExternalSyncStrategySchema,
14
+ ScaffoldEntryKindSchema,
15
15
  ScaffoldRegistrySchema
16
16
  } from './schema'
17
- export type {
18
- ExternalSyncCategory,
19
- ExternalSyncDeletePolicy,
20
- ExternalSyncOwner,
21
- ExternalSyncStrategy,
17
+ export type {
18
+ ExternalSyncCategory,
19
+ ExternalSyncDeletePolicy,
20
+ ExternalSyncOwner,
21
+ ExternalSyncStrategy,
22
22
  ScaffoldEntryKind,
23
23
  ScaffoldRef,
24
24
  ScaffoldRegistry,
@@ -46,13 +46,24 @@ export const ExternalSyncStrategySchema = z.enum([
46
46
 
47
47
  export type ExternalSyncStrategy = z.infer<typeof ExternalSyncStrategySchema>
48
48
 
49
- export const ExternalSyncDeletePolicySchema = z.enum(['none', 'manifest-only'])
50
-
51
- export type ExternalSyncDeletePolicy = z.infer<typeof ExternalSyncDeletePolicySchema>
52
-
53
- // ---------------------------------------------------------------------------
54
- // Scaffold reference (a single downstream artifact that needs attention)
55
- // ---------------------------------------------------------------------------
49
+ export const ExternalSyncDeletePolicySchema = z.enum(['none', 'manifest-only'])
50
+
51
+ export type ExternalSyncDeletePolicy = z.infer<typeof ExternalSyncDeletePolicySchema>
52
+
53
+ export const ExternalSyncLaneSeveritySchema = z.enum(['critical-manual-merge', 'optional-feature-selection'])
54
+
55
+ export type ExternalSyncLaneSeverity = z.infer<typeof ExternalSyncLaneSeveritySchema>
56
+
57
+ export const ExternalSyncLaneSeverityAnnotationSchema = z.object({
58
+ path: z.string().min(1),
59
+ severity: ExternalSyncLaneSeveritySchema
60
+ })
61
+
62
+ export type ExternalSyncLaneSeverityAnnotation = z.infer<typeof ExternalSyncLaneSeverityAnnotationSchema>
63
+
64
+ // ---------------------------------------------------------------------------
65
+ // Scaffold reference (a single downstream artifact that needs attention)
66
+ // ---------------------------------------------------------------------------
56
67
 
57
68
  export const ScaffoldRefSchema = z.object({
58
69
  /**
@@ -82,7 +93,7 @@ export const ScaffoldRegistryEntrySchema = z
82
93
  .object({
83
94
  /**
84
95
  * Stable slug identifier for this entry (kebab-case).
85
- * Referenced by hooks, CI checks, and the /scaffold verify skill.
96
+ * Referenced by hooks, CI checks, and the /scaffold heal skill.
86
97
  */
87
98
  id: z
88
99
  .string()
@@ -140,10 +151,17 @@ export const ScaffoldRegistryEntrySchema = z
140
151
  /**
141
152
  * Optional delete behavior for managed external sync surfaces.
142
153
  */
143
- delete_policy: ExternalSyncDeletePolicySchema.optional(),
144
-
145
- /**
146
- * Free-form notes. Required when kind is "other".
154
+ delete_policy: ExternalSyncDeletePolicySchema.optional(),
155
+
156
+ /**
157
+ * Optional sync-lane severity tags for project-relative external sync
158
+ * paths. Used by sync-apply lane routing only; classification ownership
159
+ * still comes from category/strategy/delete_policy.
160
+ */
161
+ sync_lane_severity: z.array(ExternalSyncLaneSeverityAnnotationSchema).optional(),
162
+
163
+ /**
164
+ * Free-form notes. Required when kind is "other".
147
165
  */
148
166
  notes: z.string().optional(),
149
167
 
@@ -13,8 +13,6 @@ export type SupabaseUserProfile = Tables<'users'>
13
13
  export type SupabaseOrganization = Tables<'organizations'>
14
14
  export type SupabaseOrgMembership = Tables<'org_memberships'>
15
15
  export type SupabaseTaskSchedule = Tables<'task_schedules'>
16
- /** @deprecated Use SupabaseTaskSchedule instead. Alias for backward compatibility. */
17
- export type SupabaseScheduledTask = SupabaseTaskSchedule
18
16
  export type SupabaseCommandQueue = Tables<'command_queue'>
19
17
  export type SupabaseExecutionLogs = Tables<'execution_logs'>
20
18
  export type SupabaseApiKey = Tables<'api_keys'>
@@ -25,8 +23,6 @@ export type SupabaseOrganizationCredential = Tables<'credentials'>
25
23
  export type SupabaseUserProfileInsert = TablesInsert<'users'>
26
24
  export type SupabaseOrganizationInsert = TablesInsert<'organizations'>
27
25
  export type SupabaseTaskScheduleInsert = TablesInsert<'task_schedules'>
28
- /** @deprecated Use SupabaseTaskScheduleInsert instead. Alias for backward compatibility. */
29
- export type SupabaseScheduledTaskInsert = SupabaseTaskScheduleInsert
30
26
  export type SupabaseCommandQueueInsert = TablesInsert<'command_queue'>
31
27
  export type SupabaseApiKeyInsert = TablesInsert<'api_keys'>
32
28
  export type SupabaseExecutionLogsInsert = TablesInsert<'execution_logs'>
@@ -35,8 +31,6 @@ export type SupabaseOrganizationCredentialInsert = TablesInsert<'credentials'>
35
31
  export type SupabaseUserProfileUpdate = TablesUpdate<'users'>
36
32
  export type SupabaseOrganizationUpdate = TablesUpdate<'organizations'>
37
33
  export type SupabaseTaskScheduleUpdate = TablesUpdate<'task_schedules'>
38
- /** @deprecated Use SupabaseTaskScheduleUpdate instead. Alias for backward compatibility. */
39
- export type SupabaseScheduledTaskUpdate = SupabaseTaskScheduleUpdate
40
34
  export type SupabaseCommandQueueUpdate = TablesUpdate<'command_queue'>
41
35
  export type SupabaseApiKeyUpdate = TablesUpdate<'api_keys'>
42
36
  export type SupabaseExecutionLogsUpdate = TablesUpdate<'execution_logs'>
@@ -1,219 +0,0 @@
1
- /**
2
- * pdfmake PDF Generation Test
3
- *
4
- * Tests that pdfmake can generate PDFs in this environment.
5
- * This is a verification test before full migration from @react-pdf/renderer.
6
- *
7
- * Run with: npx tsx packages/core/src/pdf/server/__tests__/pdfmake-test.ts
8
- */
9
- import { writeFileSync } from 'node:fs'
10
- import { join } from 'node:path'
11
- import type { PDFDocument } from '../../types'
12
- import { PdfMakeService } from '../pdfmake-service'
13
-
14
- // Mock storage service for testing (matches real StorageService interface)
15
- const mockStorageService = {
16
- async upload(params: { organizationId: string; bucket: string; path: string; file: Buffer; contentType: string; upsert?: boolean }) {
17
- const size = params.file.byteLength
18
- console.log(`[mock-storage] Would upload ${size} bytes to ${params.organizationId}/${params.bucket}/${params.path}`)
19
- return {
20
- path: params.path,
21
- fullPath: `${params.organizationId}/${params.path}`,
22
- size
23
- }
24
- },
25
- async createSignedUrl(params: { organizationId: string; bucket: string; path: string; expiresIn: number }) {
26
- console.log(`[mock-storage] Creating signed URL for ${params.bucket}/${params.path} (expires in ${params.expiresIn}s)`)
27
- return {
28
- signedUrl: `https://mock.storage/${params.bucket}/${params.organizationId}/${params.path}?token=mock`,
29
- path: params.path,
30
- expiresAt: new Date(Date.now() + params.expiresIn * 1000)
31
- }
32
- }
33
- }
34
-
35
- // Sample document matching the PDFDocument schema
36
- const sampleDocument: PDFDocument = {
37
- metadata: {
38
- title: 'pdfmake Test Document',
39
- author: 'Elevasis Platform'
40
- },
41
- pages: [
42
- // Page 1: Cover page
43
- {
44
- sections: [
45
- { type: 'text', content: 'ELEVASIS', variant: 'coverVertical' },
46
- { type: 'text', content: 'Automation Solutions Proposal', variant: 'coverScope' },
47
- { type: 'text', content: 'Le Development LLC', variant: 'coverSolutions' }
48
- ],
49
- footer: false,
50
- cover: {
51
- bottomLeft: [
52
- { type: 'text', content: 'Prepared for', variant: 'caption' },
53
- { type: 'text', content: 'Alexander Le', variant: 'body' }
54
- ],
55
- bottomRight: [
56
- { type: 'text', content: 'January 2026', variant: 'caption' }
57
- ]
58
- }
59
- },
60
- // Page 2: Executive summary with metrics
61
- {
62
- sections: [
63
- { type: 'text', content: 'Executive Summary', variant: 'title' },
64
- { type: 'text', content: 'This proposal outlines automation solutions designed to streamline your operations and reduce manual workload.', variant: 'body' },
65
- {
66
- type: 'card',
67
- title: 'Key Metrics',
68
- variant: 'accent',
69
- content: [
70
- { type: 'metric', value: '$51,506', label: 'Projected Annual Savings' },
71
- { type: 'metric', value: '16.1 hrs', label: 'Hours Reclaimed Weekly' }
72
- ]
73
- }
74
- ],
75
- header: { title: 'Executive Summary' },
76
- footer: true
77
- },
78
- // Page 3: Bottlenecks analysis
79
- {
80
- sections: [
81
- { type: 'text', content: 'Current Bottlenecks', variant: 'title' },
82
- {
83
- type: 'list',
84
- items: [
85
- { text: 'Manual client reporting - 15 hrs/week', highlight: true },
86
- { text: 'Invoice generation and follow-up - 8 hrs/week', highlight: true },
87
- 'Email campaign management',
88
- 'Data entry across platforms'
89
- ]
90
- },
91
- {
92
- type: 'table',
93
- headers: ['Bottleneck', 'Hours/Week', 'Annual Cost'],
94
- rows: [
95
- ['Client Reporting', '15', '$50,700'],
96
- ['Invoice Management', '8', '$22,880'],
97
- ['Total', '23', '$73,580']
98
- ]
99
- }
100
- ],
101
- header: { title: 'Analysis' },
102
- footer: true
103
- },
104
- // Page 4: Solutions with cards
105
- {
106
- sections: [
107
- { type: 'text', content: 'Proposed Solutions', variant: 'title' },
108
- {
109
- type: 'card',
110
- title: 'Solution 1: Automated Reporting',
111
- content: [
112
- { type: 'text', content: 'Automated data aggregation from multiple sources into unified client reports.', variant: 'body' },
113
- { type: 'list', items: ['Real-time data sync', 'Custom templates', 'Scheduled delivery'] }
114
- ]
115
- },
116
- {
117
- type: 'card',
118
- title: 'Solution 2: Invoice Automation',
119
- content: [
120
- { type: 'text', content: 'End-to-end invoice generation with automatic follow-ups and payment tracking.', variant: 'body' },
121
- { type: 'list', items: ['Auto-generation', 'Payment reminders', 'Cash flow analytics'], ordered: true }
122
- ]
123
- }
124
- ],
125
- header: { title: 'Solutions' },
126
- footer: true
127
- }
128
- ]
129
- }
130
-
131
- async function runTest() {
132
- console.log('========================================')
133
- console.log('pdfmake PDF Generation Test')
134
- console.log('========================================')
135
- console.log('')
136
-
137
- try {
138
- // Test 1: Create service
139
- console.log('[TEST 1] Creating PdfMakeService...')
140
- const service = new PdfMakeService(mockStorageService)
141
- console.log('[TEST 1] ✅ Service created successfully')
142
- console.log('')
143
-
144
- // Test 2: Render to buffer (no storage upload)
145
- console.log('[TEST 2] Rendering sample document to buffer...')
146
- console.log(` Document: ${sampleDocument.pages.length} pages`)
147
- console.log(` Title: ${sampleDocument.metadata?.title}`)
148
-
149
- const startTime = Date.now()
150
- const buffer = await service.renderToBuffer({
151
- organizationId: 'test-org',
152
- document: sampleDocument
153
- })
154
- const elapsed = Date.now() - startTime
155
-
156
- console.log(`[TEST 2] ✅ PDF rendered successfully`)
157
- console.log(` Buffer size: ${buffer.byteLength} bytes`)
158
- console.log(` Time: ${elapsed}ms`)
159
- console.log('')
160
-
161
- // Test 3: Verify it's a valid PDF (starts with %PDF-)
162
- console.log('[TEST 3] Validating PDF format...')
163
- const header = buffer.subarray(0, 5).toString('utf-8')
164
- if (header === '%PDF-') {
165
- console.log(`[TEST 3] ✅ Valid PDF header detected: ${header}`)
166
- } else {
167
- throw new Error(`Invalid PDF header: ${header}`)
168
- }
169
- console.log('')
170
-
171
- // Test 4: Write to file for manual inspection
172
- const outputPath = join(process.cwd(), 'pdfmake-test-output.pdf')
173
- console.log('[TEST 4] Writing PDF to file for inspection...')
174
- writeFileSync(outputPath, buffer)
175
- console.log(`[TEST 4] ✅ PDF written to: ${outputPath}`)
176
- console.log('')
177
-
178
- // Test 5: Test full render with mock storage
179
- console.log('[TEST 5] Testing full render with storage upload...')
180
- const result = await service.render({
181
- organizationId: 'test-org',
182
- document: sampleDocument,
183
- storage: {
184
- bucket: 'test-bucket',
185
- path: 'proposals/test/output.pdf'
186
- }
187
- })
188
- console.log(`[TEST 5] ✅ Full render completed`)
189
- console.log(` Success: ${result.success}`)
190
- console.log(` Size: ${result.size} bytes`)
191
- console.log(` URL: ${result.pdfUrl}`)
192
- console.log('')
193
-
194
- console.log('========================================')
195
- console.log('✅ ALL TESTS PASSED')
196
- console.log('========================================')
197
- console.log('')
198
- console.log('pdfmake is working correctly in this environment.')
199
- console.log(`Check the output PDF at: ${outputPath}`)
200
- console.log('')
201
-
202
- } catch (error) {
203
- console.error('')
204
- console.error('========================================')
205
- console.error('❌ TEST FAILED')
206
- console.error('========================================')
207
- console.error('')
208
- console.error('Error:', error instanceof Error ? error.message : String(error))
209
- if (error instanceof Error && error.stack) {
210
- console.error('')
211
- console.error('Stack trace:')
212
- console.error(error.stack)
213
- }
214
- process.exit(1)
215
- }
216
- }
217
-
218
- // Run the test
219
- runTest()