@clivly/core 0.9.7 → 0.10.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.
Files changed (48) hide show
  1. package/README.md +17 -10
  2. package/dist/builder.cjs +599 -0
  3. package/dist/builder.d.cts +336 -0
  4. package/dist/builder.d.mts +336 -0
  5. package/dist/builder.mjs +589 -0
  6. package/dist/drizzle.d.cts +1 -1
  7. package/dist/drizzle.d.mts +1 -1
  8. package/dist/{entity-config-25v_udeY.cjs → entity-config-C5jBmG2C.cjs} +83 -68
  9. package/dist/{entity-config-buOIVtMM.d.cts → entity-config-DCa785OE.d.cts} +27 -1
  10. package/dist/{entity-config-buOIVtMM.d.mts → entity-config-DCa785OE.d.mts} +27 -1
  11. package/dist/{entity-config-DwGXbUo_.mjs → entity-config-DpHPMFIS.mjs} +71 -38
  12. package/dist/entity-config.cjs +1 -1
  13. package/dist/entity-config.d.cts +1 -1
  14. package/dist/entity-config.d.mts +1 -1
  15. package/dist/entity-config.mjs +1 -1
  16. package/dist/entity-heuristics.cjs +34 -1
  17. package/dist/entity-heuristics.d.cts +8 -2
  18. package/dist/entity-heuristics.d.mts +8 -2
  19. package/dist/entity-heuristics.mjs +34 -2
  20. package/dist/index.cjs +136 -199
  21. package/dist/index.d.cts +135 -89
  22. package/dist/index.d.mts +135 -89
  23. package/dist/index.mjs +124 -188
  24. package/dist/mapping-form.d.cts +1 -1
  25. package/dist/mapping-form.d.mts +1 -1
  26. package/dist/mappings-config.cjs +2 -16
  27. package/dist/mappings-config.d.cts +1 -1
  28. package/dist/mappings-config.d.mts +1 -1
  29. package/dist/mappings-config.mjs +1 -15
  30. package/dist/{projection-OJYCYmS_.cjs → projection-DFgCoyZl.cjs} +0 -6
  31. package/dist/{projection-BXw_iiw5.mjs → projection-SCNrLJMV.mjs} +1 -1
  32. package/dist/schema-meta-Ac7938mT.mjs +46 -0
  33. package/dist/schema-meta-Cgi0MnHh.cjs +69 -0
  34. package/dist/sync-engine.cjs +1 -1
  35. package/dist/sync-engine.d.cts +1 -1
  36. package/dist/sync-engine.d.mts +1 -1
  37. package/dist/sync-engine.mjs +1 -1
  38. package/dist/types.cjs +11 -0
  39. package/dist/types.d.cts +28 -2
  40. package/dist/types.d.mts +28 -2
  41. package/dist/types.mjs +9 -1
  42. package/dist/{view-compiler-u3GGRgnv.mjs → view-compiler-CLvZ0wJW.mjs} +1 -1
  43. package/dist/{view-compiler-D30HNRnA.cjs → view-compiler-DP4Fbj7-.cjs} +1 -1
  44. package/dist/view-compiler.cjs +1 -1
  45. package/dist/view-compiler.d.cts +1 -1
  46. package/dist/view-compiler.d.mts +1 -1
  47. package/dist/view-compiler.mjs +1 -1
  48. package/package.json +11 -1
@@ -1,4 +1,4 @@
1
- import { a as MATERIALIZING_CONCEPTS } from "./entity-config-DwGXbUo_.mjs";
1
+ import { a as MATERIALIZING_CONCEPTS } from "./entity-config-DpHPMFIS.mjs";
2
2
  import { CONCEPT_TIERS, FIELD_TIERS, RELATIONSHIP_TIERS, W, isAmbiguous, isNumericLike, isTextLike, isTimestampLike, tierFor } from "./mapping-score.mjs";
3
3
  //#region src/entity-heuristics.ts
4
4
  const TARGET_CONCEPTS = [
@@ -250,6 +250,38 @@ function matchesConcept(tableName, concept) {
250
250
  if (entry.names.some((name) => candidates.some((candidate) => candidate.includes(name)))) return { exact: false };
251
251
  return null;
252
252
  }
253
+ const SENSITIVE_COLUMNS = /* @__PURE__ */ new Set([
254
+ "password",
255
+ "password_hash",
256
+ "passwordhash",
257
+ "access_token",
258
+ "accesstoken",
259
+ "api_key",
260
+ "apikey",
261
+ "client_secret",
262
+ "clientsecret",
263
+ "encrypted_password",
264
+ "encryptedpassword",
265
+ "refresh_token",
266
+ "refreshtoken",
267
+ "id_token",
268
+ "idtoken",
269
+ "password_digest",
270
+ "passworddigest",
271
+ "private_key",
272
+ "privatekey",
273
+ "secret",
274
+ "session_token",
275
+ "sessiontoken"
276
+ ]);
277
+ /**
278
+ * Does this table carry credentials? Such tables are withheld from suggestions
279
+ * and from bulk apply, so one click can never map an auth table into the CRM.
280
+ * They stay manually selectable — an explicit, informed choice is legitimate.
281
+ */
282
+ function hasSensitiveColumns(columns) {
283
+ return columns.some((column) => SENSITIVE_COLUMNS.has(column.toLowerCase().replaceAll("-", "_")));
284
+ }
253
285
  function metaFor(table, column) {
254
286
  return table.columnsMeta?.find((c) => c.name === column);
255
287
  }
@@ -461,4 +493,4 @@ function toFieldMap(scored) {
461
493
  return map;
462
494
  }
463
495
  //#endregion
464
- export { TARGET_CONCEPTS, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
496
+ export { TARGET_CONCEPTS, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
package/dist/index.cjs CHANGED
@@ -1,218 +1,154 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_auth_adapter = require("./auth-adapter.cjs");
3
- const require_projection = require("./projection-OJYCYmS_.cjs");
4
- const require_entity_config = require("./entity-config-25v_udeY.cjs");
3
+ const require_projection = require("./projection-DFgCoyZl.cjs");
4
+ const require_schema_meta = require("./schema-meta-Cgi0MnHh.cjs");
5
+ const require_entity_config = require("./entity-config-C5jBmG2C.cjs");
5
6
  const require_mapping_form = require("./mapping-form.cjs");
6
7
  const require_mappings_config = require("./mappings-config.cjs");
7
- const require_view_compiler = require("./view-compiler-D30HNRnA.cjs");
8
+ const require_view_compiler = require("./view-compiler-DP4Fbj7-.cjs");
8
9
  const require_sync_engine = require("./sync-engine.cjs");
9
- //#region src/projection-draft.ts
10
- function emptyProjectionDraft(baseTable) {
11
- return {
12
- baseTable,
13
- entityKey: "",
14
- fieldBindings: {},
15
- identity: { kind: "base_pk" },
16
- joins: []
17
- };
18
- }
10
+ const require_types = require("./types.cjs");
11
+ //#region src/slug.ts
19
12
  /**
20
- * The ON conditions implied by a foreign key between the two tables, so the
21
- * builder can pre-fill a join instead of making the user hand-pick columns.
22
- * Returns [] when no FK relates them — the user then picks manually.
13
+ * The one `slugify`.
14
+ *
15
+ * Three byte-identical copies existed before this module — in `@clivly/api`
16
+ * (the custom object-type slug), in `apps/web`'s onboarding route (the
17
+ * organisation slug), and in `@clivly/sdk`. The first two now import this; the
18
+ * SDK's copy stays where it is on purpose, because `@clivly/sdk` cannot depend
19
+ * on this package and its own comment records that its pattern is deliberately
20
+ * kept in step with the server's by hand.
21
+ *
22
+ * Note that the two callers this replaces slug *different things* — an
23
+ * object type and an organisation. They share a transform, not a namespace.
24
+ * Sharing the function stops the transform drifting; it does not make those two
25
+ * identifiers the same identifier.
23
26
  */
24
- function suggestJoinConditions(baseTable, joinTable, schema, joinKey) {
25
- const join = schema.find((t) => t.name === joinTable);
26
- const conditions = [];
27
- for (const column of join?.columnsMeta ?? []) if (column.references?.table === baseTable) conditions.push({
28
- left: {
29
- table: joinKey,
30
- column: column.name
31
- },
32
- op: "eq",
33
- right: {
34
- table: require_projection.BASE_REF,
35
- column: column.references.column
36
- }
37
- });
38
- return conditions;
39
- }
27
+ const NON_ALNUM = /[^a-z0-9]+/g;
28
+ const EDGE_HYPHENS = /(^-|-$)/g;
40
29
  /**
41
- * Add a join on `joinTable`, keyed and pre-filled.
30
+ * Lowercase, trim, collapse every run of non-alphanumerics to one hyphen, and
31
+ * drop leading/trailing hyphens. `"Participant Info"` becomes
32
+ * `"participant-info"`.
42
33
  *
43
- * The key is the table's own name where that is free, because it is what the
44
- * user already calls the table; a collision falls back to `_2`, `_3` and so on.
45
- * Uniqueness is not cosmetic — the key is the SQL alias and the name every ref
46
- * addresses the table by, so two joins sharing one would make every ref
47
- * ambiguous. `base` is reserved for the base table and can never be taken.
34
+ * The result is NOT guaranteed to be an acceptable slug. Both
35
+ * `OBJECT_TYPE_SLUG_PATTERN` (server) and `PROJECTION_KEY_PATTERN` (this
36
+ * package) require a leading letter, and this function happily returns
37
+ * `"2024-invoices"` for `"2024 Invoices"`. Callers that need an
38
+ * acceptance-guaranteed identifier want `toObjectTypeSlug`.
48
39
  */
49
- function addDraftJoin(draft, joinTable, schema) {
50
- const taken = /* @__PURE__ */ new Set([require_projection.BASE_REF, ...draft.joins.map((j) => j.key)]);
51
- let key = joinTable;
52
- let suffix = 2;
53
- while (taken.has(key)) {
54
- key = `${joinTable}_${suffix}`;
55
- suffix += 1;
56
- }
57
- return {
58
- ...draft,
59
- joins: [...draft.joins, {
60
- key,
61
- table: joinTable,
62
- type: "left",
63
- on: suggestJoinConditions(draft.baseTable, joinTable, schema, key)
64
- }]
65
- };
40
+ function slugify(value) {
41
+ return value.toLowerCase().trim().replace(NON_ALNUM, "-").replace(EDGE_HYPHENS, "");
66
42
  }
67
43
  /**
68
- * Remove a join, and everything that addressed it.
44
+ * Prefixed onto a slug that would otherwise not start with a letter.
69
45
  *
70
- * Refs to a removed join are refs to a table the projection no longer declares.
71
- * Left in place they fail validation as "unknown ref table", which blames the
72
- * field — or, worse, the identity — for the join's removal. Identity falls back
73
- * to the base primary key, the same default a new draft starts from.
46
+ * Chosen over trimming the offending characters because dropping them loses
47
+ * information the user typed: `"2024 Invoices"` would become `"invoices"`,
48
+ * which collides with a genuinely different object of that name.
74
49
  */
75
- function removeDraftJoin(draft, joinKey) {
76
- const fieldBindings = Object.fromEntries(Object.entries(draft.fieldBindings).filter(([, binding]) => binding.from.table !== joinKey));
77
- const identityDependsOnJoin = require_projection.identityRefs(draft.identity, "").some((ref) => ref.table === joinKey);
78
- return {
79
- ...draft,
80
- joins: draft.joins.filter((join) => join.key !== joinKey),
81
- fieldBindings,
82
- identity: identityDependsOnJoin ? { kind: "base_pk" } : draft.identity
83
- };
84
- }
50
+ const LEADING_DIGIT_PREFIX = "obj-";
51
+ /** Mirrors `PROJECTION_KEY_PATTERN` / the server's `OBJECT_TYPE_SLUG_PATTERN`. */
52
+ const MUST_START_WITH_LETTER = /^[a-z]/;
85
53
  /**
86
- * Every table a field or identity may currently read from, in ref order: the
87
- * base table first, then each join.
54
+ * A slug the server will accept, derived from a display name.
88
55
  *
89
- * Returns [] when the base table is not in the discovered schema — there is
90
- * nothing truthful to offer, and inventing columns would let someone build a
91
- * projection that cannot compile.
56
+ * `slugify` alone is not enough: the server's `OBJECT_TYPE_SLUG_PATTERN`
57
+ * (`apps/server/src/index.ts`) demands a leading letter, so a name beginning
58
+ * with a digit slugs to something the platform rejects at push time — long
59
+ * after the object was authored. `@clivly/sdk`'s `custom-slug.ts` already knows
60
+ * this case and deliberately withholds `"2024-invoices"` as a suggestion
61
+ * because it would be rejected too.
62
+ *
63
+ * The prefix is applied ONLY when the derived slug does not already start with
64
+ * a letter, so the overwhelmingly common name is untouched.
65
+ *
66
+ * This value must be shown to whoever authored the name. It is the identifier
67
+ * the host app declares as its `objectType`, so a slug derived silently is a
68
+ * slug the developer cannot copy into their config.
69
+ *
70
+ * Returns an empty string for a name with no alphanumerics at all — the caller
71
+ * decides whether that is "keep typing" or an error, since only it knows
72
+ * whether the field is still being edited.
92
73
  */
93
- function draftRefOptions(draft, schema) {
94
- const byName = new Map(schema.map((table) => [table.name, table]));
95
- const base = byName.get(draft.baseTable);
96
- if (!base) return [];
97
- const options = [{
98
- ref: require_projection.BASE_REF,
99
- label: `${base.name} (${require_projection.BASE_REF})`,
100
- columns: base.columns
101
- }];
102
- for (const join of draft.joins) {
103
- const table = byName.get(join.table);
104
- if (table) options.push({
105
- ref: join.key,
106
- label: `${table.name} (${join.key})`,
107
- columns: table.columns
108
- });
109
- }
110
- return options;
74
+ function toObjectTypeSlug(displayName) {
75
+ const slug = slugify(displayName);
76
+ if (slug === "") return "";
77
+ return MUST_START_WITH_LETTER.test(slug) ? slug : `${LEADING_DIGIT_PREFIX}${slug}`;
78
+ }
79
+ //#endregion
80
+ //#region src/stage-rules.ts
81
+ const CONDITION_OPS = /* @__PURE__ */ new Set([
82
+ "is_empty",
83
+ "is_not_empty",
84
+ "equals",
85
+ "not_equals",
86
+ "greater_than",
87
+ "less_than",
88
+ "before",
89
+ "after"
90
+ ]);
91
+ function isCondition(value) {
92
+ if (!value || typeof value !== "object") return false;
93
+ const condition = value;
94
+ return typeof condition.field === "string" && condition.field.length > 0 && typeof condition.op === "string" && CONDITION_OPS.has(condition.op) && (condition.value === void 0 || typeof condition.value === "string");
111
95
  }
112
- /** A draft becomes a projection once it has a valid key and ≥1 binding. */
113
- function draftToProjection(draft) {
114
- if (!require_projection.PROJECTION_KEY_PATTERN.test(draft.entityKey)) return null;
115
- if (Object.keys(draft.fieldBindings).length === 0) return null;
116
- return {
117
- version: 1,
118
- kind: "projection",
119
- entityKey: draft.entityKey,
120
- baseTable: draft.baseTable,
121
- joins: draft.joins,
122
- fieldBindings: draft.fieldBindings,
123
- identity: draft.identity
124
- };
96
+ /** Host fields arrive as strings; null and "" are both absent. */
97
+ function isEmpty(value) {
98
+ return value === null || value === void 0 || value === "";
125
99
  }
126
- const PROBE_KEY = "draft";
127
- /**
128
- * A draft rendered as a projection so the semantic checks can run against it
129
- * while it is being written, not only once it is finished.
130
- *
131
- * `entityKey` is stood in for rather than taken from the draft: it is the one
132
- * field `validateProjection` never looks at, and a half-typed key would
133
- * otherwise have to be valid before any join or identity could be checked. The
134
- * missing or malformed key is reported separately, by `draftErrors`.
135
- */
136
- function probeProjection(draft) {
137
- return {
138
- version: 1,
139
- kind: "projection",
140
- entityKey: PROBE_KEY,
141
- baseTable: draft.baseTable,
142
- joins: draft.joins,
143
- fieldBindings: draft.fieldBindings,
144
- identity: draft.identity
145
- };
100
+ function compareNumbers(raw, operand, op) {
101
+ const left = Number(raw);
102
+ const right = Number(operand);
103
+ if (Number.isNaN(left) || Number.isNaN(right)) return false;
104
+ return op === "greater_than" ? left > right : left < right;
146
105
  }
147
- /**
148
- * `validateProjection` appends its own `projection.` segment to the base path it
149
- * is given, because in a config the base is the entity that owns the projection
150
- * (`entities.accounts` → `entities.accounts.projection.identity`). A draft has
151
- * no owning entity, so passing "projection" as the base produced
152
- * `projection.projection.identity` — a path no caller could match against, and
153
- * the reason `draftErrors` was only ever consumed as a flat list of messages.
154
- *
155
- * Passing an empty base and dropping the leading separator leaves one
156
- * convention: every path here starts `projection.` exactly once, whether it came
157
- * from this module or from the validator.
158
- */
159
- function semanticErrors(draft, schema) {
160
- return require_entity_config.validateProjection(probeProjection(draft), schema, "").map((error) => ({
161
- ...error,
162
- path: error.path.startsWith(".") ? error.path.slice(1) : error.path
163
- }));
106
+ function compareDates(raw, operand, op) {
107
+ const left = new Date(raw).getTime();
108
+ const right = new Date(operand ?? "").getTime();
109
+ if (Number.isNaN(left) || Number.isNaN(right)) return false;
110
+ return op === "before" ? left < right : left > right;
164
111
  }
165
112
  /**
166
- * Every reason this draft cannot be saved, one per cause and each anchored to
167
- * the section that owns it.
113
+ * Whether one condition holds for a host row.
168
114
  *
169
- * One lumped "Name the object and map a field." was all this used to return for
170
- * an incomplete draft, at the bare path "projection". Two consequences, both
171
- * bad: a builder had nowhere to attach the message, and — because it returned
172
- * before validating — a fanning join under a `base_pk` identity stayed silent
173
- * until the draft was otherwise complete, which is well after the point where
174
- * the user chose the join.
115
+ * `mappedFields` is the set of columns the organization actually exposed. A
116
+ * condition naming anything outside it never matches, whatever the operator: a
117
+ * rule referencing a dropped column must fail safe, because treating the field
118
+ * as null would make `is_empty` match every deal.
175
119
  */
176
- function draftErrors(draft, schema) {
177
- const errors = [];
178
- if (draft.entityKey === "") errors.push({
179
- path: "projection.entityKey",
180
- message: "Key is required."
181
- });
182
- else if (!require_projection.PROJECTION_KEY_PATTERN.test(draft.entityKey)) errors.push({
183
- path: "projection.entityKey",
184
- message: `Key ${require_projection.PROJECTION_KEY_MESSAGE}.`
185
- });
186
- if (Object.keys(draft.fieldBindings).length === 0) errors.push({
187
- path: "projection.fieldBindings",
188
- message: "Map at least one field."
189
- });
190
- if (draft.baseTable === "") {
191
- errors.push({
192
- path: "projection.baseTable",
193
- message: "Pick a base table."
194
- });
195
- return errors;
196
- }
197
- errors.push(...semanticErrors(draft, schema));
198
- return errors;
120
+ function matchesCondition(condition, fields, mappedFields) {
121
+ if (!mappedFields.has(condition.field)) return false;
122
+ const raw = fields[condition.field] ?? null;
123
+ if (condition.op === "is_empty") return isEmpty(raw);
124
+ if (condition.op === "is_not_empty") return !isEmpty(raw);
125
+ if (isEmpty(raw)) return false;
126
+ const value = raw;
127
+ if (condition.op === "equals") return value === condition.value;
128
+ if (condition.op === "not_equals") return value !== condition.value;
129
+ if (condition.op === "greater_than" || condition.op === "less_than") return compareNumbers(value, condition.value, condition.op);
130
+ return compareDates(value, condition.value, condition.op);
199
131
  }
200
132
  /**
201
- * Per-join fan-out, for the builder's inline cardinality hints.
133
+ * The id of the first rule whose conditions all hold, or null when none do.
134
+ *
135
+ * Returns a rule id rather than a stage key because the caller needs the
136
+ * matched rule's `allowClose` before it may move a deal into a closed stage.
202
137
  *
203
- * Answered from the joins alone. Joins are chosen before the key and the fields
204
- * are filled in, and a fan-out warning is precisely what should steer the
205
- * identity choice while it is being made — requiring a complete draft put the
206
- * hint after the decision it exists to inform.
138
+ * `rules` must arrive already ordered — stage position first, then rule
139
+ * position within a stage. Sorting needs stage rows this module deliberately
140
+ * does not see.
141
+ *
142
+ * A rule with no conditions never matches: an empty list would otherwise
143
+ * vacuously AND to true and capture every deal, which is the opposite of what
144
+ * a half-written rule should do.
207
145
  */
208
- function describeCardinality(draft, schema) {
209
- const projection = probeProjection(draft);
210
- const tablesByName = new Map(schema.map((t) => [t.name, t]));
211
- const fanning = new Set(require_entity_config.fanOutJoins(projection, tablesByName).map((j) => j.key));
212
- return projection.joins.map((join) => ({
213
- joinKey: join.key,
214
- fansOut: fanning.has(join.key)
215
- }));
146
+ function evaluateStage(rules, fields, mappedFields) {
147
+ for (const rule of rules) {
148
+ if (!Array.isArray(rule.conditions) || rule.conditions.length === 0 || !rule.conditions.every(isCondition)) continue;
149
+ if (rule.conditions.every((condition) => matchesCondition(condition, fields, mappedFields))) return rule.id;
150
+ }
151
+ return null;
216
152
  }
217
153
  //#endregion
218
154
  exports.BASE_REF = require_projection.BASE_REF;
@@ -221,12 +157,13 @@ exports.CRM_CONCEPTS = require_entity_config.CRM_CONCEPTS;
221
157
  exports.ClivlyConfigError = require_entity_config.ClivlyConfigError;
222
158
  exports.DEFAULT_VIEW_PREFIX = require_view_compiler.DEFAULT_VIEW_PREFIX;
223
159
  exports.MATERIALIZING_CONCEPTS = require_entity_config.MATERIALIZING_CONCEPTS;
160
+ exports.OPEN_STAGE_TYPE = require_types.OPEN_STAGE_TYPE;
224
161
  exports.PREVIEW_MAX_ROWS = require_view_compiler.PREVIEW_MAX_ROWS;
225
- exports.addDraftJoin = addDraftJoin;
162
+ exports.PROJECTION_KEY_PATTERN = require_projection.PROJECTION_KEY_PATTERN;
226
163
  exports.authCustom = require_auth_adapter.authCustom;
227
164
  exports.buildFilterFromDiscriminator = require_mapping_form.buildFilterFromDiscriminator;
228
165
  exports.buildRelationships = require_mapping_form.buildRelationships;
229
- exports.columnMetaFor = require_entity_config.columnMetaFor;
166
+ exports.columnMetaFor = require_schema_meta.columnMetaFor;
230
167
  exports.compileEntityView = require_view_compiler.compileEntityView;
231
168
  exports.compileEntityViews = require_view_compiler.compileEntityViews;
232
169
  exports.compileProjectionFrom = require_view_compiler.compileProjectionFrom;
@@ -234,30 +171,30 @@ exports.compileProjectionIdentity = require_view_compiler.compileProjectionIdent
234
171
  exports.compileProjectionJoins = require_view_compiler.compileProjectionJoins;
235
172
  exports.compileProjectionPreview = require_view_compiler.compileProjectionPreview;
236
173
  exports.compileProjectionSelect = require_view_compiler.compileProjectionSelect;
237
- exports.coversUniqueKey = require_entity_config.coversUniqueKey;
174
+ exports.coversUniqueKey = require_schema_meta.coversUniqueKey;
238
175
  exports.defineClivlyConfig = require_entity_config.defineClivlyConfig;
239
- exports.describeCardinality = describeCardinality;
240
- exports.draftErrors = draftErrors;
241
- exports.draftRefOptions = draftRefOptions;
242
- exports.draftToProjection = draftToProjection;
243
- exports.emptyProjectionDraft = emptyProjectionDraft;
244
176
  exports.entitiesConfigSchema = require_entity_config.entitiesConfigSchema;
177
+ exports.evaluateStage = evaluateStage;
245
178
  exports.explainEntitiesConfig = require_view_compiler.explainEntitiesConfig;
246
179
  exports.fanOutJoins = require_entity_config.fanOutJoins;
247
180
  exports.filterSchema = require_entity_config.filterSchema;
248
- exports.hasRichMeta = require_entity_config.hasRichMeta;
181
+ exports.hasRichMeta = require_schema_meta.hasRichMeta;
249
182
  exports.identityRefs = require_projection.identityRefs;
183
+ exports.isClosedStageType = require_types.isClosedStageType;
250
184
  exports.joinFansOut = require_entity_config.joinFansOut;
251
185
  exports.mappingsToEntitiesConfig = require_mappings_config.mappingsToEntitiesConfig;
252
- exports.primaryKeyColumns = require_entity_config.primaryKeyColumns;
186
+ exports.matchesCondition = matchesCondition;
187
+ exports.primaryKeyColumns = require_schema_meta.primaryKeyColumns;
188
+ exports.projectionFields = require_entity_config.projectionFields;
253
189
  exports.projectionSchema = require_projection.projectionSchema;
254
190
  exports.quoteIdent = require_view_compiler.quoteIdent;
255
191
  exports.reconcile = require_sync_engine.reconcile;
256
192
  exports.relationshipSchema = require_entity_config.relationshipSchema;
257
193
  exports.relationshipViaSignature = require_mapping_form.relationshipViaSignature;
258
194
  exports.relationshipsSchema = require_entity_config.relationshipsSchema;
259
- exports.removeDraftJoin = removeDraftJoin;
260
195
  exports.runSync = require_sync_engine.runSync;
261
- exports.suggestJoinConditions = suggestJoinConditions;
196
+ exports.slugify = slugify;
197
+ exports.toObjectTypeSlug = toObjectTypeSlug;
262
198
  exports.validateEntitiesConfig = require_entity_config.validateEntitiesConfig;
263
199
  exports.validateProjection = require_entity_config.validateProjection;
200
+ exports.validateProjectionFilter = require_entity_config.validateProjectionFilter;