crewly 1.5.10 → 1.5.12
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/config/constants.ts +3 -3
- package/config/orchestrator_tasks/prompts/orchestrator-prompt.md +73 -0
- package/config/roles/architect/prompt.md +9 -0
- package/config/roles/backend-developer/prompt.md +9 -0
- package/config/roles/content-strategist/prompt.md +10 -0
- package/config/roles/designer/prompt.md +9 -0
- package/config/roles/developer/prompt.md +9 -0
- package/config/roles/frontend-developer/prompt.md +9 -0
- package/config/roles/fullstack-dev/prompt.md +9 -0
- package/config/roles/generalist/prompt.md +9 -0
- package/config/roles/ops/prompt.md +9 -0
- package/config/roles/product-manager/prompt.md +9 -0
- package/config/roles/qa/prompt.md +9 -0
- package/config/roles/qa-engineer/prompt.md +9 -0
- package/config/roles/researcher/prompt.md +9 -0
- package/config/roles/sales/prompt.md +9 -0
- package/config/roles/support/prompt.md +9 -0
- package/config/roles/team-leader/prompt.md +11 -0
- package/config/roles/tpm/prompt.md +9 -0
- package/config/roles/ux-designer/prompt.md +9 -0
- package/config/skills/agent/core/block-task/execute.sh +3 -1
- package/config/skills/agent/core/pipe-to-sink/execute.sh +41 -0
- package/config/skills/agent/core/read-task/execute.sh +3 -1
- package/config/skills/agent/core/report-progress/execute.sh +3 -1
- package/config/skills/agent/screenshot-compare/SKILL.md +75 -0
- package/config/skills/agent/screenshot-compare/execute.sh +182 -0
- package/config/skills/agent/screenshot-compare/skill.json +10 -0
- package/config/skills/agent/xiaoyuzhoufm-transcript/SKILL.md +85 -0
- package/config/skills/agent/xiaoyuzhoufm-transcript/execute.sh +306 -0
- package/config/skills/agent/xiaoyuzhoufm-transcript/skill.json +10 -0
- package/config/skills/orchestrator/cancel-cron/SKILL.md +44 -0
- package/config/skills/orchestrator/create-cron/SKILL.md +58 -0
- package/config/skills/orchestrator/list-cron/SKILL.md +51 -0
- package/config/skills/orchestrator/update-cron/SKILL.md +52 -0
- package/config/skills/orchestrator/update-team-member/SKILL.md +36 -0
- package/config/skills/orchestrator/update-team-member/execute.sh +25 -0
- package/dist/backend/backend/src/constants.d.ts +7 -4
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +6 -3
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts +21 -2
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.js +167 -29
- package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.d.ts +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.routes.js +7 -3
- package/dist/backend/backend/src/controllers/browser/browser.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/data/data.controller.d.ts +47 -0
- package/dist/backend/backend/src/controllers/data/data.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/data/data.controller.js +201 -0
- package/dist/backend/backend/src/controllers/data/data.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/data/data.routes.d.ts +18 -0
- package/dist/backend/backend/src/controllers/data/data.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/data/data.routes.js +44 -0
- package/dist/backend/backend/src/controllers/data/data.routes.js.map +1 -0
- package/dist/backend/backend/src/controllers/monitoring/token-usage.controller.d.ts +3 -2
- package/dist/backend/backend/src/controllers/monitoring/token-usage.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/token-usage.controller.js +5 -3
- package/dist/backend/backend/src/controllers/monitoring/token-usage.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/system/cron-task.controller.d.ts +4 -0
- package/dist/backend/backend/src/controllers/system/cron-task.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/cron-task.controller.js +20 -0
- package/dist/backend/backend/src/controllers/system/cron-task.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +18 -0
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team-export.controller.d.ts +32 -0
- package/dist/backend/backend/src/controllers/team/team-export.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/team/team-export.controller.js +61 -0
- package/dist/backend/backend/src/controllers/team/team-export.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.js +66 -46
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.routes.js +7 -0
- package/dist/backend/backend/src/controllers/team/team.routes.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +37 -7
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +4 -1
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +6 -2
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js +17 -2
- package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +2 -2
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/backend/backend/src/services/agent/task-planning.service.d.ts +134 -0
- package/dist/backend/backend/src/services/agent/task-planning.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/task-planning.service.js +291 -0
- package/dist/backend/backend/src/services/agent/task-planning.service.js.map +1 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js +8 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +3 -3
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts +13 -9
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js +44 -12
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts +176 -0
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js +441 -0
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -0
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts +162 -0
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js +350 -0
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js.map +1 -0
- package/dist/backend/backend/src/services/cloud/cloud-initializer.d.ts +8 -0
- package/dist/backend/backend/src/services/cloud/cloud-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-initializer.js +27 -0
- package/dist/backend/backend/src/services/cloud/cloud-initializer.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.js +2 -0
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/dist/backend/backend/src/services/core/team-export.service.d.ts +103 -0
- package/dist/backend/backend/src/services/core/team-export.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/core/team-export.service.js +182 -0
- package/dist/backend/backend/src/services/core/team-export.service.js.map +1 -0
- package/dist/backend/backend/src/services/data/data-object-store.service.d.ts +160 -0
- package/dist/backend/backend/src/services/data/data-object-store.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/data/data-object-store.service.js +434 -0
- package/dist/backend/backend/src/services/data/data-object-store.service.js.map +1 -0
- package/dist/backend/backend/src/services/data/data-object.types.d.ts +190 -0
- package/dist/backend/backend/src/services/data/data-object.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/data/data-object.types.js +143 -0
- package/dist/backend/backend/src/services/data/data-object.types.js.map +1 -0
- package/dist/backend/backend/src/services/data/schema-registry.service.d.ts +108 -0
- package/dist/backend/backend/src/services/data/schema-registry.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/data/schema-registry.service.js +290 -0
- package/dist/backend/backend/src/services/data/schema-registry.service.js.map +1 -0
- package/dist/backend/backend/src/services/data/sink-registry.service.d.ts +87 -0
- package/dist/backend/backend/src/services/data/sink-registry.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/data/sink-registry.service.js +188 -0
- package/dist/backend/backend/src/services/data/sink-registry.service.js.map +1 -0
- package/dist/backend/backend/src/services/messaging/message-router.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/message-router.service.js +7 -0
- package/dist/backend/backend/src/services/messaging/message-router.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts +55 -2
- package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js +89 -5
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js.map +1 -1
- package/dist/backend/backend/src/services/session/pty/pty-session-backend.js +1 -1
- package/dist/backend/backend/src/services/session/pty/pty-session-backend.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/cron-task.service.d.ts +105 -14
- package/dist/backend/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/cron-task.service.js +400 -123
- package/dist/backend/backend/src/services/workflow/cron-task.service.js.map +1 -1
- package/dist/backend/backend/src/types/cron-task.types.d.ts +1 -1
- package/dist/backend/backend/src/types/data-object.types.d.ts +117 -0
- package/dist/backend/backend/src/types/data-object.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/data-object.types.js +23 -0
- package/dist/backend/backend/src/types/data-object.types.js.map +1 -0
- package/dist/backend/backend/src/types/settings.types.js +1 -1
- package/dist/backend/config/constants.d.ts +3 -3
- package/dist/backend/config/constants.js +3 -3
- package/dist/backend/config/constants.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +7 -4
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +6 -3
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/types/settings.types.js +1 -1
- package/dist/cli/config/constants.d.ts +3 -3
- package/dist/cli/config/constants.js +3 -3
- package/dist/cli/config/constants.js.map +1 -1
- package/frontend/dist/assets/index-371b68d4.css +33 -0
- package/frontend/dist/assets/{index-76782e9e.js → index-506f70da.js} +321 -321
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/frontend/dist/assets/index-b19b2478.css +0 -33
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data Architecture V2.2 — Unified DataObject Model (UDM)
|
|
3
|
+
*
|
|
4
|
+
* Defines the core types for the structured data fabric:
|
|
5
|
+
* DataObject, SchemaDefinition, SinkDefinition, and related types.
|
|
6
|
+
*
|
|
7
|
+
* @see specs/crewly-data-architecture-v2.md
|
|
8
|
+
*/
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Type Guards
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/**
|
|
13
|
+
* Runtime check that a value is a valid DataObject.
|
|
14
|
+
*
|
|
15
|
+
* Validates the presence and types of all required top-level fields
|
|
16
|
+
* and the nested metadata structure.
|
|
17
|
+
*
|
|
18
|
+
* @param value - The value to check
|
|
19
|
+
* @returns true if value satisfies the DataObject interface
|
|
20
|
+
*/
|
|
21
|
+
export function isDataObject(value) {
|
|
22
|
+
if (typeof value !== 'object' || value === null)
|
|
23
|
+
return false;
|
|
24
|
+
const obj = value;
|
|
25
|
+
// Top-level required strings
|
|
26
|
+
if (typeof obj.id !== 'string')
|
|
27
|
+
return false;
|
|
28
|
+
if (!isDataObjectType(obj.type))
|
|
29
|
+
return false;
|
|
30
|
+
if (!isDataObjectScope(obj.scope))
|
|
31
|
+
return false;
|
|
32
|
+
if (typeof obj.schema_id !== 'string')
|
|
33
|
+
return false;
|
|
34
|
+
if (!isDataObjectStatus(obj.status))
|
|
35
|
+
return false;
|
|
36
|
+
if (typeof obj.owner_id !== 'string')
|
|
37
|
+
return false;
|
|
38
|
+
if (typeof obj.namespace !== 'string')
|
|
39
|
+
return false;
|
|
40
|
+
if (!isSyncState(obj.sync_state))
|
|
41
|
+
return false;
|
|
42
|
+
// payload
|
|
43
|
+
if (typeof obj.payload !== 'object' || obj.payload === null)
|
|
44
|
+
return false;
|
|
45
|
+
// metadata
|
|
46
|
+
if (typeof obj.metadata !== 'object' || obj.metadata === null)
|
|
47
|
+
return false;
|
|
48
|
+
const meta = obj.metadata;
|
|
49
|
+
if (typeof meta.created_at !== 'string')
|
|
50
|
+
return false;
|
|
51
|
+
if (typeof meta.updated_at !== 'string')
|
|
52
|
+
return false;
|
|
53
|
+
if (!Array.isArray(meta.tags))
|
|
54
|
+
return false;
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Runtime check that a value is a valid SchemaDefinition.
|
|
59
|
+
*
|
|
60
|
+
* @param value - The value to check
|
|
61
|
+
* @returns true if value satisfies the SchemaDefinition interface
|
|
62
|
+
*/
|
|
63
|
+
export function isSchemaDefinition(value) {
|
|
64
|
+
if (typeof value !== 'object' || value === null)
|
|
65
|
+
return false;
|
|
66
|
+
const obj = value;
|
|
67
|
+
if (typeof obj.id !== 'string')
|
|
68
|
+
return false;
|
|
69
|
+
if (typeof obj.name !== 'string')
|
|
70
|
+
return false;
|
|
71
|
+
if (typeof obj.version !== 'string')
|
|
72
|
+
return false;
|
|
73
|
+
if (typeof obj.fields !== 'object' || obj.fields === null)
|
|
74
|
+
return false;
|
|
75
|
+
if (typeof obj.write_policy !== 'object' || obj.write_policy === null)
|
|
76
|
+
return false;
|
|
77
|
+
const wp = obj.write_policy;
|
|
78
|
+
if (typeof wp.allow_unstructured !== 'boolean')
|
|
79
|
+
return false;
|
|
80
|
+
if (!isValidationLevel(wp.validation_level))
|
|
81
|
+
return false;
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Runtime check that a value is a valid SinkDefinition.
|
|
86
|
+
*
|
|
87
|
+
* @param value - The value to check
|
|
88
|
+
* @returns true if value satisfies the SinkDefinition interface
|
|
89
|
+
*/
|
|
90
|
+
export function isSinkDefinition(value) {
|
|
91
|
+
if (typeof value !== 'object' || value === null)
|
|
92
|
+
return false;
|
|
93
|
+
const obj = value;
|
|
94
|
+
if (typeof obj.id !== 'string')
|
|
95
|
+
return false;
|
|
96
|
+
if (typeof obj.name !== 'string')
|
|
97
|
+
return false;
|
|
98
|
+
if (!isSinkType(obj.type))
|
|
99
|
+
return false;
|
|
100
|
+
if (typeof obj.path !== 'string')
|
|
101
|
+
return false;
|
|
102
|
+
if (!isSinkFormat(obj.format))
|
|
103
|
+
return false;
|
|
104
|
+
if (typeof obj.responsible_agent !== 'string')
|
|
105
|
+
return false;
|
|
106
|
+
if (!Array.isArray(obj.notify))
|
|
107
|
+
return false;
|
|
108
|
+
if (typeof obj.description !== 'string')
|
|
109
|
+
return false;
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// Internal helpers — narrow literal unions
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
/** @internal */
|
|
116
|
+
function isDataObjectType(v) {
|
|
117
|
+
return v === 'memory' || v === 'knowledge' || v === 'sink_entry';
|
|
118
|
+
}
|
|
119
|
+
/** @internal */
|
|
120
|
+
function isDataObjectScope(v) {
|
|
121
|
+
return v === 'agent' || v === 'project' || v === 'global';
|
|
122
|
+
}
|
|
123
|
+
/** @internal */
|
|
124
|
+
function isDataObjectStatus(v) {
|
|
125
|
+
return v === 'new' || v === 'processed' || v === 'archived';
|
|
126
|
+
}
|
|
127
|
+
/** @internal */
|
|
128
|
+
function isSyncState(v) {
|
|
129
|
+
return v === 'local' || v === 'synced' || v === 'conflict';
|
|
130
|
+
}
|
|
131
|
+
/** @internal */
|
|
132
|
+
function isValidationLevel(v) {
|
|
133
|
+
return v === 'strict' || v === 'loose' || v === 'none';
|
|
134
|
+
}
|
|
135
|
+
/** @internal */
|
|
136
|
+
function isSinkType(v) {
|
|
137
|
+
return v === 'collection' || v === 'log';
|
|
138
|
+
}
|
|
139
|
+
/** @internal */
|
|
140
|
+
function isSinkFormat(v) {
|
|
141
|
+
return v === 'markdown' || v === 'json' || v === 'jsonl';
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=data-object.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-object.types.js","sourceRoot":"","sources":["../../../../../../backend/src/services/data/data-object.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Registry Service
|
|
3
|
+
*
|
|
4
|
+
* Loads schema definitions from project sink directories and validates
|
|
5
|
+
* data payloads against those schemas. Central to the Data Architecture V2
|
|
6
|
+
* governance layer — ensures every piece of data entering a sink conforms
|
|
7
|
+
* to its declared structure.
|
|
8
|
+
*
|
|
9
|
+
* @module services/data/schema-registry.service
|
|
10
|
+
*/
|
|
11
|
+
import type { SchemaDefinition, ValidationResult } from '../../types/data-object.types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Singleton service that manages schema definitions and validates payloads.
|
|
14
|
+
*
|
|
15
|
+
* Schemas are loaded from `{projectPath}/sinks/{sinkDir}/_schema.json` for
|
|
16
|
+
* each registered sink, or from a consolidated registry file. The validate()
|
|
17
|
+
* method applies all declared field rules and returns a structured result.
|
|
18
|
+
*/
|
|
19
|
+
export declare class SchemaRegistryService {
|
|
20
|
+
private static instance;
|
|
21
|
+
private readonly logger;
|
|
22
|
+
private readonly schemas;
|
|
23
|
+
private constructor();
|
|
24
|
+
/**
|
|
25
|
+
* Get the singleton instance.
|
|
26
|
+
*
|
|
27
|
+
* @returns SchemaRegistryService singleton
|
|
28
|
+
*/
|
|
29
|
+
static getInstance(): SchemaRegistryService;
|
|
30
|
+
/**
|
|
31
|
+
* Reset the singleton (for testing).
|
|
32
|
+
*/
|
|
33
|
+
static resetInstance(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Load schemas from a project's sinks directory.
|
|
36
|
+
*
|
|
37
|
+
* Scans `{projectPath}/sinks/` for sub-directories containing a
|
|
38
|
+
* `_schema.json` file and registers each valid schema.
|
|
39
|
+
*
|
|
40
|
+
* @param projectPath - Absolute path to the Crewly project root
|
|
41
|
+
*/
|
|
42
|
+
loadSchemas(projectPath: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Register a schema definition directly (e.g. from tests or programmatic setup).
|
|
45
|
+
*
|
|
46
|
+
* @param schema - The schema to register
|
|
47
|
+
*/
|
|
48
|
+
registerSchema(schema: SchemaDefinition): void;
|
|
49
|
+
/**
|
|
50
|
+
* Get a schema by its ID.
|
|
51
|
+
*
|
|
52
|
+
* @param schemaId - Unique schema identifier
|
|
53
|
+
* @returns The schema, or null if not found
|
|
54
|
+
*/
|
|
55
|
+
getSchema(schemaId: string): SchemaDefinition | null;
|
|
56
|
+
/**
|
|
57
|
+
* List all loaded schemas.
|
|
58
|
+
*
|
|
59
|
+
* @returns Array of all registered SchemaDefinitions
|
|
60
|
+
*/
|
|
61
|
+
listSchemas(): SchemaDefinition[];
|
|
62
|
+
/**
|
|
63
|
+
* Validate a payload against a registered schema.
|
|
64
|
+
*
|
|
65
|
+
* Applies the following rules per field:
|
|
66
|
+
* - **required**: field must exist and not be null/undefined
|
|
67
|
+
* - **type**: JS typeof must match (with special handling for array, datetime, enum)
|
|
68
|
+
* - **max_length**: string length must not exceed limit
|
|
69
|
+
* - **enum options**: value must be one of the declared options
|
|
70
|
+
* - **array min_items**: array length must meet minimum
|
|
71
|
+
* - **datetime**: value must match ISO 8601 format
|
|
72
|
+
*
|
|
73
|
+
* @param schemaId - ID of the schema to validate against
|
|
74
|
+
* @param payload - Key-value data to validate
|
|
75
|
+
* @returns Structured validation result with any errors
|
|
76
|
+
*/
|
|
77
|
+
validate(schemaId: string, payload: Record<string, unknown>): ValidationResult;
|
|
78
|
+
/**
|
|
79
|
+
* Validate a single field against its definition, pushing errors into the array.
|
|
80
|
+
*
|
|
81
|
+
* @param fieldName - Name of the field being validated
|
|
82
|
+
* @param fieldDef - Schema field definition
|
|
83
|
+
* @param value - Actual value from the payload
|
|
84
|
+
* @param errors - Mutable array to collect validation errors
|
|
85
|
+
*/
|
|
86
|
+
private validateField;
|
|
87
|
+
/**
|
|
88
|
+
* Validate a string field (typeof + max_length).
|
|
89
|
+
*/
|
|
90
|
+
private validateString;
|
|
91
|
+
/**
|
|
92
|
+
* Validate a primitive type via typeof.
|
|
93
|
+
*/
|
|
94
|
+
private validateType;
|
|
95
|
+
/**
|
|
96
|
+
* Validate an array field (isArray + min_items).
|
|
97
|
+
*/
|
|
98
|
+
private validateArray;
|
|
99
|
+
/**
|
|
100
|
+
* Validate a datetime field (must be a string matching ISO 8601).
|
|
101
|
+
*/
|
|
102
|
+
private validateDatetime;
|
|
103
|
+
/**
|
|
104
|
+
* Validate an enum field (value must be one of options).
|
|
105
|
+
*/
|
|
106
|
+
private validateEnum;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=schema-registry.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-registry.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/data/schema-registry.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EACV,gBAAgB,EAEhB,gBAAgB,EAEjB,MAAM,kCAAkC,CAAC;AAM1C;;;;;;GAMG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAsC;IAC7D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4C;IAEpE,OAAO;IAIP;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,qBAAqB;IAO3C;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;IAQ5B;;;;;;;OAOG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCrD;;;;OAIG;IACH,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAQ9C;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAIpD;;;;OAIG;IACH,WAAW,IAAI,gBAAgB,EAAE;IAQjC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB;IAwB9E;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IAwCrB;;OAEG;IACH,OAAO,CAAC,cAAc;IAwBtB;;OAEG;IACH,OAAO,CAAC,YAAY;IAepB;;OAEG;IACH,OAAO,CAAC,aAAa;IAwBrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuBxB;;OAEG;IACH,OAAO,CAAC,YAAY;CAuBrB"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Registry Service
|
|
3
|
+
*
|
|
4
|
+
* Loads schema definitions from project sink directories and validates
|
|
5
|
+
* data payloads against those schemas. Central to the Data Architecture V2
|
|
6
|
+
* governance layer — ensures every piece of data entering a sink conforms
|
|
7
|
+
* to its declared structure.
|
|
8
|
+
*
|
|
9
|
+
* @module services/data/schema-registry.service
|
|
10
|
+
*/
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import * as fs from 'fs/promises';
|
|
13
|
+
import { existsSync } from 'fs';
|
|
14
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
15
|
+
import { DATA_CONSTANTS } from '../../types/data-object.types.js';
|
|
16
|
+
/** ISO 8601 date-time regex (accepts both Z and +/-offset) */
|
|
17
|
+
const ISO8601_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
|
|
18
|
+
/**
|
|
19
|
+
* Singleton service that manages schema definitions and validates payloads.
|
|
20
|
+
*
|
|
21
|
+
* Schemas are loaded from `{projectPath}/sinks/{sinkDir}/_schema.json` for
|
|
22
|
+
* each registered sink, or from a consolidated registry file. The validate()
|
|
23
|
+
* method applies all declared field rules and returns a structured result.
|
|
24
|
+
*/
|
|
25
|
+
export class SchemaRegistryService {
|
|
26
|
+
static instance = null;
|
|
27
|
+
logger;
|
|
28
|
+
schemas = new Map();
|
|
29
|
+
constructor() {
|
|
30
|
+
this.logger = LoggerService.getInstance().createComponentLogger('SchemaRegistryService');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the singleton instance.
|
|
34
|
+
*
|
|
35
|
+
* @returns SchemaRegistryService singleton
|
|
36
|
+
*/
|
|
37
|
+
static getInstance() {
|
|
38
|
+
if (!SchemaRegistryService.instance) {
|
|
39
|
+
SchemaRegistryService.instance = new SchemaRegistryService();
|
|
40
|
+
}
|
|
41
|
+
return SchemaRegistryService.instance;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Reset the singleton (for testing).
|
|
45
|
+
*/
|
|
46
|
+
static resetInstance() {
|
|
47
|
+
SchemaRegistryService.instance = null;
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Loading
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
/**
|
|
53
|
+
* Load schemas from a project's sinks directory.
|
|
54
|
+
*
|
|
55
|
+
* Scans `{projectPath}/sinks/` for sub-directories containing a
|
|
56
|
+
* `_schema.json` file and registers each valid schema.
|
|
57
|
+
*
|
|
58
|
+
* @param projectPath - Absolute path to the Crewly project root
|
|
59
|
+
*/
|
|
60
|
+
async loadSchemas(projectPath) {
|
|
61
|
+
const sinksDir = path.join(projectPath, DATA_CONSTANTS.SINKS_DIR);
|
|
62
|
+
if (!existsSync(sinksDir)) {
|
|
63
|
+
this.logger.warn('Sinks directory does not exist, no schemas loaded', { sinksDir });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const entries = await fs.readdir(sinksDir, { withFileTypes: true });
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
if (!entry.isDirectory() || entry.name.startsWith('_')) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const schemaPath = path.join(sinksDir, entry.name, DATA_CONSTANTS.SCHEMA_FILE);
|
|
72
|
+
if (!existsSync(schemaPath)) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const raw = await fs.readFile(schemaPath, 'utf-8');
|
|
77
|
+
const schema = JSON.parse(raw);
|
|
78
|
+
if (!schema.id || !schema.fields) {
|
|
79
|
+
this.logger.warn('Skipping invalid schema file (missing id or fields)', { schemaPath });
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
this.schemas.set(schema.id, schema);
|
|
83
|
+
this.logger.debug?.(`Loaded schema: ${schema.id}`, { name: schema.name });
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
this.logger.warn('Failed to parse schema file', {
|
|
87
|
+
schemaPath,
|
|
88
|
+
error: err.message,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Register a schema definition directly (e.g. from tests or programmatic setup).
|
|
95
|
+
*
|
|
96
|
+
* @param schema - The schema to register
|
|
97
|
+
*/
|
|
98
|
+
registerSchema(schema) {
|
|
99
|
+
this.schemas.set(schema.id, schema);
|
|
100
|
+
}
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// Accessors
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
/**
|
|
105
|
+
* Get a schema by its ID.
|
|
106
|
+
*
|
|
107
|
+
* @param schemaId - Unique schema identifier
|
|
108
|
+
* @returns The schema, or null if not found
|
|
109
|
+
*/
|
|
110
|
+
getSchema(schemaId) {
|
|
111
|
+
return this.schemas.get(schemaId) ?? null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* List all loaded schemas.
|
|
115
|
+
*
|
|
116
|
+
* @returns Array of all registered SchemaDefinitions
|
|
117
|
+
*/
|
|
118
|
+
listSchemas() {
|
|
119
|
+
return Array.from(this.schemas.values());
|
|
120
|
+
}
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Validation
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
/**
|
|
125
|
+
* Validate a payload against a registered schema.
|
|
126
|
+
*
|
|
127
|
+
* Applies the following rules per field:
|
|
128
|
+
* - **required**: field must exist and not be null/undefined
|
|
129
|
+
* - **type**: JS typeof must match (with special handling for array, datetime, enum)
|
|
130
|
+
* - **max_length**: string length must not exceed limit
|
|
131
|
+
* - **enum options**: value must be one of the declared options
|
|
132
|
+
* - **array min_items**: array length must meet minimum
|
|
133
|
+
* - **datetime**: value must match ISO 8601 format
|
|
134
|
+
*
|
|
135
|
+
* @param schemaId - ID of the schema to validate against
|
|
136
|
+
* @param payload - Key-value data to validate
|
|
137
|
+
* @returns Structured validation result with any errors
|
|
138
|
+
*/
|
|
139
|
+
validate(schemaId, payload) {
|
|
140
|
+
const schema = this.schemas.get(schemaId);
|
|
141
|
+
if (!schema) {
|
|
142
|
+
return {
|
|
143
|
+
valid: false,
|
|
144
|
+
errors: [{ field: '_schema', message: `Schema '${schemaId}' not found`, rule: 'schema_exists' }],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const errors = [];
|
|
148
|
+
for (const [fieldName, fieldDef] of Object.entries(schema.fields)) {
|
|
149
|
+
const value = payload[fieldName];
|
|
150
|
+
this.validateField(fieldName, fieldDef, value, errors);
|
|
151
|
+
}
|
|
152
|
+
return { valid: errors.length === 0, errors };
|
|
153
|
+
}
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
// Private helpers
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
/**
|
|
158
|
+
* Validate a single field against its definition, pushing errors into the array.
|
|
159
|
+
*
|
|
160
|
+
* @param fieldName - Name of the field being validated
|
|
161
|
+
* @param fieldDef - Schema field definition
|
|
162
|
+
* @param value - Actual value from the payload
|
|
163
|
+
* @param errors - Mutable array to collect validation errors
|
|
164
|
+
*/
|
|
165
|
+
validateField(fieldName, fieldDef, value, errors) {
|
|
166
|
+
// Required check
|
|
167
|
+
if (fieldDef.required && (value === undefined || value === null)) {
|
|
168
|
+
errors.push({ field: fieldName, message: `Field '${fieldName}' is required`, rule: 'required' });
|
|
169
|
+
return; // Skip further checks if missing
|
|
170
|
+
}
|
|
171
|
+
// If field is absent and not required, skip remaining rules
|
|
172
|
+
if (value === undefined || value === null) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
// Type-specific checks
|
|
176
|
+
switch (fieldDef.type) {
|
|
177
|
+
case 'string':
|
|
178
|
+
this.validateString(fieldName, fieldDef, value, errors);
|
|
179
|
+
break;
|
|
180
|
+
case 'number':
|
|
181
|
+
this.validateType(fieldName, 'number', value, errors);
|
|
182
|
+
break;
|
|
183
|
+
case 'boolean':
|
|
184
|
+
this.validateType(fieldName, 'boolean', value, errors);
|
|
185
|
+
break;
|
|
186
|
+
case 'array':
|
|
187
|
+
this.validateArray(fieldName, fieldDef, value, errors);
|
|
188
|
+
break;
|
|
189
|
+
case 'datetime':
|
|
190
|
+
this.validateDatetime(fieldName, value, errors);
|
|
191
|
+
break;
|
|
192
|
+
case 'enum':
|
|
193
|
+
this.validateEnum(fieldName, fieldDef, value, errors);
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Validate a string field (typeof + max_length).
|
|
199
|
+
*/
|
|
200
|
+
validateString(fieldName, fieldDef, value, errors) {
|
|
201
|
+
if (typeof value !== 'string') {
|
|
202
|
+
errors.push({
|
|
203
|
+
field: fieldName,
|
|
204
|
+
message: `Expected type 'string', got '${typeof value}'`,
|
|
205
|
+
rule: 'type',
|
|
206
|
+
});
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (fieldDef.max_length !== undefined && value.length > fieldDef.max_length) {
|
|
210
|
+
errors.push({
|
|
211
|
+
field: fieldName,
|
|
212
|
+
message: `String exceeds max length of ${fieldDef.max_length} (got ${value.length})`,
|
|
213
|
+
rule: 'max_length',
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Validate a primitive type via typeof.
|
|
219
|
+
*/
|
|
220
|
+
validateType(fieldName, expectedType, value, errors) {
|
|
221
|
+
if (typeof value !== expectedType) {
|
|
222
|
+
errors.push({
|
|
223
|
+
field: fieldName,
|
|
224
|
+
message: `Expected type '${expectedType}', got '${typeof value}'`,
|
|
225
|
+
rule: 'type',
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Validate an array field (isArray + min_items).
|
|
231
|
+
*/
|
|
232
|
+
validateArray(fieldName, fieldDef, value, errors) {
|
|
233
|
+
if (!Array.isArray(value)) {
|
|
234
|
+
errors.push({
|
|
235
|
+
field: fieldName,
|
|
236
|
+
message: `Expected type 'array', got '${typeof value}'`,
|
|
237
|
+
rule: 'type',
|
|
238
|
+
});
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (fieldDef.min_items !== undefined && value.length < fieldDef.min_items) {
|
|
242
|
+
errors.push({
|
|
243
|
+
field: fieldName,
|
|
244
|
+
message: `Array must have at least ${fieldDef.min_items} item(s), got ${value.length}`,
|
|
245
|
+
rule: 'min_items',
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Validate a datetime field (must be a string matching ISO 8601).
|
|
251
|
+
*/
|
|
252
|
+
validateDatetime(fieldName, value, errors) {
|
|
253
|
+
if (typeof value !== 'string') {
|
|
254
|
+
errors.push({
|
|
255
|
+
field: fieldName,
|
|
256
|
+
message: `Expected type 'datetime' (ISO8601 string), got '${typeof value}'`,
|
|
257
|
+
rule: 'type',
|
|
258
|
+
});
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (!ISO8601_REGEX.test(value)) {
|
|
262
|
+
errors.push({
|
|
263
|
+
field: fieldName,
|
|
264
|
+
message: `Value '${value}' is not a valid ISO8601 datetime`,
|
|
265
|
+
rule: 'datetime',
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Validate an enum field (value must be one of options).
|
|
271
|
+
*/
|
|
272
|
+
validateEnum(fieldName, fieldDef, value, errors) {
|
|
273
|
+
if (typeof value !== 'string') {
|
|
274
|
+
errors.push({
|
|
275
|
+
field: fieldName,
|
|
276
|
+
message: `Expected type 'string' for enum, got '${typeof value}'`,
|
|
277
|
+
rule: 'type',
|
|
278
|
+
});
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (fieldDef.options && !fieldDef.options.includes(value)) {
|
|
282
|
+
errors.push({
|
|
283
|
+
field: fieldName,
|
|
284
|
+
message: `Value '${value}' is not in allowed options: [${fieldDef.options.join(', ')}]`,
|
|
285
|
+
rule: 'enum',
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=schema-registry.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-registry.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/data/schema-registry.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sink Registry Service
|
|
3
|
+
*
|
|
4
|
+
* Manages sink definitions loaded from a project's `_sinks.json` file.
|
|
5
|
+
* Provides lookup, listing, tag-based matching, and registration of new sinks.
|
|
6
|
+
* Works alongside SchemaRegistryService to form the Data Architecture V2
|
|
7
|
+
* ingestion layer.
|
|
8
|
+
*
|
|
9
|
+
* @module services/data/sink-registry.service
|
|
10
|
+
*/
|
|
11
|
+
import type { SinkDefinition } from '../../types/data-object.types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Singleton service that manages data sink definitions.
|
|
14
|
+
*
|
|
15
|
+
* Sinks are loaded from `{projectPath}/sinks/_sinks.json`. Each sink declares
|
|
16
|
+
* a name, schema reference, tags, and a directory for storage. The matchSink()
|
|
17
|
+
* method enables content-aware routing of incoming data.
|
|
18
|
+
*/
|
|
19
|
+
export declare class SinkRegistryService {
|
|
20
|
+
private static instance;
|
|
21
|
+
private readonly logger;
|
|
22
|
+
private readonly sinks;
|
|
23
|
+
private constructor();
|
|
24
|
+
/**
|
|
25
|
+
* Get the singleton instance.
|
|
26
|
+
*
|
|
27
|
+
* @returns SinkRegistryService singleton
|
|
28
|
+
*/
|
|
29
|
+
static getInstance(): SinkRegistryService;
|
|
30
|
+
/**
|
|
31
|
+
* Reset the singleton (for testing).
|
|
32
|
+
*/
|
|
33
|
+
static resetInstance(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Load sink definitions from a project's `_sinks.json` file.
|
|
36
|
+
*
|
|
37
|
+
* If the file does not exist, the service starts with an empty registry
|
|
38
|
+
* (no error thrown). Invalid entries (missing id) are skipped with a warning.
|
|
39
|
+
*
|
|
40
|
+
* @param projectPath - Absolute path to the Crewly project root
|
|
41
|
+
*/
|
|
42
|
+
loadSinks(projectPath: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Get a sink by its ID.
|
|
45
|
+
*
|
|
46
|
+
* @param sinkId - Unique sink identifier
|
|
47
|
+
* @returns The sink definition, or null if not found
|
|
48
|
+
*/
|
|
49
|
+
getSink(sinkId: string): SinkDefinition | null;
|
|
50
|
+
/**
|
|
51
|
+
* List all registered sinks.
|
|
52
|
+
*
|
|
53
|
+
* @returns Array of all SinkDefinitions
|
|
54
|
+
*/
|
|
55
|
+
listSinks(): SinkDefinition[];
|
|
56
|
+
/**
|
|
57
|
+
* Match incoming data to the best sink based on tag overlap.
|
|
58
|
+
*
|
|
59
|
+
* Scores each sink by the number of matching tags (intersection with the
|
|
60
|
+
* provided tags array). If `content` is provided and a sink name appears
|
|
61
|
+
* in the content, that sink gets a bonus point. Returns the highest-scoring
|
|
62
|
+
* sink, or null if no sink has any overlap.
|
|
63
|
+
*
|
|
64
|
+
* @param tags - Tags from the incoming data
|
|
65
|
+
* @param content - Optional content string for keyword matching
|
|
66
|
+
* @returns Best-matching SinkDefinition, or null
|
|
67
|
+
*/
|
|
68
|
+
matchSink(tags: string[], content?: string): SinkDefinition | null;
|
|
69
|
+
/**
|
|
70
|
+
* Register a new sink definition and persist it to `_sinks.json`.
|
|
71
|
+
*
|
|
72
|
+
* Creates the sinks directory and registry file if they don't exist.
|
|
73
|
+
* If a sink with the same ID already exists, it is overwritten.
|
|
74
|
+
*
|
|
75
|
+
* @param projectPath - Absolute path to the Crewly project root
|
|
76
|
+
* @param sink - The sink definition to register
|
|
77
|
+
*/
|
|
78
|
+
registerSink(projectPath: string, sink: SinkDefinition): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Compute the absolute path to the _sinks.json registry file.
|
|
81
|
+
*
|
|
82
|
+
* @param projectPath - Project root
|
|
83
|
+
* @returns Absolute path to _sinks.json
|
|
84
|
+
*/
|
|
85
|
+
private registryPath;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=sink-registry.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sink-registry.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/data/sink-registry.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAWvE;;;;;;GAMG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAoC;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0C;IAEhE,OAAO;IAIP;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,mBAAmB;IAOzC;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;IAQ5B;;;;;;;OAOG;IACG,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCnD;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAI9C;;;;OAIG;IACH,SAAS,IAAI,cAAc,EAAE;IAQ7B;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAkClE;;;;;;;;OAQG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B5E;;;;;OAKG;IACH,OAAO,CAAC,YAAY;CAGrB"}
|