@google-cloud/kcmd 0.0.0-stage → 0.2.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 (150) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +264 -2
  3. package/build/ts/kcmd/cli.js +20252 -0
  4. package/build/ts/kcmd/gcp/alloydb.d.ts +12 -0
  5. package/build/ts/kcmd/gcp/alloydb.js +70 -0
  6. package/build/ts/kcmd/gcp/api.d.ts +29 -0
  7. package/build/ts/kcmd/gcp/api.js +162 -0
  8. package/build/ts/kcmd/gcp/biglake.d.ts +18 -0
  9. package/build/ts/kcmd/gcp/biglake.js +59 -0
  10. package/build/ts/kcmd/gcp/bigquery.d.ts +57 -0
  11. package/build/ts/kcmd/gcp/bigquery.js +134 -0
  12. package/build/ts/kcmd/gcp/context.d.ts +10 -0
  13. package/build/ts/kcmd/gcp/context.js +74 -0
  14. package/build/ts/kcmd/gcp/crm.d.ts +13 -0
  15. package/build/ts/kcmd/gcp/crm.js +91 -0
  16. package/build/ts/kcmd/gcp/dataplex.d.ts +147 -0
  17. package/build/ts/kcmd/gcp/dataplex.js +406 -0
  18. package/build/ts/kcmd/gcp/index.d.ts +3 -0
  19. package/build/ts/kcmd/gcp/index.js +21 -0
  20. package/build/ts/kcmd/gcp/spanner.d.ts +73 -0
  21. package/build/ts/kcmd/gcp/spanner.js +126 -0
  22. package/build/ts/kcmd/index.d.ts +7 -0
  23. package/build/ts/kcmd/index.js +46 -0
  24. package/build/ts/kcmd/layout.d.ts +16 -0
  25. package/build/ts/kcmd/layout.js +31 -0
  26. package/build/ts/kcmd/layouts/documents.d.ts +24 -0
  27. package/build/ts/kcmd/layouts/documents.js +264 -0
  28. package/build/ts/kcmd/layouts/okf.d.ts +31 -0
  29. package/build/ts/kcmd/layouts/okf.js +386 -0
  30. package/build/ts/kcmd/layouts/semantic-model.d.ts +74 -0
  31. package/build/ts/kcmd/layouts/semantic-model.js +621 -0
  32. package/build/ts/kcmd/layouts/standard.d.ts +13 -0
  33. package/build/ts/kcmd/layouts/standard.js +108 -0
  34. package/build/ts/kcmd/manifest.d.ts +34 -0
  35. package/build/ts/kcmd/manifest.js +262 -0
  36. package/build/ts/kcmd/metadata.d.ts +25 -0
  37. package/build/ts/kcmd/metadata.js +8 -0
  38. package/build/ts/kcmd/okf/catalog_residue.d.ts +14 -0
  39. package/build/ts/kcmd/okf/catalog_residue.js +124 -0
  40. package/build/ts/kcmd/okf/concept.d.ts +14 -0
  41. package/build/ts/kcmd/okf/concept.js +110 -0
  42. package/build/ts/kcmd/okf/concept_to_entry.d.ts +10 -0
  43. package/build/ts/kcmd/okf/concept_to_entry.js +281 -0
  44. package/build/ts/kcmd/okf/init_okf_workspace.d.ts +15 -0
  45. package/build/ts/kcmd/okf/init_okf_workspace.js +113 -0
  46. package/build/ts/kcmd/okf/links.d.ts +23 -0
  47. package/build/ts/kcmd/okf/links.js +468 -0
  48. package/build/ts/kcmd/okf/okf_metadata.d.ts +12 -0
  49. package/build/ts/kcmd/okf/okf_metadata.js +99 -0
  50. package/build/ts/kcmd/semantic/bigquery.d.ts +22 -0
  51. package/build/ts/kcmd/semantic/bigquery.js +469 -0
  52. package/build/ts/kcmd/semantic/binding.d.ts +3 -0
  53. package/build/ts/kcmd/semantic/binding.js +92 -0
  54. package/build/ts/kcmd/semantic/catalog_entry.d.ts +24 -0
  55. package/build/ts/kcmd/semantic/catalog_entry.js +35 -0
  56. package/build/ts/kcmd/semantic/converters/owl/convert.d.ts +26 -0
  57. package/build/ts/kcmd/semantic/converters/owl/convert.js +41 -0
  58. package/build/ts/kcmd/semantic/converters/owl/model.d.ts +98 -0
  59. package/build/ts/kcmd/semantic/converters/owl/model.js +30 -0
  60. package/build/ts/kcmd/semantic/converters/owl/parse.d.ts +11 -0
  61. package/build/ts/kcmd/semantic/converters/owl/parse.js +634 -0
  62. package/build/ts/kcmd/semantic/converters/owl/to_ir.d.ts +19 -0
  63. package/build/ts/kcmd/semantic/converters/owl/to_ir.js +390 -0
  64. package/build/ts/kcmd/semantic/deploy_bigquery.d.ts +20 -0
  65. package/build/ts/kcmd/semantic/deploy_bigquery.js +226 -0
  66. package/build/ts/kcmd/semantic/deploy_knowledge_catalog.d.ts +104 -0
  67. package/build/ts/kcmd/semantic/deploy_knowledge_catalog.js +1367 -0
  68. package/build/ts/kcmd/semantic/deploy_spanner.d.ts +15 -0
  69. package/build/ts/kcmd/semantic/deploy_spanner.js +150 -0
  70. package/build/ts/kcmd/semantic/deployment_target.d.ts +93 -0
  71. package/build/ts/kcmd/semantic/deployment_target.js +379 -0
  72. package/build/ts/kcmd/semantic/graph_ddl.d.ts +44 -0
  73. package/build/ts/kcmd/semantic/graph_ddl.js +656 -0
  74. package/build/ts/kcmd/semantic/import_model.d.ts +72 -0
  75. package/build/ts/kcmd/semantic/import_model.js +1698 -0
  76. package/build/ts/kcmd/semantic/ir.d.ts +589 -0
  77. package/build/ts/kcmd/semantic/ir.js +247 -0
  78. package/build/ts/kcmd/semantic/kc_actions.d.ts +45 -0
  79. package/build/ts/kcmd/semantic/kc_actions.js +531 -0
  80. package/build/ts/kcmd/semantic/kc_constraints.d.ts +44 -0
  81. package/build/ts/kcmd/semantic/kc_constraints.js +279 -0
  82. package/build/ts/kcmd/semantic/kc_converter.d.ts +37 -0
  83. package/build/ts/kcmd/semantic/kc_converter.js +839 -0
  84. package/build/ts/kcmd/semantic/kc_custom_types.d.ts +63 -0
  85. package/build/ts/kcmd/semantic/kc_custom_types.js +751 -0
  86. package/build/ts/kcmd/semantic/kc_entries.d.ts +155 -0
  87. package/build/ts/kcmd/semantic/kc_entries.js +284 -0
  88. package/build/ts/kcmd/semantic/kc_ids.d.ts +102 -0
  89. package/build/ts/kcmd/semantic/kc_ids.js +188 -0
  90. package/build/ts/kcmd/semantic/knowledge_catalog.d.ts +29 -0
  91. package/build/ts/kcmd/semantic/knowledge_catalog.js +960 -0
  92. package/build/ts/kcmd/semantic/loader.d.ts +258 -0
  93. package/build/ts/kcmd/semantic/loader.js +3576 -0
  94. package/build/ts/kcmd/semantic/names.d.ts +10 -0
  95. package/build/ts/kcmd/semantic/names.js +85 -0
  96. package/build/ts/kcmd/semantic/osi_converter.d.ts +60 -0
  97. package/build/ts/kcmd/semantic/osi_converter.js +910 -0
  98. package/build/ts/kcmd/semantic/parameters.d.ts +19 -0
  99. package/build/ts/kcmd/semantic/parameters.js +171 -0
  100. package/build/ts/kcmd/semantic/pull_kc.d.ts +10 -0
  101. package/build/ts/kcmd/semantic/pull_kc.js +272 -0
  102. package/build/ts/kcmd/semantic/resolve_inheritance.d.ts +59 -0
  103. package/build/ts/kcmd/semantic/resolve_inheritance.js +346 -0
  104. package/build/ts/kcmd/semantic/resolve_profiles.d.ts +291 -0
  105. package/build/ts/kcmd/semantic/resolve_profiles.js +2003 -0
  106. package/build/ts/kcmd/semantic/runtime/agent_tools.d.ts +93 -0
  107. package/build/ts/kcmd/semantic/runtime/agent_tools.js +243 -0
  108. package/build/ts/kcmd/semantic/runtime/dialect.d.ts +13 -0
  109. package/build/ts/kcmd/semantic/runtime/dialect.js +39 -0
  110. package/build/ts/kcmd/semantic/runtime/runtime.d.ts +88 -0
  111. package/build/ts/kcmd/semantic/runtime/runtime.js +301 -0
  112. package/build/ts/kcmd/semantic/runtime/store.d.ts +112 -0
  113. package/build/ts/kcmd/semantic/runtime/store.js +344 -0
  114. package/build/ts/kcmd/semantic/skills.d.ts +110 -0
  115. package/build/ts/kcmd/semantic/skills.js +697 -0
  116. package/build/ts/kcmd/semantic/source_dialect.d.ts +17 -0
  117. package/build/ts/kcmd/semantic/source_dialect.js +311 -0
  118. package/build/ts/kcmd/semantic/source_entries.d.ts +12 -0
  119. package/build/ts/kcmd/semantic/source_entries.js +341 -0
  120. package/build/ts/kcmd/semantic/spanner.d.ts +18 -0
  121. package/build/ts/kcmd/semantic/spanner.js +60 -0
  122. package/build/ts/kcmd/semantic/sql_expr_utils.d.ts +23 -0
  123. package/build/ts/kcmd/semantic/sql_expr_utils.js +394 -0
  124. package/build/ts/kcmd/semantic/sql_identifiers.d.ts +6 -0
  125. package/build/ts/kcmd/semantic/sql_identifiers.js +267 -0
  126. package/build/ts/kcmd/semantic/sql_parser.d.ts +47 -0
  127. package/build/ts/kcmd/semantic/sql_parser.js +400 -0
  128. package/build/ts/kcmd/semantic/transpile.d.ts +76 -0
  129. package/build/ts/kcmd/semantic/transpile.js +581 -0
  130. package/build/ts/kcmd/semantic/validate.d.ts +70 -0
  131. package/build/ts/kcmd/semantic/validate.js +2266 -0
  132. package/build/ts/kcmd/semantic/yaml_options.d.ts +6 -0
  133. package/build/ts/kcmd/semantic/yaml_options.js +58 -0
  134. package/build/ts/kcmd/semantic/yaml_update.d.ts +26 -0
  135. package/build/ts/kcmd/semantic/yaml_update.js +782 -0
  136. package/build/ts/kcmd/snapshot.d.ts +37 -0
  137. package/build/ts/kcmd/snapshot.js +386 -0
  138. package/build/ts/kcmd/source.d.ts +31 -0
  139. package/build/ts/kcmd/source.js +119 -0
  140. package/build/ts/kcmd/sources/bq-dataset.d.ts +17 -0
  141. package/build/ts/kcmd/sources/bq-dataset.js +131 -0
  142. package/build/ts/kcmd/sources/entrygroup.d.ts +21 -0
  143. package/build/ts/kcmd/sources/entrygroup.js +83 -0
  144. package/build/ts/kcmd/sources/kb.d.ts +21 -0
  145. package/build/ts/kcmd/sources/kb.js +82 -0
  146. package/build/ts/kcmd/sources/semantic-model.d.ts +18 -0
  147. package/build/ts/kcmd/sources/semantic-model.js +48 -0
  148. package/build/ts/kcmd/sync.d.ts +35 -0
  149. package/build/ts/kcmd/sync.js +734 -0
  150. package/package.json +62 -4
@@ -0,0 +1,155 @@
1
+ import { Entry, EntryLink, EntryReference } from '../gcp/dataplex';
2
+ import { KcResources } from './knowledge_catalog';
3
+ /** Options overriding the system-type project, location, and V2 aspect mode. */
4
+ export interface SystemTypeOptions {
5
+ systemTypeProject?: string;
6
+ systemTypeLocation?: string;
7
+ v2Aspects?: boolean;
8
+ }
9
+ /**
10
+ * A model anchor ID paired with the child entry-ID prefixes it owns across the
11
+ * V1 dotted (`<anchorId>.`) and V2/LookML slash (`<anchorId>/`) ID schemes.
12
+ */
13
+ export interface KcAnchor {
14
+ readonly anchorId: string;
15
+ readonly ownedPrefixes: readonly string[];
16
+ }
17
+ /**
18
+ * A model owner representation (`KcResources` or `KcAnchor`) used to test entry
19
+ * and entry-link ownership.
20
+ */
21
+ export type KcOwner = KcResources | KcAnchor;
22
+ /**
23
+ * Returns the bare entry ID of `entry` (everything after `/entries/`).
24
+ *
25
+ * Examples:
26
+ * - `'projects/p/locations/us/entryGroups/eg/entries/sales.entities.orders'`
27
+ * -> `'sales.entities.orders'`
28
+ * - `'projects/p/locations/us/entryGroups/eg/entries/sales/entities/orders'`
29
+ * -> `'sales/entities/orders'`
30
+ */
31
+ export declare function entryId(entry: Entry | EntryReference): string;
32
+ /**
33
+ * Returns the bare entry-type ID of `entry` (everything after `/entryTypes/`).
34
+ *
35
+ * Example:
36
+ * - `'projects/dataplex-types/locations/global/entryTypes/semantic-entity'`
37
+ * -> `'semantic-entity'`
38
+ */
39
+ export declare function entryTypeId(entry: Entry): string;
40
+ /**
41
+ * Returns the bare entry-link ID of `link` (everything after `/entryLinks/`).
42
+ *
43
+ * Example:
44
+ * - `'projects/p/locations/us/entryGroups/eg/entryLinks/sales-orders-to-users'`
45
+ * -> `'sales-orders-to-users'`
46
+ */
47
+ export declare function linkId(link: EntryLink): string;
48
+ /**
49
+ * Returns the bare entry-link-type ID of `link` (everything after
50
+ * `/entryLinkTypes/`).
51
+ *
52
+ * Example:
53
+ * - `'projects/dataplex-types/locations/global/entryLinkTypes/schema-join'`
54
+ * -> `'schema-join'`
55
+ */
56
+ export declare function linkTypeId(link: EntryLink): string;
57
+ /**
58
+ * Returns true when `entry` is a `semantic-model` entry.
59
+ */
60
+ export declare function isModelEntry(entry: Entry): boolean;
61
+ /**
62
+ * Returns true when `entry` is a model anchor entry (`semantic-model`).
63
+ *
64
+ * Alias for `isModelEntry`.
65
+ */
66
+ export declare const isAnchorEntry: typeof isModelEntry;
67
+ /**
68
+ * Returns the bare entry ID of `entry` if it is a model anchor entry
69
+ * (`isAnchorEntry(entry)`), or `undefined` otherwise.
70
+ */
71
+ export declare function anchorId(entry: Entry | undefined): string | undefined;
72
+ /**
73
+ * Returns true when `entry` is a `semantic-entity` entry.
74
+ */
75
+ export declare function isEntityEntry(entry: Entry): boolean;
76
+ /**
77
+ * Returns true when `entry` is a `semantic-metric` entry.
78
+ */
79
+ export declare function isMetricEntry(entry: Entry): boolean;
80
+ /**
81
+ * Returns true when `entry` is the entry of a model, entity, metric or
82
+ * relationship.
83
+ */
84
+ export declare function isSemanticObjectEntry(entry: Entry): boolean;
85
+ /**
86
+ * Returns true when `entry` is a `semantic-explore` entry.
87
+ */
88
+ export declare function isExploreEntry(entry: Entry): boolean;
89
+ /**
90
+ * Returns true when `entry` depends on a `semantic-entity` entry.
91
+ *
92
+ * Dependent entries (`semantic-metric` and `semantic-explore`) reference
93
+ * entity entries by name and must be written in the second wave after entity
94
+ * entries exist.
95
+ */
96
+ export declare function isDependentEntry(entry: Entry): boolean;
97
+ /**
98
+ * Returns true when `link` is of a kind push writes for a model: `schema-join`
99
+ * in V1, and in V2 `semantic-link` or a `reference` link whose ID starts with
100
+ * `semantic-relationship-` or `semantic-extends-`.
101
+ *
102
+ * Includes both V1 and V2 regardless of `v2Aspects`, so a model pushed with V1
103
+ * and then V2 still discovers and cleans up its old `schema-join` links
104
+ * without passing a link type in a server-side `lookupEntryLinks` filter.
105
+ */
106
+ export declare function isModelLink(link: EntryLink): boolean;
107
+ /**
108
+ * Returns the full resource names of all `semantic-entity` entries in
109
+ * `entries`.
110
+ */
111
+ export declare function collectEntityNames(entries: readonly Entry[]): string[];
112
+ /**
113
+ * Returns true when `entry` is owned by `owner`:
114
+ * * For `KcResources`, matches child entries under `owner.ownedPrefixes`
115
+ * (the model anchor itself is not a child prefix).
116
+ * * For `KcAnchor`, matches both the model anchor entry (`owner.anchorId`)
117
+ * and child entries under `owner.ownedPrefixes`.
118
+ */
119
+ export declare function isEntryOwner(owner: KcOwner, entry: Entry | EntryReference): boolean;
120
+ /**
121
+ * Filters `entries` to those owned by `owner` (`KcResources` or `KcAnchor`).
122
+ */
123
+ export declare function collectOwnedEntries(owner: KcOwner, entries: readonly Entry[]): Entry[];
124
+ /**
125
+ * Returns the endpoint references of `link` that belong to `link`'s own entry
126
+ * group (when `link.name` carries a full resource container) and are owned by
127
+ * `owner` (`KcResources` or `KcAnchor`).
128
+ *
129
+ * `link.name` and its references must spell the project the same way.
130
+ */
131
+ export declare function collectOwnedReferences(owner: KcOwner, link: EntryLink): EntryReference[];
132
+ /**
133
+ * Returns true when both endpoints of `link` are in `link`'s entry group and
134
+ * owned by `owner` (`KcResources` or `KcAnchor`).
135
+ */
136
+ export declare function isLinkOwner(owner: KcOwner, link: EntryLink): boolean;
137
+ /**
138
+ * Returns the set of aspect keys to include when updating `entry`.
139
+ *
140
+ * Includes every aspect key present on `entry.aspects` plus the optional
141
+ * `<proj>.<loc>.guidelines` aspect. When `opts?.v2Aspects` is true:
142
+ * * Adds `<proj>.<loc>.semantic-extensions` and `<proj>.<loc>.overview` on
143
+ * model, entity, metric and relationship entries, so Dataplex removes the
144
+ * aspect when the object no longer has content for it.
145
+ * * Adds `<proj>.<loc>.sql-expressions` on entity and metric entries.
146
+ * * Adds `<proj>.<loc>.<type>@*` for guidelines, semantic-extensions and
147
+ * overview on entity entries, so Dataplex writes each field's instance
148
+ * `entry` carries and removes the others. A field's own key is left out.
149
+ */
150
+ export declare function entryAspectKeys(entry: Entry, opts?: SystemTypeOptions): Set<string>;
151
+ /**
152
+ * Compares the `entryReferences` of two entry links by bare entry ID, reference
153
+ * type, and path, independent of reference order.
154
+ */
155
+ export declare function sameLinkReferences(a: EntryLink, b: EntryLink): boolean;
@@ -0,0 +1,284 @@
1
+ "use strict";
2
+ // Pure helper operations on Knowledge Catalog `Entry` and `EntryLink` objects.
3
+ //
4
+ // Centralizes ID/type extraction, entry/link type predicates, ownership
5
+ // checks, and aspect-key extraction for entries and entry links.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.isAnchorEntry = void 0;
8
+ exports.entryId = entryId;
9
+ exports.entryTypeId = entryTypeId;
10
+ exports.linkId = linkId;
11
+ exports.linkTypeId = linkTypeId;
12
+ exports.isModelEntry = isModelEntry;
13
+ exports.anchorId = anchorId;
14
+ exports.isEntityEntry = isEntityEntry;
15
+ exports.isMetricEntry = isMetricEntry;
16
+ exports.isSemanticObjectEntry = isSemanticObjectEntry;
17
+ exports.isExploreEntry = isExploreEntry;
18
+ exports.isDependentEntry = isDependentEntry;
19
+ exports.isModelLink = isModelLink;
20
+ exports.collectEntityNames = collectEntityNames;
21
+ exports.isEntryOwner = isEntryOwner;
22
+ exports.collectOwnedEntries = collectOwnedEntries;
23
+ exports.collectOwnedReferences = collectOwnedReferences;
24
+ exports.isLinkOwner = isLinkOwner;
25
+ exports.entryAspectKeys = entryAspectKeys;
26
+ exports.sameLinkReferences = sameLinkReferences;
27
+ const kc_ids_1 = require("./kc_ids");
28
+ // ---------------------------------------------------------------------------
29
+ // 1. Bare ID and Type-ID Extraction
30
+ // ---------------------------------------------------------------------------
31
+ /**
32
+ * Returns the bare entry ID of `entry` (everything after `/entries/`).
33
+ *
34
+ * Examples:
35
+ * - `'projects/p/locations/us/entryGroups/eg/entries/sales.entities.orders'`
36
+ * -> `'sales.entities.orders'`
37
+ * - `'projects/p/locations/us/entryGroups/eg/entries/sales/entities/orders'`
38
+ * -> `'sales/entities/orders'`
39
+ */
40
+ function entryId(entry) {
41
+ return (0, kc_ids_1.entryIdOf)(entry.name);
42
+ }
43
+ /**
44
+ * Returns the bare entry-type ID of `entry` (everything after `/entryTypes/`).
45
+ *
46
+ * Example:
47
+ * - `'projects/dataplex-types/locations/global/entryTypes/semantic-entity'`
48
+ * -> `'semantic-entity'`
49
+ */
50
+ function entryTypeId(entry) {
51
+ return (0, kc_ids_1.entryIdOf)(entry.entryType ?? '');
52
+ }
53
+ /**
54
+ * Returns the bare entry-link ID of `link` (everything after `/entryLinks/`).
55
+ *
56
+ * Example:
57
+ * - `'projects/p/locations/us/entryGroups/eg/entryLinks/sales-orders-to-users'`
58
+ * -> `'sales-orders-to-users'`
59
+ */
60
+ function linkId(link) {
61
+ return (0, kc_ids_1.entryIdOf)(link.name ?? '');
62
+ }
63
+ /**
64
+ * Returns the bare entry-link-type ID of `link` (everything after
65
+ * `/entryLinkTypes/`).
66
+ *
67
+ * Example:
68
+ * - `'projects/dataplex-types/locations/global/entryLinkTypes/schema-join'`
69
+ * -> `'schema-join'`
70
+ */
71
+ function linkTypeId(link) {
72
+ return (0, kc_ids_1.entryIdOf)(link.entryLinkType ?? '');
73
+ }
74
+ // ---------------------------------------------------------------------------
75
+ // 2. Entry & EntryLink Type Predicates & Anchor Extraction
76
+ // ---------------------------------------------------------------------------
77
+ /**
78
+ * Returns true when `entry` is a `semantic-model` entry.
79
+ */
80
+ function isModelEntry(entry) {
81
+ return entryTypeId(entry) === 'semantic-model';
82
+ }
83
+ /**
84
+ * Returns true when `entry` is a model anchor entry (`semantic-model`).
85
+ *
86
+ * Alias for `isModelEntry`.
87
+ */
88
+ exports.isAnchorEntry = isModelEntry;
89
+ /**
90
+ * Returns the bare entry ID of `entry` if it is a model anchor entry
91
+ * (`isAnchorEntry(entry)`), or `undefined` otherwise.
92
+ */
93
+ function anchorId(entry) {
94
+ return entry && (0, exports.isAnchorEntry)(entry) ? entryId(entry) : undefined;
95
+ }
96
+ /**
97
+ * Returns true when `entry` is a `semantic-entity` entry.
98
+ */
99
+ function isEntityEntry(entry) {
100
+ return entryTypeId(entry) === 'semantic-entity';
101
+ }
102
+ /**
103
+ * Returns true when `entry` is a `semantic-metric` entry.
104
+ */
105
+ function isMetricEntry(entry) {
106
+ return entryTypeId(entry) === 'semantic-metric';
107
+ }
108
+ /**
109
+ * Returns true when `entry` is the entry of a model, entity, metric or
110
+ * relationship.
111
+ */
112
+ function isSemanticObjectEntry(entry) {
113
+ return isModelEntry(entry) || isEntityEntry(entry) || isMetricEntry(entry) ||
114
+ entryTypeId(entry) === 'semantic-relationship';
115
+ }
116
+ /**
117
+ * Returns true when `entry` is a `semantic-explore` entry.
118
+ */
119
+ function isExploreEntry(entry) {
120
+ return entryTypeId(entry) === 'semantic-explore';
121
+ }
122
+ /**
123
+ * Returns true when `entry` depends on a `semantic-entity` entry.
124
+ *
125
+ * Dependent entries (`semantic-metric` and `semantic-explore`) reference
126
+ * entity entries by name and must be written in the second wave after entity
127
+ * entries exist.
128
+ */
129
+ function isDependentEntry(entry) {
130
+ return isMetricEntry(entry) || isExploreEntry(entry);
131
+ }
132
+ /**
133
+ * Returns true when `link` is of a kind push writes for a model: `schema-join`
134
+ * in V1, and in V2 `semantic-link` or a `reference` link whose ID starts with
135
+ * `semantic-relationship-` or `semantic-extends-`.
136
+ *
137
+ * Includes both V1 and V2 regardless of `v2Aspects`, so a model pushed with V1
138
+ * and then V2 still discovers and cleans up its old `schema-join` links
139
+ * without passing a link type in a server-side `lookupEntryLinks` filter.
140
+ */
141
+ function isModelLink(link) {
142
+ const type = linkTypeId(link);
143
+ return type === 'schema-join' || type === 'semantic-link' ||
144
+ (type === 'reference' &&
145
+ /^semantic-(relationship|extends)-/.test(linkId(link)));
146
+ }
147
+ // ---------------------------------------------------------------------------
148
+ // 3. Ownership & Filtering Helpers
149
+ // ---------------------------------------------------------------------------
150
+ /**
151
+ * Returns true when `str` starts with any non-empty prefix in `prefixes`.
152
+ */
153
+ function startsWithAny(str, prefixes) {
154
+ return prefixes.some(p => p.length > 0 && str.startsWith(p));
155
+ }
156
+ /**
157
+ * Returns the full resource names of all `semantic-entity` entries in
158
+ * `entries`.
159
+ */
160
+ function collectEntityNames(entries) {
161
+ return entries.filter(isEntityEntry).map(e => e.name);
162
+ }
163
+ /**
164
+ * Returns true when `entry` is owned by `owner`:
165
+ * * For `KcResources`, matches child entries under `owner.ownedPrefixes`
166
+ * (the model anchor itself is not a child prefix).
167
+ * * For `KcAnchor`, matches both the model anchor entry (`owner.anchorId`)
168
+ * and child entries under `owner.ownedPrefixes`.
169
+ */
170
+ function isEntryOwner(owner, entry) {
171
+ if ('anchorId' in owner) {
172
+ if (!owner.anchorId)
173
+ return false;
174
+ if ('entryType' in entry && anchorId(entry) === owner.anchorId)
175
+ return true;
176
+ }
177
+ return startsWithAny(entryId(entry), owner.ownedPrefixes);
178
+ }
179
+ /**
180
+ * Filters `entries` to those owned by `owner` (`KcResources` or `KcAnchor`).
181
+ */
182
+ function collectOwnedEntries(owner, entries) {
183
+ return entries.filter(e => isEntryOwner(owner, e));
184
+ }
185
+ const LINK_CONTAINER_RE = /^(projects\/[^/]+\/locations\/[^/]+\/entryGroups\/[^/]+\/)entryLinks\//;
186
+ /**
187
+ * Returns the endpoint references of `link` that belong to `link`'s own entry
188
+ * group (when `link.name` carries a full resource container) and are owned by
189
+ * `owner` (`KcResources` or `KcAnchor`).
190
+ *
191
+ * `link.name` and its references must spell the project the same way.
192
+ */
193
+ function collectOwnedReferences(owner, link) {
194
+ // A reference `r` in `link.entryReferences` is owned by `owner` when:
195
+ // 1. Either `link.name` has no container prefix, or `r.name` starts with
196
+ // `${m[1]}entries/` (`projects/<project>/locations/<location>/
197
+ // entryGroups/<entryGroup>/entries/`). A different prefix means `r`
198
+ // points to another entry group or project.
199
+ // 2. `isEntryOwner(owner, r)` is true (`r`'s entry ID belongs to `owner`).
200
+ const m = link.name?.match(LINK_CONTAINER_RE);
201
+ return link.entryReferences.filter(r => (!m || r.name.startsWith(`${m[1]}entries/`)) &&
202
+ isEntryOwner(owner, r));
203
+ }
204
+ /**
205
+ * Returns true when both endpoints of `link` are in `link`'s entry group and
206
+ * owned by `owner` (`KcResources` or `KcAnchor`).
207
+ */
208
+ function isLinkOwner(owner, link) {
209
+ return link.entryReferences.length === 2 &&
210
+ collectOwnedReferences(owner, link).length === 2;
211
+ }
212
+ // ---------------------------------------------------------------------------
213
+ // 4. Aspect Keys & Link-Reference Comparison
214
+ // ---------------------------------------------------------------------------
215
+ /**
216
+ * Resolves the project and location where built-in system types live.
217
+ *
218
+ * Uses `opts` overrides when provided and defaults to `DEFAULT_TYPE_PROJECT`
219
+ * and `DEFAULT_TYPE_LOCATION`.
220
+ */
221
+ function systemTypeProjectAndLocation(opts) {
222
+ return {
223
+ proj: opts?.systemTypeProject ?? kc_ids_1.DEFAULT_TYPE_PROJECT,
224
+ loc: opts?.systemTypeLocation ?? kc_ids_1.DEFAULT_TYPE_LOCATION,
225
+ };
226
+ }
227
+ /**
228
+ * Returns the set of aspect keys to include when updating `entry`.
229
+ *
230
+ * Includes every aspect key present on `entry.aspects` plus the optional
231
+ * `<proj>.<loc>.guidelines` aspect. When `opts?.v2Aspects` is true:
232
+ * * Adds `<proj>.<loc>.semantic-extensions` and `<proj>.<loc>.overview` on
233
+ * model, entity, metric and relationship entries, so Dataplex removes the
234
+ * aspect when the object no longer has content for it.
235
+ * * Adds `<proj>.<loc>.sql-expressions` on entity and metric entries.
236
+ * * Adds `<proj>.<loc>.<type>@*` for guidelines, semantic-extensions and
237
+ * overview on entity entries, so Dataplex writes each field's instance
238
+ * `entry` carries and removes the others. A field's own key is left out.
239
+ */
240
+ function entryAspectKeys(entry, opts) {
241
+ const { proj, loc } = systemTypeProjectAndLocation(opts);
242
+ const keys = new Set([
243
+ ...Object.keys(entry.aspects ?? {}).filter(key => !key.includes('@')),
244
+ `${proj}.${loc}.guidelines`,
245
+ ]);
246
+ if (!opts?.v2Aspects)
247
+ return keys;
248
+ if (isSemanticObjectEntry(entry)) {
249
+ keys.add(`${proj}.${loc}.semantic-extensions`);
250
+ keys.add(`${proj}.${loc}.overview`);
251
+ }
252
+ if (isEntityEntry(entry) || isMetricEntry(entry)) {
253
+ keys.add(`${proj}.${loc}.sql-expressions`);
254
+ }
255
+ if (isEntityEntry(entry)) {
256
+ for (const type of ['guidelines', 'semantic-extensions', 'overview']) {
257
+ keys.add(`${proj}.${loc}.${type}@*`);
258
+ }
259
+ }
260
+ return keys;
261
+ }
262
+ /**
263
+ * Formats an `EntryReference` into a canonical comparison key combining its
264
+ * bare entry ID, reference type (defaulting to `'UNSPECIFIED'`), and path
265
+ * (treating an absent path and `''` as equal).
266
+ */
267
+ function formatLinkReference(ref) {
268
+ const id = (0, kc_ids_1.entryIdOf)(ref.name);
269
+ const type = ref.type ?? 'UNSPECIFIED';
270
+ return `${id}|${type}|${ref.path ?? ''}`;
271
+ }
272
+ /**
273
+ * Compares the `entryReferences` of two entry links by bare entry ID, reference
274
+ * type, and path, independent of reference order.
275
+ */
276
+ function sameLinkReferences(a, b) {
277
+ const refsA = a.entryReferences;
278
+ const refsB = b.entryReferences;
279
+ if (refsA.length !== refsB.length)
280
+ return false;
281
+ const sortedA = refsA.map(formatLinkReference).sort();
282
+ const sortedB = refsB.map(formatLinkReference).sort();
283
+ return sortedA.every((ref, i) => ref === sortedB[i]);
284
+ }
@@ -0,0 +1,102 @@
1
+ import { Entity, Metric, Relationship, SemanticModel } from './ir';
2
+ export declare const DEFAULT_TYPE_PROJECT = "dataplex-types";
3
+ export declare const DEFAULT_TYPE_LOCATION = "global";
4
+ /** Destination and layout options for constructing Knowledge Catalog names. */
5
+ export interface NamerOptions {
6
+ project: string;
7
+ location: string;
8
+ entryGroup: string;
9
+ systemTypeProject?: string;
10
+ systemTypeLocation?: string;
11
+ v2Aspects?: boolean;
12
+ }
13
+ /**
14
+ * Builds the fully-qualified resource names and bare entry/link IDs for a
15
+ * destination. Kept in one place so entry/type name construction is consistent
16
+ * and the emitter body reads as pure mapping.
17
+ */
18
+ export declare class Namer {
19
+ private readonly typeProject;
20
+ private readonly typeLocation;
21
+ private readonly container;
22
+ private readonly v2Aspects;
23
+ constructor(opts: NamerOptions);
24
+ /** Full resource name of a system type. `kind` selects the collection. */
25
+ typeName(kind: 'entry' | 'aspect' | 'entryLink', name: string): string;
26
+ /**
27
+ * Aspect-map key: the `project.location.type` reference form the client keys
28
+ * an entry's aspects by (see dataplex._nameToTypeRef / _fixEntry).
29
+ */
30
+ aspectRef(name: string): string;
31
+ /** Full resource name of an entry in the destination entry group. */
32
+ entry(entryId: string): string;
33
+ /** Full resource name of an entry link in the destination entry group. */
34
+ entryLink(linkId: string): string;
35
+ /**
36
+ * Bare entry ID for a semantic model, used as the `semantic-model` anchor
37
+ * entry's ID and as the prefix for action and constraint entry IDs.
38
+ *
39
+ * V1 sanitizes `model.name` with `slug()` because `model.name` may contain
40
+ * characters (e.g. spaces) that Knowledge Catalog disallows in entry IDs.
41
+ * V2 returns `model.name` verbatim because V2 model names are restricted to
42
+ * letters, digits, underscores and hyphens, all of which `slug()` keeps. This
43
+ * means `slug(model.name)` and `model.name` are equal for valid V2 models.
44
+ */
45
+ modelId(model: SemanticModel): string;
46
+ /** Bare entry ID for an entity within a semantic model. */
47
+ entityId(model: SemanticModel, entity: Entity): string;
48
+ /** Bare entry ID for a metric within a semantic model. */
49
+ metricId(model: SemanticModel, metric: Metric): string;
50
+ /** Bare V2 entry ID for a relationship within a semantic model. */
51
+ relationshipId(model: SemanticModel, rel: Relationship): string;
52
+ /**
53
+ * Entry link IDs are more restricted than entry IDs: lowercase letters,
54
+ * numbers and hyphens only, starting with a letter (see `linkSlug`). Does not
55
+ * branch on `v2Aspects`.
56
+ */
57
+ linkId(model: SemanticModel, rel: Relationship): string;
58
+ }
59
+ /** Entry-link ID for a relationship on a model. */
60
+ export declare function relationshipLinkId(modelName: string, relName: string): string;
61
+ /**
62
+ * ID of a link push writes: `semantic-<kind>-` and the first 32 hex characters
63
+ * of the SHA-256 of `parts` joined by '/'. It must stay the same across
64
+ * releases, so that push finds the links it wrote.
65
+ */
66
+ export declare function semanticLinkId(kind: 'link' | 'relationship' | 'extends', ...parts: string[]): string;
67
+ /**
68
+ * Entry-ID prefixes owned by `modelName` across both the first-generation
69
+ * dotted layout and the second-generation slash layout.
70
+ *
71
+ * The dotted prefixes use `slug(modelName)` to match V1 entries, while the
72
+ * slash prefixes use `modelName` verbatim to match V2 entity, metric and
73
+ * relationship entries. Because V2 model names are restricted to letters,
74
+ * digits, underscores and hyphens, all of which `slug()` keeps,
75
+ * `slug(modelName)` and `modelName` are equal for valid V2 models.
76
+ *
77
+ * No push writes under `.files.` any more: an older kcmd stored a copy of
78
+ * each model and profile file there. The prefix stays so the next push
79
+ * deletes those copies.
80
+ */
81
+ export declare function ownedEntryIdPrefixes(modelName: string): string[];
82
+ /**
83
+ * Extracts the bare resource ID from a full Knowledge Catalog resource name
84
+ * (entry, entry link, or type), or returns `resourceName` unchanged if it does
85
+ * not match a known resource container.
86
+ *
87
+ * Matches known container collections via `RESOURCE_ID_RE` and leaves
88
+ * non-matching strings untouched, rather than falling back to
89
+ * `.split('/').pop()` (which would corrupt an already-bare V2 slash entry ID
90
+ * like `'retail_sales/entities/store_orders'` into `'store_orders'`).
91
+ */
92
+ export declare function entryIdOf(resourceName: string): string;
93
+ /**
94
+ * Entry IDs allow letters, numbers, underscores, hyphens, and periods; maps
95
+ * anything else to an underscore.
96
+ */
97
+ export declare function slug(s: string): string;
98
+ /**
99
+ * Entry link IDs allow only lowercase letters, numbers and hyphens, must start
100
+ * with a letter, must end with a letter or number, and are capped at 63 chars.
101
+ */
102
+ export declare function linkSlug(s: string): string;