clivly 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +52 -3
  2. package/adapter-nLfZpgIG.d.cts +40 -0
  3. package/adapter-xs04z0KX.d.mts +40 -0
  4. package/auth-adapter-CBOKDhlc.cjs +11 -0
  5. package/auth-adapter-FEOR1nx-.d.mts +30 -0
  6. package/auth-adapter-wqnnEjo3.mjs +6 -0
  7. package/auth-adapter-wvfGKsOJ.d.cts +30 -0
  8. package/auth-better-auth.cjs +28 -0
  9. package/auth-better-auth.d.cts +33 -0
  10. package/auth-better-auth.d.mts +33 -0
  11. package/auth-better-auth.mjs +26 -0
  12. package/auth-clerk.cjs +34 -0
  13. package/auth-clerk.d.cts +32 -0
  14. package/auth-clerk.d.mts +32 -0
  15. package/auth-clerk.mjs +32 -0
  16. package/auth-workos.cjs +47 -0
  17. package/auth-workos.d.cts +30 -0
  18. package/auth-workos.d.mts +30 -0
  19. package/auth-workos.mjs +45 -0
  20. package/core-adapter.cjs +0 -0
  21. package/core-adapter.d.cts +2 -0
  22. package/core-adapter.d.mts +2 -0
  23. package/core-adapter.mjs +1 -0
  24. package/core-auth-adapter.cjs +3 -0
  25. package/core-auth-adapter.d.cts +2 -0
  26. package/core-auth-adapter.d.mts +2 -0
  27. package/core-auth-adapter.mjs +2 -0
  28. package/core-drizzle.cjs +32 -0
  29. package/core-drizzle.d.cts +21 -0
  30. package/core-drizzle.d.mts +21 -0
  31. package/core-drizzle.mjs +31 -0
  32. package/core-entity-config.cjs +13 -0
  33. package/core-entity-config.d.cts +2 -0
  34. package/core-entity-config.d.mts +2 -0
  35. package/core-entity-config.mjs +2 -0
  36. package/core-entity-heuristics.cjs +442 -0
  37. package/core-entity-heuristics.d.cts +68 -0
  38. package/core-entity-heuristics.d.mts +68 -0
  39. package/core-entity-heuristics.mjs +431 -0
  40. package/core-mapping-form.cjs +5 -0
  41. package/core-mapping-form.d.cts +2 -0
  42. package/core-mapping-form.d.mts +2 -0
  43. package/core-mapping-form.mjs +2 -0
  44. package/core-mapping-score.cjs +12 -0
  45. package/core-mapping-score.d.cts +2 -0
  46. package/core-mapping-score.d.mts +2 -0
  47. package/core-mapping-score.mjs +2 -0
  48. package/core-mappings-config.cjs +3 -0
  49. package/core-mappings-config.d.cts +2 -0
  50. package/core-mappings-config.d.mts +2 -0
  51. package/core-mappings-config.mjs +2 -0
  52. package/core-sync-engine.cjs +6 -0
  53. package/core-sync-engine.d.cts +2 -0
  54. package/core-sync-engine.d.mts +2 -0
  55. package/core-sync-engine.mjs +2 -0
  56. package/core-types.cjs +0 -0
  57. package/core-types.d.cts +2 -0
  58. package/core-types.d.mts +2 -0
  59. package/core-types.mjs +1 -0
  60. package/core-view-compiler.cjs +5 -0
  61. package/core-view-compiler.d.cts +2 -0
  62. package/core-view-compiler.d.mts +2 -0
  63. package/core-view-compiler.mjs +2 -0
  64. package/core.cjs +27 -0
  65. package/core.d.cts +9 -0
  66. package/core.d.mts +9 -0
  67. package/core.mjs +7 -0
  68. package/drizzle-meta-BGn0BqGb.cjs +9 -0
  69. package/drizzle-meta-CnC336L-.mjs +4 -0
  70. package/drizzle.cjs +107 -0
  71. package/drizzle.d.cts +28 -0
  72. package/drizzle.d.mts +28 -0
  73. package/drizzle.mjs +105 -0
  74. package/entity-config-Cvjo1cpv.cjs +4598 -0
  75. package/entity-config-D1DFyeUp.d.mts +2403 -0
  76. package/entity-config-DoR0khce.mjs +4533 -0
  77. package/entity-config-GczjD3y8.d.cts +2403 -0
  78. package/index.cjs +926 -0
  79. package/index.d.cts +56 -0
  80. package/index.d.mts +56 -0
  81. package/{dist/index.mjs → index.mjs} +430 -47
  82. package/mapping-form-BHtPexzI.mjs +47 -0
  83. package/mapping-form-CUlFVfG8.d.cts +35 -0
  84. package/mapping-form-DdmDebC3.cjs +64 -0
  85. package/mapping-form-kjSiJaCX.d.mts +35 -0
  86. package/mapping-score-A2lRnlpk.d.mts +49 -0
  87. package/mapping-score-BJNe0lFn.mjs +87 -0
  88. package/mapping-score-BcjC0ZQs.d.cts +49 -0
  89. package/mapping-score-D9gfhtRu.cjs +146 -0
  90. package/mappings-config-CYPrzB3K.mjs +99 -0
  91. package/mappings-config-DTu_2cyx.cjs +104 -0
  92. package/mappings-config-DjRLCb2Q.d.cts +42 -0
  93. package/mappings-config-GxiYsSBQ.d.mts +42 -0
  94. package/namespace-probe-BtS0nXcr.d.cts +299 -0
  95. package/namespace-probe-CYMie-BI.d.mts +299 -0
  96. package/package.json +223 -26
  97. package/sdk-BZUn6wzs.mjs +764 -0
  98. package/sdk-CP_mYZa5.cjs +793 -0
  99. package/sdk.cjs +7 -0
  100. package/sdk.d.cts +33 -0
  101. package/sdk.d.mts +33 -0
  102. package/sdk.mjs +2 -0
  103. package/sync-engine-DUc0qWgo.cjs +230 -0
  104. package/sync-engine-DWnQPjV3.d.mts +183 -0
  105. package/sync-engine-DedXngop.mjs +207 -0
  106. package/sync-engine-uhfzKM-e.d.cts +183 -0
  107. package/types-C4POUcvk.d.mts +158 -0
  108. package/types-LJTBhkcN.d.cts +158 -0
  109. package/view-compiler-B4UYTvRM.d.cts +71 -0
  110. package/view-compiler-BHzbI9b7.cjs +202 -0
  111. package/view-compiler-CosFGar8.mjs +185 -0
  112. package/view-compiler-i_xFf-L0.d.mts +71 -0
  113. package/vite.cjs +38 -0
  114. package/vite.d.cts +23 -0
  115. package/vite.d.mts +23 -0
  116. package/vite.mjs +37 -0
@@ -0,0 +1,35 @@
1
+ import { _ as RelationshipsMap, d as FilterExpr, g as RelationshipVia } from "./entity-config-GczjD3y8.cjs";
2
+
3
+ //#region ../core/src/mapping-form.d.ts
4
+ /**
5
+ * A relationship the mapping UI can offer or has configured, in the shape the
6
+ * heuristic suggester produces. `entityTable` is the *host table name*; the
7
+ * mappings→config compiler resolves it to the canonical entity key, so it is
8
+ * persisted verbatim as the relationship's `entity` reference.
9
+ */
10
+ interface RelationshipCandidate {
11
+ entityTable: string;
12
+ name: string;
13
+ via: RelationshipVia;
14
+ }
15
+ /**
16
+ * Build the filter for a discriminated entity: rows where `column` equals
17
+ * `value` belong to this entity (e.g. `role = "owner"`). Returns `undefined`
18
+ * when either side is blank so the caller can omit the filter entirely.
19
+ */
20
+ declare function buildFilterFromDiscriminator(column: string | null | undefined, value: string): FilterExpr | undefined;
21
+ /**
22
+ * A stable identity string for a relationship's `via`. Two candidates on the
23
+ * same source table always differ in their join (`fkOn`+column, join-table
24
+ * keys, or raw SQL), so this disambiguates candidates the heuristic gives the
25
+ * same `name` (every contact→company candidate is named "company").
26
+ */
27
+ declare function relationshipViaSignature(via: RelationshipVia): string;
28
+ /**
29
+ * Compile the selected relationship candidates into the persisted
30
+ * `RelationshipsMap`. Returns `undefined` for an empty selection so the caller
31
+ * omits the field.
32
+ */
33
+ declare function buildRelationships(candidates: RelationshipCandidate[]): RelationshipsMap | undefined;
34
+ //#endregion
35
+ export { relationshipViaSignature as i, buildFilterFromDiscriminator as n, buildRelationships as r, RelationshipCandidate as t };
@@ -0,0 +1,64 @@
1
+ //#region ../core/src/mapping-form.ts
2
+ /**
3
+ * Build the filter for a discriminated entity: rows where `column` equals
4
+ * `value` belong to this entity (e.g. `role = "owner"`). Returns `undefined`
5
+ * when either side is blank so the caller can omit the filter entirely.
6
+ */
7
+ function buildFilterFromDiscriminator(column, value) {
8
+ const col = column?.trim();
9
+ const val = value.trim();
10
+ if (!col || val === "") return;
11
+ return { [col]: { eq: val } };
12
+ }
13
+ /**
14
+ * A stable identity string for a relationship's `via`. Two candidates on the
15
+ * same source table always differ in their join (`fkOn`+column, join-table
16
+ * keys, or raw SQL), so this disambiguates candidates the heuristic gives the
17
+ * same `name` (every contact→company candidate is named "company").
18
+ */
19
+ function relationshipViaSignature(via) {
20
+ if ("fkOn" in via) return `fk:${via.fkOn}:${via.column}`;
21
+ if ("through" in via) return `through:${via.through}:${via.localKey}:${via.foreignKey}`;
22
+ return `raw:${via.$raw}`;
23
+ }
24
+ /**
25
+ * Compile the selected relationship candidates into the persisted
26
+ * `RelationshipsMap`. Returns `undefined` for an empty selection so the caller
27
+ * omits the field.
28
+ */
29
+ function buildRelationships(candidates) {
30
+ if (candidates.length === 0) return;
31
+ const map = {};
32
+ for (const candidate of candidates) {
33
+ let key = candidate.name;
34
+ let suffix = 2;
35
+ while (key in map) {
36
+ key = `${candidate.name}_${suffix}`;
37
+ suffix++;
38
+ }
39
+ map[key] = {
40
+ entity: candidate.entityTable,
41
+ via: candidate.via
42
+ };
43
+ }
44
+ return map;
45
+ }
46
+ //#endregion
47
+ Object.defineProperty(exports, "buildFilterFromDiscriminator", {
48
+ enumerable: true,
49
+ get: function() {
50
+ return buildFilterFromDiscriminator;
51
+ }
52
+ });
53
+ Object.defineProperty(exports, "buildRelationships", {
54
+ enumerable: true,
55
+ get: function() {
56
+ return buildRelationships;
57
+ }
58
+ });
59
+ Object.defineProperty(exports, "relationshipViaSignature", {
60
+ enumerable: true,
61
+ get: function() {
62
+ return relationshipViaSignature;
63
+ }
64
+ });
@@ -0,0 +1,35 @@
1
+ import { _ as RelationshipsMap, d as FilterExpr, g as RelationshipVia } from "./entity-config-D1DFyeUp.mjs";
2
+
3
+ //#region ../core/src/mapping-form.d.ts
4
+ /**
5
+ * A relationship the mapping UI can offer or has configured, in the shape the
6
+ * heuristic suggester produces. `entityTable` is the *host table name*; the
7
+ * mappings→config compiler resolves it to the canonical entity key, so it is
8
+ * persisted verbatim as the relationship's `entity` reference.
9
+ */
10
+ interface RelationshipCandidate {
11
+ entityTable: string;
12
+ name: string;
13
+ via: RelationshipVia;
14
+ }
15
+ /**
16
+ * Build the filter for a discriminated entity: rows where `column` equals
17
+ * `value` belong to this entity (e.g. `role = "owner"`). Returns `undefined`
18
+ * when either side is blank so the caller can omit the filter entirely.
19
+ */
20
+ declare function buildFilterFromDiscriminator(column: string | null | undefined, value: string): FilterExpr | undefined;
21
+ /**
22
+ * A stable identity string for a relationship's `via`. Two candidates on the
23
+ * same source table always differ in their join (`fkOn`+column, join-table
24
+ * keys, or raw SQL), so this disambiguates candidates the heuristic gives the
25
+ * same `name` (every contact→company candidate is named "company").
26
+ */
27
+ declare function relationshipViaSignature(via: RelationshipVia): string;
28
+ /**
29
+ * Compile the selected relationship candidates into the persisted
30
+ * `RelationshipsMap`. Returns `undefined` for an empty selection so the caller
31
+ * omits the field.
32
+ */
33
+ declare function buildRelationships(candidates: RelationshipCandidate[]): RelationshipsMap | undefined;
34
+ //#endregion
35
+ export { relationshipViaSignature as i, buildFilterFromDiscriminator as n, buildRelationships as r, RelationshipCandidate as t };
@@ -0,0 +1,49 @@
1
+ //#region ../core/src/mapping-score.d.ts
2
+ type Tier = "High" | "Medium" | "Low";
3
+ interface Scored<T> {
4
+ /** Human-readable chips, e.g. `type text`, `name matches "contacts"`. */
5
+ reasons: string[];
6
+ /** Internal — used for ranking and the apply threshold. Never rendered. */
7
+ score: number;
8
+ tier: Tier;
9
+ value: T;
10
+ }
11
+ /** Tier cut-offs: score >= high → High; >= medium → Medium; else Low. */
12
+ interface Thresholds {
13
+ high: number;
14
+ medium: number;
15
+ }
16
+ declare const CONCEPT_TIERS: Thresholds;
17
+ declare const FIELD_TIERS: Thresholds;
18
+ declare const RELATIONSHIP_TIERS: Thresholds;
19
+ /** Two concept candidates closer than this are treated as ambiguous. */
20
+ declare const AMBIGUITY_MARGIN = 15;
21
+ /** Signal weights. Tuned against fixtures; adjust here, not at call sites. */
22
+ declare const W: {
23
+ readonly nameExact: 50;
24
+ readonly nameSubstring: 25;
25
+ readonly definingColumn: 20;
26
+ readonly hasPrimaryKey: 10;
27
+ readonly hasRows: 10;
28
+ readonly emptyTable: -20;
29
+ readonly fieldNameMatch: 50;
30
+ readonly typeCompatible: 30;
31
+ readonly typeMismatch: -30;
32
+ readonly requiredNotNull: 10;
33
+ readonly fkResolved: 60;
34
+ readonly fkNameHint: 30;
35
+ readonly joinTable: 20;
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;
41
+ /**
42
+ * True when the top two candidates are too close to call. Callers must never
43
+ * one-click apply an ambiguous result — the user picks.
44
+ */
45
+ declare function isAmbiguous(ranked: Array<{
46
+ score: number;
47
+ }>): boolean;
48
+ //#endregion
49
+ export { Scored as a, W as c, isTextLike as d, isTimestampLike as f, RELATIONSHIP_TIERS as i, isAmbiguous as l, CONCEPT_TIERS as n, Thresholds as o, tierFor as p, FIELD_TIERS as r, Tier as s, AMBIGUITY_MARGIN as t, isNumericLike as u };
@@ -0,0 +1,87 @@
1
+ //#region ../core/src/mapping-score.ts
2
+ const CONCEPT_TIERS = {
3
+ high: 70,
4
+ medium: 40
5
+ };
6
+ const FIELD_TIERS = {
7
+ high: 70,
8
+ medium: 40
9
+ };
10
+ const RELATIONSHIP_TIERS = {
11
+ high: 60,
12
+ medium: 30
13
+ };
14
+ /** Two concept candidates closer than this are treated as ambiguous. */
15
+ const AMBIGUITY_MARGIN = 15;
16
+ /** Signal weights. Tuned against fixtures; adjust here, not at call sites. */
17
+ const W = {
18
+ nameExact: 50,
19
+ nameSubstring: 25,
20
+ definingColumn: 20,
21
+ hasPrimaryKey: 10,
22
+ hasRows: 10,
23
+ emptyTable: -20,
24
+ fieldNameMatch: 50,
25
+ typeCompatible: 30,
26
+ typeMismatch: -30,
27
+ requiredNotNull: 10,
28
+ fkResolved: 60,
29
+ fkNameHint: 30,
30
+ joinTable: 20
31
+ };
32
+ function tierFor(score, t) {
33
+ if (score >= t.high) return "High";
34
+ if (score >= t.medium) return "Medium";
35
+ return "Low";
36
+ }
37
+ const TEXT_TYPES = [
38
+ "text",
39
+ "varchar",
40
+ "char",
41
+ "citext",
42
+ "uuid",
43
+ "string"
44
+ ];
45
+ const NUMERIC_TYPES = [
46
+ "numeric",
47
+ "decimal",
48
+ "int",
49
+ "integer",
50
+ "bigint",
51
+ "smallint",
52
+ "float",
53
+ "double",
54
+ "real",
55
+ "money"
56
+ ];
57
+ const TIMESTAMP_TYPES = [
58
+ "timestamp",
59
+ "timestamptz",
60
+ "date",
61
+ "datetime"
62
+ ];
63
+ function matchesType(type, list) {
64
+ if (!type) return false;
65
+ const normalized = type.toLowerCase();
66
+ return list.some((t) => normalized.startsWith(t));
67
+ }
68
+ function isTextLike(type) {
69
+ return matchesType(type, TEXT_TYPES);
70
+ }
71
+ function isNumericLike(type) {
72
+ return matchesType(type, NUMERIC_TYPES);
73
+ }
74
+ function isTimestampLike(type) {
75
+ return matchesType(type, TIMESTAMP_TYPES);
76
+ }
77
+ /**
78
+ * True when the top two candidates are too close to call. Callers must never
79
+ * one-click apply an ambiguous result — the user picks.
80
+ */
81
+ function isAmbiguous(ranked) {
82
+ const [first, second] = ranked;
83
+ if (!(first && second)) return false;
84
+ return first.score - second.score < 15;
85
+ }
86
+ //#endregion
87
+ export { W as a, isTextLike as c, RELATIONSHIP_TIERS as i, isTimestampLike as l, CONCEPT_TIERS as n, isAmbiguous as o, FIELD_TIERS as r, isNumericLike as s, AMBIGUITY_MARGIN as t, tierFor as u };
@@ -0,0 +1,49 @@
1
+ //#region ../core/src/mapping-score.d.ts
2
+ type Tier = "High" | "Medium" | "Low";
3
+ interface Scored<T> {
4
+ /** Human-readable chips, e.g. `type text`, `name matches "contacts"`. */
5
+ reasons: string[];
6
+ /** Internal — used for ranking and the apply threshold. Never rendered. */
7
+ score: number;
8
+ tier: Tier;
9
+ value: T;
10
+ }
11
+ /** Tier cut-offs: score >= high → High; >= medium → Medium; else Low. */
12
+ interface Thresholds {
13
+ high: number;
14
+ medium: number;
15
+ }
16
+ declare const CONCEPT_TIERS: Thresholds;
17
+ declare const FIELD_TIERS: Thresholds;
18
+ declare const RELATIONSHIP_TIERS: Thresholds;
19
+ /** Two concept candidates closer than this are treated as ambiguous. */
20
+ declare const AMBIGUITY_MARGIN = 15;
21
+ /** Signal weights. Tuned against fixtures; adjust here, not at call sites. */
22
+ declare const W: {
23
+ readonly nameExact: 50;
24
+ readonly nameSubstring: 25;
25
+ readonly definingColumn: 20;
26
+ readonly hasPrimaryKey: 10;
27
+ readonly hasRows: 10;
28
+ readonly emptyTable: -20;
29
+ readonly fieldNameMatch: 50;
30
+ readonly typeCompatible: 30;
31
+ readonly typeMismatch: -30;
32
+ readonly requiredNotNull: 10;
33
+ readonly fkResolved: 60;
34
+ readonly fkNameHint: 30;
35
+ readonly joinTable: 20;
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;
41
+ /**
42
+ * True when the top two candidates are too close to call. Callers must never
43
+ * one-click apply an ambiguous result — the user picks.
44
+ */
45
+ declare function isAmbiguous(ranked: Array<{
46
+ score: number;
47
+ }>): boolean;
48
+ //#endregion
49
+ export { Scored as a, W as c, isTextLike as d, isTimestampLike as f, RELATIONSHIP_TIERS as i, isAmbiguous as l, CONCEPT_TIERS as n, Thresholds as o, tierFor as p, FIELD_TIERS as r, Tier as s, AMBIGUITY_MARGIN as t, isNumericLike as u };
@@ -0,0 +1,146 @@
1
+ //#region ../core/src/mapping-score.ts
2
+ const CONCEPT_TIERS = {
3
+ high: 70,
4
+ medium: 40
5
+ };
6
+ const FIELD_TIERS = {
7
+ high: 70,
8
+ medium: 40
9
+ };
10
+ const RELATIONSHIP_TIERS = {
11
+ high: 60,
12
+ medium: 30
13
+ };
14
+ /** Two concept candidates closer than this are treated as ambiguous. */
15
+ const AMBIGUITY_MARGIN = 15;
16
+ /** Signal weights. Tuned against fixtures; adjust here, not at call sites. */
17
+ const W = {
18
+ nameExact: 50,
19
+ nameSubstring: 25,
20
+ definingColumn: 20,
21
+ hasPrimaryKey: 10,
22
+ hasRows: 10,
23
+ emptyTable: -20,
24
+ fieldNameMatch: 50,
25
+ typeCompatible: 30,
26
+ typeMismatch: -30,
27
+ requiredNotNull: 10,
28
+ fkResolved: 60,
29
+ fkNameHint: 30,
30
+ joinTable: 20
31
+ };
32
+ function tierFor(score, t) {
33
+ if (score >= t.high) return "High";
34
+ if (score >= t.medium) return "Medium";
35
+ return "Low";
36
+ }
37
+ const TEXT_TYPES = [
38
+ "text",
39
+ "varchar",
40
+ "char",
41
+ "citext",
42
+ "uuid",
43
+ "string"
44
+ ];
45
+ const NUMERIC_TYPES = [
46
+ "numeric",
47
+ "decimal",
48
+ "int",
49
+ "integer",
50
+ "bigint",
51
+ "smallint",
52
+ "float",
53
+ "double",
54
+ "real",
55
+ "money"
56
+ ];
57
+ const TIMESTAMP_TYPES = [
58
+ "timestamp",
59
+ "timestamptz",
60
+ "date",
61
+ "datetime"
62
+ ];
63
+ function matchesType(type, list) {
64
+ if (!type) return false;
65
+ const normalized = type.toLowerCase();
66
+ return list.some((t) => normalized.startsWith(t));
67
+ }
68
+ function isTextLike(type) {
69
+ return matchesType(type, TEXT_TYPES);
70
+ }
71
+ function isNumericLike(type) {
72
+ return matchesType(type, NUMERIC_TYPES);
73
+ }
74
+ function isTimestampLike(type) {
75
+ return matchesType(type, TIMESTAMP_TYPES);
76
+ }
77
+ /**
78
+ * True when the top two candidates are too close to call. Callers must never
79
+ * one-click apply an ambiguous result — the user picks.
80
+ */
81
+ function isAmbiguous(ranked) {
82
+ const [first, second] = ranked;
83
+ if (!(first && second)) return false;
84
+ return first.score - second.score < 15;
85
+ }
86
+ //#endregion
87
+ Object.defineProperty(exports, "AMBIGUITY_MARGIN", {
88
+ enumerable: true,
89
+ get: function() {
90
+ return AMBIGUITY_MARGIN;
91
+ }
92
+ });
93
+ Object.defineProperty(exports, "CONCEPT_TIERS", {
94
+ enumerable: true,
95
+ get: function() {
96
+ return CONCEPT_TIERS;
97
+ }
98
+ });
99
+ Object.defineProperty(exports, "FIELD_TIERS", {
100
+ enumerable: true,
101
+ get: function() {
102
+ return FIELD_TIERS;
103
+ }
104
+ });
105
+ Object.defineProperty(exports, "RELATIONSHIP_TIERS", {
106
+ enumerable: true,
107
+ get: function() {
108
+ return RELATIONSHIP_TIERS;
109
+ }
110
+ });
111
+ Object.defineProperty(exports, "W", {
112
+ enumerable: true,
113
+ get: function() {
114
+ return W;
115
+ }
116
+ });
117
+ Object.defineProperty(exports, "isAmbiguous", {
118
+ enumerable: true,
119
+ get: function() {
120
+ return isAmbiguous;
121
+ }
122
+ });
123
+ Object.defineProperty(exports, "isNumericLike", {
124
+ enumerable: true,
125
+ get: function() {
126
+ return isNumericLike;
127
+ }
128
+ });
129
+ Object.defineProperty(exports, "isTextLike", {
130
+ enumerable: true,
131
+ get: function() {
132
+ return isTextLike;
133
+ }
134
+ });
135
+ Object.defineProperty(exports, "isTimestampLike", {
136
+ enumerable: true,
137
+ get: function() {
138
+ return isTimestampLike;
139
+ }
140
+ });
141
+ Object.defineProperty(exports, "tierFor", {
142
+ enumerable: true,
143
+ get: function() {
144
+ return tierFor;
145
+ }
146
+ });
@@ -0,0 +1,99 @@
1
+ import { t as CANONICAL_FIELDS } from "./entity-config-DoR0khce.mjs";
2
+ //#region ../core/src/mappings-config.ts
3
+ const RESERVED_FIELD = "id";
4
+ /**
5
+ * Restrict a persisted field map to what the mirror can actually store: drop
6
+ * the reserved `id` key (for every concept) and, for materialized concepts
7
+ * (contact/company), any key that isn't canonical. This makes the pipeline
8
+ * resilient to legacy or mis-suggested field maps — a stray `id` no longer
9
+ * blocks the whole sync.
10
+ */
11
+ function canonicalFields(concept, fieldMap) {
12
+ const allowed = CANONICAL_FIELDS[concept];
13
+ const result = {};
14
+ for (const [field, column] of Object.entries(fieldMap)) {
15
+ if (field === RESERVED_FIELD) continue;
16
+ if (allowed && !allowed.includes(field)) continue;
17
+ result[field] = column;
18
+ }
19
+ return result;
20
+ }
21
+ const DEFAULT_ROLE = "primary";
22
+ const ACTIVE_STATUS = "active";
23
+ function isEligible(row) {
24
+ return (row.status ?? ACTIVE_STATUS) === ACTIVE_STATUS && Object.keys(row.fieldMap ?? {}).length > 0;
25
+ }
26
+ /**
27
+ * Preferred key for a row: the bare source table when it backs a single entity,
28
+ * else role-suffixed so multiple roles on one table stay distinct and stable
29
+ * (the primary role keeps the bare name). Uniqueness is still enforced by the
30
+ * caller in case two rows land on the same preferred key.
31
+ */
32
+ function preferredKey(row, tableCounts) {
33
+ const role = row.role ?? DEFAULT_ROLE;
34
+ if ((tableCounts.get(row.sourceTable) ?? 0) <= 1) return row.sourceTable;
35
+ return role === DEFAULT_ROLE ? row.sourceTable : `${row.sourceTable}__${role}`;
36
+ }
37
+ function uniquify(base, used) {
38
+ if (!used.has(base)) {
39
+ used.add(base);
40
+ return base;
41
+ }
42
+ let suffix = 2;
43
+ while (used.has(`${base}__${suffix}`)) suffix++;
44
+ const key = `${base}__${suffix}`;
45
+ used.add(key);
46
+ return key;
47
+ }
48
+ function buildEntity(row, refIndex) {
49
+ const entity = {
50
+ concept: row.targetConcept,
51
+ source: row.sourceTable,
52
+ role: row.role ?? DEFAULT_ROLE,
53
+ fields: canonicalFields(row.targetConcept, row.fieldMap)
54
+ };
55
+ if (row.targetConcept === "custom" && row.targetObjectTypeId) entity.targetObjectTypeId = row.targetObjectTypeId;
56
+ if (row.filter && Object.keys(row.filter).length > 0) entity.filter = row.filter;
57
+ if (row.relationships && Object.keys(row.relationships).length > 0) {
58
+ const relationships = {};
59
+ for (const [name, spec] of Object.entries(row.relationships)) {
60
+ const rel = spec;
61
+ relationships[name] = {
62
+ entity: refIndex.get(rel.entity) ?? rel.entity,
63
+ via: rel.via
64
+ };
65
+ }
66
+ entity.relationships = relationships;
67
+ }
68
+ return entity;
69
+ }
70
+ /**
71
+ * Compile persisted mapping rows into a `ClivlyEntitiesConfig`. Only `active`
72
+ * rows with at least one mapped field are included; disabled/suggested rows and
73
+ * unmapped rows are skipped. Returns `{ entities: {} }` when nothing is
74
+ * eligible — a no-op the view compiler and sync engine both tolerate.
75
+ */
76
+ function mappingsToEntitiesConfig(rows) {
77
+ const eligible = rows.filter(isEligible);
78
+ const tableCounts = /* @__PURE__ */ new Map();
79
+ for (const row of eligible) tableCounts.set(row.sourceTable, (tableCounts.get(row.sourceTable) ?? 0) + 1);
80
+ const used = /* @__PURE__ */ new Set();
81
+ const tableAnchor = /* @__PURE__ */ new Map();
82
+ const assigned = [];
83
+ for (const row of eligible) {
84
+ const key = uniquify(preferredKey(row, tableCounts), used);
85
+ assigned.push({
86
+ row,
87
+ key
88
+ });
89
+ if ((row.role ?? DEFAULT_ROLE) === DEFAULT_ROLE || !tableAnchor.has(row.sourceTable)) tableAnchor.set(row.sourceTable, key);
90
+ }
91
+ const refIndex = /* @__PURE__ */ new Map();
92
+ for (const { key } of assigned) refIndex.set(key, key);
93
+ for (const [table, key] of tableAnchor) if (!refIndex.has(table)) refIndex.set(table, key);
94
+ const entities = {};
95
+ for (const { row, key } of assigned) entities[key] = buildEntity(row, refIndex);
96
+ return { entities };
97
+ }
98
+ //#endregion
99
+ export { mappingsToEntitiesConfig as t };
@@ -0,0 +1,104 @@
1
+ const require_entity_config = require("./entity-config-Cvjo1cpv.cjs");
2
+ //#region ../core/src/mappings-config.ts
3
+ const RESERVED_FIELD = "id";
4
+ /**
5
+ * Restrict a persisted field map to what the mirror can actually store: drop
6
+ * the reserved `id` key (for every concept) and, for materialized concepts
7
+ * (contact/company), any key that isn't canonical. This makes the pipeline
8
+ * resilient to legacy or mis-suggested field maps — a stray `id` no longer
9
+ * blocks the whole sync.
10
+ */
11
+ function canonicalFields(concept, fieldMap) {
12
+ const allowed = require_entity_config.CANONICAL_FIELDS[concept];
13
+ const result = {};
14
+ for (const [field, column] of Object.entries(fieldMap)) {
15
+ if (field === RESERVED_FIELD) continue;
16
+ if (allowed && !allowed.includes(field)) continue;
17
+ result[field] = column;
18
+ }
19
+ return result;
20
+ }
21
+ const DEFAULT_ROLE = "primary";
22
+ const ACTIVE_STATUS = "active";
23
+ function isEligible(row) {
24
+ return (row.status ?? ACTIVE_STATUS) === ACTIVE_STATUS && Object.keys(row.fieldMap ?? {}).length > 0;
25
+ }
26
+ /**
27
+ * Preferred key for a row: the bare source table when it backs a single entity,
28
+ * else role-suffixed so multiple roles on one table stay distinct and stable
29
+ * (the primary role keeps the bare name). Uniqueness is still enforced by the
30
+ * caller in case two rows land on the same preferred key.
31
+ */
32
+ function preferredKey(row, tableCounts) {
33
+ const role = row.role ?? DEFAULT_ROLE;
34
+ if ((tableCounts.get(row.sourceTable) ?? 0) <= 1) return row.sourceTable;
35
+ return role === DEFAULT_ROLE ? row.sourceTable : `${row.sourceTable}__${role}`;
36
+ }
37
+ function uniquify(base, used) {
38
+ if (!used.has(base)) {
39
+ used.add(base);
40
+ return base;
41
+ }
42
+ let suffix = 2;
43
+ while (used.has(`${base}__${suffix}`)) suffix++;
44
+ const key = `${base}__${suffix}`;
45
+ used.add(key);
46
+ return key;
47
+ }
48
+ function buildEntity(row, refIndex) {
49
+ const entity = {
50
+ concept: row.targetConcept,
51
+ source: row.sourceTable,
52
+ role: row.role ?? DEFAULT_ROLE,
53
+ fields: canonicalFields(row.targetConcept, row.fieldMap)
54
+ };
55
+ if (row.targetConcept === "custom" && row.targetObjectTypeId) entity.targetObjectTypeId = row.targetObjectTypeId;
56
+ if (row.filter && Object.keys(row.filter).length > 0) entity.filter = row.filter;
57
+ if (row.relationships && Object.keys(row.relationships).length > 0) {
58
+ const relationships = {};
59
+ for (const [name, spec] of Object.entries(row.relationships)) {
60
+ const rel = spec;
61
+ relationships[name] = {
62
+ entity: refIndex.get(rel.entity) ?? rel.entity,
63
+ via: rel.via
64
+ };
65
+ }
66
+ entity.relationships = relationships;
67
+ }
68
+ return entity;
69
+ }
70
+ /**
71
+ * Compile persisted mapping rows into a `ClivlyEntitiesConfig`. Only `active`
72
+ * rows with at least one mapped field are included; disabled/suggested rows and
73
+ * unmapped rows are skipped. Returns `{ entities: {} }` when nothing is
74
+ * eligible — a no-op the view compiler and sync engine both tolerate.
75
+ */
76
+ function mappingsToEntitiesConfig(rows) {
77
+ const eligible = rows.filter(isEligible);
78
+ const tableCounts = /* @__PURE__ */ new Map();
79
+ for (const row of eligible) tableCounts.set(row.sourceTable, (tableCounts.get(row.sourceTable) ?? 0) + 1);
80
+ const used = /* @__PURE__ */ new Set();
81
+ const tableAnchor = /* @__PURE__ */ new Map();
82
+ const assigned = [];
83
+ for (const row of eligible) {
84
+ const key = uniquify(preferredKey(row, tableCounts), used);
85
+ assigned.push({
86
+ row,
87
+ key
88
+ });
89
+ if ((row.role ?? DEFAULT_ROLE) === DEFAULT_ROLE || !tableAnchor.has(row.sourceTable)) tableAnchor.set(row.sourceTable, key);
90
+ }
91
+ const refIndex = /* @__PURE__ */ new Map();
92
+ for (const { key } of assigned) refIndex.set(key, key);
93
+ for (const [table, key] of tableAnchor) if (!refIndex.has(table)) refIndex.set(table, key);
94
+ const entities = {};
95
+ for (const { row, key } of assigned) entities[key] = buildEntity(row, refIndex);
96
+ return { entities };
97
+ }
98
+ //#endregion
99
+ Object.defineProperty(exports, "mappingsToEntitiesConfig", {
100
+ enumerable: true,
101
+ get: function() {
102
+ return mappingsToEntitiesConfig;
103
+ }
104
+ });