@google-cloud/kcmd 0.0.0-stage → 0.1.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/LICENSE +203 -0
- package/README.md +266 -2
- package/build/ts/kcmd/cli.js +19578 -0
- package/build/ts/kcmd/gcp/alloydb.d.ts +12 -0
- package/build/ts/kcmd/gcp/alloydb.js +70 -0
- package/build/ts/kcmd/gcp/api.d.ts +29 -0
- package/build/ts/kcmd/gcp/api.js +162 -0
- package/build/ts/kcmd/gcp/biglake.d.ts +16 -0
- package/build/ts/kcmd/gcp/biglake.js +50 -0
- package/build/ts/kcmd/gcp/bigquery.d.ts +57 -0
- package/build/ts/kcmd/gcp/bigquery.js +134 -0
- package/build/ts/kcmd/gcp/context.d.ts +10 -0
- package/build/ts/kcmd/gcp/context.js +74 -0
- package/build/ts/kcmd/gcp/crm.d.ts +13 -0
- package/build/ts/kcmd/gcp/crm.js +91 -0
- package/build/ts/kcmd/gcp/dataplex.d.ts +147 -0
- package/build/ts/kcmd/gcp/dataplex.js +406 -0
- package/build/ts/kcmd/gcp/index.d.ts +3 -0
- package/build/ts/kcmd/gcp/index.js +21 -0
- package/build/ts/kcmd/gcp/spanner.d.ts +63 -0
- package/build/ts/kcmd/gcp/spanner.js +123 -0
- package/build/ts/kcmd/index.d.ts +7 -0
- package/build/ts/kcmd/index.js +46 -0
- package/build/ts/kcmd/layout.d.ts +16 -0
- package/build/ts/kcmd/layout.js +31 -0
- package/build/ts/kcmd/layouts/documents.d.ts +24 -0
- package/build/ts/kcmd/layouts/documents.js +264 -0
- package/build/ts/kcmd/layouts/okf.d.ts +31 -0
- package/build/ts/kcmd/layouts/okf.js +344 -0
- package/build/ts/kcmd/layouts/semantic-model.d.ts +61 -0
- package/build/ts/kcmd/layouts/semantic-model.js +542 -0
- package/build/ts/kcmd/layouts/standard.d.ts +13 -0
- package/build/ts/kcmd/layouts/standard.js +108 -0
- package/build/ts/kcmd/manifest.d.ts +34 -0
- package/build/ts/kcmd/manifest.js +262 -0
- package/build/ts/kcmd/metadata.d.ts +25 -0
- package/build/ts/kcmd/metadata.js +8 -0
- package/build/ts/kcmd/okf/catalog_residue.d.ts +14 -0
- package/build/ts/kcmd/okf/catalog_residue.js +124 -0
- package/build/ts/kcmd/okf/concept.d.ts +14 -0
- package/build/ts/kcmd/okf/concept.js +104 -0
- package/build/ts/kcmd/okf/concept_to_entry.d.ts +8 -0
- package/build/ts/kcmd/okf/concept_to_entry.js +254 -0
- package/build/ts/kcmd/okf/init_okf_workspace.d.ts +15 -0
- package/build/ts/kcmd/okf/init_okf_workspace.js +115 -0
- package/build/ts/kcmd/okf/links.d.ts +23 -0
- package/build/ts/kcmd/okf/links.js +468 -0
- package/build/ts/kcmd/okf/okf_metadata.d.ts +12 -0
- package/build/ts/kcmd/okf/okf_metadata.js +82 -0
- package/build/ts/kcmd/semantic/bigquery.d.ts +22 -0
- package/build/ts/kcmd/semantic/bigquery.js +525 -0
- package/build/ts/kcmd/semantic/binding.d.ts +3 -0
- package/build/ts/kcmd/semantic/binding.js +97 -0
- package/build/ts/kcmd/semantic/catalog_entry.d.ts +24 -0
- package/build/ts/kcmd/semantic/catalog_entry.js +35 -0
- package/build/ts/kcmd/semantic/converters/owl/convert.d.ts +26 -0
- package/build/ts/kcmd/semantic/converters/owl/convert.js +41 -0
- package/build/ts/kcmd/semantic/converters/owl/model.d.ts +98 -0
- package/build/ts/kcmd/semantic/converters/owl/model.js +30 -0
- package/build/ts/kcmd/semantic/converters/owl/parse.d.ts +11 -0
- package/build/ts/kcmd/semantic/converters/owl/parse.js +634 -0
- package/build/ts/kcmd/semantic/converters/owl/to_ir.d.ts +19 -0
- package/build/ts/kcmd/semantic/converters/owl/to_ir.js +390 -0
- package/build/ts/kcmd/semantic/deploy_bigquery.d.ts +20 -0
- package/build/ts/kcmd/semantic/deploy_bigquery.js +226 -0
- package/build/ts/kcmd/semantic/deploy_knowledge_catalog.d.ts +129 -0
- package/build/ts/kcmd/semantic/deploy_knowledge_catalog.js +1396 -0
- package/build/ts/kcmd/semantic/deploy_spanner.d.ts +15 -0
- package/build/ts/kcmd/semantic/deploy_spanner.js +150 -0
- package/build/ts/kcmd/semantic/deployment_target.d.ts +93 -0
- package/build/ts/kcmd/semantic/deployment_target.js +379 -0
- package/build/ts/kcmd/semantic/graph_ddl.d.ts +34 -0
- package/build/ts/kcmd/semantic/graph_ddl.js +563 -0
- package/build/ts/kcmd/semantic/import_model.d.ts +50 -0
- package/build/ts/kcmd/semantic/import_model.js +1275 -0
- package/build/ts/kcmd/semantic/ir.d.ts +589 -0
- package/build/ts/kcmd/semantic/ir.js +247 -0
- package/build/ts/kcmd/semantic/kc_actions.d.ts +45 -0
- package/build/ts/kcmd/semantic/kc_actions.js +531 -0
- package/build/ts/kcmd/semantic/kc_constraints.d.ts +44 -0
- package/build/ts/kcmd/semantic/kc_constraints.js +279 -0
- package/build/ts/kcmd/semantic/kc_converter.d.ts +31 -0
- package/build/ts/kcmd/semantic/kc_converter.js +824 -0
- package/build/ts/kcmd/semantic/kc_custom_types.d.ts +70 -0
- package/build/ts/kcmd/semantic/kc_custom_types.js +828 -0
- package/build/ts/kcmd/semantic/kc_entries.d.ts +155 -0
- package/build/ts/kcmd/semantic/kc_entries.js +284 -0
- package/build/ts/kcmd/semantic/kc_ids.d.ts +103 -0
- package/build/ts/kcmd/semantic/kc_ids.js +191 -0
- package/build/ts/kcmd/semantic/knowledge_catalog.d.ts +32 -0
- package/build/ts/kcmd/semantic/knowledge_catalog.js +1043 -0
- package/build/ts/kcmd/semantic/loader.d.ts +262 -0
- package/build/ts/kcmd/semantic/loader.js +3440 -0
- package/build/ts/kcmd/semantic/names.d.ts +10 -0
- package/build/ts/kcmd/semantic/names.js +85 -0
- package/build/ts/kcmd/semantic/osi_converter.d.ts +60 -0
- package/build/ts/kcmd/semantic/osi_converter.js +911 -0
- package/build/ts/kcmd/semantic/parameters.d.ts +18 -0
- package/build/ts/kcmd/semantic/parameters.js +152 -0
- package/build/ts/kcmd/semantic/pull_kc.d.ts +14 -0
- package/build/ts/kcmd/semantic/pull_kc.js +346 -0
- package/build/ts/kcmd/semantic/resolve_inheritance.d.ts +54 -0
- package/build/ts/kcmd/semantic/resolve_inheritance.js +330 -0
- package/build/ts/kcmd/semantic/resolve_profiles.d.ts +250 -0
- package/build/ts/kcmd/semantic/resolve_profiles.js +1822 -0
- package/build/ts/kcmd/semantic/runtime/agent_tools.d.ts +93 -0
- package/build/ts/kcmd/semantic/runtime/agent_tools.js +243 -0
- package/build/ts/kcmd/semantic/runtime/dialect.d.ts +13 -0
- package/build/ts/kcmd/semantic/runtime/dialect.js +39 -0
- package/build/ts/kcmd/semantic/runtime/runtime.d.ts +94 -0
- package/build/ts/kcmd/semantic/runtime/runtime.js +318 -0
- package/build/ts/kcmd/semantic/runtime/store.d.ts +112 -0
- package/build/ts/kcmd/semantic/runtime/store.js +344 -0
- package/build/ts/kcmd/semantic/skills.d.ts +110 -0
- package/build/ts/kcmd/semantic/skills.js +697 -0
- package/build/ts/kcmd/semantic/source_dialect.d.ts +10 -0
- package/build/ts/kcmd/semantic/source_dialect.js +261 -0
- package/build/ts/kcmd/semantic/source_entries.d.ts +12 -0
- package/build/ts/kcmd/semantic/source_entries.js +282 -0
- package/build/ts/kcmd/semantic/spanner.d.ts +18 -0
- package/build/ts/kcmd/semantic/spanner.js +60 -0
- package/build/ts/kcmd/semantic/sql_expr_utils.d.ts +17 -0
- package/build/ts/kcmd/semantic/sql_expr_utils.js +221 -0
- package/build/ts/kcmd/semantic/sql_identifiers.d.ts +6 -0
- package/build/ts/kcmd/semantic/sql_identifiers.js +267 -0
- package/build/ts/kcmd/semantic/sql_parser.d.ts +44 -0
- package/build/ts/kcmd/semantic/sql_parser.js +378 -0
- package/build/ts/kcmd/semantic/transpile.d.ts +74 -0
- package/build/ts/kcmd/semantic/transpile.js +563 -0
- package/build/ts/kcmd/semantic/validate.d.ts +35 -0
- package/build/ts/kcmd/semantic/validate.js +1899 -0
- package/build/ts/kcmd/semantic/yaml_options.d.ts +6 -0
- package/build/ts/kcmd/semantic/yaml_options.js +58 -0
- package/build/ts/kcmd/semantic/yaml_update.d.ts +26 -0
- package/build/ts/kcmd/semantic/yaml_update.js +782 -0
- package/build/ts/kcmd/snapshot.d.ts +33 -0
- package/build/ts/kcmd/snapshot.js +379 -0
- package/build/ts/kcmd/source.d.ts +31 -0
- package/build/ts/kcmd/source.js +119 -0
- package/build/ts/kcmd/sources/bq-dataset.d.ts +17 -0
- package/build/ts/kcmd/sources/bq-dataset.js +131 -0
- package/build/ts/kcmd/sources/entrygroup.d.ts +21 -0
- package/build/ts/kcmd/sources/entrygroup.js +83 -0
- package/build/ts/kcmd/sources/kb.d.ts +21 -0
- package/build/ts/kcmd/sources/kb.js +82 -0
- package/build/ts/kcmd/sources/semantic-model.d.ts +18 -0
- package/build/ts/kcmd/sources/semantic-model.js +48 -0
- package/build/ts/kcmd/sync.d.ts +35 -0
- package/build/ts/kcmd/sync.js +697 -0
- package/package.json +62 -4
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// API client for Cloud Resource Manager
|
|
3
|
+
//
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.ResourceManagerClient = void 0;
|
|
39
|
+
exports.projectNumber = projectNumber;
|
|
40
|
+
exports.fixProject = fixProject;
|
|
41
|
+
const api = __importStar(require("./api"));
|
|
42
|
+
const PROJECT_NUM_TO_ID_CACHE = new Map();
|
|
43
|
+
PROJECT_NUM_TO_ID_CACHE.set('655216118709', 'dataplex-types');
|
|
44
|
+
class ResourceManagerClient extends api.ApiClient {
|
|
45
|
+
constructor(ctx) {
|
|
46
|
+
super('https://cloudresourcemanager.googleapis.com', 'v3', ctx);
|
|
47
|
+
}
|
|
48
|
+
async getProject(project) {
|
|
49
|
+
const name = `projects/${project}`;
|
|
50
|
+
return await this._get(name);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.ResourceManagerClient = ResourceManagerClient;
|
|
54
|
+
// Returns the project number of `project`, which is a project ID or number.
|
|
55
|
+
// Uses the number `fixProject` already resolved for this ID when there is one.
|
|
56
|
+
// Returns undefined when Cloud Resource Manager does not give it, for example
|
|
57
|
+
// when the caller lacks `resourcemanager.projects.get`.
|
|
58
|
+
async function projectNumber(project, ctx) {
|
|
59
|
+
if (/^\d+$/.test(project))
|
|
60
|
+
return project;
|
|
61
|
+
for (const [number, id] of PROJECT_NUM_TO_ID_CACHE) {
|
|
62
|
+
if (id === project)
|
|
63
|
+
return number;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const res = await new ResourceManagerClient(ctx).getProject(project);
|
|
67
|
+
// A project's resource name is `projects/<project number>`.
|
|
68
|
+
const number = res.status == 200 ? res.result?.name?.split('/')[1] : undefined;
|
|
69
|
+
return number && /^\d+$/.test(number) ? number : undefined;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function fixProject(resource, ctx) {
|
|
76
|
+
// projects/<project_id> or projects/<project_number> -> projects/<project_id>
|
|
77
|
+
const parts = resource.split('/');
|
|
78
|
+
if (/^\d+$/.test(parts[1])) {
|
|
79
|
+
let id = PROJECT_NUM_TO_ID_CACHE.get(parts[1]);
|
|
80
|
+
if (!id) {
|
|
81
|
+
const res = await new ResourceManagerClient(ctx).getProject(parts[1]);
|
|
82
|
+
id = res.status == 200 ? res.result?.projectId : '';
|
|
83
|
+
}
|
|
84
|
+
if (id) {
|
|
85
|
+
PROJECT_NUM_TO_ID_CACHE.set(parts[1], id);
|
|
86
|
+
parts[1] = id;
|
|
87
|
+
}
|
|
88
|
+
resource = parts.join('/');
|
|
89
|
+
}
|
|
90
|
+
return resource;
|
|
91
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import * as api from './api';
|
|
2
|
+
import * as context from './context';
|
|
3
|
+
export interface EntryGroup {
|
|
4
|
+
name: string;
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
}
|
|
7
|
+
export interface EntryType {
|
|
8
|
+
name: string;
|
|
9
|
+
requiredAspects: {
|
|
10
|
+
type: string;
|
|
11
|
+
}[];
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
}
|
|
14
|
+
export interface AspectType {
|
|
15
|
+
name: string;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
export interface Operation {
|
|
19
|
+
name?: string;
|
|
20
|
+
done?: boolean;
|
|
21
|
+
error?: {
|
|
22
|
+
code?: number;
|
|
23
|
+
message?: string;
|
|
24
|
+
};
|
|
25
|
+
metadata?: {
|
|
26
|
+
failedRequests?: Record<string, {
|
|
27
|
+
code?: number;
|
|
28
|
+
message?: string;
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface MetadataChange {
|
|
33
|
+
createEntryRequest?: {
|
|
34
|
+
parent: string;
|
|
35
|
+
entryId: string;
|
|
36
|
+
entry: Entry;
|
|
37
|
+
};
|
|
38
|
+
updateEntryRequest?: {
|
|
39
|
+
entry: Entry;
|
|
40
|
+
updateMask: string;
|
|
41
|
+
aspectKeys: string[];
|
|
42
|
+
deleteMissingAspects: boolean;
|
|
43
|
+
};
|
|
44
|
+
deleteEntryRequest?: {
|
|
45
|
+
name: string;
|
|
46
|
+
};
|
|
47
|
+
createEntryLinkRequest?: {
|
|
48
|
+
parent: string;
|
|
49
|
+
entryLinkId: string;
|
|
50
|
+
entryLink: EntryLink;
|
|
51
|
+
};
|
|
52
|
+
updateEntryLinkRequest?: {
|
|
53
|
+
entryLink: EntryLink;
|
|
54
|
+
allowMissing?: boolean;
|
|
55
|
+
aspectKeys?: string[];
|
|
56
|
+
};
|
|
57
|
+
deleteEntryLinkRequest?: {
|
|
58
|
+
name: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export interface LookupEntryOptions {
|
|
62
|
+
aspects?: string[];
|
|
63
|
+
paths?: string[];
|
|
64
|
+
view?: 'BASIC' | 'CUSTOM' | 'ALL';
|
|
65
|
+
}
|
|
66
|
+
export interface Aspect {
|
|
67
|
+
aspectType?: string;
|
|
68
|
+
path?: string;
|
|
69
|
+
data?: Record<string, any>;
|
|
70
|
+
}
|
|
71
|
+
export interface Entry {
|
|
72
|
+
name: string;
|
|
73
|
+
entryType: string;
|
|
74
|
+
parentEntry?: string;
|
|
75
|
+
fullyQualifiedName?: string;
|
|
76
|
+
createTime?: string;
|
|
77
|
+
updateTime?: string;
|
|
78
|
+
entrySource?: {
|
|
79
|
+
resource?: string;
|
|
80
|
+
system?: string;
|
|
81
|
+
platform?: string;
|
|
82
|
+
ancestors?: {
|
|
83
|
+
name: string;
|
|
84
|
+
type: string;
|
|
85
|
+
}[];
|
|
86
|
+
displayName?: string;
|
|
87
|
+
description?: string;
|
|
88
|
+
labels?: Record<string, string>;
|
|
89
|
+
location?: string;
|
|
90
|
+
createTime?: string;
|
|
91
|
+
updateTime?: string;
|
|
92
|
+
};
|
|
93
|
+
aspects?: Record<string, Aspect>;
|
|
94
|
+
}
|
|
95
|
+
export interface EntryReference {
|
|
96
|
+
name: string;
|
|
97
|
+
path?: string;
|
|
98
|
+
type: 'UNSPECIFIED' | 'SOURCE' | 'TARGET';
|
|
99
|
+
}
|
|
100
|
+
export interface EntryLink {
|
|
101
|
+
name?: string;
|
|
102
|
+
entryLinkType: string;
|
|
103
|
+
entryReferences: EntryReference[];
|
|
104
|
+
aspects?: Record<string, Aspect>;
|
|
105
|
+
}
|
|
106
|
+
export declare class CatalogClient extends api.ApiClient {
|
|
107
|
+
constructor(ctx: context.ApiContext);
|
|
108
|
+
getEntryGroup(project: string, location: string, entryGroup: string): Promise<api.ApiResult<EntryGroup>>;
|
|
109
|
+
getEntryType(project: string, location: string, type: string): Promise<api.ApiResult<EntryType>>;
|
|
110
|
+
getAspectType(project: string, location: string, type: string): Promise<api.ApiResult<AspectType>>;
|
|
111
|
+
getEntry(project: string, location: string, entryGroup: string, entry: string, aspects?: string[], fix?: FixOptions): Promise<api.ApiResult<Entry>>;
|
|
112
|
+
lookupEntry(project: string, location: string, name: string, opts?: LookupEntryOptions): Promise<api.ApiResult<Entry>>;
|
|
113
|
+
lookupEntryAspectTypes(project: string, location: string, name: string): Promise<api.ApiResult<string[]>>;
|
|
114
|
+
modifyEntry(project: string, location: string, entry: Entry, updateMask?: string[], aspectKeys?: string[]): Promise<api.ApiResult<Entry>>;
|
|
115
|
+
updateEntry(entry: Entry, updateMask?: string[], aspectKeys?: string[], deleteMissingAspects?: boolean): Promise<api.ApiResult<Entry>>;
|
|
116
|
+
listEntries(project: string, location: string, entryGroup: string, fix?: FixOptions): AsyncGenerator<Entry, void, unknown>;
|
|
117
|
+
createEntry(project: string, location: string, entryGroup: string, entryId: string, entry?: Entry): Promise<api.ApiResult<Entry>>;
|
|
118
|
+
deleteEntry(project: string, location: string, entryGroup: string, entry: string): Promise<api.ApiResult<Entry>>;
|
|
119
|
+
batchChangeMetadata(project: string, location: string, entryGroup: string, changes: MetadataChange[]): Promise<api.ApiResult<Operation>>;
|
|
120
|
+
createEntryGroup(project: string, location: string, entryGroupId: string, entryGroup?: EntryGroup): Promise<api.ApiResult<EntryGroup>>;
|
|
121
|
+
updateEntryGroup(project: string, location: string, entryGroupId: string, entryGroup: Partial<EntryGroup>, updateMask?: string[]): Promise<api.ApiResult<Operation>>;
|
|
122
|
+
createAspectType(project: string, location: string, aspectTypeId: string, aspectType: Omit<AspectType, 'name'>): Promise<api.ApiResult<Operation>>;
|
|
123
|
+
updateAspectType(project: string, location: string, aspectTypeId: string, aspectType: Omit<AspectType, 'name'>, updateMask?: string[]): Promise<api.ApiResult<Operation>>;
|
|
124
|
+
createEntryType(project: string, location: string, entryTypeId: string, entryType: Omit<EntryType, 'name'>): Promise<api.ApiResult<Operation>>;
|
|
125
|
+
getOperation(operationName: string): Promise<api.ApiResult<Operation>>;
|
|
126
|
+
pollOperation(op: Operation | undefined, what: string, timeoutMs?: number): Promise<{
|
|
127
|
+
operation?: Operation;
|
|
128
|
+
error?: string;
|
|
129
|
+
}>;
|
|
130
|
+
awaitOperation(op: Operation | undefined, what: string, timeoutMs?: number): Promise<string | undefined>;
|
|
131
|
+
createEntryLink(project: string, location: string, entryGroup: string, entryLinkId: string, entryLink: EntryLink): Promise<api.ApiResult<EntryLink>>;
|
|
132
|
+
updateEntryLink(entryLink: EntryLink, aspectKeys?: string[]): Promise<api.ApiResult<EntryLink>>;
|
|
133
|
+
getEntryLink(name: string): Promise<api.ApiResult<EntryLink>>;
|
|
134
|
+
deleteEntryLink(project: string, location: string, entryGroup: string, entryLinkId: string): Promise<api.ApiResult<EntryLink>>;
|
|
135
|
+
lookupEntryLinks(project: string, location: string, opts: {
|
|
136
|
+
entry: string;
|
|
137
|
+
entryLinkTypes?: string[];
|
|
138
|
+
entryMode?: 'UNSPECIFIED' | 'SOURCE' | 'TARGET';
|
|
139
|
+
}): Promise<api.ApiResult<EntryLink[]>>;
|
|
140
|
+
}
|
|
141
|
+
export interface FixOptions {
|
|
142
|
+
keepSourceResource?: boolean;
|
|
143
|
+
}
|
|
144
|
+
export declare function _fixEntry(entry: Entry, ctx: context.ApiContext, fix?: FixOptions): Promise<void>;
|
|
145
|
+
export declare function catalogContainer(project: string, location: string, entryGroup?: string): string;
|
|
146
|
+
export declare function _typeRefToName(ref: string, type: string): string;
|
|
147
|
+
export declare function _nameToTypeRef(name: string): string;
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// API client for Knowledge Catalog (Dataplex)
|
|
3
|
+
//
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.CatalogClient = void 0;
|
|
39
|
+
exports._fixEntry = _fixEntry;
|
|
40
|
+
exports.catalogContainer = catalogContainer;
|
|
41
|
+
exports._typeRefToName = _typeRefToName;
|
|
42
|
+
exports._nameToTypeRef = _nameToTypeRef;
|
|
43
|
+
const api = __importStar(require("./api"));
|
|
44
|
+
const crm = __importStar(require("./crm"));
|
|
45
|
+
// Renders a finished operation's failure as a message, or returns undefined
|
|
46
|
+
// when it succeeded.
|
|
47
|
+
function operationFailure(op, what) {
|
|
48
|
+
if (!op.error)
|
|
49
|
+
return undefined;
|
|
50
|
+
return `${what}: ${op.error.message || `operation failed (${op.error.code})`}`;
|
|
51
|
+
}
|
|
52
|
+
class CatalogClient extends api.ApiClient {
|
|
53
|
+
constructor(ctx) {
|
|
54
|
+
// Defaults to the production Dataplex endpoint. Override via DATAPLEX_ENDPOINT
|
|
55
|
+
// to target a non-prod host (e.g. an autopush/sandbox EAP), same env-var
|
|
56
|
+
// knob style as GCP_LOG.
|
|
57
|
+
super(process.env.DATAPLEX_ENDPOINT || 'https://dataplex.googleapis.com', 'v1', ctx);
|
|
58
|
+
}
|
|
59
|
+
async getEntryGroup(project, location, entryGroup) {
|
|
60
|
+
const name = catalogContainer(project, location, entryGroup);
|
|
61
|
+
return await this._get(name);
|
|
62
|
+
}
|
|
63
|
+
async getEntryType(project, location, type) {
|
|
64
|
+
const name = `${catalogContainer(project, location)}/entryTypes/${type}`;
|
|
65
|
+
return await this._get(name);
|
|
66
|
+
}
|
|
67
|
+
async getAspectType(project, location, type) {
|
|
68
|
+
const name = `${catalogContainer(project, location)}/aspectTypes/${type}`;
|
|
69
|
+
return await this._get(name);
|
|
70
|
+
}
|
|
71
|
+
// `fix.keepSourceResource` returns `entrySource.resource` exactly as stored.
|
|
72
|
+
async getEntry(project, location, entryGroup, entry, aspects, fix = {}) {
|
|
73
|
+
const name = `${catalogContainer(project, location, entryGroup)}/entries/${entry}`;
|
|
74
|
+
const params = { view: 'BASIC' };
|
|
75
|
+
if (aspects && aspects.length) {
|
|
76
|
+
params.view = 'CUSTOM';
|
|
77
|
+
params.aspectTypes = aspects;
|
|
78
|
+
}
|
|
79
|
+
const res = await this._get(name, params);
|
|
80
|
+
if (res.status == 200 && res.result) {
|
|
81
|
+
await _fixEntry(res.result, this.context, fix);
|
|
82
|
+
}
|
|
83
|
+
return res;
|
|
84
|
+
}
|
|
85
|
+
// With `opts.aspects`, `opts.paths` keeps only the aspects at those paths.
|
|
86
|
+
// The path '' is the entry itself, and `Schema.<field>` is a field. Passing
|
|
87
|
+
// `{view: 'ALL'}` reads every aspect without naming aspect types.
|
|
88
|
+
async lookupEntry(project, location, name, opts = {}) {
|
|
89
|
+
const container = `${catalogContainer(project, location)}:lookupEntry`;
|
|
90
|
+
const params = { entry: name, view: opts.view ?? 'BASIC' };
|
|
91
|
+
if (opts.view !== 'ALL' && opts.aspects && opts.aspects.length) {
|
|
92
|
+
params.view = 'CUSTOM';
|
|
93
|
+
params.aspectTypes = opts.aspects;
|
|
94
|
+
params.paths = opts.paths;
|
|
95
|
+
}
|
|
96
|
+
const res = await this._get(container, params);
|
|
97
|
+
if (res.status == 200 && res.result) {
|
|
98
|
+
await _fixEntry(res.result, this.context);
|
|
99
|
+
}
|
|
100
|
+
return res;
|
|
101
|
+
}
|
|
102
|
+
// The type of every aspect on an entry, as project.location.type, each
|
|
103
|
+
// once. A FULL read lists every aspect but gives data only to those the
|
|
104
|
+
// entry's type requires, so this reads the keys alone, which lookupEntry
|
|
105
|
+
// would drop.
|
|
106
|
+
async lookupEntryAspectTypes(project, location, name) {
|
|
107
|
+
const container = `${catalogContainer(project, location)}:lookupEntry`;
|
|
108
|
+
const res = await this._get(container, { entry: name, view: 'FULL' });
|
|
109
|
+
if (res.status != 200 || !res.result) {
|
|
110
|
+
return { status: res.status, message: res.message, body: res.body };
|
|
111
|
+
}
|
|
112
|
+
// Each type is resolved once: crm caches only the projects it can read,
|
|
113
|
+
// so several field-path keys of one unreadable type would each look it up.
|
|
114
|
+
const typeRefs = new Set(Object.keys(res.result.aspects ?? {})
|
|
115
|
+
.map(key => key.split('@')[0]));
|
|
116
|
+
const types = new Set();
|
|
117
|
+
for (const typeRef of typeRefs) {
|
|
118
|
+
const { aspectType } = await _aspectTypeOfKey(typeRef, this.context);
|
|
119
|
+
types.add(_nameToTypeRef(aspectType));
|
|
120
|
+
}
|
|
121
|
+
return { status: 200, result: [...types] };
|
|
122
|
+
}
|
|
123
|
+
async modifyEntry(project, location, entry, updateMask, aspectKeys) {
|
|
124
|
+
const container = `${catalogContainer(project, location)}:modifyEntry`;
|
|
125
|
+
const body = {
|
|
126
|
+
entry: entry,
|
|
127
|
+
updateMask: updateMask ? updateMask.join(',') : undefined,
|
|
128
|
+
aspectKeys: aspectKeys ?? undefined
|
|
129
|
+
};
|
|
130
|
+
const res = await this._post(container, body);
|
|
131
|
+
if (res.status == 200 && res.result) {
|
|
132
|
+
await _fixEntry(res.result, this.context);
|
|
133
|
+
}
|
|
134
|
+
return res;
|
|
135
|
+
}
|
|
136
|
+
// `deleteMissingAspects` removes each aspect `aspectKeys` names that `entry`
|
|
137
|
+
// does not carry. Without it Dataplex keeps such an aspect. The returned
|
|
138
|
+
// entry leaves out every aspect the update removed.
|
|
139
|
+
async updateEntry(entry, updateMask, aspectKeys, deleteMissingAspects) {
|
|
140
|
+
const params = {};
|
|
141
|
+
if (updateMask && updateMask.length) {
|
|
142
|
+
params.updateMask = updateMask.join(',');
|
|
143
|
+
}
|
|
144
|
+
if (aspectKeys && aspectKeys.length) {
|
|
145
|
+
params.aspectKeys = aspectKeys;
|
|
146
|
+
}
|
|
147
|
+
if (deleteMissingAspects) {
|
|
148
|
+
params.deleteMissingAspects = true;
|
|
149
|
+
}
|
|
150
|
+
const res = await this._patch(entry.name, entry, params);
|
|
151
|
+
if (res.status == 200 && res.result) {
|
|
152
|
+
await _fixEntry(res.result, this.context);
|
|
153
|
+
}
|
|
154
|
+
return res;
|
|
155
|
+
}
|
|
156
|
+
// `fix.keepSourceResource` returns each `entrySource.resource` exactly as
|
|
157
|
+
// stored.
|
|
158
|
+
async *listEntries(project, location, entryGroup, fix = {}) {
|
|
159
|
+
const parent = catalogContainer(project, location, entryGroup);
|
|
160
|
+
const resourceName = `${parent}/entries`;
|
|
161
|
+
let pageToken = undefined;
|
|
162
|
+
do {
|
|
163
|
+
const params = { pageSize: 1000 };
|
|
164
|
+
if (pageToken) {
|
|
165
|
+
params.pageToken = pageToken;
|
|
166
|
+
}
|
|
167
|
+
const res = await this._get(resourceName, params);
|
|
168
|
+
if (res.status !== 200) {
|
|
169
|
+
throw new Error(`Failed to list entries: ${res.message || res.status}`);
|
|
170
|
+
}
|
|
171
|
+
const entries = res.result?.entries || [];
|
|
172
|
+
for (const entry of entries) {
|
|
173
|
+
await _fixEntry(entry, this.context, fix);
|
|
174
|
+
yield entry;
|
|
175
|
+
}
|
|
176
|
+
pageToken = res.result?.nextPageToken;
|
|
177
|
+
} while (pageToken);
|
|
178
|
+
}
|
|
179
|
+
async createEntry(project, location, entryGroup, entryId, entry) {
|
|
180
|
+
const parent = catalogContainer(project, location, entryGroup);
|
|
181
|
+
const resourceName = `${parent}/entries`;
|
|
182
|
+
const params = { entryId };
|
|
183
|
+
const res = await this._post(resourceName, entry, params);
|
|
184
|
+
if (res.status == 200 && res.result) {
|
|
185
|
+
await _fixEntry(res.result, this.context);
|
|
186
|
+
}
|
|
187
|
+
return res;
|
|
188
|
+
}
|
|
189
|
+
async deleteEntry(project, location, entryGroup, entry) {
|
|
190
|
+
const name = `${catalogContainer(project, location, entryGroup)}/entries/${entry}`;
|
|
191
|
+
return await this._delete(name);
|
|
192
|
+
}
|
|
193
|
+
// Applies up to 250 entry changes to one entry group in a single call, and
|
|
194
|
+
// returns the LRO to poll. Per-change failures arrive in the operation's
|
|
195
|
+
// metadata rather than as a non-200.
|
|
196
|
+
async batchChangeMetadata(project, location, entryGroup, changes) {
|
|
197
|
+
const name = catalogContainer(project, location, entryGroup);
|
|
198
|
+
return await this._post(`${name}:batchChangeMetadata`, { name, changes });
|
|
199
|
+
}
|
|
200
|
+
async createEntryGroup(project, location, entryGroupId, entryGroup) {
|
|
201
|
+
const parent = catalogContainer(project, location);
|
|
202
|
+
const resourceName = `${parent}/entryGroups`;
|
|
203
|
+
const params = { entryGroupId };
|
|
204
|
+
const res = await this._post(resourceName, entryGroup, params);
|
|
205
|
+
return res;
|
|
206
|
+
}
|
|
207
|
+
async updateEntryGroup(project, location, entryGroupId, entryGroup, updateMask) {
|
|
208
|
+
const name = catalogContainer(project, location, entryGroupId);
|
|
209
|
+
const params = {};
|
|
210
|
+
if (updateMask && updateMask.length) {
|
|
211
|
+
params.updateMask = updateMask.join(',');
|
|
212
|
+
}
|
|
213
|
+
return await this._patch(name, entryGroup, params);
|
|
214
|
+
}
|
|
215
|
+
// Creates a custom aspect type. `aspectType` carries the display name,
|
|
216
|
+
// description and metadataTemplate; the resource name comes from the id.
|
|
217
|
+
async createAspectType(project, location, aspectTypeId, aspectType) {
|
|
218
|
+
const resourceName = `${catalogContainer(project, location)}/aspectTypes`;
|
|
219
|
+
const params = { aspectTypeId };
|
|
220
|
+
return await this._post(resourceName, aspectType, params);
|
|
221
|
+
}
|
|
222
|
+
// Patches an existing aspect type. Dataplex rejects a backwards-incompatible
|
|
223
|
+
// metadataTemplate change, so an update only ever adds fields.
|
|
224
|
+
async updateAspectType(project, location, aspectTypeId, aspectType, updateMask) {
|
|
225
|
+
const name = `${catalogContainer(project, location)}/aspectTypes/${aspectTypeId}`;
|
|
226
|
+
const params = {};
|
|
227
|
+
if (updateMask && updateMask.length) {
|
|
228
|
+
params.updateMask = updateMask.join(',');
|
|
229
|
+
}
|
|
230
|
+
return await this._patch(name, aspectType, params);
|
|
231
|
+
}
|
|
232
|
+
// Creates a custom entry type.
|
|
233
|
+
async createEntryType(project, location, entryTypeId, entryType) {
|
|
234
|
+
const resourceName = `${catalogContainer(project, location)}/entryTypes`;
|
|
235
|
+
const params = { entryTypeId };
|
|
236
|
+
return await this._post(resourceName, entryType, params);
|
|
237
|
+
}
|
|
238
|
+
// Fetches a long-running operation by the resource name the call that started
|
|
239
|
+
// it returned. Disables per-call _get retry so poll loops control backoff.
|
|
240
|
+
async getOperation(operationName) {
|
|
241
|
+
return await this._get(operationName, undefined, { retry: false });
|
|
242
|
+
}
|
|
243
|
+
// Polls a long-running operation until it finishes, returning both the final
|
|
244
|
+
// operation (for callers that inspect `metadata.failedRequests`) and any
|
|
245
|
+
// failure message.
|
|
246
|
+
async pollOperation(op, what, timeoutMs = 120000) {
|
|
247
|
+
if (!op || !op.name)
|
|
248
|
+
return { operation: op };
|
|
249
|
+
if (op.done)
|
|
250
|
+
return { operation: op, error: operationFailure(op, what) };
|
|
251
|
+
const deadline = Date.now() + timeoutMs;
|
|
252
|
+
let delayMs = 500;
|
|
253
|
+
while (Date.now() < deadline) {
|
|
254
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
255
|
+
delayMs = Math.min(delayMs * 2, 5000);
|
|
256
|
+
const polled = await this.getOperation(op.name);
|
|
257
|
+
// A client error will not resolve itself, so report it rather than spend
|
|
258
|
+
// the whole timeout rediscovering it and then blame the timeout. A 5xx or
|
|
259
|
+
// a throttle is worth another attempt.
|
|
260
|
+
if (polled.status >= 400 && polled.status < 500 &&
|
|
261
|
+
polled.status !== 429) {
|
|
262
|
+
return {
|
|
263
|
+
error: `${what}: reading ${op.name}: ${polled.message || polled.status}`
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
if (polled.status !== 200 || !polled.result)
|
|
267
|
+
continue;
|
|
268
|
+
if (polled.result.done) {
|
|
269
|
+
return {
|
|
270
|
+
operation: polled.result,
|
|
271
|
+
error: operationFailure(polled.result, what)
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return { error: `${what}: timed out after ${timeoutMs}ms waiting for ${op.name}` };
|
|
276
|
+
}
|
|
277
|
+
// Polls a long-running operation until it finishes, and returns a message
|
|
278
|
+
// describing the failure when it fails or does not finish in time. Creating a
|
|
279
|
+
// type is asynchronous, so a caller that skips this races the server: an
|
|
280
|
+
// entry type that names an aspect type the server cannot see yet is rejected
|
|
281
|
+
// with `The following aspect types do not exist`.
|
|
282
|
+
async awaitOperation(op, what, timeoutMs = 120000) {
|
|
283
|
+
return (await this.pollOperation(op, what, timeoutMs)).error;
|
|
284
|
+
}
|
|
285
|
+
async createEntryLink(project, location, entryGroup, entryLinkId, entryLink) {
|
|
286
|
+
const parent = catalogContainer(project, location, entryGroup);
|
|
287
|
+
const resourceName = `${parent}/entryLinks`;
|
|
288
|
+
const params = { entryLinkId };
|
|
289
|
+
return await this._post(resourceName, entryLink, params);
|
|
290
|
+
}
|
|
291
|
+
// Patches an existing entry link. UpdateEntryLink has no update mask: the
|
|
292
|
+
// aspects present in the request body are the ones written, narrowed to
|
|
293
|
+
// `aspectKeys` (each `project.location.aspectType`) when given. The entry
|
|
294
|
+
// references and link type are immutable server-side.
|
|
295
|
+
async updateEntryLink(entryLink, aspectKeys) {
|
|
296
|
+
const params = {};
|
|
297
|
+
if (aspectKeys && aspectKeys.length) {
|
|
298
|
+
params.aspectKeys = aspectKeys;
|
|
299
|
+
}
|
|
300
|
+
return await this._patch(entryLink.name, entryLink, params);
|
|
301
|
+
}
|
|
302
|
+
// Reads an entry link by its full resource name.
|
|
303
|
+
async getEntryLink(name) {
|
|
304
|
+
return await this._get(name);
|
|
305
|
+
}
|
|
306
|
+
async deleteEntryLink(project, location, entryGroup, entryLinkId) {
|
|
307
|
+
const name = `${catalogContainer(project, location, entryGroup)}/entryLinks/${entryLinkId}`;
|
|
308
|
+
return await this._delete(name);
|
|
309
|
+
}
|
|
310
|
+
// Returns every entry link that references `entry` (its full resource name),
|
|
311
|
+
// draining all pages. There is no list-entry-links collection API; the server
|
|
312
|
+
// only exposes links per referenced entry, via the location-scoped
|
|
313
|
+
// :lookupEntryLinks custom verb (mirroring :lookupEntry). `entryLinkTypes`
|
|
314
|
+
// optionally filters to specific link types (server caps it at 10); `entryMode`
|
|
315
|
+
// filters by the entry's role in the link (SOURCE/TARGET). The server caps a
|
|
316
|
+
// page at 10 links, so this follows nextPageToken until exhausted and returns
|
|
317
|
+
// the flat list. A non-200 on any page aborts and is returned as-is.
|
|
318
|
+
async lookupEntryLinks(project, location, opts) {
|
|
319
|
+
const container = `${catalogContainer(project, location)}:lookupEntryLinks`;
|
|
320
|
+
const links = [];
|
|
321
|
+
let pageToken = undefined;
|
|
322
|
+
do {
|
|
323
|
+
const params = {
|
|
324
|
+
entry: opts.entry,
|
|
325
|
+
entryLinkTypes: opts.entryLinkTypes,
|
|
326
|
+
entryMode: opts.entryMode,
|
|
327
|
+
pageSize: 10,
|
|
328
|
+
pageToken,
|
|
329
|
+
};
|
|
330
|
+
const res = await this._get(container, params);
|
|
331
|
+
if (res.status != 200) {
|
|
332
|
+
return { status: res.status, message: res.message, body: res.body };
|
|
333
|
+
}
|
|
334
|
+
for (const link of res.result?.entryLinks ?? []) {
|
|
335
|
+
links.push(link);
|
|
336
|
+
}
|
|
337
|
+
pageToken = res.result?.nextPageToken;
|
|
338
|
+
} while (pageToken);
|
|
339
|
+
return { status: 200, result: links };
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
exports.CatalogClient = CatalogClient;
|
|
343
|
+
// Normalises an entry and its aspects in place so resource names and aspect
|
|
344
|
+
// keys consistently use project IDs (rather than project numbers), while
|
|
345
|
+
// preserving `@<path>` suffixes and `path` fields on field-level aspects.
|
|
346
|
+
// Drops an aspect whose value is null or has no fields. An update's response
|
|
347
|
+
// lists each aspect it removed with an empty value.
|
|
348
|
+
async function _fixEntry(entry, ctx, fix = {}) {
|
|
349
|
+
entry.name = await crm.fixProject(entry.name, ctx);
|
|
350
|
+
entry.entryType = await crm.fixProject(entry.entryType, ctx);
|
|
351
|
+
if (entry.entrySource?.resource && !fix.keepSourceResource) {
|
|
352
|
+
entry.entrySource.resource = await crm.fixProject(entry.entrySource.resource, ctx);
|
|
353
|
+
}
|
|
354
|
+
if (entry.aspects) {
|
|
355
|
+
const fixedAspects = {};
|
|
356
|
+
for (const [aspectKey, aspectValue] of Object.entries(entry.aspects)) {
|
|
357
|
+
if (!aspectValue || !Object.keys(aspectValue).length)
|
|
358
|
+
continue;
|
|
359
|
+
const { aspectType, keyPath } = await _aspectTypeOfKey(aspectKey, ctx);
|
|
360
|
+
const path = aspectValue.path || keyPath;
|
|
361
|
+
const baseKey = _nameToTypeRef(aspectType);
|
|
362
|
+
const fixedKey = path ? `${baseKey}@${path}` : baseKey;
|
|
363
|
+
fixedAspects[fixedKey] = {
|
|
364
|
+
aspectType: aspectType,
|
|
365
|
+
...(path ? { path } : {}),
|
|
366
|
+
data: aspectValue.data ?? {}
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
entry.aspects = fixedAspects;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// The aspect type an aspect key names, as a resource name with a project ID,
|
|
373
|
+
// and the key's `@<path>` part, if any.
|
|
374
|
+
async function _aspectTypeOfKey(key, ctx) {
|
|
375
|
+
const atIdx = key.indexOf('@');
|
|
376
|
+
const typeRef = atIdx === -1 ? key : key.slice(0, atIdx);
|
|
377
|
+
return {
|
|
378
|
+
aspectType: await crm.fixProject(_typeRefToName(typeRef, 'aspect'), ctx),
|
|
379
|
+
keyPath: atIdx === -1 ? undefined : key.slice(atIdx + 1),
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
// Constructs canonical names for catalog container resources, identified by project, location and
|
|
383
|
+
// optionally, depending on use-case, the entry group.
|
|
384
|
+
function catalogContainer(project, location, entryGroup = '') {
|
|
385
|
+
let container = `projects/${project}/locations/${location}`;
|
|
386
|
+
if (entryGroup) {
|
|
387
|
+
container += `/entryGroups/${entryGroup}`;
|
|
388
|
+
}
|
|
389
|
+
return container;
|
|
390
|
+
}
|
|
391
|
+
// Converts project.location.type to projects/${project}/locations/${location}/typeTypes/${type}
|
|
392
|
+
function _typeRefToName(ref, type) {
|
|
393
|
+
const refParts = ref.split('.');
|
|
394
|
+
if (refParts.length !== 3) {
|
|
395
|
+
throw new Error(`Invalid type reference: ${ref}`);
|
|
396
|
+
}
|
|
397
|
+
return `projects/${refParts[0]}/locations/${refParts[1]}/${type}Types/${refParts[2]}`;
|
|
398
|
+
}
|
|
399
|
+
// Converts projects/${project}/locations/${location}/typeTypes/${type} -> project.location.type
|
|
400
|
+
function _nameToTypeRef(name) {
|
|
401
|
+
const nameParts = name.split('/');
|
|
402
|
+
if (nameParts.length < 6) {
|
|
403
|
+
throw new Error(`Invalid type name: ${name}`);
|
|
404
|
+
}
|
|
405
|
+
return `${nameParts[1]}.${nameParts[3]}.${nameParts[5]}`;
|
|
406
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// GCP Client Library and Helpers
|
|
3
|
+
//
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
16
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
__exportStar(require("./context"), exports);
|
|
20
|
+
__exportStar(require("./api"), exports);
|
|
21
|
+
__exportStar(require("./dataplex"), exports);
|