@clivly/core 0.10.9 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter.d.cts +44 -7
- package/dist/adapter.d.mts +44 -7
- package/dist/auth-adapter.d.cts +6 -7
- package/dist/auth-adapter.d.mts +6 -7
- package/dist/builder.d.cts +12 -12
- package/dist/builder.d.mts +12 -12
- package/dist/drizzle.d.cts +5 -6
- package/dist/drizzle.d.mts +5 -6
- package/dist/{entity-config-C_NDVfrL.mjs → entity-config-C0rtu-K_.mjs} +20 -2
- package/dist/{entity-config-J5KYJVTO.cjs → entity-config-C2sKAti2.cjs} +20 -2
- package/dist/{entity-config-ChHLozko.d.cts → entity-config-OhC4Otkz.d.cts} +4 -2
- package/dist/{entity-config-ChHLozko.d.mts → entity-config-OhC4Otkz.d.mts} +4 -2
- package/dist/entity-config.cjs +1 -1
- package/dist/entity-config.d.cts +1 -1
- package/dist/entity-config.d.mts +1 -1
- package/dist/entity-config.mjs +1 -1
- package/dist/entity-heuristics.cjs +43 -24
- package/dist/entity-heuristics.d.cts +21 -21
- package/dist/entity-heuristics.d.mts +21 -21
- package/dist/entity-heuristics.mjs +43 -24
- package/dist/env-file.d.cts +6 -7
- package/dist/env-file.d.mts +6 -7
- package/dist/index.cjs +83 -1
- package/dist/index.d.cts +89 -22
- package/dist/index.d.mts +89 -22
- package/dist/index.mjs +80 -2
- package/dist/integration-state.d.cts +30 -31
- package/dist/integration-state.d.mts +30 -31
- package/dist/mapping-form.d.cts +6 -7
- package/dist/mapping-form.d.mts +6 -7
- package/dist/mapping-score.d.cts +14 -15
- package/dist/mapping-score.d.mts +14 -15
- package/dist/mappings-config.cjs +2 -1
- package/dist/mappings-config.d.cts +8 -7
- package/dist/mappings-config.d.mts +8 -7
- package/dist/mappings-config.mjs +2 -1
- package/dist/sync-engine.d.cts +15 -16
- package/dist/sync-engine.d.mts +15 -16
- package/dist/types.d.cts +99 -33
- package/dist/types.d.mts +99 -33
- package/dist/view-compiler.d.cts +10 -11
- package/dist/view-compiler.d.mts +10 -11
- package/package.json +2 -2
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
//#region src/integration-state.d.ts
|
|
2
|
-
declare const INTEGRATION_STEPS: readonly ["credential", "application", "schema", "mapping", "trigger", "sync", "widget"];
|
|
3
|
-
type StepId = (typeof INTEGRATION_STEPS)[number];
|
|
2
|
+
export declare const INTEGRATION_STEPS: readonly ["credential", "application", "schema", "mapping", "trigger", "sync", "widget"];
|
|
3
|
+
export type StepId = (typeof INTEGRATION_STEPS)[number];
|
|
4
4
|
/** `blocked` means "prerequisite unmet", never "broken" — see C-19. */
|
|
5
|
-
type StepState = "done" | "active" | "blocked" | "failed" | "skipped";
|
|
6
|
-
type IntegrationStatus = "not_configured" | "sdk_installed" | "awaiting_connection" | "connected" | "schema_discovered" | "mapping_required" | "trigger_required" | "ready_to_sync" | "syncing" | "healthy" | "warning" | "error" |
|
|
5
|
+
export type StepState = "done" | "active" | "blocked" | "failed" | "skipped";
|
|
6
|
+
export type IntegrationStatus = "not_configured" | "sdk_installed" | "awaiting_connection" | "connected" | "schema_discovered" | "mapping_required" | "trigger_required" | "ready_to_sync" | "syncing" | "healthy" | "warning" | "error" |
|
|
7
7
|
/**
|
|
8
8
|
* @deprecated No longer derived. Liveness is its own dimension — read
|
|
9
9
|
* `ConnectionHealth` from `deriveLiveness`. Setup progress does not move
|
|
10
10
|
* backwards just because an app stopped running.
|
|
11
11
|
*/
|
|
12
12
|
"disconnected";
|
|
13
|
-
declare const INTEGRATION_STEP_LABELS: Record<StepId, string>;
|
|
13
|
+
export declare const INTEGRATION_STEP_LABELS: Record<StepId, string>;
|
|
14
14
|
/** Each step's prerequisites. Ordering is enforced by a test, not convention. */
|
|
15
|
-
declare const STEP_PREREQUISITES: Record<StepId, readonly StepId[]>;
|
|
16
|
-
declare function stepIndex(id: StepId): number;
|
|
17
|
-
interface RunFact {
|
|
15
|
+
export declare const STEP_PREREQUISITES: Record<StepId, readonly StepId[]>;
|
|
16
|
+
export declare function stepIndex(id: StepId): number;
|
|
17
|
+
export interface RunFact {
|
|
18
18
|
at: number;
|
|
19
19
|
message?: string;
|
|
20
20
|
ok: boolean;
|
|
@@ -36,8 +36,8 @@ interface RunFact {
|
|
|
36
36
|
* such a host to `local_dev` would file a production box's faults under local
|
|
37
37
|
* development, where nobody would look for them.
|
|
38
38
|
*/
|
|
39
|
-
type HostEnvironment = "local_dev" | "preview" | "production" | "unknown";
|
|
40
|
-
interface IntegrationFacts {
|
|
39
|
+
export type HostEnvironment = "local_dev" | "preview" | "production" | "unknown";
|
|
40
|
+
export interface IntegrationFacts {
|
|
41
41
|
discoveredTableCount: number;
|
|
42
42
|
/** The environment the app reported on its last heartbeat. */
|
|
43
43
|
environment?: HostEnvironment | null;
|
|
@@ -95,12 +95,12 @@ interface IntegrationFacts {
|
|
|
95
95
|
warnings: string[];
|
|
96
96
|
widgetInstalled: boolean;
|
|
97
97
|
}
|
|
98
|
-
interface StepProblem {
|
|
98
|
+
export interface StepProblem {
|
|
99
99
|
code: string;
|
|
100
100
|
fix: string;
|
|
101
101
|
message: string;
|
|
102
102
|
}
|
|
103
|
-
interface IntegrationStep {
|
|
103
|
+
export interface IntegrationStep {
|
|
104
104
|
blockedBy: StepId | null;
|
|
105
105
|
evidence: string | null;
|
|
106
106
|
id: StepId;
|
|
@@ -108,10 +108,10 @@ interface IntegrationStep {
|
|
|
108
108
|
problem: StepProblem | null;
|
|
109
109
|
state: StepState;
|
|
110
110
|
}
|
|
111
|
-
declare function formatAge(ms: number): string;
|
|
111
|
+
export declare function formatAge(ms: number): string;
|
|
112
112
|
/** The cadence `createClivlySDK` uses when the host app configures none. */
|
|
113
|
-
declare const DEFAULT_HEARTBEAT_INTERVAL_MS = 60000;
|
|
114
|
-
type ConnectionHealth = "live" | "live_with_issues" | "stale" | "offline";
|
|
113
|
+
export declare const DEFAULT_HEARTBEAT_INTERVAL_MS = 60000;
|
|
114
|
+
export type ConnectionHealth = "live" | "live_with_issues" | "stale" | "offline";
|
|
115
115
|
/**
|
|
116
116
|
* Clivly's own answer to "is this app up", obtained by asking it rather than
|
|
117
117
|
* waiting to be told.
|
|
@@ -121,15 +121,15 @@ type ConnectionHealth = "live" | "live_with_issues" | "stale" | "offline";
|
|
|
121
121
|
* that answers `200`. Only silence — a timeout, a refused connection, DNS that
|
|
122
122
|
* does not resolve — means offline.
|
|
123
123
|
*/
|
|
124
|
-
interface ReachabilityProbe {
|
|
124
|
+
export interface ReachabilityProbe {
|
|
125
125
|
/** When Clivly performed the check. Probe results are cached, so this ages. */
|
|
126
126
|
checkedAt: number;
|
|
127
127
|
/** Did anything answer at the other end? */
|
|
128
128
|
reachable: boolean;
|
|
129
129
|
}
|
|
130
130
|
/** Which algorithm decides whether this deployment is up. */
|
|
131
|
-
type PresenceTransport = "websocket" | "http";
|
|
132
|
-
type PresenceConnectionState = "connected" | "reconnecting" | "disconnected";
|
|
131
|
+
export type PresenceTransport = "websocket" | "http";
|
|
132
|
+
export type PresenceConnectionState = "connected" | "reconnecting" | "disconnected";
|
|
133
133
|
/**
|
|
134
134
|
* A deployment's connection state as its `PresenceRoom` last persisted it.
|
|
135
135
|
*
|
|
@@ -138,13 +138,13 @@ type PresenceConnectionState = "connected" | "reconnecting" | "disconnected";
|
|
|
138
138
|
* shown as live for 150 seconds and offline only after ten minutes, which is
|
|
139
139
|
* the whole reason this transport exists.
|
|
140
140
|
*/
|
|
141
|
-
interface DeploymentPresence {
|
|
141
|
+
export interface DeploymentPresence {
|
|
142
142
|
/** Sockets currently accepted in the room. */
|
|
143
143
|
activeInstanceCount: number;
|
|
144
144
|
connectionState: PresenceConnectionState;
|
|
145
145
|
transport: PresenceTransport;
|
|
146
146
|
}
|
|
147
|
-
interface ConnectionLiveness {
|
|
147
|
+
export interface ConnectionLiveness {
|
|
148
148
|
/** `"8s ago"`, or `"No heartbeat yet"` when the app has never reported. */
|
|
149
149
|
ageLabel: string;
|
|
150
150
|
ageMs: number | null;
|
|
@@ -165,30 +165,30 @@ interface ConnectionLiveness {
|
|
|
165
165
|
* negative — falls back to the SDK default rather than producing a window of
|
|
166
166
|
* zero that would call every app offline.
|
|
167
167
|
*/
|
|
168
|
-
declare function livenessWindows(intervalMs: number | null | undefined): {
|
|
168
|
+
export declare function livenessWindows(intervalMs: number | null | undefined): {
|
|
169
169
|
liveMs: number;
|
|
170
170
|
staleMs: number;
|
|
171
171
|
};
|
|
172
|
-
declare function deriveLiveness(facts: IntegrationFacts): ConnectionLiveness;
|
|
172
|
+
export declare function deriveLiveness(facts: IntegrationFacts): ConnectionLiveness;
|
|
173
173
|
/**
|
|
174
174
|
* Walk the ladder once. A step is `blocked` when an earlier step it needs has
|
|
175
175
|
* not been satisfied — a prerequisite statement, not a verdict about this step
|
|
176
176
|
* — and only the first unsatisfied step is `active`, so exactly one root cause
|
|
177
177
|
* ever surfaces.
|
|
178
178
|
*/
|
|
179
|
-
declare function resolveSteps(facts: IntegrationFacts): IntegrationStep[];
|
|
179
|
+
export declare function resolveSteps(facts: IntegrationFacts): IntegrationStep[];
|
|
180
180
|
/**
|
|
181
181
|
* Collapse the ladder to the single status the surfaces switch on. This is the
|
|
182
182
|
* setup dimension only: it answers how far configuration got, never whether the
|
|
183
183
|
* app is up. Pair it with `deriveLiveness` for the second half of the picture.
|
|
184
184
|
*/
|
|
185
|
-
declare function deriveStatus(steps: IntegrationStep[], facts: IntegrationFacts): IntegrationStatus;
|
|
186
|
-
interface NextAction {
|
|
185
|
+
export declare function deriveStatus(steps: IntegrationStep[], facts: IntegrationFacts): IntegrationStatus;
|
|
186
|
+
export interface NextAction {
|
|
187
187
|
command: string | null;
|
|
188
188
|
envFile: string | null;
|
|
189
189
|
label: string;
|
|
190
190
|
}
|
|
191
|
-
interface IntegrationState {
|
|
191
|
+
export interface IntegrationState {
|
|
192
192
|
/**
|
|
193
193
|
* Is the app running right now. Deliberately alongside `status` rather than
|
|
194
194
|
* folded into it: a surface must be able to say "setup reached mapping" and
|
|
@@ -205,14 +205,13 @@ interface IntegrationState {
|
|
|
205
205
|
* dialog prints it too, and it must be the same string as the one the ladder
|
|
206
206
|
* recommends — that pairing is what C-05 broke.
|
|
207
207
|
*/
|
|
208
|
-
declare const INSTALL_COMMAND = "npx clivly init";
|
|
208
|
+
export declare const INSTALL_COMMAND = "npx clivly init";
|
|
209
209
|
/**
|
|
210
210
|
* THE one producer of `next.command`. Six surfaces previously each invented
|
|
211
211
|
* their own "run this next" string, and one of them named a read-only command
|
|
212
212
|
* as the fix for a write problem (C-05). If you need a command for the
|
|
213
213
|
* next-action slot, call this — do not write another one.
|
|
214
214
|
*/
|
|
215
|
-
declare function nextAction(steps: IntegrationStep[], status: IntegrationStatus, liveness: ConnectionLiveness): NextAction | null;
|
|
216
|
-
declare function computeIntegrationState(facts: IntegrationFacts): IntegrationState;
|
|
217
|
-
//#endregion
|
|
218
|
-
export { ConnectionHealth, ConnectionLiveness, DEFAULT_HEARTBEAT_INTERVAL_MS, DeploymentPresence, HostEnvironment, INSTALL_COMMAND, INTEGRATION_STEPS, INTEGRATION_STEP_LABELS, IntegrationFacts, IntegrationState, IntegrationStatus, IntegrationStep, NextAction, PresenceConnectionState, PresenceTransport, ReachabilityProbe, RunFact, STEP_PREREQUISITES, StepId, StepProblem, StepState, computeIntegrationState, deriveLiveness, deriveStatus, formatAge, livenessWindows, nextAction, resolveSteps, stepIndex };
|
|
215
|
+
export declare function nextAction(steps: IntegrationStep[], status: IntegrationStatus, liveness: ConnectionLiveness): NextAction | null;
|
|
216
|
+
export declare function computeIntegrationState(facts: IntegrationFacts): IntegrationState;
|
|
217
|
+
//#endregion
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
//#region src/integration-state.d.ts
|
|
2
|
-
declare const INTEGRATION_STEPS: readonly ["credential", "application", "schema", "mapping", "trigger", "sync", "widget"];
|
|
3
|
-
type StepId = (typeof INTEGRATION_STEPS)[number];
|
|
2
|
+
export declare const INTEGRATION_STEPS: readonly ["credential", "application", "schema", "mapping", "trigger", "sync", "widget"];
|
|
3
|
+
export type StepId = (typeof INTEGRATION_STEPS)[number];
|
|
4
4
|
/** `blocked` means "prerequisite unmet", never "broken" — see C-19. */
|
|
5
|
-
type StepState = "done" | "active" | "blocked" | "failed" | "skipped";
|
|
6
|
-
type IntegrationStatus = "not_configured" | "sdk_installed" | "awaiting_connection" | "connected" | "schema_discovered" | "mapping_required" | "trigger_required" | "ready_to_sync" | "syncing" | "healthy" | "warning" | "error" |
|
|
5
|
+
export type StepState = "done" | "active" | "blocked" | "failed" | "skipped";
|
|
6
|
+
export type IntegrationStatus = "not_configured" | "sdk_installed" | "awaiting_connection" | "connected" | "schema_discovered" | "mapping_required" | "trigger_required" | "ready_to_sync" | "syncing" | "healthy" | "warning" | "error" |
|
|
7
7
|
/**
|
|
8
8
|
* @deprecated No longer derived. Liveness is its own dimension — read
|
|
9
9
|
* `ConnectionHealth` from `deriveLiveness`. Setup progress does not move
|
|
10
10
|
* backwards just because an app stopped running.
|
|
11
11
|
*/
|
|
12
12
|
"disconnected";
|
|
13
|
-
declare const INTEGRATION_STEP_LABELS: Record<StepId, string>;
|
|
13
|
+
export declare const INTEGRATION_STEP_LABELS: Record<StepId, string>;
|
|
14
14
|
/** Each step's prerequisites. Ordering is enforced by a test, not convention. */
|
|
15
|
-
declare const STEP_PREREQUISITES: Record<StepId, readonly StepId[]>;
|
|
16
|
-
declare function stepIndex(id: StepId): number;
|
|
17
|
-
interface RunFact {
|
|
15
|
+
export declare const STEP_PREREQUISITES: Record<StepId, readonly StepId[]>;
|
|
16
|
+
export declare function stepIndex(id: StepId): number;
|
|
17
|
+
export interface RunFact {
|
|
18
18
|
at: number;
|
|
19
19
|
message?: string;
|
|
20
20
|
ok: boolean;
|
|
@@ -36,8 +36,8 @@ interface RunFact {
|
|
|
36
36
|
* such a host to `local_dev` would file a production box's faults under local
|
|
37
37
|
* development, where nobody would look for them.
|
|
38
38
|
*/
|
|
39
|
-
type HostEnvironment = "local_dev" | "preview" | "production" | "unknown";
|
|
40
|
-
interface IntegrationFacts {
|
|
39
|
+
export type HostEnvironment = "local_dev" | "preview" | "production" | "unknown";
|
|
40
|
+
export interface IntegrationFacts {
|
|
41
41
|
discoveredTableCount: number;
|
|
42
42
|
/** The environment the app reported on its last heartbeat. */
|
|
43
43
|
environment?: HostEnvironment | null;
|
|
@@ -95,12 +95,12 @@ interface IntegrationFacts {
|
|
|
95
95
|
warnings: string[];
|
|
96
96
|
widgetInstalled: boolean;
|
|
97
97
|
}
|
|
98
|
-
interface StepProblem {
|
|
98
|
+
export interface StepProblem {
|
|
99
99
|
code: string;
|
|
100
100
|
fix: string;
|
|
101
101
|
message: string;
|
|
102
102
|
}
|
|
103
|
-
interface IntegrationStep {
|
|
103
|
+
export interface IntegrationStep {
|
|
104
104
|
blockedBy: StepId | null;
|
|
105
105
|
evidence: string | null;
|
|
106
106
|
id: StepId;
|
|
@@ -108,10 +108,10 @@ interface IntegrationStep {
|
|
|
108
108
|
problem: StepProblem | null;
|
|
109
109
|
state: StepState;
|
|
110
110
|
}
|
|
111
|
-
declare function formatAge(ms: number): string;
|
|
111
|
+
export declare function formatAge(ms: number): string;
|
|
112
112
|
/** The cadence `createClivlySDK` uses when the host app configures none. */
|
|
113
|
-
declare const DEFAULT_HEARTBEAT_INTERVAL_MS = 60000;
|
|
114
|
-
type ConnectionHealth = "live" | "live_with_issues" | "stale" | "offline";
|
|
113
|
+
export declare const DEFAULT_HEARTBEAT_INTERVAL_MS = 60000;
|
|
114
|
+
export type ConnectionHealth = "live" | "live_with_issues" | "stale" | "offline";
|
|
115
115
|
/**
|
|
116
116
|
* Clivly's own answer to "is this app up", obtained by asking it rather than
|
|
117
117
|
* waiting to be told.
|
|
@@ -121,15 +121,15 @@ type ConnectionHealth = "live" | "live_with_issues" | "stale" | "offline";
|
|
|
121
121
|
* that answers `200`. Only silence — a timeout, a refused connection, DNS that
|
|
122
122
|
* does not resolve — means offline.
|
|
123
123
|
*/
|
|
124
|
-
interface ReachabilityProbe {
|
|
124
|
+
export interface ReachabilityProbe {
|
|
125
125
|
/** When Clivly performed the check. Probe results are cached, so this ages. */
|
|
126
126
|
checkedAt: number;
|
|
127
127
|
/** Did anything answer at the other end? */
|
|
128
128
|
reachable: boolean;
|
|
129
129
|
}
|
|
130
130
|
/** Which algorithm decides whether this deployment is up. */
|
|
131
|
-
type PresenceTransport = "websocket" | "http";
|
|
132
|
-
type PresenceConnectionState = "connected" | "reconnecting" | "disconnected";
|
|
131
|
+
export type PresenceTransport = "websocket" | "http";
|
|
132
|
+
export type PresenceConnectionState = "connected" | "reconnecting" | "disconnected";
|
|
133
133
|
/**
|
|
134
134
|
* A deployment's connection state as its `PresenceRoom` last persisted it.
|
|
135
135
|
*
|
|
@@ -138,13 +138,13 @@ type PresenceConnectionState = "connected" | "reconnecting" | "disconnected";
|
|
|
138
138
|
* shown as live for 150 seconds and offline only after ten minutes, which is
|
|
139
139
|
* the whole reason this transport exists.
|
|
140
140
|
*/
|
|
141
|
-
interface DeploymentPresence {
|
|
141
|
+
export interface DeploymentPresence {
|
|
142
142
|
/** Sockets currently accepted in the room. */
|
|
143
143
|
activeInstanceCount: number;
|
|
144
144
|
connectionState: PresenceConnectionState;
|
|
145
145
|
transport: PresenceTransport;
|
|
146
146
|
}
|
|
147
|
-
interface ConnectionLiveness {
|
|
147
|
+
export interface ConnectionLiveness {
|
|
148
148
|
/** `"8s ago"`, or `"No heartbeat yet"` when the app has never reported. */
|
|
149
149
|
ageLabel: string;
|
|
150
150
|
ageMs: number | null;
|
|
@@ -165,30 +165,30 @@ interface ConnectionLiveness {
|
|
|
165
165
|
* negative — falls back to the SDK default rather than producing a window of
|
|
166
166
|
* zero that would call every app offline.
|
|
167
167
|
*/
|
|
168
|
-
declare function livenessWindows(intervalMs: number | null | undefined): {
|
|
168
|
+
export declare function livenessWindows(intervalMs: number | null | undefined): {
|
|
169
169
|
liveMs: number;
|
|
170
170
|
staleMs: number;
|
|
171
171
|
};
|
|
172
|
-
declare function deriveLiveness(facts: IntegrationFacts): ConnectionLiveness;
|
|
172
|
+
export declare function deriveLiveness(facts: IntegrationFacts): ConnectionLiveness;
|
|
173
173
|
/**
|
|
174
174
|
* Walk the ladder once. A step is `blocked` when an earlier step it needs has
|
|
175
175
|
* not been satisfied — a prerequisite statement, not a verdict about this step
|
|
176
176
|
* — and only the first unsatisfied step is `active`, so exactly one root cause
|
|
177
177
|
* ever surfaces.
|
|
178
178
|
*/
|
|
179
|
-
declare function resolveSteps(facts: IntegrationFacts): IntegrationStep[];
|
|
179
|
+
export declare function resolveSteps(facts: IntegrationFacts): IntegrationStep[];
|
|
180
180
|
/**
|
|
181
181
|
* Collapse the ladder to the single status the surfaces switch on. This is the
|
|
182
182
|
* setup dimension only: it answers how far configuration got, never whether the
|
|
183
183
|
* app is up. Pair it with `deriveLiveness` for the second half of the picture.
|
|
184
184
|
*/
|
|
185
|
-
declare function deriveStatus(steps: IntegrationStep[], facts: IntegrationFacts): IntegrationStatus;
|
|
186
|
-
interface NextAction {
|
|
185
|
+
export declare function deriveStatus(steps: IntegrationStep[], facts: IntegrationFacts): IntegrationStatus;
|
|
186
|
+
export interface NextAction {
|
|
187
187
|
command: string | null;
|
|
188
188
|
envFile: string | null;
|
|
189
189
|
label: string;
|
|
190
190
|
}
|
|
191
|
-
interface IntegrationState {
|
|
191
|
+
export interface IntegrationState {
|
|
192
192
|
/**
|
|
193
193
|
* Is the app running right now. Deliberately alongside `status` rather than
|
|
194
194
|
* folded into it: a surface must be able to say "setup reached mapping" and
|
|
@@ -205,14 +205,13 @@ interface IntegrationState {
|
|
|
205
205
|
* dialog prints it too, and it must be the same string as the one the ladder
|
|
206
206
|
* recommends — that pairing is what C-05 broke.
|
|
207
207
|
*/
|
|
208
|
-
declare const INSTALL_COMMAND = "npx clivly init";
|
|
208
|
+
export declare const INSTALL_COMMAND = "npx clivly init";
|
|
209
209
|
/**
|
|
210
210
|
* THE one producer of `next.command`. Six surfaces previously each invented
|
|
211
211
|
* their own "run this next" string, and one of them named a read-only command
|
|
212
212
|
* as the fix for a write problem (C-05). If you need a command for the
|
|
213
213
|
* next-action slot, call this — do not write another one.
|
|
214
214
|
*/
|
|
215
|
-
declare function nextAction(steps: IntegrationStep[], status: IntegrationStatus, liveness: ConnectionLiveness): NextAction | null;
|
|
216
|
-
declare function computeIntegrationState(facts: IntegrationFacts): IntegrationState;
|
|
217
|
-
//#endregion
|
|
218
|
-
export { ConnectionHealth, ConnectionLiveness, DEFAULT_HEARTBEAT_INTERVAL_MS, DeploymentPresence, HostEnvironment, INSTALL_COMMAND, INTEGRATION_STEPS, INTEGRATION_STEP_LABELS, IntegrationFacts, IntegrationState, IntegrationStatus, IntegrationStep, NextAction, PresenceConnectionState, PresenceTransport, ReachabilityProbe, RunFact, STEP_PREREQUISITES, StepId, StepProblem, StepState, computeIntegrationState, deriveLiveness, deriveStatus, formatAge, livenessWindows, nextAction, resolveSteps, stepIndex };
|
|
215
|
+
export declare function nextAction(steps: IntegrationStep[], status: IntegrationStatus, liveness: ConnectionLiveness): NextAction | null;
|
|
216
|
+
export declare function computeIntegrationState(facts: IntegrationFacts): IntegrationState;
|
|
217
|
+
//#endregion
|
package/dist/mapping-form.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as RelationshipsMap, h as FilterExpr, x as RelationshipVia } from "./entity-config-
|
|
1
|
+
import { S as RelationshipsMap, h as FilterExpr, x as RelationshipVia } from "./entity-config-OhC4Otkz.cjs";
|
|
2
2
|
//#region src/mapping-form.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* A relationship the mapping UI can offer or has configured, in the shape the
|
|
@@ -6,7 +6,7 @@ import { S as RelationshipsMap, h as FilterExpr, x as RelationshipVia } from "./
|
|
|
6
6
|
* mappings→config compiler resolves it to the canonical entity key, so it is
|
|
7
7
|
* persisted verbatim as the relationship's `entity` reference.
|
|
8
8
|
*/
|
|
9
|
-
interface RelationshipCandidate {
|
|
9
|
+
export interface RelationshipCandidate {
|
|
10
10
|
entityTable: string;
|
|
11
11
|
name: string;
|
|
12
12
|
via: RelationshipVia;
|
|
@@ -16,19 +16,18 @@ interface RelationshipCandidate {
|
|
|
16
16
|
* `value` belong to this entity (e.g. `role = "owner"`). Returns `undefined`
|
|
17
17
|
* when either side is blank so the caller can omit the filter entirely.
|
|
18
18
|
*/
|
|
19
|
-
declare function buildFilterFromDiscriminator(column: string | null | undefined, value: string): FilterExpr | undefined;
|
|
19
|
+
export declare function buildFilterFromDiscriminator(column: string | null | undefined, value: string): FilterExpr | undefined;
|
|
20
20
|
/**
|
|
21
21
|
* A stable identity string for a relationship's `via`. Two candidates on the
|
|
22
22
|
* same source table always differ in their join (`fkOn`+column, join-table
|
|
23
23
|
* keys, or raw SQL), so this disambiguates candidates the heuristic gives the
|
|
24
24
|
* same `name` (every contact→company candidate is named "company").
|
|
25
25
|
*/
|
|
26
|
-
declare function relationshipViaSignature(via: RelationshipVia): string;
|
|
26
|
+
export declare function relationshipViaSignature(via: RelationshipVia): string;
|
|
27
27
|
/**
|
|
28
28
|
* Compile the selected relationship candidates into the persisted
|
|
29
29
|
* `RelationshipsMap`. Returns `undefined` for an empty selection so the caller
|
|
30
30
|
* omits the field.
|
|
31
31
|
*/
|
|
32
|
-
declare function buildRelationships(candidates: RelationshipCandidate[]): RelationshipsMap | undefined;
|
|
33
|
-
//#endregion
|
|
34
|
-
export { RelationshipCandidate, buildFilterFromDiscriminator, buildRelationships, relationshipViaSignature };
|
|
32
|
+
export declare function buildRelationships(candidates: RelationshipCandidate[]): RelationshipsMap | undefined;
|
|
33
|
+
//#endregion
|
package/dist/mapping-form.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as RelationshipsMap, h as FilterExpr, x as RelationshipVia } from "./entity-config-
|
|
1
|
+
import { S as RelationshipsMap, h as FilterExpr, x as RelationshipVia } from "./entity-config-OhC4Otkz.mjs";
|
|
2
2
|
//#region src/mapping-form.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* A relationship the mapping UI can offer or has configured, in the shape the
|
|
@@ -6,7 +6,7 @@ import { S as RelationshipsMap, h as FilterExpr, x as RelationshipVia } from "./
|
|
|
6
6
|
* mappings→config compiler resolves it to the canonical entity key, so it is
|
|
7
7
|
* persisted verbatim as the relationship's `entity` reference.
|
|
8
8
|
*/
|
|
9
|
-
interface RelationshipCandidate {
|
|
9
|
+
export interface RelationshipCandidate {
|
|
10
10
|
entityTable: string;
|
|
11
11
|
name: string;
|
|
12
12
|
via: RelationshipVia;
|
|
@@ -16,19 +16,18 @@ interface RelationshipCandidate {
|
|
|
16
16
|
* `value` belong to this entity (e.g. `role = "owner"`). Returns `undefined`
|
|
17
17
|
* when either side is blank so the caller can omit the filter entirely.
|
|
18
18
|
*/
|
|
19
|
-
declare function buildFilterFromDiscriminator(column: string | null | undefined, value: string): FilterExpr | undefined;
|
|
19
|
+
export declare function buildFilterFromDiscriminator(column: string | null | undefined, value: string): FilterExpr | undefined;
|
|
20
20
|
/**
|
|
21
21
|
* A stable identity string for a relationship's `via`. Two candidates on the
|
|
22
22
|
* same source table always differ in their join (`fkOn`+column, join-table
|
|
23
23
|
* keys, or raw SQL), so this disambiguates candidates the heuristic gives the
|
|
24
24
|
* same `name` (every contact→company candidate is named "company").
|
|
25
25
|
*/
|
|
26
|
-
declare function relationshipViaSignature(via: RelationshipVia): string;
|
|
26
|
+
export declare function relationshipViaSignature(via: RelationshipVia): string;
|
|
27
27
|
/**
|
|
28
28
|
* Compile the selected relationship candidates into the persisted
|
|
29
29
|
* `RelationshipsMap`. Returns `undefined` for an empty selection so the caller
|
|
30
30
|
* omits the field.
|
|
31
31
|
*/
|
|
32
|
-
declare function buildRelationships(candidates: RelationshipCandidate[]): RelationshipsMap | undefined;
|
|
33
|
-
//#endregion
|
|
34
|
-
export { RelationshipCandidate, buildFilterFromDiscriminator, buildRelationships, relationshipViaSignature };
|
|
32
|
+
export declare function buildRelationships(candidates: RelationshipCandidate[]): RelationshipsMap | undefined;
|
|
33
|
+
//#endregion
|
package/dist/mapping-score.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/mapping-score.d.ts
|
|
2
|
-
type Tier = "High" | "Medium" | "Low";
|
|
3
|
-
interface Scored<T> {
|
|
2
|
+
export type Tier = "High" | "Medium" | "Low";
|
|
3
|
+
export interface Scored<T> {
|
|
4
4
|
/** Human-readable chips, e.g. `type text`, `name matches "contacts"`. */
|
|
5
5
|
reasons: string[];
|
|
6
6
|
/** Internal — used for ranking and the apply threshold. Never rendered. */
|
|
@@ -9,17 +9,17 @@ interface Scored<T> {
|
|
|
9
9
|
value: T;
|
|
10
10
|
}
|
|
11
11
|
/** Tier cut-offs: score >= high → High; >= medium → Medium; else Low. */
|
|
12
|
-
interface Thresholds {
|
|
12
|
+
export interface Thresholds {
|
|
13
13
|
high: number;
|
|
14
14
|
medium: number;
|
|
15
15
|
}
|
|
16
|
-
declare const CONCEPT_TIERS: Thresholds;
|
|
17
|
-
declare const FIELD_TIERS: Thresholds;
|
|
18
|
-
declare const RELATIONSHIP_TIERS: Thresholds;
|
|
16
|
+
export declare const CONCEPT_TIERS: Thresholds;
|
|
17
|
+
export declare const FIELD_TIERS: Thresholds;
|
|
18
|
+
export declare const RELATIONSHIP_TIERS: Thresholds;
|
|
19
19
|
/** Two concept candidates closer than this are treated as ambiguous. */
|
|
20
|
-
declare const AMBIGUITY_MARGIN = 15;
|
|
20
|
+
export declare const AMBIGUITY_MARGIN = 15;
|
|
21
21
|
/** Signal weights. Tuned against fixtures; adjust here, not at call sites. */
|
|
22
|
-
declare const W: {
|
|
22
|
+
export declare const W: {
|
|
23
23
|
readonly nameExact: 50;
|
|
24
24
|
readonly nameSubstring: 25;
|
|
25
25
|
readonly definingColumn: 20;
|
|
@@ -34,16 +34,15 @@ declare const W: {
|
|
|
34
34
|
readonly fkNameHint: 30;
|
|
35
35
|
readonly joinTable: 20;
|
|
36
36
|
};
|
|
37
|
-
declare function tierFor(score: number, t: Thresholds): Tier;
|
|
38
|
-
declare function isTextLike(type: string | undefined): boolean;
|
|
39
|
-
declare function isNumericLike(type: string | undefined): boolean;
|
|
40
|
-
declare function isTimestampLike(type: string | undefined): boolean;
|
|
37
|
+
export declare function tierFor(score: number, t: Thresholds): Tier;
|
|
38
|
+
export declare function isTextLike(type: string | undefined): boolean;
|
|
39
|
+
export declare function isNumericLike(type: string | undefined): boolean;
|
|
40
|
+
export declare function isTimestampLike(type: string | undefined): boolean;
|
|
41
41
|
/**
|
|
42
42
|
* True when the top two candidates are too close to call. Callers must never
|
|
43
43
|
* one-click apply an ambiguous result — the user picks.
|
|
44
44
|
*/
|
|
45
|
-
declare function isAmbiguous(ranked: Array<{
|
|
45
|
+
export declare function isAmbiguous(ranked: Array<{
|
|
46
46
|
score: number;
|
|
47
47
|
}>): boolean;
|
|
48
|
-
//#endregion
|
|
49
|
-
export { AMBIGUITY_MARGIN, CONCEPT_TIERS, FIELD_TIERS, RELATIONSHIP_TIERS, Scored, Thresholds, Tier, W, isAmbiguous, isNumericLike, isTextLike, isTimestampLike, tierFor };
|
|
48
|
+
//#endregion
|
package/dist/mapping-score.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/mapping-score.d.ts
|
|
2
|
-
type Tier = "High" | "Medium" | "Low";
|
|
3
|
-
interface Scored<T> {
|
|
2
|
+
export type Tier = "High" | "Medium" | "Low";
|
|
3
|
+
export interface Scored<T> {
|
|
4
4
|
/** Human-readable chips, e.g. `type text`, `name matches "contacts"`. */
|
|
5
5
|
reasons: string[];
|
|
6
6
|
/** Internal — used for ranking and the apply threshold. Never rendered. */
|
|
@@ -9,17 +9,17 @@ interface Scored<T> {
|
|
|
9
9
|
value: T;
|
|
10
10
|
}
|
|
11
11
|
/** Tier cut-offs: score >= high → High; >= medium → Medium; else Low. */
|
|
12
|
-
interface Thresholds {
|
|
12
|
+
export interface Thresholds {
|
|
13
13
|
high: number;
|
|
14
14
|
medium: number;
|
|
15
15
|
}
|
|
16
|
-
declare const CONCEPT_TIERS: Thresholds;
|
|
17
|
-
declare const FIELD_TIERS: Thresholds;
|
|
18
|
-
declare const RELATIONSHIP_TIERS: Thresholds;
|
|
16
|
+
export declare const CONCEPT_TIERS: Thresholds;
|
|
17
|
+
export declare const FIELD_TIERS: Thresholds;
|
|
18
|
+
export declare const RELATIONSHIP_TIERS: Thresholds;
|
|
19
19
|
/** Two concept candidates closer than this are treated as ambiguous. */
|
|
20
|
-
declare const AMBIGUITY_MARGIN = 15;
|
|
20
|
+
export declare const AMBIGUITY_MARGIN = 15;
|
|
21
21
|
/** Signal weights. Tuned against fixtures; adjust here, not at call sites. */
|
|
22
|
-
declare const W: {
|
|
22
|
+
export declare const W: {
|
|
23
23
|
readonly nameExact: 50;
|
|
24
24
|
readonly nameSubstring: 25;
|
|
25
25
|
readonly definingColumn: 20;
|
|
@@ -34,16 +34,15 @@ declare const W: {
|
|
|
34
34
|
readonly fkNameHint: 30;
|
|
35
35
|
readonly joinTable: 20;
|
|
36
36
|
};
|
|
37
|
-
declare function tierFor(score: number, t: Thresholds): Tier;
|
|
38
|
-
declare function isTextLike(type: string | undefined): boolean;
|
|
39
|
-
declare function isNumericLike(type: string | undefined): boolean;
|
|
40
|
-
declare function isTimestampLike(type: string | undefined): boolean;
|
|
37
|
+
export declare function tierFor(score: number, t: Thresholds): Tier;
|
|
38
|
+
export declare function isTextLike(type: string | undefined): boolean;
|
|
39
|
+
export declare function isNumericLike(type: string | undefined): boolean;
|
|
40
|
+
export declare function isTimestampLike(type: string | undefined): boolean;
|
|
41
41
|
/**
|
|
42
42
|
* True when the top two candidates are too close to call. Callers must never
|
|
43
43
|
* one-click apply an ambiguous result — the user picks.
|
|
44
44
|
*/
|
|
45
|
-
declare function isAmbiguous(ranked: Array<{
|
|
45
|
+
export declare function isAmbiguous(ranked: Array<{
|
|
46
46
|
score: number;
|
|
47
47
|
}>): boolean;
|
|
48
|
-
//#endregion
|
|
49
|
-
export { AMBIGUITY_MARGIN, CONCEPT_TIERS, FIELD_TIERS, RELATIONSHIP_TIERS, Scored, Thresholds, Tier, W, isAmbiguous, isNumericLike, isTextLike, isTimestampLike, tierFor };
|
|
48
|
+
//#endregion
|
package/dist/mappings-config.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_entity_config = require("./entity-config-
|
|
2
|
+
const require_entity_config = require("./entity-config-C2sKAti2.cjs");
|
|
3
3
|
//#region src/mappings-config.ts
|
|
4
4
|
const RESERVED_FIELD = "id";
|
|
5
5
|
/**
|
|
@@ -120,6 +120,7 @@ function entitiesToMappings(config) {
|
|
|
120
120
|
fieldMap: entity.projection ? {} : entity.fields
|
|
121
121
|
};
|
|
122
122
|
if (entity.filter) row.filter = entity.filter;
|
|
123
|
+
if (entity.isPrimaryContact) row.isPrimaryContact = true;
|
|
123
124
|
if (entity.relationships) row.relationships = entity.relationships;
|
|
124
125
|
if (entity.projection) row.projection = entity.projection;
|
|
125
126
|
if (entity.concept === CUSTOM_CONCEPT) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as ProjectionMapping, S as RelationshipsMap, a as ClivlyEntitiesConfig, h as FilterExpr } from "./entity-config-
|
|
1
|
+
import { R as ProjectionMapping, S as RelationshipsMap, a as ClivlyEntitiesConfig, h as FilterExpr } from "./entity-config-OhC4Otkz.cjs";
|
|
2
2
|
//#region src/mappings-config.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Mappings → Entity Config bridge.
|
|
@@ -20,7 +20,7 @@ import { R as ProjectionMapping, S as RelationshipsMap, a as ClivlyEntitiesConfi
|
|
|
20
20
|
* reads. Structurally compatible with the Drizzle row (jsonb columns typed
|
|
21
21
|
* loosely) so the API layer can pass `db.select()` results straight in.
|
|
22
22
|
*/
|
|
23
|
-
interface EntityMappingRow {
|
|
23
|
+
export interface EntityMappingRow {
|
|
24
24
|
fieldMap: Record<string, string>;
|
|
25
25
|
filter?: Record<string, unknown> | null;
|
|
26
26
|
/**
|
|
@@ -42,7 +42,7 @@ interface EntityMappingRow {
|
|
|
42
42
|
* unmapped rows are skipped. Returns `{ entities: {} }` when nothing is
|
|
43
43
|
* eligible — a no-op the view compiler and sync engine both tolerate.
|
|
44
44
|
*/
|
|
45
|
-
declare function mappingsToEntitiesConfig(rows: EntityMappingRow[]): ClivlyEntitiesConfig;
|
|
45
|
+
export declare function mappingsToEntitiesConfig(rows: EntityMappingRow[]): ClivlyEntitiesConfig;
|
|
46
46
|
/**
|
|
47
47
|
* Entity Config → Mappings, the inverse of `mappingsToEntitiesConfig`.
|
|
48
48
|
*
|
|
@@ -57,7 +57,7 @@ declare function mappingsToEntitiesConfig(rows: EntityMappingRow[]): ClivlyEntit
|
|
|
57
57
|
* ("client-accounts" derived from "accounts"). So the key travels explicitly on
|
|
58
58
|
* every row rather than being left for the reverse derivation to guess.
|
|
59
59
|
*/
|
|
60
|
-
interface MappingFromConfig {
|
|
60
|
+
export interface MappingFromConfig {
|
|
61
61
|
/**
|
|
62
62
|
* The config entity key this row came from. Not a row column — the caller
|
|
63
63
|
* needs it to resolve a custom object type and to report what it wrote.
|
|
@@ -65,6 +65,8 @@ interface MappingFromConfig {
|
|
|
65
65
|
entityKey: string;
|
|
66
66
|
fieldMap: Record<string, string>;
|
|
67
67
|
filter?: FilterExpr;
|
|
68
|
+
/** Rows from this entity are their company's point of contact. */
|
|
69
|
+
isPrimaryContact?: boolean;
|
|
68
70
|
/** Declared custom object, when the config declares one rather than pinning an id. */
|
|
69
71
|
objectType?: {
|
|
70
72
|
iconKey?: string;
|
|
@@ -80,6 +82,5 @@ interface MappingFromConfig {
|
|
|
80
82
|
targetConcept: string;
|
|
81
83
|
targetObjectTypeId?: string;
|
|
82
84
|
}
|
|
83
|
-
declare function entitiesToMappings(config: ClivlyEntitiesConfig): MappingFromConfig[];
|
|
84
|
-
//#endregion
|
|
85
|
-
export { EntityMappingRow, MappingFromConfig, entitiesToMappings, mappingsToEntitiesConfig };
|
|
85
|
+
export declare function entitiesToMappings(config: ClivlyEntitiesConfig): MappingFromConfig[];
|
|
86
|
+
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as ProjectionMapping, S as RelationshipsMap, a as ClivlyEntitiesConfig, h as FilterExpr } from "./entity-config-
|
|
1
|
+
import { R as ProjectionMapping, S as RelationshipsMap, a as ClivlyEntitiesConfig, h as FilterExpr } from "./entity-config-OhC4Otkz.mjs";
|
|
2
2
|
//#region src/mappings-config.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Mappings → Entity Config bridge.
|
|
@@ -20,7 +20,7 @@ import { R as ProjectionMapping, S as RelationshipsMap, a as ClivlyEntitiesConfi
|
|
|
20
20
|
* reads. Structurally compatible with the Drizzle row (jsonb columns typed
|
|
21
21
|
* loosely) so the API layer can pass `db.select()` results straight in.
|
|
22
22
|
*/
|
|
23
|
-
interface EntityMappingRow {
|
|
23
|
+
export interface EntityMappingRow {
|
|
24
24
|
fieldMap: Record<string, string>;
|
|
25
25
|
filter?: Record<string, unknown> | null;
|
|
26
26
|
/**
|
|
@@ -42,7 +42,7 @@ interface EntityMappingRow {
|
|
|
42
42
|
* unmapped rows are skipped. Returns `{ entities: {} }` when nothing is
|
|
43
43
|
* eligible — a no-op the view compiler and sync engine both tolerate.
|
|
44
44
|
*/
|
|
45
|
-
declare function mappingsToEntitiesConfig(rows: EntityMappingRow[]): ClivlyEntitiesConfig;
|
|
45
|
+
export declare function mappingsToEntitiesConfig(rows: EntityMappingRow[]): ClivlyEntitiesConfig;
|
|
46
46
|
/**
|
|
47
47
|
* Entity Config → Mappings, the inverse of `mappingsToEntitiesConfig`.
|
|
48
48
|
*
|
|
@@ -57,7 +57,7 @@ declare function mappingsToEntitiesConfig(rows: EntityMappingRow[]): ClivlyEntit
|
|
|
57
57
|
* ("client-accounts" derived from "accounts"). So the key travels explicitly on
|
|
58
58
|
* every row rather than being left for the reverse derivation to guess.
|
|
59
59
|
*/
|
|
60
|
-
interface MappingFromConfig {
|
|
60
|
+
export interface MappingFromConfig {
|
|
61
61
|
/**
|
|
62
62
|
* The config entity key this row came from. Not a row column — the caller
|
|
63
63
|
* needs it to resolve a custom object type and to report what it wrote.
|
|
@@ -65,6 +65,8 @@ interface MappingFromConfig {
|
|
|
65
65
|
entityKey: string;
|
|
66
66
|
fieldMap: Record<string, string>;
|
|
67
67
|
filter?: FilterExpr;
|
|
68
|
+
/** Rows from this entity are their company's point of contact. */
|
|
69
|
+
isPrimaryContact?: boolean;
|
|
68
70
|
/** Declared custom object, when the config declares one rather than pinning an id. */
|
|
69
71
|
objectType?: {
|
|
70
72
|
iconKey?: string;
|
|
@@ -80,6 +82,5 @@ interface MappingFromConfig {
|
|
|
80
82
|
targetConcept: string;
|
|
81
83
|
targetObjectTypeId?: string;
|
|
82
84
|
}
|
|
83
|
-
declare function entitiesToMappings(config: ClivlyEntitiesConfig): MappingFromConfig[];
|
|
84
|
-
//#endregion
|
|
85
|
-
export { EntityMappingRow, MappingFromConfig, entitiesToMappings, mappingsToEntitiesConfig };
|
|
85
|
+
export declare function entitiesToMappings(config: ClivlyEntitiesConfig): MappingFromConfig[];
|
|
86
|
+
//#endregion
|
package/dist/mappings-config.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { f as projectionFields, t as CANONICAL_FIELDS } from "./entity-config-
|
|
1
|
+
import { f as projectionFields, t as CANONICAL_FIELDS } from "./entity-config-C0rtu-K_.mjs";
|
|
2
2
|
//#region src/mappings-config.ts
|
|
3
3
|
const RESERVED_FIELD = "id";
|
|
4
4
|
/**
|
|
@@ -119,6 +119,7 @@ function entitiesToMappings(config) {
|
|
|
119
119
|
fieldMap: entity.projection ? {} : entity.fields
|
|
120
120
|
};
|
|
121
121
|
if (entity.filter) row.filter = entity.filter;
|
|
122
|
+
if (entity.isPrimaryContact) row.isPrimaryContact = true;
|
|
122
123
|
if (entity.relationships) row.relationships = entity.relationships;
|
|
123
124
|
if (entity.projection) row.projection = entity.projection;
|
|
124
125
|
if (entity.concept === CUSTOM_CONCEPT) {
|