@google-cloud/kcmd 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/ts/kcmd/cli.js +241 -382
- package/build/ts/kcmd/okf/init_okf_workspace.js +1 -1
- package/build/ts/kcmd/semantic/deploy_bigquery.js +6 -13
- package/build/ts/kcmd/semantic/deploy_knowledge_catalog.d.ts +3 -3
- package/build/ts/kcmd/semantic/deploy_knowledge_catalog.js +16 -44
- package/build/ts/kcmd/semantic/deploy_spanner.js +7 -14
- package/build/ts/kcmd/semantic/deployment_target.d.ts +1 -4
- package/build/ts/kcmd/semantic/deployment_target.js +6 -62
- package/build/ts/kcmd/semantic/import_model.js +5 -8
- package/build/ts/kcmd/semantic/ir.d.ts +2 -4
- package/build/ts/kcmd/semantic/kc_converter.js +12 -22
- package/build/ts/kcmd/semantic/kc_custom_types.js +27 -21
- package/build/ts/kcmd/semantic/loader.js +3 -28
- package/build/ts/kcmd/semantic/osi_converter.js +13 -63
- package/build/ts/kcmd/semantic/runtime/runtime.d.ts +4 -6
- package/build/ts/kcmd/semantic/runtime/store.d.ts +14 -19
- package/build/ts/kcmd/semantic/runtime/store.js +21 -37
- package/build/ts/kcmd/semantic/validate.js +4 -30
- package/package.json +1 -1
package/build/ts/kcmd/cli.js
CHANGED
|
@@ -35,7 +35,7 @@ var cac = __toESM(require("cac"));
|
|
|
35
35
|
// package.json
|
|
36
36
|
var package_default = {
|
|
37
37
|
name: "@google-cloud/kcmd",
|
|
38
|
-
version: "0.2.
|
|
38
|
+
version: "0.2.1",
|
|
39
39
|
description: "Google Knowledge Catalog Metadata as Code Library, CLI and MCP Server",
|
|
40
40
|
repository: {
|
|
41
41
|
type: "git",
|
|
@@ -3743,12 +3743,6 @@ function normalizeModelSugars(m, extended) {
|
|
|
3743
3743
|
delete m.entities;
|
|
3744
3744
|
}
|
|
3745
3745
|
}
|
|
3746
|
-
function deploymentTargetsExtension(targets) {
|
|
3747
|
-
return {
|
|
3748
|
-
vendorName: GOOGLE_VENDOR,
|
|
3749
|
-
data: JSON.stringify({ deploymentTargets: targets })
|
|
3750
|
-
};
|
|
3751
|
-
}
|
|
3752
3746
|
function isGoogleVendor(vendorName) {
|
|
3753
3747
|
return typeof vendorName === "string" && vendorName.toUpperCase() === GOOGLE_VENDOR;
|
|
3754
3748
|
}
|
|
@@ -4359,13 +4353,6 @@ function convertModel(m, version, opts, warnings) {
|
|
|
4359
4353
|
model.aiContext = ai;
|
|
4360
4354
|
if (block.kept)
|
|
4361
4355
|
model.customExtensions = block.kept;
|
|
4362
|
-
const foldedTargets = version === GOOGLE_VERSION ? deployments.map((d) => d.target) : [];
|
|
4363
|
-
if (foldedTargets.length) {
|
|
4364
|
-
model.customExtensions = [
|
|
4365
|
-
...model.customExtensions ?? [],
|
|
4366
|
-
deploymentTargetsExtension(foldedTargets)
|
|
4367
|
-
];
|
|
4368
|
-
}
|
|
4369
4356
|
return model;
|
|
4370
4357
|
}
|
|
4371
4358
|
function convertDataset(ds, block, version, opts, warnings, dialect) {
|
|
@@ -8947,7 +8934,7 @@ async function initOkfWorkspace(ctx, manifest2, options = {}) {
|
|
|
8947
8934
|
const hasConceptFiles = fs8.readdirSync(BUNDLE_DIR).some((f) => f.endsWith(".md"));
|
|
8948
8935
|
if (!fs8.existsSync(indexPath) && !fs8.existsSync(agentsPath) && !hasConceptFiles) {
|
|
8949
8936
|
fs8.writeFileSync(indexPath, `---
|
|
8950
|
-
okf_version: "0.
|
|
8937
|
+
okf_version: "0.2"
|
|
8951
8938
|
---
|
|
8952
8939
|
# ${groupId}
|
|
8953
8940
|
`, "utf8");
|
|
@@ -8957,225 +8944,7 @@ okf_version: "0.3"
|
|
|
8957
8944
|
|
|
8958
8945
|
// src/libts/semantic/osi_converter.ts
|
|
8959
8946
|
var yaml12 = __toESM(require("yaml"));
|
|
8960
|
-
|
|
8961
|
-
// src/libts/semantic/deployment_target.ts
|
|
8962
8947
|
var GOOGLE_VENDOR2 = "GOOGLE";
|
|
8963
|
-
var BQ_GRAPH_TARGET = /^\/\/bigquery\.googleapis\.com\/projects\/([A-Za-z0-9_-]+)\/datasets\/([A-Za-z0-9_-]+)\/propertyGraphs\/([A-Za-z0-9_-]+)$/;
|
|
8964
|
-
var SPANNER_GRAPH_TARGET = /^\/\/spanner\.googleapis\.com\/projects\/([A-Za-z0-9_-]+)\/instances\/([A-Za-z0-9_-]+)\/databases\/([A-Za-z0-9_-]+)\/graphs\/([A-Za-z0-9_-]+)$/;
|
|
8965
|
-
var SPANNER_PROPERTY_GRAPH = /^(spanner\.googleapis\.com\/projects\/[A-Za-z0-9_-]+\/instances\/[A-Za-z0-9_-]+\/databases\/[A-Za-z0-9_-]+)\/propertyGraphs\/([A-Za-z0-9_-]+)$/;
|
|
8966
|
-
var ALLOYDB_TARGET = /^\/\/alloydb\.googleapis\.com\/projects\/([A-Za-z0-9_-]+)\/locations\/([A-Za-z0-9_-]+)\/clusters\/([A-Za-z0-9_-]+)\/databases\/([A-Za-z0-9_-]+)$/;
|
|
8967
|
-
var LEGACY_ALLOYDB_TARGET = /^\/\/alloydb\.googleapis\.com\/projects\/([A-Za-z0-9_-]+)\/locations\/([A-Za-z0-9_-]+)\/clusters\/([A-Za-z0-9_-]+)\/instances\/([A-Za-z0-9_-]+)\/databases\/([A-Za-z0-9_-]+)$/;
|
|
8968
|
-
var BQ_GRAPH_FORM = "bigquery.googleapis.com/projects/<p>/datasets/<d>/propertyGraphs/<g>";
|
|
8969
|
-
var SPANNER_GRAPH_FORM = "spanner.googleapis.com/projects/<p>/instances/<i>/databases/<db>/graphs/<g>";
|
|
8970
|
-
var ALLOYDB_FORM = "alloydb.googleapis.com/projects/<p>/locations/<l>/clusters/<c>/databases/<db>";
|
|
8971
|
-
var CATALOG_PREFIXES = [
|
|
8972
|
-
["bigquery:graph:", BQ_GRAPH_FORM],
|
|
8973
|
-
["bigquery:propertygraph:", BQ_GRAPH_FORM],
|
|
8974
|
-
["spanner:graph:", SPANNER_GRAPH_FORM],
|
|
8975
|
-
["alloydb:", ALLOYDB_FORM]
|
|
8976
|
-
];
|
|
8977
|
-
function parseTarget(uri) {
|
|
8978
|
-
if (uri.startsWith("//"))
|
|
8979
|
-
return;
|
|
8980
|
-
const resource = asResourceUri(uri);
|
|
8981
|
-
const bq = resource.match(BQ_GRAPH_TARGET);
|
|
8982
|
-
if (bq) {
|
|
8983
|
-
return {
|
|
8984
|
-
engine: "bigquery",
|
|
8985
|
-
coordinates: { project: bq[1], dataset: bq[2], graphName: bq[3], uri }
|
|
8986
|
-
};
|
|
8987
|
-
}
|
|
8988
|
-
const sp = resource.match(SPANNER_GRAPH_TARGET);
|
|
8989
|
-
if (sp) {
|
|
8990
|
-
return {
|
|
8991
|
-
engine: "spanner",
|
|
8992
|
-
coordinates: {
|
|
8993
|
-
project: sp[1],
|
|
8994
|
-
instance: sp[2],
|
|
8995
|
-
database: sp[3],
|
|
8996
|
-
graphName: sp[4],
|
|
8997
|
-
uri
|
|
8998
|
-
}
|
|
8999
|
-
};
|
|
9000
|
-
}
|
|
9001
|
-
const ad = resource.match(ALLOYDB_TARGET);
|
|
9002
|
-
if (ad) {
|
|
9003
|
-
return {
|
|
9004
|
-
engine: "alloydb",
|
|
9005
|
-
coordinates: {
|
|
9006
|
-
project: ad[1],
|
|
9007
|
-
location: ad[2],
|
|
9008
|
-
cluster: ad[3],
|
|
9009
|
-
database: ad[4],
|
|
9010
|
-
uri
|
|
9011
|
-
}
|
|
9012
|
-
};
|
|
9013
|
-
}
|
|
9014
|
-
return;
|
|
9015
|
-
}
|
|
9016
|
-
function clusterUri(legacy) {
|
|
9017
|
-
return `//alloydb.googleapis.com/projects/${legacy[1]}/locations/${legacy[2]}/clusters/${legacy[3]}/databases/${legacy[5]}`;
|
|
9018
|
-
}
|
|
9019
|
-
function deploymentTargetError(model, d) {
|
|
9020
|
-
return targetError(`Model '${model.name}': deployment '${d.name}' targets '${d.target}'`, d.target);
|
|
9021
|
-
}
|
|
9022
|
-
function googleBlockTargetError(model, target) {
|
|
9023
|
-
return targetError(`Model '${model.name}': the GOOGLE custom_extension's ` + `'deploymentTargets' lists '${target}'`, target);
|
|
9024
|
-
}
|
|
9025
|
-
function spannerGraphName(target) {
|
|
9026
|
-
const m = asResourceName(target).match(SPANNER_PROPERTY_GRAPH);
|
|
9027
|
-
return m ? `${m[1]}/graphs/${m[2]}` : undefined;
|
|
9028
|
-
}
|
|
9029
|
-
function targetProblem(at2, target) {
|
|
9030
|
-
return parseTarget(target) ? undefined : targetError(at2, target);
|
|
9031
|
-
}
|
|
9032
|
-
function targetError(at2, target) {
|
|
9033
|
-
const legacy = asResourceUri(target).match(LEGACY_ALLOYDB_TARGET);
|
|
9034
|
-
if (legacy) {
|
|
9035
|
-
return `${at2}, the instance-based AlloyDB name, which names no real ` + `resource. An AlloyDB database belongs to its cluster; write '${asResourceName(clusterUri(legacy))}'.`;
|
|
9036
|
-
}
|
|
9037
|
-
const name = asResourceName(target);
|
|
9038
|
-
if (name !== target && parseTarget(name)) {
|
|
9039
|
-
return `${at2}, which is ${resourceUriFix(target)}.`;
|
|
9040
|
-
}
|
|
9041
|
-
const graph = spannerGraphName(target);
|
|
9042
|
-
if (graph) {
|
|
9043
|
-
return `${at2}, which names a Spanner graph by 'propertyGraphs'; write ` + `its Dataplex name: '${graph}'.`;
|
|
9044
|
-
}
|
|
9045
|
-
const form = CATALOG_PREFIXES.find(([prefix]) => target.startsWith(prefix))?.[1];
|
|
9046
|
-
if (form) {
|
|
9047
|
-
return `${at2}, which is a Knowledge Catalog name. Write the GCP resource ` + `name instead: '${form}'.`;
|
|
9048
|
-
}
|
|
9049
|
-
return `${at2}, which is not a BigQuery graph, a Spanner graph or an ` + `AlloyDB database. Write a GCP resource name: '${BQ_GRAPH_FORM}', '${SPANNER_GRAPH_FORM}' or '${ALLOYDB_FORM}'.`;
|
|
9050
|
-
}
|
|
9051
|
-
function parseDeploymentSelection(raw) {
|
|
9052
|
-
if (raw === undefined || typeof raw === "boolean")
|
|
9053
|
-
return;
|
|
9054
|
-
const noNames = `--deployment names no deployment; give one or more ` + `deployment names, comma-separated.`;
|
|
9055
|
-
const names = [];
|
|
9056
|
-
const parts = Array.isArray(raw) ? raw : [raw];
|
|
9057
|
-
for (const part of parts) {
|
|
9058
|
-
const pieces = typeof part === "boolean" ? [] : String(part).split(",").map((p) => p.trim()).filter((p) => p);
|
|
9059
|
-
if (!pieces.length)
|
|
9060
|
-
throw new Error(noNames);
|
|
9061
|
-
for (const name of pieces) {
|
|
9062
|
-
if (!names.includes(name))
|
|
9063
|
-
names.push(name);
|
|
9064
|
-
}
|
|
9065
|
-
}
|
|
9066
|
-
if (!names.length)
|
|
9067
|
-
throw new Error(noNames);
|
|
9068
|
-
return names;
|
|
9069
|
-
}
|
|
9070
|
-
function resolveModelDeployments(model, selected) {
|
|
9071
|
-
const declared = model.deployments ?? [];
|
|
9072
|
-
let chosen = declared;
|
|
9073
|
-
if (selected !== undefined) {
|
|
9074
|
-
const byName = new Map(declared.map((d) => [d.name, d]));
|
|
9075
|
-
chosen = [];
|
|
9076
|
-
for (const name of selected) {
|
|
9077
|
-
const d = byName.get(name);
|
|
9078
|
-
if (!d) {
|
|
9079
|
-
const available = declared.length ? declared.map((x) => x.name).join(", ") : "none";
|
|
9080
|
-
return {
|
|
9081
|
-
error: `Model '${model.name}' has no deployment named '${name}' (available: ${available}).`
|
|
9082
|
-
};
|
|
9083
|
-
}
|
|
9084
|
-
chosen.push(d);
|
|
9085
|
-
}
|
|
9086
|
-
}
|
|
9087
|
-
const deployments = [];
|
|
9088
|
-
for (const d of chosen) {
|
|
9089
|
-
const parsed = parseTarget(d.target);
|
|
9090
|
-
if (!parsed)
|
|
9091
|
-
return { error: deploymentTargetError(model, d) };
|
|
9092
|
-
deployments.push({
|
|
9093
|
-
...parsed,
|
|
9094
|
-
name: d.name,
|
|
9095
|
-
profile: d.profile ?? DEFAULT_PROFILE
|
|
9096
|
-
});
|
|
9097
|
-
}
|
|
9098
|
-
return { deployments };
|
|
9099
|
-
}
|
|
9100
|
-
var targetsCache = new WeakMap;
|
|
9101
|
-
function extensionTargets(model) {
|
|
9102
|
-
return googleBlockTargets(model.customExtensions, model.name);
|
|
9103
|
-
}
|
|
9104
|
-
function googleBlockTargets(exts, modelName) {
|
|
9105
|
-
const uris = [];
|
|
9106
|
-
for (const ext of exts ?? []) {
|
|
9107
|
-
if (ext.vendorName !== GOOGLE_VENDOR2) {
|
|
9108
|
-
continue;
|
|
9109
|
-
}
|
|
9110
|
-
let data;
|
|
9111
|
-
try {
|
|
9112
|
-
data = JSON.parse(ext.data);
|
|
9113
|
-
} catch {
|
|
9114
|
-
throw new Error(`Model '${modelName}': GOOGLE custom_extension 'data' is not valid JSON.`);
|
|
9115
|
-
}
|
|
9116
|
-
const list = data?.deploymentTargets;
|
|
9117
|
-
if (!Array.isArray(list)) {
|
|
9118
|
-
continue;
|
|
9119
|
-
}
|
|
9120
|
-
for (const uri of list) {
|
|
9121
|
-
if (typeof uri !== "string") {
|
|
9122
|
-
uris.push(JSON.stringify(uri));
|
|
9123
|
-
} else if (uri.trim() !== "") {
|
|
9124
|
-
uris.push(uri.trim());
|
|
9125
|
-
}
|
|
9126
|
-
}
|
|
9127
|
-
}
|
|
9128
|
-
return uris;
|
|
9129
|
-
}
|
|
9130
|
-
function unnamedDeployments(targets) {
|
|
9131
|
-
const seen = new Set;
|
|
9132
|
-
const kept = targets.map((t) => t.trim()).filter((t) => {
|
|
9133
|
-
if (t === "" || seen.has(t))
|
|
9134
|
-
return false;
|
|
9135
|
-
seen.add(t);
|
|
9136
|
-
return true;
|
|
9137
|
-
});
|
|
9138
|
-
return kept.map((target, i) => ({
|
|
9139
|
-
name: kept.length === 1 ? "default" : `deployment_${i + 1}`,
|
|
9140
|
-
target
|
|
9141
|
-
}));
|
|
9142
|
-
}
|
|
9143
|
-
function googleDeploymentTargets(model) {
|
|
9144
|
-
const cached = targetsCache.get(model);
|
|
9145
|
-
if (cached)
|
|
9146
|
-
return cached;
|
|
9147
|
-
const uris = model.deployments !== undefined ? model.deployments.map((d) => d.target) : extensionTargets(model);
|
|
9148
|
-
const bigQuery = [];
|
|
9149
|
-
const spanner = [];
|
|
9150
|
-
const alloyDb = [];
|
|
9151
|
-
const malformed = [];
|
|
9152
|
-
for (const uri of uris) {
|
|
9153
|
-
const parsed = parseTarget(uri);
|
|
9154
|
-
if (parsed?.engine === "bigquery") {
|
|
9155
|
-
bigQuery.push(parsed.coordinates);
|
|
9156
|
-
} else if (parsed?.engine === "spanner") {
|
|
9157
|
-
spanner.push(parsed.coordinates);
|
|
9158
|
-
} else if (parsed?.engine === "alloydb") {
|
|
9159
|
-
alloyDb.push(parsed.coordinates);
|
|
9160
|
-
} else {
|
|
9161
|
-
malformed.push(uri);
|
|
9162
|
-
}
|
|
9163
|
-
}
|
|
9164
|
-
const result = { uris, bigQuery, spanner, alloyDb, malformed };
|
|
9165
|
-
targetsCache.set(model, result);
|
|
9166
|
-
return result;
|
|
9167
|
-
}
|
|
9168
|
-
function bigQueryGraphTargets(model) {
|
|
9169
|
-
const { bigQuery, malformed } = googleDeploymentTargets(model);
|
|
9170
|
-
return { targets: bigQuery, malformed };
|
|
9171
|
-
}
|
|
9172
|
-
function spannerGraphTargets(model) {
|
|
9173
|
-
const { spanner, malformed } = googleDeploymentTargets(model);
|
|
9174
|
-
return { targets: spanner, malformed };
|
|
9175
|
-
}
|
|
9176
|
-
|
|
9177
|
-
// src/libts/semantic/osi_converter.ts
|
|
9178
|
-
var GOOGLE_VENDOR3 = "GOOGLE";
|
|
9179
8948
|
var CANONICAL_DIALECT = "BIGQUERY";
|
|
9180
8949
|
var ALLOWED_DIALECT_SET = new Set(ALLOWED_DIALECTS);
|
|
9181
8950
|
function serializeModelFiles(model, opts = {}) {
|
|
@@ -9316,7 +9085,7 @@ function modelDoc(model, warnings, logical, version) {
|
|
|
9316
9085
|
target: d.target,
|
|
9317
9086
|
profile: d.profile
|
|
9318
9087
|
}));
|
|
9319
|
-
const deployments = placement.model.deployments === "native" ? nonEmpty(namedDeployments
|
|
9088
|
+
const deployments = placement.model.deployments === "native" ? nonEmpty(namedDeployments) : undefined;
|
|
9320
9089
|
const blockProfiles = placement.model.profiles === "block" ? nonEmpty(profileDocuments(model, warnings).map((p) => p.doc)) : undefined;
|
|
9321
9090
|
const blockDeployments = placement.model.deployments === "block" ? nonEmpty(namedDeployments) : undefined;
|
|
9322
9091
|
const blockPayload = compact({
|
|
@@ -9336,7 +9105,7 @@ function modelDoc(model, warnings, logical, version) {
|
|
|
9336
9105
|
metrics: nonEmpty((model.metrics ?? []).map((m) => metricDoc(m, warnings, version))),
|
|
9337
9106
|
actions: placement.model.actions === "native" ? nonEmpty((model.actions ?? []).map((a) => actionDoc(a, warnings, emittedFields))) : undefined,
|
|
9338
9107
|
constraints: placement.model.constraints === "native" ? nonEmpty((model.constraints ?? []).map((c) => constraintDoc(c))) : undefined,
|
|
9339
|
-
custom_extensions: customExtensionsDoc(model.customExtensions, `model '${model.name}'`, isGoogleVersion,
|
|
9108
|
+
custom_extensions: customExtensionsDoc(model.customExtensions, `model '${model.name}'`, isGoogleVersion, warnings, false, blockPayload)
|
|
9340
9109
|
});
|
|
9341
9110
|
}
|
|
9342
9111
|
function warnGoogleOnlyContent(model, warnings) {
|
|
@@ -9375,7 +9144,7 @@ function datasetDoc(entity, warnings, logical, version) {
|
|
|
9375
9144
|
description: entity.description,
|
|
9376
9145
|
ai_context: aiContextDoc(entity.aiContext, isGoogleVersion),
|
|
9377
9146
|
fields: nonEmpty((entity.fields ?? []).map((f) => fieldDoc(f, warnings, logical || isGoogleVersion && !!entity.abstract, isGoogleVersion))),
|
|
9378
|
-
custom_extensions: customExtensionsDoc(entity.customExtensions, `entity '${entity.name}'`, isGoogleVersion,
|
|
9147
|
+
custom_extensions: customExtensionsDoc(entity.customExtensions, `entity '${entity.name}'`, isGoogleVersion, warnings, false, blockPayload)
|
|
9379
9148
|
});
|
|
9380
9149
|
}
|
|
9381
9150
|
function datatypeDoc(type) {
|
|
@@ -9394,7 +9163,7 @@ function fieldDoc(field, warnings, logical, isGoogleVersion) {
|
|
|
9394
9163
|
dimension: dimensionDoc(field),
|
|
9395
9164
|
description: field.description,
|
|
9396
9165
|
ai_context: aiContextDoc(field.aiContext, isGoogleVersion),
|
|
9397
|
-
custom_extensions: customExtensionsDoc(field.customExtensions, `field '${field.name}'`, isGoogleVersion,
|
|
9166
|
+
custom_extensions: customExtensionsDoc(field.customExtensions, `field '${field.name}'`, isGoogleVersion, warnings, true)
|
|
9398
9167
|
});
|
|
9399
9168
|
}
|
|
9400
9169
|
function metricDoc(metric, warnings, version) {
|
|
@@ -9413,7 +9182,7 @@ function metricDoc(metric, warnings, version) {
|
|
|
9413
9182
|
datatype: datatypeDoc(metric.type),
|
|
9414
9183
|
description: metric.description,
|
|
9415
9184
|
ai_context: aiContextDoc(metric.aiContext, isGoogleVersion),
|
|
9416
|
-
custom_extensions: customExtensionsDoc(metric.customExtensions, `metric '${metric.name}'`, isGoogleVersion,
|
|
9185
|
+
custom_extensions: customExtensionsDoc(metric.customExtensions, `metric '${metric.name}'`, isGoogleVersion, warnings, false, blockPayload)
|
|
9417
9186
|
});
|
|
9418
9187
|
}
|
|
9419
9188
|
function emitted(model) {
|
|
@@ -9513,7 +9282,7 @@ function relationshipDoc(rel, warnings, version) {
|
|
|
9513
9282
|
to_columns: nonEmpty(rel.destination.columns),
|
|
9514
9283
|
description: placement.relationship.description === "native" ? description : undefined,
|
|
9515
9284
|
ai_context: aiContextDoc(rel.aiContext, isGoogleVersion),
|
|
9516
|
-
custom_extensions: customExtensionsDoc(rel.customExtensions, `relationship '${rel.name}'`, isGoogleVersion,
|
|
9285
|
+
custom_extensions: customExtensionsDoc(rel.customExtensions, `relationship '${rel.name}'`, isGoogleVersion, warnings, false, blockPayload)
|
|
9517
9286
|
});
|
|
9518
9287
|
}
|
|
9519
9288
|
function expressionDoc(item, isGoogleVersion, where, warnings) {
|
|
@@ -9579,11 +9348,7 @@ function aiContextDoc(ai, isGoogleVersion) {
|
|
|
9579
9348
|
}
|
|
9580
9349
|
return isGoogleVersion ? { ...base, custom } : { ...custom, ...base };
|
|
9581
9350
|
}
|
|
9582
|
-
function
|
|
9583
|
-
const targets = (model.customExtensions ?? []).flatMap((ext) => blockTargets(ext, model.name));
|
|
9584
|
-
return unnamedDeployments(targets);
|
|
9585
|
-
}
|
|
9586
|
-
function customExtensionsDoc(exts, where, isGoogleVersion, isModel, warnings, isField = false, blockPayload) {
|
|
9351
|
+
function customExtensionsDoc(exts, where, isGoogleVersion, warnings, isField = false, blockPayload) {
|
|
9587
9352
|
const payload = blockPayload ? { ...blockPayload } : {};
|
|
9588
9353
|
if (!exts?.length && Object.keys(payload).length === 0)
|
|
9589
9354
|
return;
|
|
@@ -9591,13 +9356,10 @@ function customExtensionsDoc(exts, where, isGoogleVersion, isModel, warnings, is
|
|
|
9591
9356
|
const kept2 = [];
|
|
9592
9357
|
let droppedGoogle2 = 0;
|
|
9593
9358
|
for (const e of exts ?? []) {
|
|
9594
|
-
if (e.vendorName !==
|
|
9359
|
+
if (e.vendorName !== GOOGLE_VENDOR2) {
|
|
9595
9360
|
kept2.push({ vendor_name: e.vendorName, data: e.data });
|
|
9596
9361
|
continue;
|
|
9597
9362
|
}
|
|
9598
|
-
if (isModel && payload.deployments !== undefined && isDeploymentTargetsBlock(e)) {
|
|
9599
|
-
continue;
|
|
9600
|
-
}
|
|
9601
9363
|
droppedGoogle2 += 1;
|
|
9602
9364
|
}
|
|
9603
9365
|
if (droppedGoogle2 > 0) {
|
|
@@ -9605,7 +9367,7 @@ function customExtensionsDoc(exts, where, isGoogleVersion, isModel, warnings, is
|
|
|
9605
9367
|
}
|
|
9606
9368
|
if (Object.keys(payload).length > 0) {
|
|
9607
9369
|
kept2.push({
|
|
9608
|
-
vendor_name:
|
|
9370
|
+
vendor_name: GOOGLE_VENDOR2,
|
|
9609
9371
|
data: JSON.stringify(payload)
|
|
9610
9372
|
});
|
|
9611
9373
|
}
|
|
@@ -9614,12 +9376,10 @@ function customExtensionsDoc(exts, where, isGoogleVersion, isModel, warnings, is
|
|
|
9614
9376
|
const kept = [];
|
|
9615
9377
|
let droppedGoogle = 0;
|
|
9616
9378
|
for (const ext of exts ?? []) {
|
|
9617
|
-
if (ext.vendorName !==
|
|
9379
|
+
if (ext.vendorName !== GOOGLE_VENDOR2) {
|
|
9618
9380
|
kept.push({ vendor_name: ext.vendorName, data: ext.data });
|
|
9619
9381
|
continue;
|
|
9620
9382
|
}
|
|
9621
|
-
if (isModel && blockTargets(ext, "").length > 0)
|
|
9622
|
-
continue;
|
|
9623
9383
|
droppedGoogle += 1;
|
|
9624
9384
|
}
|
|
9625
9385
|
if (droppedGoogle > 0) {
|
|
@@ -9627,21 +9387,6 @@ function customExtensionsDoc(exts, where, isGoogleVersion, isModel, warnings, is
|
|
|
9627
9387
|
}
|
|
9628
9388
|
return nonEmpty(kept);
|
|
9629
9389
|
}
|
|
9630
|
-
function isDeploymentTargetsBlock(e) {
|
|
9631
|
-
try {
|
|
9632
|
-
const d = JSON.parse(e.data);
|
|
9633
|
-
return !!d && typeof d === "object" && Object.hasOwn(d, "deploymentTargets");
|
|
9634
|
-
} catch {
|
|
9635
|
-
return false;
|
|
9636
|
-
}
|
|
9637
|
-
}
|
|
9638
|
-
function blockTargets(ext, modelName) {
|
|
9639
|
-
try {
|
|
9640
|
-
return googleBlockTargets([ext], modelName);
|
|
9641
|
-
} catch {
|
|
9642
|
-
return [];
|
|
9643
|
-
}
|
|
9644
|
-
}
|
|
9645
9390
|
function compact(obj) {
|
|
9646
9391
|
const out = {};
|
|
9647
9392
|
for (const [k, v] of Object.entries(obj)) {
|
|
@@ -10921,6 +10666,189 @@ function quote(s) {
|
|
|
10921
10666
|
return `"${escaped}"`;
|
|
10922
10667
|
}
|
|
10923
10668
|
|
|
10669
|
+
// src/libts/semantic/deployment_target.ts
|
|
10670
|
+
var BQ_GRAPH_TARGET = /^\/\/bigquery\.googleapis\.com\/projects\/([A-Za-z0-9_-]+)\/datasets\/([A-Za-z0-9_-]+)\/propertyGraphs\/([A-Za-z0-9_-]+)$/;
|
|
10671
|
+
var SPANNER_GRAPH_TARGET = /^\/\/spanner\.googleapis\.com\/projects\/([A-Za-z0-9_-]+)\/instances\/([A-Za-z0-9_-]+)\/databases\/([A-Za-z0-9_-]+)\/graphs\/([A-Za-z0-9_-]+)$/;
|
|
10672
|
+
var SPANNER_PROPERTY_GRAPH = /^(spanner\.googleapis\.com\/projects\/[A-Za-z0-9_-]+\/instances\/[A-Za-z0-9_-]+\/databases\/[A-Za-z0-9_-]+)\/propertyGraphs\/([A-Za-z0-9_-]+)$/;
|
|
10673
|
+
var ALLOYDB_TARGET = /^\/\/alloydb\.googleapis\.com\/projects\/([A-Za-z0-9_-]+)\/locations\/([A-Za-z0-9_-]+)\/clusters\/([A-Za-z0-9_-]+)\/databases\/([A-Za-z0-9_-]+)$/;
|
|
10674
|
+
var LEGACY_ALLOYDB_TARGET = /^\/\/alloydb\.googleapis\.com\/projects\/([A-Za-z0-9_-]+)\/locations\/([A-Za-z0-9_-]+)\/clusters\/([A-Za-z0-9_-]+)\/instances\/([A-Za-z0-9_-]+)\/databases\/([A-Za-z0-9_-]+)$/;
|
|
10675
|
+
var BQ_GRAPH_FORM = "bigquery.googleapis.com/projects/<p>/datasets/<d>/propertyGraphs/<g>";
|
|
10676
|
+
var SPANNER_GRAPH_FORM = "spanner.googleapis.com/projects/<p>/instances/<i>/databases/<db>/graphs/<g>";
|
|
10677
|
+
var ALLOYDB_FORM = "alloydb.googleapis.com/projects/<p>/locations/<l>/clusters/<c>/databases/<db>";
|
|
10678
|
+
var CATALOG_PREFIXES = [
|
|
10679
|
+
["bigquery:graph:", BQ_GRAPH_FORM],
|
|
10680
|
+
["bigquery:propertygraph:", BQ_GRAPH_FORM],
|
|
10681
|
+
["spanner:graph:", SPANNER_GRAPH_FORM],
|
|
10682
|
+
["alloydb:", ALLOYDB_FORM]
|
|
10683
|
+
];
|
|
10684
|
+
function parseTarget(uri) {
|
|
10685
|
+
if (uri.startsWith("//"))
|
|
10686
|
+
return;
|
|
10687
|
+
const resource = asResourceUri(uri);
|
|
10688
|
+
const bq = resource.match(BQ_GRAPH_TARGET);
|
|
10689
|
+
if (bq) {
|
|
10690
|
+
return {
|
|
10691
|
+
engine: "bigquery",
|
|
10692
|
+
coordinates: { project: bq[1], dataset: bq[2], graphName: bq[3], uri }
|
|
10693
|
+
};
|
|
10694
|
+
}
|
|
10695
|
+
const sp = resource.match(SPANNER_GRAPH_TARGET);
|
|
10696
|
+
if (sp) {
|
|
10697
|
+
return {
|
|
10698
|
+
engine: "spanner",
|
|
10699
|
+
coordinates: {
|
|
10700
|
+
project: sp[1],
|
|
10701
|
+
instance: sp[2],
|
|
10702
|
+
database: sp[3],
|
|
10703
|
+
graphName: sp[4],
|
|
10704
|
+
uri
|
|
10705
|
+
}
|
|
10706
|
+
};
|
|
10707
|
+
}
|
|
10708
|
+
const ad = resource.match(ALLOYDB_TARGET);
|
|
10709
|
+
if (ad) {
|
|
10710
|
+
return {
|
|
10711
|
+
engine: "alloydb",
|
|
10712
|
+
coordinates: {
|
|
10713
|
+
project: ad[1],
|
|
10714
|
+
location: ad[2],
|
|
10715
|
+
cluster: ad[3],
|
|
10716
|
+
database: ad[4],
|
|
10717
|
+
uri
|
|
10718
|
+
}
|
|
10719
|
+
};
|
|
10720
|
+
}
|
|
10721
|
+
return;
|
|
10722
|
+
}
|
|
10723
|
+
function clusterUri(legacy) {
|
|
10724
|
+
return `//alloydb.googleapis.com/projects/${legacy[1]}/locations/${legacy[2]}/clusters/${legacy[3]}/databases/${legacy[5]}`;
|
|
10725
|
+
}
|
|
10726
|
+
function deploymentTargetError(model, d) {
|
|
10727
|
+
return targetError(`Model '${model.name}': deployment '${d.name}' targets '${d.target}'`, d.target);
|
|
10728
|
+
}
|
|
10729
|
+
function spannerGraphName(target) {
|
|
10730
|
+
const m = asResourceName(target).match(SPANNER_PROPERTY_GRAPH);
|
|
10731
|
+
return m ? `${m[1]}/graphs/${m[2]}` : undefined;
|
|
10732
|
+
}
|
|
10733
|
+
function targetProblem(at2, target) {
|
|
10734
|
+
return parseTarget(target) ? undefined : targetError(at2, target);
|
|
10735
|
+
}
|
|
10736
|
+
function targetError(at2, target) {
|
|
10737
|
+
const legacy = asResourceUri(target).match(LEGACY_ALLOYDB_TARGET);
|
|
10738
|
+
if (legacy) {
|
|
10739
|
+
return `${at2}, the instance-based AlloyDB name, which names no real ` + `resource. An AlloyDB database belongs to its cluster; write '${asResourceName(clusterUri(legacy))}'.`;
|
|
10740
|
+
}
|
|
10741
|
+
const name = asResourceName(target);
|
|
10742
|
+
if (name !== target && parseTarget(name)) {
|
|
10743
|
+
return `${at2}, which is ${resourceUriFix(target)}.`;
|
|
10744
|
+
}
|
|
10745
|
+
const graph = spannerGraphName(target);
|
|
10746
|
+
if (graph) {
|
|
10747
|
+
return `${at2}, which names a Spanner graph by 'propertyGraphs'; write ` + `its Dataplex name: '${graph}'.`;
|
|
10748
|
+
}
|
|
10749
|
+
const form = CATALOG_PREFIXES.find(([prefix]) => target.startsWith(prefix))?.[1];
|
|
10750
|
+
if (form) {
|
|
10751
|
+
return `${at2}, which is a Knowledge Catalog name. Write the GCP resource ` + `name instead: '${form}'.`;
|
|
10752
|
+
}
|
|
10753
|
+
return `${at2}, which is not a BigQuery graph, a Spanner graph or an ` + `AlloyDB database. Write a GCP resource name: '${BQ_GRAPH_FORM}', '${SPANNER_GRAPH_FORM}' or '${ALLOYDB_FORM}'.`;
|
|
10754
|
+
}
|
|
10755
|
+
function parseDeploymentSelection(raw) {
|
|
10756
|
+
if (raw === undefined || typeof raw === "boolean")
|
|
10757
|
+
return;
|
|
10758
|
+
const noNames = `--deployment names no deployment; give one or more ` + `deployment names, comma-separated.`;
|
|
10759
|
+
const names = [];
|
|
10760
|
+
const parts = Array.isArray(raw) ? raw : [raw];
|
|
10761
|
+
for (const part of parts) {
|
|
10762
|
+
const pieces = typeof part === "boolean" ? [] : String(part).split(",").map((p) => p.trim()).filter((p) => p);
|
|
10763
|
+
if (!pieces.length)
|
|
10764
|
+
throw new Error(noNames);
|
|
10765
|
+
for (const name of pieces) {
|
|
10766
|
+
if (!names.includes(name))
|
|
10767
|
+
names.push(name);
|
|
10768
|
+
}
|
|
10769
|
+
}
|
|
10770
|
+
if (!names.length)
|
|
10771
|
+
throw new Error(noNames);
|
|
10772
|
+
return names;
|
|
10773
|
+
}
|
|
10774
|
+
function resolveModelDeployments(model, selected) {
|
|
10775
|
+
const declared = model.deployments ?? [];
|
|
10776
|
+
let chosen = declared;
|
|
10777
|
+
if (selected !== undefined) {
|
|
10778
|
+
const byName = new Map(declared.map((d) => [d.name, d]));
|
|
10779
|
+
chosen = [];
|
|
10780
|
+
for (const name of selected) {
|
|
10781
|
+
const d = byName.get(name);
|
|
10782
|
+
if (!d) {
|
|
10783
|
+
const available = declared.length ? declared.map((x) => x.name).join(", ") : "none";
|
|
10784
|
+
return {
|
|
10785
|
+
error: `Model '${model.name}' has no deployment named '${name}' (available: ${available}).`
|
|
10786
|
+
};
|
|
10787
|
+
}
|
|
10788
|
+
chosen.push(d);
|
|
10789
|
+
}
|
|
10790
|
+
}
|
|
10791
|
+
const deployments = [];
|
|
10792
|
+
for (const d of chosen) {
|
|
10793
|
+
const parsed = parseTarget(d.target);
|
|
10794
|
+
if (!parsed)
|
|
10795
|
+
return { error: deploymentTargetError(model, d) };
|
|
10796
|
+
deployments.push({
|
|
10797
|
+
...parsed,
|
|
10798
|
+
name: d.name,
|
|
10799
|
+
profile: d.profile ?? DEFAULT_PROFILE
|
|
10800
|
+
});
|
|
10801
|
+
}
|
|
10802
|
+
return { deployments };
|
|
10803
|
+
}
|
|
10804
|
+
var targetsCache = new WeakMap;
|
|
10805
|
+
function unnamedDeployments(targets) {
|
|
10806
|
+
const seen = new Set;
|
|
10807
|
+
const kept = targets.map((t) => t.trim()).filter((t) => {
|
|
10808
|
+
if (t === "" || seen.has(t))
|
|
10809
|
+
return false;
|
|
10810
|
+
seen.add(t);
|
|
10811
|
+
return true;
|
|
10812
|
+
});
|
|
10813
|
+
return kept.map((target, i) => ({
|
|
10814
|
+
name: kept.length === 1 ? "default" : `deployment_${i + 1}`,
|
|
10815
|
+
target
|
|
10816
|
+
}));
|
|
10817
|
+
}
|
|
10818
|
+
function googleDeploymentTargets(model) {
|
|
10819
|
+
const cached = targetsCache.get(model);
|
|
10820
|
+
if (cached)
|
|
10821
|
+
return cached;
|
|
10822
|
+
const uris = (model.deployments ?? []).map((d) => d.target);
|
|
10823
|
+
const bigQuery = [];
|
|
10824
|
+
const spanner = [];
|
|
10825
|
+
const alloyDb = [];
|
|
10826
|
+
const malformed = [];
|
|
10827
|
+
for (const uri of uris) {
|
|
10828
|
+
const parsed = parseTarget(uri);
|
|
10829
|
+
if (parsed?.engine === "bigquery") {
|
|
10830
|
+
bigQuery.push(parsed.coordinates);
|
|
10831
|
+
} else if (parsed?.engine === "spanner") {
|
|
10832
|
+
spanner.push(parsed.coordinates);
|
|
10833
|
+
} else if (parsed?.engine === "alloydb") {
|
|
10834
|
+
alloyDb.push(parsed.coordinates);
|
|
10835
|
+
} else {
|
|
10836
|
+
malformed.push(uri);
|
|
10837
|
+
}
|
|
10838
|
+
}
|
|
10839
|
+
const result = { uris, bigQuery, spanner, alloyDb, malformed };
|
|
10840
|
+
targetsCache.set(model, result);
|
|
10841
|
+
return result;
|
|
10842
|
+
}
|
|
10843
|
+
function bigQueryGraphTargets(model) {
|
|
10844
|
+
const { bigQuery, malformed } = googleDeploymentTargets(model);
|
|
10845
|
+
return { targets: bigQuery, malformed };
|
|
10846
|
+
}
|
|
10847
|
+
function spannerGraphTargets(model) {
|
|
10848
|
+
const { spanner, malformed } = googleDeploymentTargets(model);
|
|
10849
|
+
return { targets: spanner, malformed };
|
|
10850
|
+
}
|
|
10851
|
+
|
|
10924
10852
|
// src/libts/semantic/deploy_bigquery.ts
|
|
10925
10853
|
var MAX_QUERY_POLLS = 30;
|
|
10926
10854
|
var POLL_BACKOFF_MS = 1000;
|
|
@@ -11004,18 +10932,12 @@ async function deployBigQuery(models, ctx, options = {}) {
|
|
|
11004
10932
|
};
|
|
11005
10933
|
for (const { document, model } of models) {
|
|
11006
10934
|
modelsSeen++;
|
|
11007
|
-
|
|
11008
|
-
let malformed;
|
|
11009
|
-
try {
|
|
11010
|
-
({ targets, malformed } = bigQueryGraphTargets(model));
|
|
11011
|
-
} catch (err) {
|
|
11012
|
-
return fail(`Model '${model.name}' (${document}): ${err.message || err}`);
|
|
11013
|
-
}
|
|
10935
|
+
const { targets, malformed } = bigQueryGraphTargets(model);
|
|
11014
10936
|
if (!targets.length) {
|
|
11015
10937
|
if (malformed.length) {
|
|
11016
|
-
return fail(`Model '${model.name}' (${document}) declares BigQuery Graph ` + `
|
|
10938
|
+
return fail(`Model '${model.name}' (${document}) declares BigQuery Graph ` + `deployment target(s) that could not be parsed: ` + `${malformed.join(", ")}. Expected ${BQ_GRAPH_FORM}.`);
|
|
11017
10939
|
}
|
|
11018
|
-
return fail(`Model '${model.name}' (${document}) declares no BigQuery Graph ` + `
|
|
10940
|
+
return fail(`Model '${model.name}' (${document}) declares no BigQuery Graph ` + `deployment target; nothing to deploy.`);
|
|
11019
10941
|
}
|
|
11020
10942
|
for (const bad of malformed) {
|
|
11021
10943
|
warnings.push(`[${model.name}] ignoring unparseable BigQuery Graph target: ${bad}`);
|
|
@@ -11581,13 +11503,15 @@ async function provisionOne(cat, dest, type) {
|
|
|
11581
11503
|
const aspectLabel = `aspect type '${type.id}'`;
|
|
11582
11504
|
const aspect = await cat.createAspectType(home.project, home.location, type.id, type.aspectType);
|
|
11583
11505
|
if (aspect.status === 409) {
|
|
11584
|
-
const upd = await cat.updateAspectType(home.project, home.location, type.id, type.aspectType, ["description", "display_name", "metadata_template"]);
|
|
11585
|
-
const reason = upd.status !== 200 ? `${upd.message || upd.status}` : await cat.awaitOperation(upd.result,
|
|
11506
|
+
const upd = await cat.updateAspectType(home.project, home.location, type.id, type.aspectType, ["description", "display_name", "metadata_template"]).catch((err) => ({ status: 0, message: String(err?.message || err) }));
|
|
11507
|
+
const reason = upd.status !== 200 ? `${upd.message || upd.status}` : await cat.awaitOperation(upd.result, "the update operation").catch((err) => String(err?.message || err));
|
|
11586
11508
|
if (upd.status === 403) {
|
|
11587
11509
|
warnings.push(`no permission to update the existing ${aspectLabel} in project ` + `'${home.project}' (${reason}); left it unchanged`);
|
|
11588
|
-
} else if (reason) {
|
|
11510
|
+
} else if (reason && /Backwards incompatible template change/i.test(reason)) {
|
|
11589
11511
|
const resource = customAspectTypeName(type.id, dest);
|
|
11590
|
-
warnings.push(`left the existing ${aspectLabel} unchanged (${reason}). It is ` + `${resource}, and Dataplex will not patch it into the template ` + `this build states -- a template field that was removed or ` + `renumbered is a backwards-incompatible change and is refused. A ` + `push will fail wherever the two disagree. To move it forward, ` + `delete
|
|
11512
|
+
warnings.push(`left the existing ${aspectLabel} unchanged (${reason}). It is ` + `${resource}, and Dataplex will not patch it into the template ` + `this build states -- a template field that was removed or ` + `renumbered is a backwards-incompatible change and is refused. A ` + `push will fail wherever the two disagree. To move it forward, ` + `delete the entry type and then the aspect type, and re-run this ` + `command: gcloud dataplex entry-types delete ${type.id} ` + `--project=${home.project} --location=${home.location} && gcloud ` + `dataplex aspect-types delete ${type.id} --project=${home.project} ` + `--location=${home.location}. Deleting the entry type also deletes ` + `every entry of that type in the project, so push the models that ` + `had them again afterwards.`);
|
|
11513
|
+
} else if (reason) {
|
|
11514
|
+
warnings.push(`could not update the existing ${aspectLabel} in project ` + `'${home.project}' (${reason}). Run this command again in a minute ` + `to retry the update.`);
|
|
11591
11515
|
}
|
|
11592
11516
|
} else if (aspect.status !== 200) {
|
|
11593
11517
|
const refused2 = denial(aspectLabel, aspect.status, aspect.message);
|
|
@@ -12754,21 +12678,6 @@ function sleep3(ms) {
|
|
|
12754
12678
|
}
|
|
12755
12679
|
async function preflightKnowledgeCatalog(models, ctx, opts) {
|
|
12756
12680
|
const emit = emitModels(models, opts);
|
|
12757
|
-
if (emit.error) {
|
|
12758
|
-
return {
|
|
12759
|
-
result: {
|
|
12760
|
-
success: false,
|
|
12761
|
-
details: emit.error,
|
|
12762
|
-
warnings: emit.warnings,
|
|
12763
|
-
created: 0,
|
|
12764
|
-
updated: 0,
|
|
12765
|
-
deleted: 0,
|
|
12766
|
-
linked: 0,
|
|
12767
|
-
unlinked: 0,
|
|
12768
|
-
plan: []
|
|
12769
|
-
}
|
|
12770
|
-
};
|
|
12771
|
-
}
|
|
12772
12681
|
return preflightEmittedModels(emit.emitted, emit.warnings, ctx, opts);
|
|
12773
12682
|
}
|
|
12774
12683
|
async function applyKnowledgeCatalog(prepared, ctx, opts) {
|
|
@@ -12868,7 +12777,7 @@ var MAX_ASPECT_DATA_BYTES = 120 * 1024;
|
|
|
12868
12777
|
var MAX_SCHEMA_ASPECT_DATA_BYTES = 2 * 1024 * 1024;
|
|
12869
12778
|
function checkCatalogAspects(models, opts) {
|
|
12870
12779
|
const emit = emitModels(models, opts);
|
|
12871
|
-
const error = emit.
|
|
12780
|
+
const error = emit.emitted.map(emittedAspectsError).find((e) => e);
|
|
12872
12781
|
return { error, warnings: emit.warnings };
|
|
12873
12782
|
}
|
|
12874
12783
|
function emittedAspectsError(model) {
|
|
@@ -12928,26 +12837,17 @@ async function checkCustomTypes(cat, dest, typeIds) {
|
|
|
12928
12837
|
function emitModels(models, opts) {
|
|
12929
12838
|
const emitted2 = [];
|
|
12930
12839
|
const warnings = [];
|
|
12931
|
-
for (const {
|
|
12932
|
-
|
|
12933
|
-
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
overviews: opts.overviews
|
|
12943
|
-
});
|
|
12944
|
-
} catch (err) {
|
|
12945
|
-
return {
|
|
12946
|
-
emitted: emitted2,
|
|
12947
|
-
warnings,
|
|
12948
|
-
error: `Model '${model.name}' (${document}): ${err.message || err}`
|
|
12949
|
-
};
|
|
12950
|
-
}
|
|
12840
|
+
for (const { model } of models) {
|
|
12841
|
+
const resources = generateCatalogResources(model, {
|
|
12842
|
+
project: opts.project,
|
|
12843
|
+
location: opts.location,
|
|
12844
|
+
entryGroup: opts.entryGroup,
|
|
12845
|
+
systemTypeProject: opts.systemTypeProject,
|
|
12846
|
+
systemTypeLocation: opts.systemTypeLocation,
|
|
12847
|
+
emitExpressions: opts.emitExpressions,
|
|
12848
|
+
v2Aspects: opts.v2Aspects,
|
|
12849
|
+
overviews: opts.overviews
|
|
12850
|
+
});
|
|
12951
12851
|
for (const w of resources.warnings)
|
|
12952
12852
|
warnings.push(`[${model.name}] ${w}`);
|
|
12953
12853
|
emitted2.push({ model: model.name, resources });
|
|
@@ -13609,18 +13509,12 @@ async function deploySpanner(models, ctx, options = {}) {
|
|
|
13609
13509
|
const backoffMs = options.pollBackoffMs ?? POLL_BACKOFF_MS2;
|
|
13610
13510
|
for (const { document, model } of models) {
|
|
13611
13511
|
modelsSeen++;
|
|
13612
|
-
|
|
13613
|
-
let malformed;
|
|
13614
|
-
try {
|
|
13615
|
-
({ targets, malformed } = spannerGraphTargets(model));
|
|
13616
|
-
} catch (err) {
|
|
13617
|
-
return fail(`Model '${model.name}' (${document}): ${err.message || err}`);
|
|
13618
|
-
}
|
|
13512
|
+
const { targets, malformed } = spannerGraphTargets(model);
|
|
13619
13513
|
if (!targets.length) {
|
|
13620
13514
|
if (malformed.length) {
|
|
13621
|
-
return fail(`Model '${model.name}' (${document}) declares Spanner Graph ` + `
|
|
13515
|
+
return fail(`Model '${model.name}' (${document}) declares Spanner Graph ` + `deployment target(s) that could not be parsed: ` + `${malformed.join(", ")}. Expected ${SPANNER_GRAPH_FORM}.`);
|
|
13622
13516
|
}
|
|
13623
|
-
return fail(`Model '${model.name}' (${document}) declares no Spanner Graph ` + `
|
|
13517
|
+
return fail(`Model '${model.name}' (${document}) declares no Spanner Graph ` + `deployment target; nothing to deploy.`);
|
|
13624
13518
|
}
|
|
13625
13519
|
for (const bad of malformed) {
|
|
13626
13520
|
warnings.push(`[${model.name}] ignoring unparseable Spanner Graph target: ${bad}`);
|
|
@@ -13954,13 +13848,7 @@ function validatePushRequirements(models, opts = {}) {
|
|
|
13954
13848
|
const errors = [];
|
|
13955
13849
|
for (const { document, model } of models) {
|
|
13956
13850
|
errors.push(...nameAndDescriptionErrors(model, document, !!opts.v2Aspects));
|
|
13957
|
-
|
|
13958
|
-
try {
|
|
13959
|
-
deployInfo = googleDeploymentTargets(model);
|
|
13960
|
-
} catch (err) {
|
|
13961
|
-
errors.push(`${err.message || err} (${document})`);
|
|
13962
|
-
continue;
|
|
13963
|
-
}
|
|
13851
|
+
const deployInfo = googleDeploymentTargets(model);
|
|
13964
13852
|
if (deployInfo.bigQuery.length + deployInfo.spanner.length > 0) {
|
|
13965
13853
|
for (const rel of model.relationships ?? []) {
|
|
13966
13854
|
if (rel.association)
|
|
@@ -15211,11 +15099,7 @@ async function validateBigQueryDataSources(models, bq, defaultProject, graph) {
|
|
|
15211
15099
|
return errors;
|
|
15212
15100
|
}
|
|
15213
15101
|
function billingProject(model, defaultProject) {
|
|
15214
|
-
|
|
15215
|
-
return googleDeploymentTargets(model).bigQuery[0]?.project ?? defaultProject;
|
|
15216
|
-
} catch {
|
|
15217
|
-
return defaultProject;
|
|
15218
|
-
}
|
|
15102
|
+
return googleDeploymentTargets(model).bigQuery[0]?.project ?? defaultProject;
|
|
15219
15103
|
}
|
|
15220
15104
|
function probeableRef(dataSource) {
|
|
15221
15105
|
const trimmed = (dataSource ?? "").trim();
|
|
@@ -15260,12 +15144,7 @@ async function validateSpannerActionStatements(models, spanner) {
|
|
|
15260
15144
|
const statements = pendingStatements(loaded);
|
|
15261
15145
|
if (!statements.length)
|
|
15262
15146
|
continue;
|
|
15263
|
-
|
|
15264
|
-
try {
|
|
15265
|
-
target = spannerGraphTargets(loaded.model).targets[0];
|
|
15266
|
-
} catch {
|
|
15267
|
-
continue;
|
|
15268
|
-
}
|
|
15147
|
+
const target = spannerGraphTargets(loaded.model).targets[0];
|
|
15269
15148
|
if (!target)
|
|
15270
15149
|
continue;
|
|
15271
15150
|
const key = `${target.project}/${target.instance}/${target.database}`;
|
|
@@ -16652,10 +16531,9 @@ function withDialects({ fileName, content }, profile, doc) {
|
|
|
16652
16531
|
return writeDocument({ document, links, text: text3 }, root);
|
|
16653
16532
|
}
|
|
16654
16533
|
function validateDeploymentTargets(model, doc) {
|
|
16655
|
-
for (const
|
|
16656
|
-
if (targetProblem("",
|
|
16657
|
-
|
|
16658
|
-
doc.errors.push(d ? deploymentTargetError(model, d) : googleBlockTargetError(model, t));
|
|
16534
|
+
for (const d of model.deployments ?? []) {
|
|
16535
|
+
if (targetProblem("", d.target)) {
|
|
16536
|
+
doc.errors.push(deploymentTargetError(model, d));
|
|
16659
16537
|
}
|
|
16660
16538
|
}
|
|
16661
16539
|
}
|
|
@@ -16977,10 +16855,9 @@ function modelsFromCatalogResources(entries, entryLinks = [], opts = {}) {
|
|
|
16977
16855
|
if (description !== undefined)
|
|
16978
16856
|
model.description = description;
|
|
16979
16857
|
readActionsAndConstraints(model, children(actionEntries2), children(constraintEntries2), warnings);
|
|
16980
|
-
const
|
|
16981
|
-
if (
|
|
16982
|
-
model.
|
|
16983
|
-
model.deployments = targets.deployments;
|
|
16858
|
+
const deployments = readDeploymentTargets(anchor, name, warnings);
|
|
16859
|
+
if (deployments) {
|
|
16860
|
+
model.deployments = deployments;
|
|
16984
16861
|
}
|
|
16985
16862
|
const ai = readAiContext(anchor);
|
|
16986
16863
|
if (ai)
|
|
@@ -17347,15 +17224,8 @@ function readDeploymentTargets(anchor, modelName, warnings) {
|
|
|
17347
17224
|
if (problem !== undefined)
|
|
17348
17225
|
warnings.push(problem);
|
|
17349
17226
|
}
|
|
17350
|
-
const targets = deployments.map((d) => d.target);
|
|
17351
17227
|
warnings.push(`model '${modelName}': deployment names were not recovered (the ` + `catalog stores target URIs only); using ${deployments.map((d) => `'${d.name}'`).join(", ")}`);
|
|
17352
|
-
return
|
|
17353
|
-
extension: {
|
|
17354
|
-
vendorName: "GOOGLE",
|
|
17355
|
-
data: JSON.stringify({ deploymentTargets: targets })
|
|
17356
|
-
},
|
|
17357
|
-
deployments
|
|
17358
|
-
};
|
|
17228
|
+
return deployments;
|
|
17359
17229
|
}
|
|
17360
17230
|
function readRelationships(links, modelName, entityByEntryId, warnings) {
|
|
17361
17231
|
const prefix = linkNamePrefix(modelName);
|
|
@@ -17686,18 +17556,16 @@ function strayBindings(model, store) {
|
|
|
17686
17556
|
return strays;
|
|
17687
17557
|
}
|
|
17688
17558
|
function resolveStore(model, profile = DEFAULT_PROFILE) {
|
|
17689
|
-
|
|
17690
|
-
try {
|
|
17691
|
-
all = googleDeploymentTargets(model);
|
|
17692
|
-
} catch (err) {
|
|
17693
|
-
return { error: `${err?.message || err}`, named: true, rejected: true };
|
|
17694
|
-
}
|
|
17559
|
+
const all = googleDeploymentTargets(model);
|
|
17695
17560
|
const vanilla = model.version === OSSIE_VERSION;
|
|
17696
17561
|
const where = vanilla && model.deployments ? `its GOOGLE block's 'deployments'` : `'deployments'`;
|
|
17697
17562
|
if (all.malformed.length) {
|
|
17698
|
-
const unparsed = model.deployments
|
|
17699
|
-
|
|
17700
|
-
|
|
17563
|
+
const unparsed = model.deployments.find((d) => d.target === all.malformed[0]);
|
|
17564
|
+
return {
|
|
17565
|
+
error: deploymentTargetError(model, unparsed),
|
|
17566
|
+
named: true,
|
|
17567
|
+
rejected: true
|
|
17568
|
+
};
|
|
17701
17569
|
}
|
|
17702
17570
|
const used = deploymentsFor(model, profile);
|
|
17703
17571
|
if ("error" in used)
|
|
@@ -17762,9 +17630,7 @@ function profileTargets(model, profile) {
|
|
|
17762
17630
|
return "error" in used ? [] : googleDeploymentTargets(used.model).uris;
|
|
17763
17631
|
}
|
|
17764
17632
|
function deploymentNames(model, uris, profile) {
|
|
17765
|
-
const deployments = model.deployments;
|
|
17766
|
-
if (!deployments)
|
|
17767
|
-
return "";
|
|
17633
|
+
const deployments = model.deployments ?? [];
|
|
17768
17634
|
const names = uris.map((uri) => deployments.find((d) => d.target === uri)?.name ?? uri);
|
|
17769
17635
|
return ` for profile '${profile}' (${names.join(", ")})`;
|
|
17770
17636
|
}
|
|
@@ -18771,12 +18637,8 @@ function okfWorkspace() {
|
|
|
18771
18637
|
return readWorkspaceLayout("catalog.yaml") === OKF_FORMAT;
|
|
18772
18638
|
}
|
|
18773
18639
|
function hasTargetType(loaded, type) {
|
|
18774
|
-
|
|
18775
|
-
|
|
18776
|
-
return type === "bigquery" ? t.bigQuery.length > 0 : t.spanner.length > 0;
|
|
18777
|
-
} catch {
|
|
18778
|
-
return false;
|
|
18779
|
-
}
|
|
18640
|
+
const t = googleDeploymentTargets(loaded.model);
|
|
18641
|
+
return type === "bigquery" ? t.bigQuery.length > 0 : t.spanner.length > 0;
|
|
18780
18642
|
}
|
|
18781
18643
|
function pruningDialect(model) {
|
|
18782
18644
|
return hasTargetType({ model }, "spanner") ? "SPANNER" : sourcesDialect(model);
|
|
@@ -19439,10 +19301,7 @@ async function printStore(options, ctx, snapshot2) {
|
|
|
19439
19301
|
return 0;
|
|
19440
19302
|
}
|
|
19441
19303
|
function printProfileReport(model, name) {
|
|
19442
|
-
|
|
19443
|
-
try {
|
|
19444
|
-
targets = profileTargets(model, name);
|
|
19445
|
-
} catch {}
|
|
19304
|
+
const targets = profileTargets(model, name);
|
|
19446
19305
|
const { report } = pruneUnavailable(model, name, pruningDialect({ ...model, deployments: unnamedDeployments(targets) }));
|
|
19447
19306
|
console.log(` target: ${targets.length ? targets.join(", ") : "(none; no deployment names this profile)"}`);
|
|
19448
19307
|
console.log(" sources:");
|
|
@@ -20198,7 +20057,7 @@ async function startServer(basePath = ".") {
|
|
|
20198
20057
|
}
|
|
20199
20058
|
|
|
20200
20059
|
// src/tool/main.ts
|
|
20201
|
-
var BUILD_COMMIT = `+${"
|
|
20060
|
+
var BUILD_COMMIT = `+${"5d0c5b3"}`;
|
|
20202
20061
|
async function run(command) {
|
|
20203
20062
|
let exitCode = 1;
|
|
20204
20063
|
try {
|