@lssm/example.integration-hub 0.0.0-canary-20251217083314 → 0.0.0-canary-20251220002821
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/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/connection/connection.contracts.d.ts +29 -28
- package/dist/connection/connection.contracts.d.ts.map +1 -0
- package/dist/connection/connection.contracts.js +2 -1
- package/dist/connection/connection.contracts.js.map +1 -0
- package/dist/connection/connection.enum.d.ts +4 -3
- package/dist/connection/connection.enum.d.ts.map +1 -0
- package/dist/connection/connection.enum.js +4 -4
- package/dist/connection/connection.enum.js.map +1 -0
- package/dist/connection/connection.presentation.d.ts +2 -1
- package/dist/connection/connection.presentation.d.ts.map +1 -0
- package/dist/connection/connection.presentation.js +2 -1
- package/dist/connection/connection.presentation.js.map +1 -0
- package/dist/connection/connection.schema.d.ts +18 -17
- package/dist/connection/connection.schema.d.ts.map +1 -0
- package/dist/connection/connection.schema.js +17 -18
- package/dist/connection/connection.schema.js.map +1 -0
- package/dist/docs/integration-hub.docblock.js +2 -1
- package/dist/docs/integration-hub.docblock.js.map +1 -0
- package/dist/events.d.ts +45 -44
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +44 -45
- package/dist/events.js.map +1 -0
- package/dist/example.d.ts +2 -1
- package/dist/example.d.ts.map +1 -0
- package/dist/example.js +2 -1
- package/dist/example.js.map +1 -0
- package/dist/integration/integration.contracts.d.ts +27 -26
- package/dist/integration/integration.contracts.d.ts.map +1 -0
- package/dist/integration/integration.contracts.js +2 -1
- package/dist/integration/integration.contracts.js.map +1 -0
- package/dist/integration/integration.enum.d.ts +4 -3
- package/dist/integration/integration.enum.d.ts.map +1 -0
- package/dist/integration/integration.enum.js +4 -4
- package/dist/integration/integration.enum.js.map +1 -0
- package/dist/integration/integration.presentation.d.ts +2 -1
- package/dist/integration/integration.presentation.d.ts.map +1 -0
- package/dist/integration/integration.presentation.js +2 -1
- package/dist/integration/integration.presentation.js.map +1 -0
- package/dist/integration/integration.schema.d.ts +18 -17
- package/dist/integration/integration.schema.d.ts.map +1 -0
- package/dist/integration/integration.schema.js +17 -18
- package/dist/integration/integration.schema.js.map +1 -0
- package/dist/integration-hub.feature.d.ts +2 -1
- package/dist/integration-hub.feature.d.ts.map +1 -0
- package/dist/integration-hub.feature.js +2 -1
- package/dist/integration-hub.feature.js.map +1 -0
- package/dist/libs/contracts/dist/capabilities/openbanking.js +2 -1
- package/dist/libs/contracts/dist/capabilities/openbanking.js.map +1 -0
- package/dist/libs/contracts/dist/contract-registry/schemas.js +2 -1
- package/dist/libs/contracts/dist/contract-registry/schemas.js.map +1 -0
- package/dist/libs/contracts/dist/docs/accessibility_wcag_compliance_specs.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/accessibility_wcag_compliance_specs.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/index.js +2 -6
- package/dist/libs/contracts/dist/docs/meta.docs.js +30 -0
- package/dist/libs/contracts/dist/docs/meta.docs.js.map +1 -0
- package/dist/libs/contracts/dist/docs/presentations.js +2 -1
- package/dist/libs/contracts/dist/docs/presentations.js.map +1 -0
- package/dist/libs/contracts/dist/docs/registry.js +2 -1
- package/dist/libs/contracts/dist/docs/registry.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/auth/better-auth-nextjs.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/auth/better-auth-nextjs.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/contracts/openapi-export.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/contracts/openapi-export.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/lifecycle-stage-system.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/lifecycle-stage-system.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/llm/llm-integration.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/llm/llm-integration.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/mcp-endpoints.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/mcp-endpoints.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/presentation-runtime.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/presentation-runtime.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/schema/README.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/schema/README.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/studio/learning-events.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/studio/learning-events.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/studio/learning-journeys.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/studio/learning-journeys.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/studio/platform-admin-panel.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/studio/platform-admin-panel.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/studio/project-access-teams.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/studio/project-access-teams.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/studio/project-routing.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/studio/project-routing.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/studio/sandbox-unlogged.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/studio/sandbox-unlogged.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/studio/team-invitations.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/studio/team-invitations.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/studio/workspace-ops.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/studio/workspace-ops.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/studio/workspaces.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/studio/workspaces.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/telemetry-ingest.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/telemetry-ingest.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/templates/runtime.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/templates/runtime.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/vscode-extension.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/vscode-extension.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech/workflows/overview.docblock.js +2 -1
- package/dist/libs/contracts/dist/docs/tech/workflows/overview.docblock.js.map +1 -0
- package/dist/libs/contracts/dist/docs/tech-contracts.docs.js +97 -0
- package/dist/libs/contracts/dist/docs/tech-contracts.docs.js.map +1 -0
- package/dist/libs/contracts/dist/events.js +2 -1
- package/dist/libs/contracts/dist/events.js.map +1 -0
- package/dist/libs/contracts/dist/index.js +2 -1
- package/dist/libs/contracts/dist/integrations/contracts.js +65 -66
- package/dist/libs/contracts/dist/integrations/contracts.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/openbanking/contracts/accounts.js +31 -32
- package/dist/libs/contracts/dist/integrations/openbanking/contracts/accounts.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/openbanking/contracts/balances.js +18 -19
- package/dist/libs/contracts/dist/integrations/openbanking/contracts/balances.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/openbanking/contracts/transactions.js +32 -33
- package/dist/libs/contracts/dist/integrations/openbanking/contracts/transactions.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/openbanking/models.js +60 -61
- package/dist/libs/contracts/dist/integrations/openbanking/models.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/openbanking/telemetry.js +2 -1
- package/dist/libs/contracts/dist/integrations/openbanking/telemetry.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/elevenlabs.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/elevenlabs.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/gcs-storage.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/gcs-storage.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/gmail.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/gmail.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/google-calendar.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/google-calendar.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/mistral.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/mistral.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/postmark.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/postmark.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/powens.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/powens.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/qdrant.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/qdrant.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/stripe.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/stripe.js.map +1 -0
- package/dist/libs/contracts/dist/integrations/providers/twilio-sms.js +2 -1
- package/dist/libs/contracts/dist/integrations/providers/twilio-sms.js.map +1 -0
- package/dist/libs/contracts/dist/knowledge/contracts.js +44 -45
- package/dist/libs/contracts/dist/knowledge/contracts.js.map +1 -0
- package/dist/libs/contracts/dist/knowledge/spaces/email-threads.js +2 -1
- package/dist/libs/contracts/dist/knowledge/spaces/email-threads.js.map +1 -0
- package/dist/libs/contracts/dist/knowledge/spaces/financial-docs.js +2 -1
- package/dist/libs/contracts/dist/knowledge/spaces/financial-docs.js.map +1 -0
- package/dist/libs/contracts/dist/knowledge/spaces/financial-overview.js +2 -1
- package/dist/libs/contracts/dist/knowledge/spaces/financial-overview.js.map +1 -0
- package/dist/libs/contracts/dist/knowledge/spaces/product-canon.js +2 -1
- package/dist/libs/contracts/dist/knowledge/spaces/product-canon.js.map +1 -0
- package/dist/libs/contracts/dist/knowledge/spaces/support-faq.js +2 -1
- package/dist/libs/contracts/dist/knowledge/spaces/support-faq.js.map +1 -0
- package/dist/libs/contracts/dist/knowledge/spaces/uploaded-docs.js +2 -1
- package/dist/libs/contracts/dist/knowledge/spaces/uploaded-docs.js.map +1 -0
- package/dist/libs/contracts/dist/llm/exporters.js +2 -1
- package/dist/libs/contracts/dist/llm/exporters.js.map +1 -0
- package/dist/libs/contracts/dist/onboarding-base.js +22 -23
- package/dist/libs/contracts/dist/onboarding-base.js.map +1 -0
- package/dist/libs/contracts/dist/ownership.js +4 -2
- package/dist/libs/contracts/dist/ownership.js.map +1 -0
- package/dist/libs/contracts/dist/presentations.v2.js +2 -1
- package/dist/libs/contracts/dist/presentations.v2.js.map +1 -0
- package/dist/libs/contracts/dist/regenerator/service.js +2 -1
- package/dist/libs/contracts/dist/regenerator/service.js.map +1 -0
- package/dist/libs/contracts/dist/schema/dist/index.js +3873 -6
- package/dist/libs/contracts/dist/schema/dist/index.js.map +1 -0
- package/dist/libs/contracts/dist/spec.js +2 -1
- package/dist/libs/contracts/dist/spec.js.map +1 -0
- package/dist/libs/schema/dist/index.js +4717 -6
- package/dist/libs/schema/dist/index.js.map +1 -0
- package/dist/sync/sync.contracts.d.ts +128 -127
- package/dist/sync/sync.contracts.d.ts.map +1 -0
- package/dist/sync/sync.contracts.js +2 -1
- package/dist/sync/sync.contracts.js.map +1 -0
- package/dist/sync/sync.enum.d.ts +6 -5
- package/dist/sync/sync.enum.d.ts.map +1 -0
- package/dist/sync/sync.enum.js +6 -6
- package/dist/sync/sync.enum.js.map +1 -0
- package/dist/sync/sync.presentation.d.ts +2 -1
- package/dist/sync/sync.presentation.d.ts.map +1 -0
- package/dist/sync/sync.presentation.js +2 -1
- package/dist/sync/sync.presentation.js.map +1 -0
- package/dist/sync/sync.schema.d.ts +87 -86
- package/dist/sync/sync.schema.d.ts.map +1 -0
- package/dist/sync/sync.schema.js +58 -59
- package/dist/sync/sync.schema.js.map +1 -0
- package/dist/sync-engine/index.d.ts +3 -2
- package/dist/sync-engine/index.d.ts.map +1 -0
- package/dist/sync-engine/index.js +5 -3
- package/dist/sync-engine/index.js.map +1 -0
- package/package.json +20 -13
- package/dist/libs/contracts/dist/docs/PUBLISHING.docblock.js +0 -16
- package/dist/libs/contracts/dist/docs/tech/PHASE_1_QUICKSTART.docblock.js +0 -16
- package/dist/libs/contracts/dist/docs/tech/PHASE_2_AI_NATIVE_OPERATIONS.docblock.js +0 -16
- package/dist/libs/contracts/dist/docs/tech/PHASE_3_AUTO_EVOLUTION.docblock.js +0 -16
- package/dist/libs/contracts/dist/docs/tech/PHASE_4_PERSONALIZATION_ENGINE.docblock.js +0 -16
- package/dist/libs/contracts/dist/docs/tech/PHASE_5_ZERO_TOUCH_OPERATIONS.docblock.js +0 -16
- package/dist/libs/contracts/dist/schema/dist/EnumType.js +0 -2
- package/dist/libs/contracts/dist/schema/dist/FieldType.js +0 -49
- package/dist/libs/contracts/dist/schema/dist/ScalarTypeEnum.js +0 -236
- package/dist/libs/contracts/dist/schema/dist/SchemaModel.js +0 -34
- package/dist/libs/contracts/dist/schema/dist/entity/defineEntity.js +0 -1
- package/dist/libs/contracts/dist/schema/dist/entity/index.js +0 -2
- package/dist/libs/contracts/dist/schema/dist/entity/types.js +0 -1
- package/dist/libs/schema/dist/EnumType.js +0 -56
- package/dist/libs/schema/dist/FieldType.js +0 -49
- package/dist/libs/schema/dist/ScalarTypeEnum.js +0 -236
- package/dist/libs/schema/dist/SchemaModel.js +0 -39
- package/dist/libs/schema/dist/entity/defineEntity.js +0 -1
- package/dist/libs/schema/dist/entity/index.js +0 -2
- package/dist/libs/schema/dist/entity/types.js +0 -1
package/dist/sync/sync.schema.js
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { defineSchemaModel } from "../libs/schema/dist/SchemaModel.js";
|
|
3
|
-
import "../libs/schema/dist/index.js";
|
|
1
|
+
import { E5, K5 } from "../libs/schema/dist/index.js";
|
|
4
2
|
import { MappingTypeEnum, SyncDirectionEnum, SyncStatusEnum } from "./sync.enum.js";
|
|
5
3
|
|
|
6
4
|
//#region src/sync/sync.schema.ts
|
|
7
5
|
/**
|
|
8
6
|
* A field mapping configuration.
|
|
9
7
|
*/
|
|
10
|
-
const FieldMappingModel =
|
|
8
|
+
const FieldMappingModel = K5({
|
|
11
9
|
name: "FieldMappingModel",
|
|
12
10
|
fields: {
|
|
13
11
|
id: {
|
|
14
|
-
type:
|
|
12
|
+
type: E5.String_unsecure(),
|
|
15
13
|
isOptional: false
|
|
16
14
|
},
|
|
17
15
|
sourceField: {
|
|
18
|
-
type:
|
|
16
|
+
type: E5.String_unsecure(),
|
|
19
17
|
isOptional: false
|
|
20
18
|
},
|
|
21
19
|
targetField: {
|
|
22
|
-
type:
|
|
20
|
+
type: E5.String_unsecure(),
|
|
23
21
|
isOptional: false
|
|
24
22
|
},
|
|
25
23
|
mappingType: {
|
|
@@ -27,11 +25,11 @@ const FieldMappingModel = defineSchemaModel({
|
|
|
27
25
|
isOptional: false
|
|
28
26
|
},
|
|
29
27
|
transformExpression: {
|
|
30
|
-
type:
|
|
28
|
+
type: E5.String_unsecure(),
|
|
31
29
|
isOptional: true
|
|
32
30
|
},
|
|
33
31
|
isRequired: {
|
|
34
|
-
type:
|
|
32
|
+
type: E5.Boolean(),
|
|
35
33
|
isOptional: false
|
|
36
34
|
}
|
|
37
35
|
}
|
|
@@ -39,23 +37,23 @@ const FieldMappingModel = defineSchemaModel({
|
|
|
39
37
|
/**
|
|
40
38
|
* A sync configuration.
|
|
41
39
|
*/
|
|
42
|
-
const SyncConfigModel =
|
|
40
|
+
const SyncConfigModel = K5({
|
|
43
41
|
name: "SyncConfigModel",
|
|
44
42
|
fields: {
|
|
45
43
|
id: {
|
|
46
|
-
type:
|
|
44
|
+
type: E5.String_unsecure(),
|
|
47
45
|
isOptional: false
|
|
48
46
|
},
|
|
49
47
|
integrationId: {
|
|
50
|
-
type:
|
|
48
|
+
type: E5.String_unsecure(),
|
|
51
49
|
isOptional: false
|
|
52
50
|
},
|
|
53
51
|
connectionId: {
|
|
54
|
-
type:
|
|
52
|
+
type: E5.String_unsecure(),
|
|
55
53
|
isOptional: false
|
|
56
54
|
},
|
|
57
55
|
name: {
|
|
58
|
-
type:
|
|
56
|
+
type: E5.String_unsecure(),
|
|
59
57
|
isOptional: false
|
|
60
58
|
},
|
|
61
59
|
direction: {
|
|
@@ -63,27 +61,27 @@ const SyncConfigModel = defineSchemaModel({
|
|
|
63
61
|
isOptional: false
|
|
64
62
|
},
|
|
65
63
|
sourceObject: {
|
|
66
|
-
type:
|
|
64
|
+
type: E5.String_unsecure(),
|
|
67
65
|
isOptional: false
|
|
68
66
|
},
|
|
69
67
|
targetObject: {
|
|
70
|
-
type:
|
|
68
|
+
type: E5.String_unsecure(),
|
|
71
69
|
isOptional: false
|
|
72
70
|
},
|
|
73
71
|
scheduleEnabled: {
|
|
74
|
-
type:
|
|
72
|
+
type: E5.Boolean(),
|
|
75
73
|
isOptional: false
|
|
76
74
|
},
|
|
77
75
|
scheduleCron: {
|
|
78
|
-
type:
|
|
76
|
+
type: E5.String_unsecure(),
|
|
79
77
|
isOptional: true
|
|
80
78
|
},
|
|
81
79
|
isActive: {
|
|
82
|
-
type:
|
|
80
|
+
type: E5.Boolean(),
|
|
83
81
|
isOptional: false
|
|
84
82
|
},
|
|
85
83
|
lastSyncAt: {
|
|
86
|
-
type:
|
|
84
|
+
type: E5.DateTime(),
|
|
87
85
|
isOptional: true
|
|
88
86
|
},
|
|
89
87
|
fieldMappings: {
|
|
@@ -96,15 +94,15 @@ const SyncConfigModel = defineSchemaModel({
|
|
|
96
94
|
/**
|
|
97
95
|
* A sync run.
|
|
98
96
|
*/
|
|
99
|
-
const SyncRunModel =
|
|
97
|
+
const SyncRunModel = K5({
|
|
100
98
|
name: "SyncRunModel",
|
|
101
99
|
fields: {
|
|
102
100
|
id: {
|
|
103
|
-
type:
|
|
101
|
+
type: E5.String_unsecure(),
|
|
104
102
|
isOptional: false
|
|
105
103
|
},
|
|
106
104
|
syncConfigId: {
|
|
107
|
-
type:
|
|
105
|
+
type: E5.String_unsecure(),
|
|
108
106
|
isOptional: false
|
|
109
107
|
},
|
|
110
108
|
status: {
|
|
@@ -116,39 +114,39 @@ const SyncRunModel = defineSchemaModel({
|
|
|
116
114
|
isOptional: false
|
|
117
115
|
},
|
|
118
116
|
trigger: {
|
|
119
|
-
type:
|
|
117
|
+
type: E5.String_unsecure(),
|
|
120
118
|
isOptional: false
|
|
121
119
|
},
|
|
122
120
|
recordsProcessed: {
|
|
123
|
-
type:
|
|
121
|
+
type: E5.Int_unsecure(),
|
|
124
122
|
isOptional: false
|
|
125
123
|
},
|
|
126
124
|
recordsCreated: {
|
|
127
|
-
type:
|
|
125
|
+
type: E5.Int_unsecure(),
|
|
128
126
|
isOptional: false
|
|
129
127
|
},
|
|
130
128
|
recordsUpdated: {
|
|
131
|
-
type:
|
|
129
|
+
type: E5.Int_unsecure(),
|
|
132
130
|
isOptional: false
|
|
133
131
|
},
|
|
134
132
|
recordsFailed: {
|
|
135
|
-
type:
|
|
133
|
+
type: E5.Int_unsecure(),
|
|
136
134
|
isOptional: false
|
|
137
135
|
},
|
|
138
136
|
errorMessage: {
|
|
139
|
-
type:
|
|
137
|
+
type: E5.String_unsecure(),
|
|
140
138
|
isOptional: true
|
|
141
139
|
},
|
|
142
140
|
startedAt: {
|
|
143
|
-
type:
|
|
141
|
+
type: E5.DateTime(),
|
|
144
142
|
isOptional: true
|
|
145
143
|
},
|
|
146
144
|
completedAt: {
|
|
147
|
-
type:
|
|
145
|
+
type: E5.DateTime(),
|
|
148
146
|
isOptional: true
|
|
149
147
|
},
|
|
150
148
|
createdAt: {
|
|
151
|
-
type:
|
|
149
|
+
type: E5.DateTime(),
|
|
152
150
|
isOptional: false
|
|
153
151
|
}
|
|
154
152
|
}
|
|
@@ -156,19 +154,19 @@ const SyncRunModel = defineSchemaModel({
|
|
|
156
154
|
/**
|
|
157
155
|
* Input for creating a sync config.
|
|
158
156
|
*/
|
|
159
|
-
const CreateSyncConfigInputModel =
|
|
157
|
+
const CreateSyncConfigInputModel = K5({
|
|
160
158
|
name: "CreateSyncConfigInput",
|
|
161
159
|
fields: {
|
|
162
160
|
integrationId: {
|
|
163
|
-
type:
|
|
161
|
+
type: E5.String_unsecure(),
|
|
164
162
|
isOptional: false
|
|
165
163
|
},
|
|
166
164
|
connectionId: {
|
|
167
|
-
type:
|
|
165
|
+
type: E5.String_unsecure(),
|
|
168
166
|
isOptional: false
|
|
169
167
|
},
|
|
170
168
|
name: {
|
|
171
|
-
type:
|
|
169
|
+
type: E5.NonEmptyString(),
|
|
172
170
|
isOptional: false
|
|
173
171
|
},
|
|
174
172
|
direction: {
|
|
@@ -176,19 +174,19 @@ const CreateSyncConfigInputModel = defineSchemaModel({
|
|
|
176
174
|
isOptional: false
|
|
177
175
|
},
|
|
178
176
|
sourceObject: {
|
|
179
|
-
type:
|
|
177
|
+
type: E5.NonEmptyString(),
|
|
180
178
|
isOptional: false
|
|
181
179
|
},
|
|
182
180
|
targetObject: {
|
|
183
|
-
type:
|
|
181
|
+
type: E5.NonEmptyString(),
|
|
184
182
|
isOptional: false
|
|
185
183
|
},
|
|
186
184
|
scheduleEnabled: {
|
|
187
|
-
type:
|
|
185
|
+
type: E5.Boolean(),
|
|
188
186
|
isOptional: true
|
|
189
187
|
},
|
|
190
188
|
scheduleCron: {
|
|
191
|
-
type:
|
|
189
|
+
type: E5.String_unsecure(),
|
|
192
190
|
isOptional: true
|
|
193
191
|
}
|
|
194
192
|
}
|
|
@@ -196,19 +194,19 @@ const CreateSyncConfigInputModel = defineSchemaModel({
|
|
|
196
194
|
/**
|
|
197
195
|
* Input for adding a field mapping.
|
|
198
196
|
*/
|
|
199
|
-
const AddFieldMappingInputModel =
|
|
197
|
+
const AddFieldMappingInputModel = K5({
|
|
200
198
|
name: "AddFieldMappingInput",
|
|
201
199
|
fields: {
|
|
202
200
|
syncConfigId: {
|
|
203
|
-
type:
|
|
201
|
+
type: E5.String_unsecure(),
|
|
204
202
|
isOptional: false
|
|
205
203
|
},
|
|
206
204
|
sourceField: {
|
|
207
|
-
type:
|
|
205
|
+
type: E5.NonEmptyString(),
|
|
208
206
|
isOptional: false
|
|
209
207
|
},
|
|
210
208
|
targetField: {
|
|
211
|
-
type:
|
|
209
|
+
type: E5.NonEmptyString(),
|
|
212
210
|
isOptional: false
|
|
213
211
|
},
|
|
214
212
|
mappingType: {
|
|
@@ -216,23 +214,23 @@ const AddFieldMappingInputModel = defineSchemaModel({
|
|
|
216
214
|
isOptional: false
|
|
217
215
|
},
|
|
218
216
|
transformExpression: {
|
|
219
|
-
type:
|
|
217
|
+
type: E5.String_unsecure(),
|
|
220
218
|
isOptional: true
|
|
221
219
|
},
|
|
222
220
|
lookupConfig: {
|
|
223
|
-
type:
|
|
221
|
+
type: E5.JSON(),
|
|
224
222
|
isOptional: true
|
|
225
223
|
},
|
|
226
224
|
constantValue: {
|
|
227
|
-
type:
|
|
225
|
+
type: E5.JSON(),
|
|
228
226
|
isOptional: true
|
|
229
227
|
},
|
|
230
228
|
isRequired: {
|
|
231
|
-
type:
|
|
229
|
+
type: E5.Boolean(),
|
|
232
230
|
isOptional: true
|
|
233
231
|
},
|
|
234
232
|
defaultValue: {
|
|
235
|
-
type:
|
|
233
|
+
type: E5.JSON(),
|
|
236
234
|
isOptional: true
|
|
237
235
|
}
|
|
238
236
|
}
|
|
@@ -240,11 +238,11 @@ const AddFieldMappingInputModel = defineSchemaModel({
|
|
|
240
238
|
/**
|
|
241
239
|
* Input for triggering a sync.
|
|
242
240
|
*/
|
|
243
|
-
const TriggerSyncInputModel =
|
|
241
|
+
const TriggerSyncInputModel = K5({
|
|
244
242
|
name: "TriggerSyncInput",
|
|
245
243
|
fields: {
|
|
246
244
|
syncConfigId: {
|
|
247
|
-
type:
|
|
245
|
+
type: E5.String_unsecure(),
|
|
248
246
|
isOptional: false
|
|
249
247
|
},
|
|
250
248
|
direction: {
|
|
@@ -252,7 +250,7 @@ const TriggerSyncInputModel = defineSchemaModel({
|
|
|
252
250
|
isOptional: true
|
|
253
251
|
},
|
|
254
252
|
fullSync: {
|
|
255
|
-
type:
|
|
253
|
+
type: E5.Boolean(),
|
|
256
254
|
isOptional: true
|
|
257
255
|
}
|
|
258
256
|
}
|
|
@@ -260,11 +258,11 @@ const TriggerSyncInputModel = defineSchemaModel({
|
|
|
260
258
|
/**
|
|
261
259
|
* Input for listing sync runs.
|
|
262
260
|
*/
|
|
263
|
-
const ListSyncRunsInputModel =
|
|
261
|
+
const ListSyncRunsInputModel = K5({
|
|
264
262
|
name: "ListSyncRunsInput",
|
|
265
263
|
fields: {
|
|
266
264
|
syncConfigId: {
|
|
267
|
-
type:
|
|
265
|
+
type: E5.String_unsecure(),
|
|
268
266
|
isOptional: false
|
|
269
267
|
},
|
|
270
268
|
status: {
|
|
@@ -272,12 +270,12 @@ const ListSyncRunsInputModel = defineSchemaModel({
|
|
|
272
270
|
isOptional: true
|
|
273
271
|
},
|
|
274
272
|
limit: {
|
|
275
|
-
type:
|
|
273
|
+
type: E5.Int_unsecure(),
|
|
276
274
|
isOptional: true,
|
|
277
275
|
defaultValue: 20
|
|
278
276
|
},
|
|
279
277
|
offset: {
|
|
280
|
-
type:
|
|
278
|
+
type: E5.Int_unsecure(),
|
|
281
279
|
isOptional: true,
|
|
282
280
|
defaultValue: 0
|
|
283
281
|
}
|
|
@@ -286,7 +284,7 @@ const ListSyncRunsInputModel = defineSchemaModel({
|
|
|
286
284
|
/**
|
|
287
285
|
* Output for listing sync runs.
|
|
288
286
|
*/
|
|
289
|
-
const ListSyncRunsOutputModel =
|
|
287
|
+
const ListSyncRunsOutputModel = K5({
|
|
290
288
|
name: "ListSyncRunsOutput",
|
|
291
289
|
fields: {
|
|
292
290
|
runs: {
|
|
@@ -295,11 +293,12 @@ const ListSyncRunsOutputModel = defineSchemaModel({
|
|
|
295
293
|
isOptional: false
|
|
296
294
|
},
|
|
297
295
|
total: {
|
|
298
|
-
type:
|
|
296
|
+
type: E5.Int_unsecure(),
|
|
299
297
|
isOptional: false
|
|
300
298
|
}
|
|
301
299
|
}
|
|
302
300
|
});
|
|
303
301
|
|
|
304
302
|
//#endregion
|
|
305
|
-
export { AddFieldMappingInputModel, CreateSyncConfigInputModel, FieldMappingModel, ListSyncRunsInputModel, ListSyncRunsOutputModel, SyncConfigModel, SyncRunModel, TriggerSyncInputModel };
|
|
303
|
+
export { AddFieldMappingInputModel, CreateSyncConfigInputModel, FieldMappingModel, ListSyncRunsInputModel, ListSyncRunsOutputModel, SyncConfigModel, SyncRunModel, TriggerSyncInputModel };
|
|
304
|
+
//# sourceMappingURL=sync.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.schema.js","names":["defineSchemaModel","ScalarTypeEnum"],"sources":["../../src/sync/sync.schema.ts"],"sourcesContent":["import { defineSchemaModel, ScalarTypeEnum } from '@lssm/lib.schema';\nimport {\n SyncDirectionEnum,\n SyncStatusEnum,\n MappingTypeEnum,\n} from './sync.enum';\n\n/**\n * A field mapping configuration.\n */\nexport const FieldMappingModel = defineSchemaModel({\n name: 'FieldMappingModel',\n fields: {\n id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n sourceField: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n targetField: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n mappingType: { type: MappingTypeEnum, isOptional: false },\n transformExpression: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: true,\n },\n isRequired: { type: ScalarTypeEnum.Boolean(), isOptional: false },\n },\n});\n\n/**\n * A sync configuration.\n */\nexport const SyncConfigModel = defineSchemaModel({\n name: 'SyncConfigModel',\n fields: {\n id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n integrationId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n connectionId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n direction: { type: SyncDirectionEnum, isOptional: false },\n sourceObject: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n targetObject: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n scheduleEnabled: { type: ScalarTypeEnum.Boolean(), isOptional: false },\n scheduleCron: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },\n isActive: { type: ScalarTypeEnum.Boolean(), isOptional: false },\n lastSyncAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },\n fieldMappings: { type: FieldMappingModel, isArray: true, isOptional: true },\n },\n});\n\n/**\n * A sync run.\n */\nexport const SyncRunModel = defineSchemaModel({\n name: 'SyncRunModel',\n fields: {\n id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n syncConfigId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n status: { type: SyncStatusEnum, isOptional: false },\n direction: { type: SyncDirectionEnum, isOptional: false },\n trigger: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n recordsProcessed: {\n type: ScalarTypeEnum.Int_unsecure(),\n isOptional: false,\n },\n recordsCreated: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },\n recordsUpdated: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },\n recordsFailed: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },\n errorMessage: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },\n startedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },\n completedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },\n createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },\n },\n});\n\n/**\n * Input for creating a sync config.\n */\nexport const CreateSyncConfigInputModel = defineSchemaModel({\n name: 'CreateSyncConfigInput',\n fields: {\n integrationId: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: false,\n },\n connectionId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },\n direction: { type: SyncDirectionEnum, isOptional: false },\n sourceObject: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },\n targetObject: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },\n scheduleEnabled: { type: ScalarTypeEnum.Boolean(), isOptional: true },\n scheduleCron: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },\n },\n});\n\n/**\n * Input for adding a field mapping.\n */\nexport const AddFieldMappingInputModel = defineSchemaModel({\n name: 'AddFieldMappingInput',\n fields: {\n syncConfigId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n sourceField: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },\n targetField: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },\n mappingType: { type: MappingTypeEnum, isOptional: false },\n transformExpression: {\n type: ScalarTypeEnum.String_unsecure(),\n isOptional: true,\n },\n lookupConfig: { type: ScalarTypeEnum.JSON(), isOptional: true },\n constantValue: { type: ScalarTypeEnum.JSON(), isOptional: true },\n isRequired: { type: ScalarTypeEnum.Boolean(), isOptional: true },\n defaultValue: { type: ScalarTypeEnum.JSON(), isOptional: true },\n },\n});\n\n/**\n * Input for triggering a sync.\n */\nexport const TriggerSyncInputModel = defineSchemaModel({\n name: 'TriggerSyncInput',\n fields: {\n syncConfigId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n direction: { type: SyncDirectionEnum, isOptional: true },\n fullSync: { type: ScalarTypeEnum.Boolean(), isOptional: true },\n },\n});\n\n/**\n * Input for listing sync runs.\n */\nexport const ListSyncRunsInputModel = defineSchemaModel({\n name: 'ListSyncRunsInput',\n fields: {\n syncConfigId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },\n status: { type: SyncStatusEnum, isOptional: true },\n limit: {\n type: ScalarTypeEnum.Int_unsecure(),\n isOptional: true,\n defaultValue: 20,\n },\n offset: {\n type: ScalarTypeEnum.Int_unsecure(),\n isOptional: true,\n defaultValue: 0,\n },\n },\n});\n\n/**\n * Output for listing sync runs.\n */\nexport const ListSyncRunsOutputModel = defineSchemaModel({\n name: 'ListSyncRunsOutput',\n fields: {\n runs: { type: SyncRunModel, isArray: true, isOptional: false },\n total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },\n },\n});\n"],"mappings":"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"}
|
|
@@ -91,7 +91,7 @@ declare class BasicFieldTransformer implements IFieldTransformer {
|
|
|
91
91
|
declare class BasicSyncEngine implements ISyncEngine {
|
|
92
92
|
private transformer;
|
|
93
93
|
constructor(transformer?: IFieldTransformer);
|
|
94
|
-
sync(
|
|
94
|
+
sync(_context: SyncContext): Promise<SyncResult>;
|
|
95
95
|
transformRecord(sourceRecord: SourceRecord, mappings: FieldMapping[], _context: SyncContext): TargetRecord;
|
|
96
96
|
validateRecord(record: TargetRecord, mappings: FieldMapping[]): {
|
|
97
97
|
valid: boolean;
|
|
@@ -105,4 +105,5 @@ declare function createSyncEngine(transformer?: IFieldTransformer): ISyncEngine;
|
|
|
105
105
|
declare function computeChecksum(data: Record<string, unknown>): string;
|
|
106
106
|
declare function hasChanges(sourceChecksum: string | undefined, targetChecksum: string | undefined): boolean;
|
|
107
107
|
//#endregion
|
|
108
|
-
export { BasicFieldTransformer, BasicSyncEngine, FieldMapping, IFieldTransformer, ISyncEngine, LookupConfig, SourceRecord, SyncConfig, SyncContext, SyncError, SyncResult, TargetRecord, computeChecksum, createSyncEngine, hasChanges };
|
|
108
|
+
export { BasicFieldTransformer, BasicSyncEngine, FieldMapping, IFieldTransformer, ISyncEngine, LookupConfig, SourceRecord, SyncConfig, SyncContext, SyncError, SyncResult, TargetRecord, computeChecksum, createSyncEngine, hasChanges };
|
|
109
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/sync-engine/index.ts"],"sourcesContent":[],"mappings":";;AAQA;AAWA;AAMA;AAYA;AAUiB,UAvCA,YAAA,CA+CP;EAGO,WAAA,EAAS,MAAA;EAOT,WAAA,EAAA,MAAY;EAMZ,WAAA,EAAA,QAAY,GAAA,WAEf,GAAA,QAAA,GAAA,UAAA,GAAA,UAAA;EAMG,mBAAW,CAAA,EAAA,MAAA;EAIZ,YAAA,CAAA,EAtEC,YAsED;EAAsB,aAAA,CAAA,EAAA,OAAA;EAAR,UAAA,EAAA,OAAA;EAMZ,YAAA,CAAA,EAAA,OAAA;;AAEL,UAxEI,YAAA,CAwEJ;EACR,YAAA,EAAA,MAAA;EAMO,WAAA,EAAA,MAAA;EACE,WAAA,EAAA,MAAA;;AAC0B,UA3EvB,UAAA,CA2EuB;EAKvB,EAAA,EAAA,MAAA;EAIJ,SAAA,EAAA,SAAA,GAAA,UAAsB,GAAW,eAAA;EAoDjC,YAAA,EAAA,MAAgB;EAGD,YAAA,EAAA,MAAA;EAIL,aAAA,EA1IN,YA0IM,EAAA;EAAsB,SAAA,EAAA,OAAA;EAAR,cAAA,EAAA,OAAA;EAuBnB,aAAA,EAAA,OAAA;EACJ,YAAA,CAAA,EA9JG,MA8JH,CAAA,MAAA,EAAA,OAAA,CAAA;;AAET,UA7JY,WAAA,CA6JZ;EAgEO,KAAA,EAAA,MAAA;EACE,MAAA,EA5NJ,UA4NI;EACiB,UAAA,EAAA;IAnGS,EAAA,EAAA,MAAA;IAAW,QAAA,EAAA,MAAA;IAoLnC,WAAA,CAAA,EA1SE,MA0Sc,CAAA,MAAe,EAAA,OAAA,CAAA;EAM/B,CAAA;AAahB;UAzTiB,UAAA;;;;;;;;UAQP;;UAGO,SAAA;;;;;;UAOA,YAAA;;QAET;;;UAIS,YAAA;;QAET;;;UAMS,WAAA;;;;gBAID,cAAc,QAAQ;;;;gCAMpB,wBACJ,yBACD,cACR;;;;yBAMO,wBACE;;YACiB;;;UAKd,iBAAA;;;cAIJ,qBAAA,YAAiC;;;cAoDjC,eAAA,YAA2B;;4BAGZ;iBAIL,cAAc,QAAQ;gCAuB3B,wBACJ,0BACA,cACT;yBAgEO,wBACE;;YACiB;;;;;;iBAiFf,gBAAA,eAA+B,oBAAoB;iBAMnD,eAAA,OAAsB;iBAatB,UAAA"}
|
|
@@ -33,7 +33,7 @@ var BasicSyncEngine = class {
|
|
|
33
33
|
constructor(transformer) {
|
|
34
34
|
this.transformer = transformer ?? new BasicFieldTransformer();
|
|
35
35
|
}
|
|
36
|
-
async sync(
|
|
36
|
+
async sync(_context) {
|
|
37
37
|
return {
|
|
38
38
|
success: true,
|
|
39
39
|
recordsProcessed: 0,
|
|
@@ -49,12 +49,13 @@ var BasicSyncEngine = class {
|
|
|
49
49
|
const targetData = {};
|
|
50
50
|
for (const mapping of mappings) {
|
|
51
51
|
let value;
|
|
52
|
+
let sourceValue;
|
|
52
53
|
switch (mapping.mappingType) {
|
|
53
54
|
case "DIRECT":
|
|
54
55
|
value = this.getNestedValue(sourceRecord.data, mapping.sourceField);
|
|
55
56
|
break;
|
|
56
57
|
case "TRANSFORM":
|
|
57
|
-
|
|
58
|
+
sourceValue = this.getNestedValue(sourceRecord.data, mapping.sourceField);
|
|
58
59
|
value = mapping.transformExpression ? this.transformer.transform(sourceValue, mapping.transformExpression) : sourceValue;
|
|
59
60
|
break;
|
|
60
61
|
case "CONSTANT":
|
|
@@ -143,4 +144,5 @@ function hasChanges(sourceChecksum, targetChecksum) {
|
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
//#endregion
|
|
146
|
-
export { BasicFieldTransformer, BasicSyncEngine, computeChecksum, createSyncEngine, hasChanges };
|
|
147
|
+
export { BasicFieldTransformer, BasicSyncEngine, computeChecksum, createSyncEngine, hasChanges };
|
|
148
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["targetData: Record<string, unknown>","value: unknown","sourceValue: unknown","errors: SyncError[]","current: unknown"],"sources":["../../src/sync-engine/index.ts"],"sourcesContent":["/**\n * Sync Engine\n *\n * Core sync logic for the Integration Hub.\n */\n\n// ============ Types ============\n\nexport interface FieldMapping {\n sourceField: string;\n targetField: string;\n mappingType: 'DIRECT' | 'TRANSFORM' | 'LOOKUP' | 'CONSTANT' | 'COMPUTED';\n transformExpression?: string;\n lookupConfig?: LookupConfig;\n constantValue?: unknown;\n isRequired: boolean;\n defaultValue?: unknown;\n}\n\nexport interface LookupConfig {\n sourceObject: string;\n lookupField: string;\n returnField: string;\n}\n\nexport interface SyncConfig {\n id: string;\n direction: 'INBOUND' | 'OUTBOUND' | 'BIDIRECTIONAL';\n sourceObject: string;\n targetObject: string;\n fieldMappings: FieldMapping[];\n createNew: boolean;\n updateExisting: boolean;\n deleteRemoved: boolean;\n sourceFilter?: Record<string, unknown>;\n}\n\nexport interface SyncContext {\n runId: string;\n config: SyncConfig;\n connection: {\n id: string;\n authType: string;\n credentials?: Record<string, unknown>;\n };\n}\n\nexport interface SyncResult {\n success: boolean;\n recordsProcessed: number;\n recordsCreated: number;\n recordsUpdated: number;\n recordsDeleted: number;\n recordsFailed: number;\n recordsSkipped: number;\n errors: SyncError[];\n}\n\nexport interface SyncError {\n recordId?: string;\n field?: string;\n message: string;\n code: string;\n}\n\nexport interface SourceRecord {\n id: string;\n data: Record<string, unknown>;\n checksum?: string;\n}\n\nexport interface TargetRecord {\n id: string;\n data: Record<string, unknown>;\n checksum?: string;\n}\n\n// ============ Sync Engine Interface ============\n\nexport interface ISyncEngine {\n /**\n * Execute a sync operation.\n */\n sync(context: SyncContext): Promise<SyncResult>;\n\n /**\n * Transform a source record to target format.\n */\n transformRecord(\n sourceRecord: SourceRecord,\n mappings: FieldMapping[],\n context: SyncContext\n ): TargetRecord;\n\n /**\n * Validate a transformed record.\n */\n validateRecord(\n record: TargetRecord,\n mappings: FieldMapping[]\n ): { valid: boolean; errors: SyncError[] };\n}\n\n// ============ Field Transformer ============\n\nexport interface IFieldTransformer {\n transform(value: unknown, expression: string): unknown;\n}\n\nexport class BasicFieldTransformer implements IFieldTransformer {\n transform(value: unknown, expression: string): unknown {\n // Simple expression evaluation\n // In production, use a proper expression language\n try {\n if (expression.startsWith('uppercase')) {\n return typeof value === 'string' ? value.toUpperCase() : value;\n }\n if (expression.startsWith('lowercase')) {\n return typeof value === 'string' ? value.toLowerCase() : value;\n }\n if (expression.startsWith('trim')) {\n return typeof value === 'string' ? value.trim() : value;\n }\n if (expression.startsWith('default:')) {\n const defaultVal = expression.replace('default:', '');\n return value ?? JSON.parse(defaultVal);\n }\n if (expression.startsWith('concat:')) {\n const separator = expression.replace('concat:', '') || ' ';\n if (Array.isArray(value)) {\n return value.join(separator);\n }\n return value;\n }\n if (expression.startsWith('split:')) {\n const separator = expression.replace('split:', '') || ',';\n if (typeof value === 'string') {\n return value.split(separator);\n }\n return value;\n }\n if (expression.startsWith('number')) {\n return Number(value);\n }\n if (expression.startsWith('boolean')) {\n return Boolean(value);\n }\n if (expression.startsWith('string')) {\n return String(value);\n }\n\n // Return as-is if no transformation matches\n return value;\n } catch {\n return value;\n }\n }\n}\n\n// ============ Basic Sync Engine ============\n\nexport class BasicSyncEngine implements ISyncEngine {\n private transformer: IFieldTransformer;\n\n constructor(transformer?: IFieldTransformer) {\n this.transformer = transformer ?? new BasicFieldTransformer();\n }\n\n async sync(_context: SyncContext): Promise<SyncResult> {\n const result: SyncResult = {\n success: true,\n recordsProcessed: 0,\n recordsCreated: 0,\n recordsUpdated: 0,\n recordsDeleted: 0,\n recordsFailed: 0,\n recordsSkipped: 0,\n errors: [],\n };\n\n // In a real implementation, this would:\n // 1. Fetch records from source\n // 2. Transform each record\n // 3. Validate each record\n // 4. Upsert to target\n // 5. Track sync records for deduplication\n\n return result;\n }\n\n transformRecord(\n sourceRecord: SourceRecord,\n mappings: FieldMapping[],\n _context: SyncContext\n ): TargetRecord {\n const targetData: Record<string, unknown> = {};\n\n for (const mapping of mappings) {\n let value: unknown;\n let sourceValue: unknown;\n\n switch (mapping.mappingType) {\n case 'DIRECT':\n value = this.getNestedValue(sourceRecord.data, mapping.sourceField);\n break;\n\n case 'TRANSFORM':\n sourceValue = this.getNestedValue(\n sourceRecord.data,\n mapping.sourceField\n );\n value = mapping.transformExpression\n ? this.transformer.transform(\n sourceValue,\n mapping.transformExpression\n )\n : sourceValue;\n break;\n\n case 'CONSTANT':\n value = mapping.constantValue;\n break;\n\n case 'LOOKUP':\n // In production, this would fetch from a lookup table\n value = this.getNestedValue(sourceRecord.data, mapping.sourceField);\n break;\n\n case 'COMPUTED':\n // In production, this would evaluate a computed expression\n value = mapping.transformExpression\n ? this.evaluateComputed(\n sourceRecord.data,\n mapping.transformExpression\n )\n : null;\n break;\n\n default:\n value = this.getNestedValue(sourceRecord.data, mapping.sourceField);\n }\n\n // Apply default value if needed\n if (value === undefined || value === null) {\n value = mapping.defaultValue;\n }\n\n // Set the target field\n this.setNestedValue(targetData, mapping.targetField, value);\n }\n\n return {\n id: sourceRecord.id,\n data: targetData,\n };\n }\n\n validateRecord(\n record: TargetRecord,\n mappings: FieldMapping[]\n ): { valid: boolean; errors: SyncError[] } {\n const errors: SyncError[] = [];\n\n for (const mapping of mappings) {\n if (mapping.isRequired) {\n const value = this.getNestedValue(record.data, mapping.targetField);\n if (value === undefined || value === null) {\n errors.push({\n recordId: record.id,\n field: mapping.targetField,\n message: `Required field ${mapping.targetField} is missing`,\n code: 'REQUIRED_FIELD_MISSING',\n });\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n private getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n }\n\n private setNestedValue(\n obj: Record<string, unknown>,\n path: string,\n value: unknown\n ): void {\n const parts = path.split('.');\n let current = obj;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (part === undefined) continue;\n if (!(part in current)) {\n current[part] = {};\n }\n current = current[part] as Record<string, unknown>;\n }\n\n const lastPart = parts[parts.length - 1];\n if (lastPart !== undefined) {\n current[lastPart] = value;\n }\n }\n\n private evaluateComputed(\n data: Record<string, unknown>,\n expression: string\n ): unknown {\n // Simple computed field evaluation\n // In production, use a proper expression evaluator\n try {\n // Support simple field references like ${field.path}\n const result = expression.replace(/\\$\\{([^}]+)\\}/g, (_, path) => {\n const value = this.getNestedValue(data, path);\n return String(value ?? '');\n });\n return result;\n } catch {\n return null;\n }\n }\n}\n\n// ============ Factory ============\n\nexport function createSyncEngine(transformer?: IFieldTransformer): ISyncEngine {\n return new BasicSyncEngine(transformer);\n}\n\n// ============ Checksum Utilities ============\n\nexport function computeChecksum(data: Record<string, unknown>): string {\n // Simple checksum based on JSON serialization\n // In production, use a proper hash function\n const str = JSON.stringify(data, Object.keys(data).sort());\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n return hash.toString(16);\n}\n\nexport function hasChanges(\n sourceChecksum: string | undefined,\n targetChecksum: string | undefined\n): boolean {\n if (!sourceChecksum || !targetChecksum) {\n return true;\n }\n return sourceChecksum !== targetChecksum;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lssm/example.integration-hub",
|
|
3
|
-
"version": "0.0.0-canary-
|
|
3
|
+
"version": "0.0.0-canary-20251220002821",
|
|
4
4
|
"description": "Integration Hub example with sync engine and field mappings for ContractSpec",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -18,20 +18,20 @@
|
|
|
18
18
|
"lint:check": "eslint src"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@lssm/lib.schema": "0.0.0-canary-
|
|
22
|
-
"@lssm/lib.contracts": "0.0.0-canary-
|
|
23
|
-
"@lssm/lib.bus": "0.0.0-canary-
|
|
24
|
-
"@lssm/lib.identity-rbac": "0.0.0-canary-
|
|
25
|
-
"@lssm/lib.files": "0.0.0-canary-
|
|
26
|
-
"@lssm/lib.feature-flags": "0.0.0-canary-
|
|
27
|
-
"@lssm/lib.jobs": "0.0.0-canary-
|
|
28
|
-
"@lssm/module.audit-trail": "0.0.0-canary-
|
|
29
|
-
"@lssm/module.notifications": "0.0.0-canary-
|
|
21
|
+
"@lssm/lib.schema": "0.0.0-canary-20251220002821",
|
|
22
|
+
"@lssm/lib.contracts": "0.0.0-canary-20251220002821",
|
|
23
|
+
"@lssm/lib.bus": "0.0.0-canary-20251220002821",
|
|
24
|
+
"@lssm/lib.identity-rbac": "0.0.0-canary-20251220002821",
|
|
25
|
+
"@lssm/lib.files": "0.0.0-canary-20251220002821",
|
|
26
|
+
"@lssm/lib.feature-flags": "0.0.0-canary-20251220002821",
|
|
27
|
+
"@lssm/lib.jobs": "0.0.0-canary-20251220002821",
|
|
28
|
+
"@lssm/module.audit-trail": "0.0.0-canary-20251220002821",
|
|
29
|
+
"@lssm/module.notifications": "0.0.0-canary-20251220002821",
|
|
30
30
|
"zod": "^4.1.13"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@lssm/tool.typescript": "0.0.0-canary-
|
|
34
|
-
"@lssm/tool.tsdown": "0.0.0-canary-
|
|
33
|
+
"@lssm/tool.typescript": "0.0.0-canary-20251220002821",
|
|
34
|
+
"@lssm/tool.tsdown": "0.0.0-canary-20251220002821",
|
|
35
35
|
"typescript": "^5.9.3"
|
|
36
36
|
},
|
|
37
37
|
"exports": {
|
|
@@ -90,6 +90,13 @@
|
|
|
90
90
|
"./sync/sync.presentation": "./dist/sync/sync.presentation.js",
|
|
91
91
|
"./sync/sync.schema": "./dist/sync/sync.schema.js",
|
|
92
92
|
"./*": "./*"
|
|
93
|
-
}
|
|
93
|
+
},
|
|
94
|
+
"registry": "https://registry.npmjs.org/"
|
|
95
|
+
},
|
|
96
|
+
"license": "MIT",
|
|
97
|
+
"repository": {
|
|
98
|
+
"type": "git",
|
|
99
|
+
"url": "https://github.com/lssm-tech/contractspec.git",
|
|
100
|
+
"directory": "packages/examples/integration-hub"
|
|
94
101
|
}
|
|
95
102
|
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { registerDocBlocks } from "./registry.js";
|
|
2
|
-
|
|
3
|
-
//#region ../../libs/contracts/dist/docs/PUBLISHING.docblock.js
|
|
4
|
-
const PUBLISHING_DocBlocks = [{
|
|
5
|
-
id: "docs.PUBLISHING",
|
|
6
|
-
title: "Publishing ContractSpec Libraries",
|
|
7
|
-
summary: "This guide describes how we release the ContractSpec libraries to npm. We use a dual-track release system: **Stable** (manual) and **Canary** (automatic).",
|
|
8
|
-
kind: "reference",
|
|
9
|
-
visibility: "public",
|
|
10
|
-
route: "/docs/PUBLISHING",
|
|
11
|
-
tags: ["PUBLISHING"],
|
|
12
|
-
body: "# Publishing ContractSpec Libraries\n\nThis guide describes how we release the ContractSpec libraries to npm. We use a dual-track release system: **Stable** (manual) and **Canary** (automatic).\n\n## Release Tracks\n\n| Track | Branch | npm Tag | Frequency | Versioning | Use Case |\n|-------|--------|---------|-----------|------------|----------|\n| **Stable** | `release` | `latest` | Manual | SemVer (e.g., `1.7.4`) | Production, external users |\n| **Canary** | `main` | `canary` | Every Push | Snapshot (e.g., `1.7.4-canary...`) | Dev, internal testing |\n\n## Prerequisites\n\n- ✅ `NPM_TOKEN` secret is configured in GitHub (owner or automation token with _publish_ scope).\n- ✅ `GITHUB_TOKEN` (built-in) has permissions to create PRs (enabled by default in new repos).\n- ✅ For stable releases: `release` branch exists and is protected.\n\n## Canary Workflow (Automatic)\n\nEvery commit pushed to `main` triggers the `.github/workflows/publish-canary.yml` workflow.\n\n1. **Trigger**: Push to `main`.\n2. **Versioning**: Runs `changeset version --snapshot canary` to generate a temporary snapshot version.\n3. **Publish**: Packages are published to npm with the `canary` tag using `changeset publish --tag canary`.\n\n### Consuming Canary Builds\n\nTo install the latest bleeding-edge version:\n\n```bash\nnpm install @lssm/lib.contracts@canary\n# or\nbun add @lssm/lib.contracts@canary\n```\n\n## Stable Release Workflow (Manual)\n\nStable releases are managed via the `release` branch using the standard [Changesets Action](https://github.com/changesets/action).\n\n1. **Develop on `main`**: Create features and fixes.\n2. **Add Changesets**: Run `bun changeset` to document changes and impact (major/minor/patch).\n3. **Merge to `release`**: When ready to ship, open a PR from `main` to `release` or merge manually.\n4. **\"Version Packages\" PR**:\n - The GitHub Action detects new changesets and automatically creates a Pull Request titled **\"Version Packages\"**.\n - This PR contains the version bumps and updated `CHANGELOG.md` files.\n5. **Merge & Publish**:\n - Review and merge the \"Version Packages\" PR.\n - The Action runs again, detects the versions have been bumped, builds the libraries, and publishes them to npm with the `latest` tag.\n\n### Publishing Steps\n\n1. Ensure all changesets are present on `main`.\n2. Merge `main` into `release`:\n ```bash\n git checkout release\n git pull origin release\n git merge main\n git push origin release\n ```\n3. Go to GitHub Pull Requests. You will see a **\"Version Packages\"** PR created by the bot.\n4. Merge that PR.\n5. The release is now live on npm!\n\n## Manual Verification (Optional)\n\nBefore publishing a new version you can run:\n\n```bash\nbun run build:not-apps\nnpx npm-packlist --json packages/libs/contracts\n```\n\n## Rollback\n\nIf a publish fails mid-way, re-run the workflow once the issue is fixed. Already published packages are skipped automatically. Use `npm deprecate <package>@<version>` if we need to warn consumers about a broken release.\n"
|
|
13
|
-
}];
|
|
14
|
-
registerDocBlocks(PUBLISHING_DocBlocks);
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { registerDocBlocks } from "../registry.js";
|
|
2
|
-
|
|
3
|
-
//#region ../../libs/contracts/dist/docs/tech/PHASE_1_QUICKSTART.docblock.js
|
|
4
|
-
const tech_PHASE_1_QUICKSTART_DocBlocks = [{
|
|
5
|
-
id: "docs.tech.PHASE_1_QUICKSTART",
|
|
6
|
-
title: "Phase 1: API Reference Index",
|
|
7
|
-
summary: "Quick reference for all new Phase 1 APIs.",
|
|
8
|
-
kind: "reference",
|
|
9
|
-
visibility: "public",
|
|
10
|
-
route: "/docs/tech/PHASE_1_QUICKSTART",
|
|
11
|
-
tags: ["tech", "PHASE_1_QUICKSTART"],
|
|
12
|
-
body: "# Phase 1: API Reference Index\n\nQuick reference for all new Phase 1 APIs.\n\n---\n\n## @lssm/lib.multi-tenancy\n\n### RLS\n```typescript\nimport { createRlsMiddleware, type TenantIdProvider } from '@lssm/lib.multi-tenancy/rls';\n```\n\n### Provisioning\n```typescript\nimport { \n TenantProvisioningService,\n type CreateTenantInput,\n type TenantProvisioningConfig \n} from '@lssm/lib.multi-tenancy/provisioning';\n```\n\n### Isolation\n```typescript\nimport { IsolationValidator } from '@lssm/lib.multi-tenancy/isolation';\n```\n\n---\n\n## @lssm/lib.observability\n\n### Tracing\n```typescript\nimport { \n getTracer,\n traceAsync,\n traceSync,\n createTracingMiddleware \n} from '@lssm/lib.observability/tracing';\n```\n\n### Metrics\n```typescript\nimport {\n getMeter,\n createCounter,\n createUpDownCounter,\n createHistogram,\n standardMetrics\n} from '@lssm/lib.observability/metrics';\n```\n\n### Logging\n```typescript\nimport {\n Logger,\n logger,\n type LogLevel,\n type LogEntry\n} from '@lssm/lib.observability/logging';\n```\n\n---\n\n## @lssm/lib.resilience\n\n### Circuit Breaker\n```typescript\nimport {\n CircuitBreaker,\n type CircuitState,\n type CircuitBreakerConfig\n} from '@lssm/lib.resilience/circuit-breaker';\n```\n\n### Retry\n```typescript\nimport { retry } from '@lssm/lib.resilience/retry';\n```\n\n### Timeout\n```typescript\nimport { timeout } from '@lssm/lib.resilience/timeout';\n```\n\n### Fallback\n```typescript\nimport { fallback } from '@lssm/lib.resilience/fallback';\n```\n\n---\n\n## Enhanced: @lssm/lib.contracts\n\n### DataViews\n```typescript\nimport { DataViewQueryGenerator } from '@lssm/lib.contracts/data-views/query-generator';\nimport { DataViewRuntime } from '@lssm/lib.contracts/data-views/runtime';\n```\n\n### Workflows\n```typescript\nimport { SLAMonitor, type SLABreachEvent } from '@lssm/lib.contracts/workflow/sla-monitor';\nimport { PrismaStateStore } from '@lssm/lib.contracts/workflow/adapters/db-adapter';\n```\n\n---\n\n## Enhanced: @lssm/lib.design-system\n\n### DataView Components\n```typescript\nimport { DataViewRenderer } from '@lssm/lib.design-system/components/data-view/DataViewRenderer';\n// Also available: DataViewList, DataViewTable, DataViewDetail\n```\n\n---\n\n## Usage Examples\n\n### Complete Workflow with All Features\n\n```typescript\nimport { WorkflowRunner } from '@lssm/lib.contracts/workflow/runner';\nimport { PrismaStateStore } from '@lssm/lib.contracts/workflow/adapters/db-adapter';\nimport { SLAMonitor } from '@lssm/lib.contracts/workflow/sla-monitor';\nimport { CircuitBreaker } from '@lssm/lib.resilience/circuit-breaker';\nimport { traceAsync } from '@lssm/lib.observability/tracing';\n\nconst runner = new WorkflowRunner({\n registry,\n stateStore: new PrismaStateStore(db),\n opExecutor: async (op, input, ctx) => {\n return traceAsync(`op.${op.name}`, async (span) => {\n span.setAttribute('operation', op.name);\n const breaker = getCircuitBreaker(op.name);\n return breaker.execute(() => executeOperation(op, input, ctx));\n });\n },\n eventEmitter: (event, payload) => {\n if (event.startsWith('workflow.')) {\n logger.info(event, payload);\n }\n },\n});\n\nconst monitor = new SLAMonitor((event, payload) => {\n logger.warn('SLA_BREACH', payload);\n alertOps(payload);\n});\n\n// Start workflow\nconst workflowId = await runner.start('payment.flow', 1);\n\n// Monitor SLA\nconst state = await runner.getState(workflowId);\nconst spec = registry.get('payment.flow', 1);\nmonitor.check(state, spec!);\n```\n\n### Complete DataView with Observability\n\n```typescript\nimport { DataViewRenderer } from '@lssm/lib.design-system';\nimport { DataViewQueryGenerator } from '@lssm/lib.contracts/data-views/query-generator';\nimport { traceAsync } from '@lssm/lib.observability/tracing';\nimport { MyDataView } from './specs/users.data-view';\n\nexport function UserListPage() {\n const [page, setPage] = useState(1);\n const [users, setUsers] = useState([]);\n\n const loadUsers = async () => {\n return traceAsync('load_users', async (span) => {\n const generator = new DataViewQueryGenerator(MyDataView);\n const query = generator.generate({ pagination: { page, pageSize: 20 } });\n \n span.setAttribute('page', page);\n const result = await api.execute(query);\n setUsers(result.data);\n });\n };\n\n return (\n <DataViewRenderer\n spec={MyDataView}\n items={users}\n pagination={{ page, pageSize: 20, total: users.length }}\n onPageChange={setPage}\n />\n );\n}\n```\n\n### Complete Multi-Tenant Setup\n\n```typescript\n// 1. RLS Middleware\nimport { createRlsMiddleware } from '@lssm/lib.multi-tenancy/rls';\ndb.$use(createRlsMiddleware(() => req.tenantId));\n\n// 2. Tenant Provisioning\nimport { TenantProvisioningService } from '@lssm/lib.multi-tenancy/provisioning';\nconst service = new TenantProvisioningService({ db });\n\n// 3. Create new tenant\nawait service.provision({\n id: 'acme',\n name: 'Acme Corp',\n slug: 'acme',\n ownerEmail: 'admin@acme.com',\n});\n\n// 4. Validate isolation in tests\nimport { IsolationValidator } from '@lssm/lib.multi-tenancy/isolation';\n\ntest('queries are isolated', () => {\n const isValid = IsolationValidator.validateQuery(\n 'User',\n 'findMany',\n { where: { tenantId: 'acme' } },\n 'acme'\n );\n expect(isValid).toBe(true);\n});\n```\n\n---\n\n## Testing\n\n### Test Circuit Breakers\n\n```typescript\nimport { CircuitBreaker } from '@lssm/lib.resilience/circuit-breaker';\n\ntest('circuit opens after threshold', async () => {\n const breaker = new CircuitBreaker({\n failureThreshold: 3,\n resetTimeoutMs: 5000,\n });\n\n // Trigger failures\n for (let i = 0; i < 3; i++) {\n await expect(\n breaker.execute(() => Promise.reject('error'))\n ).rejects.toThrow();\n }\n\n // Circuit should be open\n await expect(\n breaker.execute(() => Promise.resolve('ok'))\n ).rejects.toThrow('CircuitBreaker is OPEN');\n});\n```\n\n### Test Workflow Retry\n\n```typescript\ntest('workflow retries on failure', async () => {\n let attempts = 0;\n const opExecutor = async () => {\n attempts++;\n if (attempts < 3) throw new Error('fail');\n return 'success';\n };\n\n const runner = new WorkflowRunner({ /* ... */ opExecutor });\n await runner.executeStep(workflowId);\n \n expect(attempts).toBe(3);\n});\n```\n\n---\n\n## Common Patterns\n\n### Pattern: Resilient External Call\n\n```typescript\nimport { CircuitBreaker } from '@lssm/lib.resilience/circuit-breaker';\nimport { retry } from '@lssm/lib.resilience/retry';\nimport { timeout } from '@lssm/lib.resilience/timeout';\nimport { traceAsync } from '@lssm/lib.observability/tracing';\n\nconst breaker = new CircuitBreaker({ failureThreshold: 5, resetTimeoutMs: 30000 });\n\nexport async function callExternalAPI(input: any) {\n return traceAsync('external_api_call', async (span) => {\n span.setAttribute('service', 'stripe');\n \n return breaker.execute(() =>\n retry(\n () => timeout(() => stripe.api.call(input), 5000),\n 3,\n 1000,\n true\n )\n );\n });\n}\n```\n\n**Benefits**: Circuit breaker + retry + timeout + tracing in one place.\n\n---\n\n### Pattern: Tenant-Aware Operation\n\n```typescript\nimport { traceAsync } from '@lssm/lib.observability/tracing';\n\nexport async function listUsers(tenantId: string) {\n return traceAsync('list_users', async (span) => {\n span.setAttribute('tenant_id', tenantId);\n \n // RLS middleware will inject WHERE tenantId = ?\n return db.user.findMany();\n });\n}\n```\n\n---\n\n### Pattern: Monitored Workflow\n\n```typescript\nimport { WorkflowRunner } from '@lssm/lib.contracts/workflow/runner';\nimport { SLAMonitor } from '@lssm/lib.contracts/workflow/sla-monitor';\nimport { logger } from '@lssm/lib.observability/logging';\n\nconst monitor = new SLAMonitor((event, payload) => {\n logger.warn('workflow.sla_breach', payload);\n});\n\n// In workflow poller\nconst state = await runner.getState(workflowId);\nconst spec = registry.get(state.workflowName, state.workflowVersion);\nif (spec) {\n monitor.check(state, spec);\n}\n```\n\n---\n\n## Next Steps\n\n1. **Implement one quick win** (30 minutes)\n2. **Add tests for new functionality** (1 hour)\n3. **Deploy to staging and verify observability** (1 hour)\n4. **Roll out to production** (monitor closely)\n5. **Read full documentation** at https://contractspec.lssm.tech/docs\n\n---\n\n**Questions?** See `/docs/guides/phase-1-migration` or reach out via https://contractspec.lssm.tech/contact\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
13
|
-
}];
|
|
14
|
-
registerDocBlocks(tech_PHASE_1_QUICKSTART_DocBlocks);
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { registerDocBlocks } from "../registry.js";
|
|
2
|
-
|
|
3
|
-
//#region ../../libs/contracts/dist/docs/tech/PHASE_2_AI_NATIVE_OPERATIONS.docblock.js
|
|
4
|
-
const tech_PHASE_2_AI_NATIVE_OPERATIONS_DocBlocks = [{
|
|
5
|
-
id: "docs.tech.PHASE_2_AI_NATIVE_OPERATIONS",
|
|
6
|
-
title: "Phase 2: AI-Native Operations",
|
|
7
|
-
summary: "_Last updated: 2025-11-20_",
|
|
8
|
-
kind: "reference",
|
|
9
|
-
visibility: "public",
|
|
10
|
-
route: "/docs/tech/PHASE_2_AI_NATIVE_OPERATIONS",
|
|
11
|
-
tags: ["tech", "PHASE_2_AI_NATIVE_OPERATIONS"],
|
|
12
|
-
body: "# Phase 2: AI-Native Operations\n\n_Last updated: 2025-11-20_\n\nPhase 2 turns ContractSpec into an AI-first operations stack. The new libraries below are the building blocks used by support bots, growth agents, and human-in-the-loop flows.\n\n## Libraries\n\n### @lssm/lib.ai-agent\n\n- **Spec + Registry**: `defineAgent`, `AgentRegistry` keep agent definitions type-safe.\n- **Runner**: `AgentRunner` drives LLM conversations, tool calls, retries, escalation, and telemetry hooks.\n- **Tools**: `ToolExecutor` standardizes schema validation + timeouts.\n- **Memory**: `InMemoryAgentMemory` + interfaces for plugging persistent stores.\n- **Approvals**: new `ApprovalWorkflow` + `InMemoryApprovalStore` capture low-confidence decisions and surface them to reviewers.\n\n### @lssm/lib.support-bot\n\nComposable support automation primitives:\n\n- `TicketClassifier` → heuristics + optional LLM validation for category, priority, sentiment.\n- `TicketResolver` → RAG pipeline backed by knowledge spaces.\n- `AutoResponder` → tone-aware drafts with citations.\n- `SupportFeedbackLoop` → tracks resolution rates.\n- `createSupportTools` → ready-made tool definitions for AgentRunner.\n\n### @lssm/lib.content-gen\n\nContent generators that consume a `ContentBrief` and output production-ready assets:\n\n- `BlogGenerator`, `LandingPageGenerator`, `EmailCampaignGenerator`, `SocialPostGenerator`.\n- `SeoOptimizer` builds metadata + schema markup.\n\n### @lssm/lib.analytics\n\nQueryless analytics helpers:\n\n- `FunnelAnalyzer` – conversion/drop-off per step.\n- `CohortTracker` – retention + LTV per cohort.\n- `ChurnPredictor` – recency/frequency/error scoring.\n- `GrowthHypothesisGenerator` – surfaces experiment ideas from metric trends.\n\n### @lssm/lib.growth\n\nA/B testing toolkit:\n\n- `ExperimentRegistry` + `ExperimentRunner` – deterministic bucketing.\n- `ExperimentTracker` – persist exposures + metrics.\n- `StatsEngine` – Welch’s t-test + improvement calculations.\n\n### Human-in-the-loop UI\n\n`@lssm/lib.design-system` now exposes:\n\n- `ApprovalQueue` – list + act on pending approvals.\n- `AgentMonitor` – live view of agent sessions with confidence + status.\n\n## Examples\n\n- `examples/ai-support-bot/setup.ts` shows ticket classification → resolution → response draft.\n- `examples/content-generation/generate.ts` produces blog, landing, email, social, SEO output from one brief.\n\n## Next Steps\n\n1. Wire these libraries into vertical apps (H-Circle, ArtisanOS, etc.).\n2. Add background workers that consume the new analytics/growth trackers.\n3. Expand web-landing to highlight these Phase 2 capabilities (see separate TODO).\n"
|
|
13
|
-
}];
|
|
14
|
-
registerDocBlocks(tech_PHASE_2_AI_NATIVE_OPERATIONS_DocBlocks);
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { registerDocBlocks } from "../registry.js";
|
|
2
|
-
|
|
3
|
-
//#region ../../libs/contracts/dist/docs/tech/PHASE_3_AUTO_EVOLUTION.docblock.js
|
|
4
|
-
const tech_PHASE_3_AUTO_EVOLUTION_DocBlocks = [{
|
|
5
|
-
id: "docs.tech.PHASE_3_AUTO_EVOLUTION",
|
|
6
|
-
title: "Phase 3: Auto-Evolution Technical Notes",
|
|
7
|
-
summary: "**Status**: In progress",
|
|
8
|
-
kind: "reference",
|
|
9
|
-
visibility: "public",
|
|
10
|
-
route: "/docs/tech/PHASE_3_AUTO_EVOLUTION",
|
|
11
|
-
tags: ["tech", "PHASE_3_AUTO_EVOLUTION"],
|
|
12
|
-
body: "# Phase 3: Auto-Evolution Technical Notes\n\n**Status**: In progress \n**Last updated**: 2025-11-21 \n\nPhase 3 introduces self-learning capabilities that analyze production telemetry, suggest new specs, safely roll out variants, and generate golden tests from real traffic. This document captures the main building blocks delivered in this iteration.\n\n---\n\n## 1. Libraries\n\n### @lssm/lib.evolution\n\n- `SpecAnalyzer` converts raw telemetry samples into usage stats + anomalies.\n- `SpecGenerator` produces `SpecSuggestion` objects and validates confidence thresholds.\n- `SpecSuggestionOrchestrator` routes proposals through the AI approval workflow and writes approved specs to `packages/libs/contracts/src/generated`.\n- Storage adapters:\n - `InMemorySpecSuggestionRepository` for tests.\n - `PrismaSpecSuggestionRepository` persists to the new Prisma model (see §4).\n - `FileSystemSuggestionWriter` emits JSON envelopes for git review.\n\n### @lssm/lib.observability\n\n- Added intent detection modules:\n - `IntentAggregator` batches telemetry into rolling windows.\n - `IntentDetector` surfaces latency/error/throughput regressions and sequential intents.\n- `EvolutionPipeline` orchestrates aggregation → detection → intent events and exposes hooks for downstream orchestrators.\n- `createTracingMiddleware` now accepts `resolveOperation`/`onSample` hooks to feed telemetry samples into the pipeline.\n\n### @lssm/lib.growth\n\n- New `spec-experiments` module:\n - `SpecExperimentRegistry`, `SpecExperimentRunner`, `SpecExperimentAdapter`.\n - `SpecExperimentAnalyzer` + `SpecExperimentController` handle guardrails and staged rollouts.\n - Helper `createSpecVariantResolver` plugs directly into `HandlerCtx.specVariantResolver`.\n- `SpecVariantResolver` is now a first-class concept in `@lssm/lib.contracts`. The runtime will attempt to execute variant specs before falling back to the registered handler.\n\n### @lssm/lib.testing\n\n- `TrafficRecorder` + `TrafficStore` capture production requests with sampling and sanitization hooks.\n- `GoldenTestGenerator` converts `TrafficSnapshot`s into Vitest/Jest suites.\n- `generateVitestSuite` / `generateJestSuite` output self-contained test files, and `runGoldenTests` offers a programmatic harness for CI pipelines.\n\n---\n\n## 2. Telemetry → Intent → Spec Pipeline\n\n1. `createTracingMiddleware({ onSample })` emits `TelemetrySample`s for every HTTP request.\n2. `IntentAggregator` groups samples into statistical windows (default 15 minutes).\n3. `IntentDetector` raises signals for:\n - Error spikes\n - Latency regressions\n - Throughput drops\n - Sequential workflows that hint at missing specs\n4. `EvolutionPipeline` emits `intent.detected` events and hands them to `SpecGenerator`.\n5. `SpecSuggestionOrchestrator` persists suggestions, triggers approval workflows, and—upon approval—writes JSON envelopes to `packages/.../contracts/src/generated`.\n\n---\n\n## 3. Spec Experiments & Rollouts\n\n1. Register spec experiments in `SpecExperimentRegistry` with control + variant bindings.\n2. Expose bucketed specs by attaching `createSpecVariantResolver` to `HandlerCtx.specVariantResolver` inside adapters.\n3. Record outcomes via `SpecExperimentAdapter.trackOutcome()` (latency + error metrics).\n4. `SpecExperimentController` uses guardrails from config and `SpecExperimentAnalyzer` to:\n - Auto-rollback on error/latency breaches.\n - Advance rollout stages (1% → 10% → 50% → 100%) when metrics stay green.\n\n---\n\n## 4. Data Models (Prisma)\n\nFile: `packages/libs/database/prisma/schema.prisma`\n\n- `SpecSuggestion` – stores serialized suggestion payloads + statuses.\n- `IntentSnapshot` – captured detector output for auditing/training.\n- `TrafficSnapshot` – persisted production traffic (input/output/error blobs).\n- `SpecExperiment` / `SpecExperimentMetric` – rollout state + metrics for each variant.\n\n> Run `bun database generate` after pulling to refresh the Prisma client.\n\n---\n\n## 5. Golden Test Workflow\n\n1. Capture traffic via middleware or direct `TrafficRecorder.record`.\n2. Use the new CLI command to materialize suites:\n\n```bash\ncontractspec test generate \\\n --operation billing.createInvoice \\\n --output tests/billing.createInvoice.golden.test.ts \\\n --runner-import ./tests/run-operation \\\n --runner-fn runBillingCommand \\\n --from-production \\\n --days 7 \\\n --sample-rate 0.05\n```\n\n3. Generated files import your runner and assert against recorded outputs (or expected errors for negative paths).\n\n---\n\n## 6. Operational Notes\n\n- **Approvals**: By default, every suggestion still requires human approval. `EvolutionConfig.autoApproveThreshold` can be tuned per environment but should remain conservative (<0.3) until OverlaySpec tooling lands.\n- **Sampling**: Keep `TrafficRecorder.sampleRate` ≤ 0.05 in production to avoid sensitive payload storage; scrub PII through the `sanitize` callback before persistence.\n- **Rollouts**: Guardrails default to 5% error-rate and 750ms P99 latency. Override per experiment to match SLOs.\n\n---\n\n## 7. Next Steps\n\n1. Wire `SpecExperimentAdapter.trackOutcome` into adapters (REST, GraphQL, Workers) so every execution logs metrics automatically.\n2. Add a UI for reviewing `SpecSuggestion` objects alongside approval status.\n3. Expand `TrafficRecorder` to ship directly to the Prisma-backed store (currently in-memory by default).\n4. Integrate `EvolutionPipeline` events with the Regenerator to close the loop (auto-open proposals + attach evidence).\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
13
|
-
}];
|
|
14
|
-
registerDocBlocks(tech_PHASE_3_AUTO_EVOLUTION_DocBlocks);
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { registerDocBlocks } from "../registry.js";
|
|
2
|
-
|
|
3
|
-
//#region ../../libs/contracts/dist/docs/tech/PHASE_4_PERSONALIZATION_ENGINE.docblock.js
|
|
4
|
-
const tech_PHASE_4_PERSONALIZATION_ENGINE_DocBlocks = [{
|
|
5
|
-
id: "docs.tech.PHASE_4_PERSONALIZATION_ENGINE",
|
|
6
|
-
title: "Phase 4: Personalization Engine",
|
|
7
|
-
summary: "**Status**: Complete",
|
|
8
|
-
kind: "reference",
|
|
9
|
-
visibility: "public",
|
|
10
|
-
route: "/docs/tech/PHASE_4_PERSONALIZATION_ENGINE",
|
|
11
|
-
tags: ["tech", "PHASE_4_PERSONALIZATION_ENGINE"],
|
|
12
|
-
body: "# Phase 4: Personalization Engine\n\n**Status**: Complete \n**Last updated**: 2025-11-21\n\nPhase 4 unlocks tenant-scoped personalization with zero bespoke code. We shipped three new libraries, a signing-aware Overlay editor, and the persistence layer required to observe usage and apply overlays safely.\n\n---\n\n## 1. Libraries\n\n### @lssm/lib.overlay-engine\n\n- OverlaySpec types + validator mirror the public spec.\n- Cryptographic signer (`ed25519`, `rsa-pss-sha256`) with canonical JSON serialization.\n- Registry that merges tenant/role/user/device overlays with predictable specificity.\n- React hooks (`useOverlay`, `useOverlayFields`) for client-side rendering.\n- Runtime engine audits every applied overlay for traceability.\n\n### @lssm/lib.personalization\n\n- Behavior tracker buffers field/feature/workflow events and exports OTel metrics.\n- Analyzer summarizes field usage and workflow drop-offs into actionable insights.\n- Adapter translates insights into overlay suggestions or workflow tweaks.\n- In-memory store implementation + interface for plugging Prisma/ClickHouse later.\n\n### @lssm/lib.workflow-composer\n\n- `WorkflowComposer` merges base workflows with tenant/role/device extensions.\n- Step injection utilities keep transitions intact and validate anchor steps.\n- Template helpers for common tenant review/approval, plus merge helpers for multi-scope extensions.\n\n---\n\n## 2. Overlay Editor App\n\nPath: `packages/apps/overlay-editor`\n\n- Next.js App Router UI for toggling field visibility, renaming labels, and reordering lists.\n- Live JSON preview powered by `defineOverlay`.\n- Server action that signs overlays via PEM private keys (Ed25519 by default) using the overlay engine signer.\n\n---\n\n## 3. Persistence\n\nAdded Prisma models (see `packages/libs/database/prisma/schema.prisma`):\n\n- `UserBehaviorEvent` – field/feature/workflow telemetry.\n- `OverlaySigningKey` – tenant managed signing keys with revocation timestamps.\n- `Overlay` – stored overlays (tenant/user/role/device scope) plus signature metadata.\n\n---\n\n## 4. Integration Steps\n\n1. Track usage inside apps via `createBehaviorTracker`.\n2. Periodically run `BehaviorAnalyzer.analyze` to generate insights.\n3. Convert insights into OverlaySpecs or Workflow extensions.\n4. Register tenant overlays in `OverlayRegistry` and serve via presentation runtimes.\n5. Compose workflows per tenant using `WorkflowComposer`.\n\nSee the `docs/tech/personalization/*` guides for concrete examples.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
|
13
|
-
}];
|
|
14
|
-
registerDocBlocks(tech_PHASE_4_PERSONALIZATION_ENGINE_DocBlocks);
|
|
15
|
-
|
|
16
|
-
//#endregion
|