ingestron 0.17.7 → 1.0.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/NOTICE +3 -5
- package/README.md +26 -74
- package/THIRD_PARTY_NOTICES +148 -0
- package/dist/main.js +29188 -0
- package/package.json +32 -65
- package/project-recipes/adf/connections/adls-gen2.yaml +7 -0
- package/project-recipes/adf/connections/amazon-rds-oracle.yaml +9 -0
- package/project-recipes/adf/connections/amazon-rds-sqlserver.yaml +9 -0
- package/project-recipes/adf/connections/amazon-redshift.yaml +10 -0
- package/project-recipes/adf/connections/amazon-s3.yaml +8 -0
- package/project-recipes/adf/connections/azure-blob.yaml +7 -0
- package/project-recipes/adf/connections/azure-cosmos-db-mongodb.yaml +8 -0
- package/project-recipes/adf/connections/azure-cosmos-db-nosql.yaml +8 -0
- package/project-recipes/adf/connections/azure-cosmos-postgresql.yaml +10 -0
- package/project-recipes/adf/connections/azure-data-explorer.yaml +8 -0
- package/project-recipes/adf/connections/azure-databricks-delta.yaml +9 -0
- package/project-recipes/adf/connections/azure-files.yaml +8 -0
- package/project-recipes/adf/connections/azure-mysql.yaml +7 -0
- package/project-recipes/adf/connections/azure-postgresql.yaml +10 -0
- package/project-recipes/adf/connections/azure-sql-database.yaml +9 -0
- package/project-recipes/adf/connections/azure-sql-managed-instance.yaml +9 -0
- package/project-recipes/adf/connections/azure-synapse.yaml +9 -0
- package/project-recipes/adf/connections/azure-table-storage.yaml +7 -0
- package/project-recipes/adf/connections/cassandra.yaml +9 -0
- package/project-recipes/adf/connections/dataverse.yaml +9 -0
- package/project-recipes/adf/connections/db2.yaml +7 -0
- package/project-recipes/adf/connections/dynamics-365.yaml +9 -0
- package/project-recipes/adf/connections/dynamics-ax.yaml +11 -0
- package/project-recipes/adf/connections/dynamics-crm.yaml +9 -0
- package/project-recipes/adf/connections/fabric-lakehouse.yaml +8 -0
- package/project-recipes/adf/connections/fabric-warehouse.yaml +9 -0
- package/project-recipes/adf/connections/files.yaml +9 -0
- package/project-recipes/adf/connections/ftp.yaml +9 -0
- package/project-recipes/adf/connections/google-ads.yaml +12 -0
- package/project-recipes/adf/connections/google-bigquery.yaml +8 -0
- package/project-recipes/adf/connections/google-cloud-storage.yaml +8 -0
- package/project-recipes/adf/connections/greenplum.yaml +10 -0
- package/project-recipes/adf/connections/hdfs.yaml +9 -0
- package/project-recipes/adf/connections/hive.yaml +11 -0
- package/project-recipes/adf/connections/http.yaml +7 -0
- package/project-recipes/adf/connections/hubspot.yaml +10 -0
- package/project-recipes/adf/connections/impala.yaml +11 -0
- package/project-recipes/adf/connections/informix.yaml +9 -0
- package/project-recipes/adf/connections/jira.yaml +9 -0
- package/project-recipes/adf/connections/mariadb.yaml +10 -0
- package/project-recipes/adf/connections/microsoft-365.yaml +10 -0
- package/project-recipes/adf/connections/microsoft-access.yaml +9 -0
- package/project-recipes/adf/connections/mongodb-atlas.yaml +8 -0
- package/project-recipes/adf/connections/mongodb.yaml +8 -0
- package/project-recipes/adf/connections/mysql.yaml +10 -0
- package/project-recipes/adf/connections/netezza.yaml +11 -0
- package/project-recipes/adf/connections/odata.yaml +9 -0
- package/project-recipes/adf/connections/odbc.yaml +9 -0
- package/project-recipes/adf/connections/oracle-cloud-storage.yaml +9 -0
- package/project-recipes/adf/connections/oracle.yaml +9 -0
- package/project-recipes/adf/connections/postgresql.yaml +10 -0
- package/project-recipes/adf/connections/presto.yaml +11 -0
- package/project-recipes/adf/connections/quickbooks.yaml +10 -0
- package/project-recipes/adf/connections/rest.yaml +12 -0
- package/project-recipes/adf/connections/s3-compatible.yaml +9 -0
- package/project-recipes/adf/connections/salesforce-service-cloud.yaml +10 -0
- package/project-recipes/adf/connections/salesforce.yaml +10 -0
- package/project-recipes/adf/connections/sap-bw-mdx.yaml +11 -0
- package/project-recipes/adf/connections/sap-bw-open-hub.yaml +11 -0
- package/project-recipes/adf/connections/sap-c4c.yaml +9 -0
- package/project-recipes/adf/connections/sap-ecc.yaml +9 -0
- package/project-recipes/adf/connections/sap-hana.yaml +7 -0
- package/project-recipes/adf/connections/sap-table.yaml +11 -0
- package/project-recipes/adf/connections/servicenow.yaml +9 -0
- package/project-recipes/adf/connections/sftp.yaml +10 -0
- package/project-recipes/adf/connections/sharepoint-online-list.yaml +10 -0
- package/project-recipes/adf/connections/shopify.yaml +8 -0
- package/project-recipes/adf/connections/snowflake.yaml +11 -0
- package/project-recipes/adf/connections/spark.yaml +11 -0
- package/project-recipes/adf/connections/sqlserver.yaml +9 -0
- package/project-recipes/adf/connections/square.yaml +10 -0
- package/project-recipes/adf/connections/sybase.yaml +10 -0
- package/project-recipes/adf/connections/teradata.yaml +9 -0
- package/project-recipes/adf/connections/vertica.yaml +10 -0
- package/project-recipes/adf/connections/web-table.yaml +7 -0
- package/project-recipes/adf/connections/xero.yaml +10 -0
- package/project-recipes/adf/contracts/records.yaml +12 -0
- package/project-recipes/adf/contracts/salesforce-account.yaml +12 -0
- package/project-recipes/adf/flows/adls-gen2.yaml +14 -0
- package/project-recipes/adf/flows/amazon-rds-oracle.yaml +12 -0
- package/project-recipes/adf/flows/amazon-rds-sqlserver.yaml +12 -0
- package/project-recipes/adf/flows/amazon-redshift.yaml +12 -0
- package/project-recipes/adf/flows/amazon-s3.yaml +14 -0
- package/project-recipes/adf/flows/azure-blob.yaml +14 -0
- package/project-recipes/adf/flows/azure-cosmos-db-mongodb.yaml +12 -0
- package/project-recipes/adf/flows/azure-cosmos-db-nosql.yaml +12 -0
- package/project-recipes/adf/flows/azure-cosmos-postgresql.yaml +12 -0
- package/project-recipes/adf/flows/azure-data-explorer.yaml +13 -0
- package/project-recipes/adf/flows/azure-databricks-delta.yaml +15 -0
- package/project-recipes/adf/flows/azure-files.yaml +14 -0
- package/project-recipes/adf/flows/azure-mysql.yaml +12 -0
- package/project-recipes/adf/flows/azure-postgresql.yaml +12 -0
- package/project-recipes/adf/flows/azure-sql-database.yaml +12 -0
- package/project-recipes/adf/flows/azure-sql-managed-instance.yaml +12 -0
- package/project-recipes/adf/flows/azure-synapse.yaml +12 -0
- package/project-recipes/adf/flows/azure-table-storage.yaml +12 -0
- package/project-recipes/adf/flows/cassandra.yaml +12 -0
- package/project-recipes/adf/flows/dataverse.yaml +12 -0
- package/project-recipes/adf/flows/db2.yaml +12 -0
- package/project-recipes/adf/flows/dynamics-365.yaml +12 -0
- package/project-recipes/adf/flows/dynamics-ax.yaml +12 -0
- package/project-recipes/adf/flows/dynamics-crm.yaml +12 -0
- package/project-recipes/adf/flows/fabric-lakehouse.yaml +14 -0
- package/project-recipes/adf/flows/fabric-warehouse.yaml +14 -0
- package/project-recipes/adf/flows/files.yaml +14 -0
- package/project-recipes/adf/flows/ftp.yaml +14 -0
- package/project-recipes/adf/flows/google-ads.yaml +13 -0
- package/project-recipes/adf/flows/google-bigquery.yaml +12 -0
- package/project-recipes/adf/flows/google-cloud-storage.yaml +14 -0
- package/project-recipes/adf/flows/greenplum.yaml +12 -0
- package/project-recipes/adf/flows/hdfs.yaml +14 -0
- package/project-recipes/adf/flows/hive.yaml +12 -0
- package/project-recipes/adf/flows/http.yaml +18 -0
- package/project-recipes/adf/flows/hubspot.yaml +12 -0
- package/project-recipes/adf/flows/impala.yaml +12 -0
- package/project-recipes/adf/flows/informix.yaml +13 -0
- package/project-recipes/adf/flows/jira.yaml +12 -0
- package/project-recipes/adf/flows/mariadb.yaml +13 -0
- package/project-recipes/adf/flows/microsoft-365.yaml +19 -0
- package/project-recipes/adf/flows/microsoft-access.yaml +13 -0
- package/project-recipes/adf/flows/mongodb-atlas.yaml +12 -0
- package/project-recipes/adf/flows/mongodb.yaml +12 -0
- package/project-recipes/adf/flows/mysql.yaml +12 -0
- package/project-recipes/adf/flows/netezza.yaml +13 -0
- package/project-recipes/adf/flows/odata.yaml +12 -0
- package/project-recipes/adf/flows/odbc.yaml +13 -0
- package/project-recipes/adf/flows/oracle-cloud-storage.yaml +14 -0
- package/project-recipes/adf/flows/oracle.yaml +12 -0
- package/project-recipes/adf/flows/postgresql.yaml +18 -0
- package/project-recipes/adf/flows/presto.yaml +12 -0
- package/project-recipes/adf/flows/quickbooks.yaml +12 -0
- package/project-recipes/adf/flows/rest.yaml +21 -0
- package/project-recipes/adf/flows/s3-compatible.yaml +14 -0
- package/project-recipes/adf/flows/salesforce-service-cloud.yaml +12 -0
- package/project-recipes/adf/flows/salesforce.yaml +13 -0
- package/project-recipes/adf/flows/sap-bw-mdx.yaml +14 -0
- package/project-recipes/adf/flows/sap-bw-open-hub.yaml +13 -0
- package/project-recipes/adf/flows/sap-c4c.yaml +12 -0
- package/project-recipes/adf/flows/sap-ecc.yaml +13 -0
- package/project-recipes/adf/flows/sap-hana.yaml +14 -0
- package/project-recipes/adf/flows/sap-table.yaml +13 -0
- package/project-recipes/adf/flows/servicenow.yaml +12 -0
- package/project-recipes/adf/flows/sftp.yaml +14 -0
- package/project-recipes/adf/flows/sharepoint-online-list.yaml +12 -0
- package/project-recipes/adf/flows/shopify.yaml +12 -0
- package/project-recipes/adf/flows/snowflake.yaml +15 -0
- package/project-recipes/adf/flows/spark.yaml +12 -0
- package/project-recipes/adf/flows/sqlserver.yaml +12 -0
- package/project-recipes/adf/flows/square.yaml +13 -0
- package/project-recipes/adf/flows/sybase.yaml +13 -0
- package/project-recipes/adf/flows/teradata.yaml +12 -0
- package/project-recipes/adf/flows/vertica.yaml +12 -0
- package/project-recipes/adf/flows/web-table.yaml +14 -0
- package/project-recipes/adf/flows/xero.yaml +12 -0
- package/project-recipes/adf/platform.yaml +29 -0
- package/project-recipes/adf/project.yaml +10 -0
- package/project-recipes/adf/sample.yaml +3 -0
- package/project-recipes/adf/standard.yaml +15 -0
- package/project-templates/kafka/README.md +12 -0
- package/project-templates/kafka/connections/events.yaml +8 -0
- package/project-templates/kafka/contracts/page_views.yaml +13 -0
- package/project-templates/kafka/contracts/purchases.yaml +13 -0
- package/project-templates/kafka/flows/events.yaml +10 -0
- package/project-templates/kafka/project.yaml +10 -0
- package/project-templates/kafka/standard.yaml +4 -0
- package/project-templates/kafka/template.yaml +3 -0
- package/project-templates/minimal/README.md +10 -0
- package/project-templates/minimal/connections/shop.yaml +7 -0
- package/project-templates/minimal/contracts/orders.yaml +14 -0
- package/project-templates/minimal/flows/orders.yaml +6 -0
- package/project-templates/minimal/project.yaml +11 -0
- package/project-templates/minimal/standard.yaml +4 -0
- package/project-templates/minimal/template.yaml +7 -0
- package/project-templates/private-files/README.md +29 -0
- package/project-templates/private-files/connections/share.yaml +10 -0
- package/project-templates/private-files/contracts/sales.yaml +14 -0
- package/project-templates/private-files/contracts/stock.yaml +14 -0
- package/project-templates/private-files/flows/stores.yaml +9 -0
- package/project-templates/private-files/platform.yaml +11 -0
- package/project-templates/private-files/project.yaml +19 -0
- package/project-templates/private-files/standard.yaml +11 -0
- package/project-templates/private-files/template.yaml +10 -0
- package/project-templates/private-sql-server/README.md +25 -0
- package/project-templates/private-sql-server/connections/erp.yaml +10 -0
- package/project-templates/private-sql-server/contracts/customers.yaml +14 -0
- package/project-templates/private-sql-server/contracts/invoices.yaml +15 -0
- package/project-templates/private-sql-server/flows/erp.yaml +13 -0
- package/project-templates/private-sql-server/platform.yaml +11 -0
- package/project-templates/private-sql-server/project.yaml +19 -0
- package/project-templates/private-sql-server/standard.yaml +17 -0
- package/project-templates/private-sql-server/template.yaml +10 -0
- package/project-templates/pyspark/README.md +12 -0
- package/project-templates/pyspark/connections/billing.yaml +7 -0
- package/project-templates/pyspark/contracts/invoices.yaml +16 -0
- package/project-templates/pyspark/contracts/monthly_revenue.yaml +14 -0
- package/project-templates/pyspark/flows/billing.yaml +6 -0
- package/project-templates/pyspark/project.yaml +11 -0
- package/project-templates/pyspark/standard.yaml +4 -0
- package/project-templates/pyspark/template.yaml +3 -0
- package/project-templates/pyspark/transforms/monthly_revenue.py +10 -0
- package/project-templates/pyspark/transforms/monthly_revenue.yaml +10 -0
- package/project-templates/retail/README.md +22 -0
- package/project-templates/retail/connections/shop.yaml +8 -0
- package/project-templates/retail/contracts/customers.yaml +12 -0
- package/project-templates/retail/contracts/daily_sales.yaml +19 -0
- package/project-templates/retail/contracts/orders.yaml +16 -0
- package/project-templates/retail/flows/shop.yaml +18 -0
- package/project-templates/retail/platform.yaml +21 -0
- package/project-templates/retail/project.yaml +18 -0
- package/project-templates/retail/standard.yaml +15 -0
- package/project-templates/retail/template.yaml +10 -0
- package/project-templates/retail/transforms/daily_sales.sql +7 -0
- package/project-templates/retail/transforms/daily_sales.yaml +7 -0
- package/project-templates/salesforce/README.md +6 -0
- package/project-templates/salesforce/connections/salesforce.yaml +7 -0
- package/project-templates/salesforce/contracts/accounts.yaml +13 -0
- package/project-templates/salesforce/contracts/opportunities.yaml +14 -0
- package/project-templates/salesforce/flows/salesforce.yaml +7 -0
- package/project-templates/salesforce/project.yaml +9 -0
- package/project-templates/salesforce/standard.yaml +4 -0
- package/project-templates/salesforce/template.yaml +3 -0
- package/project-templates/sql-server/README.md +17 -0
- package/project-templates/sql-server/connections/erp.yaml +8 -0
- package/project-templates/sql-server/contracts/customer_balances.yaml +13 -0
- package/project-templates/sql-server/contracts/customers.yaml +13 -0
- package/project-templates/sql-server/contracts/invoices.yaml +14 -0
- package/project-templates/sql-server/flows/erp.yaml +13 -0
- package/project-templates/sql-server/platform.yaml +6 -0
- package/project-templates/sql-server/project.yaml +13 -0
- package/project-templates/sql-server/standard.yaml +9 -0
- package/project-templates/sql-server/template.yaml +3 -0
- package/project-templates/sql-server/transforms/customer_balances.sql +5 -0
- package/project-templates/sql-server/transforms/customer_balances.yaml +6 -0
- package/schemas/NOTICE.md +7 -0
- package/schemas/connection.schema.yaml +37 -0
- package/schemas/flow.schema.yaml +124 -0
- package/schemas/odcs-v3.1.0.schema.json +2808 -0
- package/schemas/platform.schema.yaml +260 -0
- package/schemas/standard.schema.yaml +211 -0
- package/schemas/transform.schema.yaml +108 -0
- package/templates/apply-contract.py.liquid +58 -0
- package/templates/change-data.sql.liquid +20 -0
- package/templates/materialised-view.py.liquid +28 -0
- package/templates/materialised-view.sql.liquid +4 -0
- package/templates/read-files.liquid +7 -0
- package/templates/streaming-table.sql.liquid +3 -0
- package/templates/table.liquid +17 -0
- package/CHANGELOG.md +0 -148
- package/SECURITY.md +0 -32
- package/THIRD_PARTY_NOTICES.md +0 -3678
- package/build/cli/cli/index.d.ts +0 -2
- package/build/cli/cli/index.js +0 -685
- package/build/cli/cli/operation-worker.d.ts +0 -1
- package/build/cli/cli/operation-worker.js +0 -5
- package/build/cli/cli/output.d.ts +0 -3
- package/build/cli/cli/output.js +0 -226
- package/build/cli/cli/plugin-browser.d.ts +0 -14
- package/build/cli/cli/plugin-browser.js +0 -74
- package/build/cli/cli/plugin-resolution.d.ts +0 -72
- package/build/cli/cli/plugin-resolution.js +0 -216
- package/build/cli/cli/presentation.d.ts +0 -12
- package/build/cli/cli/presentation.js +0 -57
- package/build/cli/cli/workflow-commands.d.ts +0 -15
- package/build/cli/cli/workflow-commands.js +0 -415
- package/build/cli/mcp/index.d.ts +0 -3
- package/build/cli/mcp/index.js +0 -67
- package/build/cli/version.d.ts +0 -2
- package/build/cli/version.js +0 -14
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/** Keep package-network work off the presentation thread so progress reflects
|
|
2
|
-
* actual pending work. This worker uses the same JSON operations as MCP/Web. */
|
|
3
|
-
import { parentPort, workerData } from "node:worker_threads";
|
|
4
|
-
import { executePluginOperation } from "./plugin-resolution.js";
|
|
5
|
-
parentPort.postMessage(await executePluginOperation(workerData.context, workerData.operation, workerData.args));
|
package/build/cli/cli/output.js
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
/** Presentation is deliberately separate from operation results. JSON is the
|
|
2
|
-
* lossless API; terminal output is bounded, plain text and actionable. Never
|
|
3
|
-
* serialise arbitrary plugin data or resolved bindings in the default summary. */
|
|
4
|
-
import { friendlyReference } from "@ingestron/core/adapter";
|
|
5
|
-
import { stringify } from "yaml";
|
|
6
|
-
import { officialPlugins } from "./plugin-resolution.js";
|
|
7
|
-
export function exitCode(result) {
|
|
8
|
-
if (result.ok)
|
|
9
|
-
return 0;
|
|
10
|
-
const codes = result.diagnostics.map((d) => d.code);
|
|
11
|
-
if (codes.includes("CANCELLED"))
|
|
12
|
-
return 130;
|
|
13
|
-
if (codes.includes("NOT_IMPLEMENTED"))
|
|
14
|
-
return 4;
|
|
15
|
-
if (codes.some((c) => ["STALE", "OWNER", "CONFLICT"].includes(c)))
|
|
16
|
-
return 5;
|
|
17
|
-
if (codes.some((c) => [
|
|
18
|
-
"INPUT",
|
|
19
|
-
"BINDING",
|
|
20
|
-
"CAPABILITY",
|
|
21
|
-
"PACKAGE",
|
|
22
|
-
"OPTION",
|
|
23
|
-
"COMMAND",
|
|
24
|
-
"SCHEMA",
|
|
25
|
-
].includes(c)))
|
|
26
|
-
return 3;
|
|
27
|
-
return 2;
|
|
28
|
-
}
|
|
29
|
-
const clean = (value) => String(value).replace(/[\u0000-\u001f\u007f-\u009f]/g, " ");
|
|
30
|
-
// Data product ownership from ODCS contracts; absent with older core versions.
|
|
31
|
-
function dataProductLines(products, quality) {
|
|
32
|
-
if (!Array.isArray(products) || !products.length)
|
|
33
|
-
return "";
|
|
34
|
-
const summary = quality?.summary;
|
|
35
|
-
const shown = products.slice(0, 20).map((p) => {
|
|
36
|
-
const owners = Array.isArray(p.owners) ? p.owners.map(clean) : [];
|
|
37
|
-
return `\n ${clean(p.contract)} ${clean(p.status ?? "no status")} ${owners.length ? `owner ${owners.join(", ")}` : "no owner"}`;
|
|
38
|
-
});
|
|
39
|
-
const recorded = products.reduce((n, p) => n + Math.max(0, (p.qualityRules ?? 0) - (p.enforcedQualityRules ?? 0)), 0);
|
|
40
|
-
return ("\nData products:" +
|
|
41
|
-
shown.join("") +
|
|
42
|
-
(products.length > 20 ? `\n … ${products.length - 20} more` : "") +
|
|
43
|
-
(summary && summary.rules
|
|
44
|
-
? `\nQuality rules: ${summary.rules} (${summary.atLoad} at load, ${summary.afterLoad} after load, ${summary.unsupported} not enforced by the target${summary.documentation ? `, ${summary.documentation} documentation only` : ""}).`
|
|
45
|
-
: !summary && recorded
|
|
46
|
-
? `\n${recorded} quality rule(s) are recorded in contracts but not yet enforced.`
|
|
47
|
-
: ""));
|
|
48
|
-
}
|
|
49
|
-
// Quality results recorded by connector runtimes before commit; counts only.
|
|
50
|
-
function runQualityLine(flows) {
|
|
51
|
-
if (!Array.isArray(flows))
|
|
52
|
-
return "";
|
|
53
|
-
const rules = flows.flatMap((f) => Array.isArray(f?.quality) ? f.quality : []);
|
|
54
|
-
if (!rules.length)
|
|
55
|
-
return "";
|
|
56
|
-
const warned = rules.filter((r) => r.passed === false);
|
|
57
|
-
return `\nQuality rules: ${rules.length} checked before commit${warned.length
|
|
58
|
-
? `; ${warned.length} warning(s): ${warned
|
|
59
|
-
.slice(0, 5)
|
|
60
|
-
.map((r) => clean(r.id))
|
|
61
|
-
.join(", ")}${warned.length > 5 ? ", …" : ""}`
|
|
62
|
-
: ", all passed"}.`;
|
|
63
|
-
}
|
|
64
|
-
// Source routes from core (PB-064); absent with older core versions.
|
|
65
|
-
const costLabel = {
|
|
66
|
-
none: "no extra cost",
|
|
67
|
-
included: "included in platform pricing",
|
|
68
|
-
"separately-billed": "billed separately",
|
|
69
|
-
};
|
|
70
|
-
function routeLabel(route) {
|
|
71
|
-
const r = route?.reference;
|
|
72
|
-
const via = route?.route === "native"
|
|
73
|
-
? `native on ${clean(route.configuration)} via ${(route.standards ?? []).map(clean).join(", ")}`
|
|
74
|
-
: `portable ${clean(route?.package ?? "connector")} on ${clean(route?.configuration)}`;
|
|
75
|
-
if (!r)
|
|
76
|
-
return `${via} [no reference record]`;
|
|
77
|
-
const stale = Date.now() - new Date(`${r.verified}T00:00:00Z`).getTime() >
|
|
78
|
-
180 * 86_400_000;
|
|
79
|
-
return `${via} [${clean(r.maturity)}, ${costLabel[r.cost?.model] ?? clean(r.cost?.model)}${stale ? `, record checked ${clean(r.verified)}` : ""}]`;
|
|
80
|
-
}
|
|
81
|
-
function sourceLines(sources) {
|
|
82
|
-
if (!Array.isArray(sources) || !sources.length)
|
|
83
|
-
return "";
|
|
84
|
-
return ("\nSources:" +
|
|
85
|
-
sources
|
|
86
|
-
.slice(0, 20)
|
|
87
|
-
.map((s) => `\n ${clean(s.flow)}: ${clean(s.connection)} (${clean(s.kind)}) ${routeLabel(s.selected)}` +
|
|
88
|
-
(s.alternative
|
|
89
|
-
? `\n Also available: ${routeLabel(s.alternative)}`
|
|
90
|
-
: ""))
|
|
91
|
-
.join("") +
|
|
92
|
-
(sources.length > 20 ? `\n … ${sources.length - 20} more` : "") +
|
|
93
|
-
"\nUse --json for every route with documentation, licence, cost and access.");
|
|
94
|
-
}
|
|
95
|
-
function pluginLabel(reference) {
|
|
96
|
-
for (const [name, entry] of Object.entries(officialPlugins)) {
|
|
97
|
-
const prefixes = [
|
|
98
|
-
`${entry.repository}/${entry.path}@`,
|
|
99
|
-
...(name === "local" ? [`${entry.repository}@`] : []),
|
|
100
|
-
];
|
|
101
|
-
for (const prefix of prefixes)
|
|
102
|
-
if (reference.startsWith(prefix)) {
|
|
103
|
-
const version = reference.slice(prefix.length);
|
|
104
|
-
if (/^\d+\.\d+\.\d+$/.test(version))
|
|
105
|
-
return `${name}@${version}`;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return friendlyReference(reference);
|
|
109
|
-
}
|
|
110
|
-
function lines(title, items, empty) {
|
|
111
|
-
if (!items.length)
|
|
112
|
-
return empty;
|
|
113
|
-
return `${title} (${items.length})\n${items
|
|
114
|
-
.slice(0, 20)
|
|
115
|
-
.map((i) => ` ${clean(i)}`)
|
|
116
|
-
.join("\n")}${items.length > 20 ? "\n More results available with --json or --verbose." : ""}`;
|
|
117
|
-
}
|
|
118
|
-
export function terminal(result, verbose = false, args = {}) {
|
|
119
|
-
if (!result.ok)
|
|
120
|
-
return result.diagnostics
|
|
121
|
-
.map((d) => `Error: ${clean(d.message)}${verbose ? ` [${d.code}]` : ""}${d.file ? `\n File: ${clean(d.file)}${clean(d.pointer ?? "")}` : ""}${d.hint ? `\n Next: ${clean(d.hint)}` : ""}`)
|
|
122
|
-
.join("\n");
|
|
123
|
-
const value = result.result;
|
|
124
|
-
if (verbose)
|
|
125
|
-
return `${result.operation.replaceAll("_", " ")}\n${typeof value === "string" ? value : stringify(value).trimEnd()}`;
|
|
126
|
-
if (value?.apiVersion === "ingestron.change/v1")
|
|
127
|
-
return (lines("Proposed file changes", value.changes.map((c) => `${c.before === null ? "Create" : "Update"} ${c.path}`), "No file changes needed.") + "\nPreview only; no files changed.");
|
|
128
|
-
if (value?.applied)
|
|
129
|
-
return lines("Saved files", value.files, "No file changes needed.");
|
|
130
|
-
switch (result.operation) {
|
|
131
|
-
case "plugin_browse":
|
|
132
|
-
return ((value.length
|
|
133
|
-
? "Installed plugins\n\n" +
|
|
134
|
-
value
|
|
135
|
-
.map((p) => ` ${clean(p.id).padEnd(13)} ${clean(p.name)} [${clean(p.kindLabel)} · ${clean(p.availability)}]\n ${clean(p.description)}\n ${clean(p.url)}`)
|
|
136
|
-
.join("\n\n")
|
|
137
|
-
: "No installed plugins match this search.") +
|
|
138
|
-
"\n\nInstall a provider: ingestron provider install local\nInstall a connector: ingestron connector install github");
|
|
139
|
-
case "plugin_versions":
|
|
140
|
-
return (lines(`Versions for ${value.provider}`, value.versions.map((v) => `${v.reference}${v.ambiguous ? " (conflicting tags; select a commit)" : ""}`), "No stable version tags found.") +
|
|
141
|
-
"\n\n" +
|
|
142
|
-
value.evidence +
|
|
143
|
-
"\nInstall: ingestron plugin install <owner/repository>@<version>");
|
|
144
|
-
case "packages_install":
|
|
145
|
-
return `${value.cached ? "Using cached" : "Installed"} ${args.kind ?? "plugin"} ${clean(pluginLabel(args.reference ?? value.reference ?? "package"))}.\nUse --verbose for the exact reference and licence information.`;
|
|
146
|
-
case "packages_list":
|
|
147
|
-
return lines("Installed plugins", Object.keys(value.packages).map(pluginLabel), "No plugins installed.\nNext: ingestron provider install local");
|
|
148
|
-
case "source_list":
|
|
149
|
-
return lines("Sources", value.map((s) => `${s.id} ${s.type}${s.format ? "/" + s.format : ""} ${s.execution}`), "No sources configured.\nNext: ingestron source add <name> --type <type>");
|
|
150
|
-
case "source_show":
|
|
151
|
-
return `Source ${clean(value.id)}\n Type: ${clean(value.type)}${value.format ? ` (${clean(value.format)})` : ""}\n Execution: ${clean(value.selected.execution)}\n Environment: ${clean(value.selected.environment)}\n Provider: ${clean(value.selected.provider ?? "project default")}\nUse --verbose to inspect connection references.`;
|
|
152
|
-
case "contract_list":
|
|
153
|
-
return lines("Contracts", value.map((c) => `${c.id} ${c.status} ${c.path}`), "No contracts drafted.\nNext: ingestron contract draft <name> --metadata <file>");
|
|
154
|
-
case "contract_show":
|
|
155
|
-
return (`Contract ${clean(value.id)} (${clean(value.status)})\n` +
|
|
156
|
-
lines("Entities", (value.schema ?? []).map((s) => `${s.physicalName ?? s.name}: ${(s.properties ?? []).length} fields`), "No entities.") +
|
|
157
|
-
"\nUse --verbose to review the complete contract.");
|
|
158
|
-
case "contract_check":
|
|
159
|
-
return `Contract valid: ${clean(value.path)}${value.status === "draft" ? "\nStatus: draft; review business requirements before use." : ""}\n${clean(value.evidence)}`;
|
|
160
|
-
case "contract_validate":
|
|
161
|
-
return `Contract valid for native table authoring (${value.columns.length} columns).`;
|
|
162
|
-
case "inspect":
|
|
163
|
-
return lines("Flows", value.flows.map((f) => `${f.id} ${f.kind} ${f.tables.length} tables, ${f.outputs.length} outputs`), "No flows configured.\nNext: ingestron flow add <name> --contract <name> --standard <standard>");
|
|
164
|
-
case "flow_show":
|
|
165
|
-
return `Flow ${clean(value.id)}\n Kind: ${clean(value.kind)}\n Tables: ${Object.keys(value.tables ?? {})
|
|
166
|
-
.map(clean)
|
|
167
|
-
.join(", ") || "none"}\n Outputs: ${Object.keys(value.publishes ?? {})
|
|
168
|
-
.map(clean)
|
|
169
|
-
.join(", ") || "none"}\nUse --verbose to inspect configuration.`;
|
|
170
|
-
case "validate":
|
|
171
|
-
return value.mode === "draft"
|
|
172
|
-
? `Draft configuration checked (${value.flows} flows).\n${value.pending.length} unresolved inputs. Strict build readiness has not been checked.`
|
|
173
|
-
: `Project checks passed${value.nodes === undefined ? "" : ` (${value.nodes} planned nodes)`}.\nValidation is local; no platform connection was tested.` +
|
|
174
|
-
dataProductLines(value.dataProducts, value.quality) +
|
|
175
|
-
sourceLines(value.sources);
|
|
176
|
-
case "doctor":
|
|
177
|
-
return `Project ${clean(value.project)} (${clean(value.environment)})\n${value.pending.length} unresolved inputs.\n${clean(value.platformAccess)}\nNext: ${clean(value.next)}`;
|
|
178
|
-
case "runtime_prepare":
|
|
179
|
-
return (`Runtime ${clean(value.status)} for ${value.flows.map(clean).join(", ")}.` +
|
|
180
|
-
(value.result?.flows ?? [])
|
|
181
|
-
.map((f) => `\n ${clean(f.flow)}: Python ${clean(f.pythonVersion ?? "3.12")} (${f.reused ? "reused" : "prepared"})`)
|
|
182
|
-
.join("") +
|
|
183
|
-
`\nUse ingestron run status ${clean(value.id)} --verbose for environment paths and details.`);
|
|
184
|
-
case "run":
|
|
185
|
-
case "run_status":
|
|
186
|
-
return `Run ${clean(value.id)}: ${clean(value.status)} (${clean(value.action)}).\nTarget: ${clean(value.configuration)}; flows: ${value.flows.map(clean).join(", ")}.${runQualityLine(value.result?.flows)}\nUse ingestron run status ${clean(value.id)} to inspect the receipt.`;
|
|
187
|
-
case "build":
|
|
188
|
-
return `Built ${value.packages?.length ?? 1} project package(s) into ${clean(value.directory)}.\n${clean(value.evidence)}`;
|
|
189
|
-
case "generate":
|
|
190
|
-
return "Generated native assets.\nUse check --output <directory> to verify local output.";
|
|
191
|
-
case "validate_output":
|
|
192
|
-
return "Generated output checks passed.\nOwnership and syntax checked locally; no platform connection was tested.";
|
|
193
|
-
case "environments":
|
|
194
|
-
return lines("Environments", value.available.map((e) => `${e}${e === value.selected ? " (selected)" : ""}`), "No environments configured.");
|
|
195
|
-
case "tables":
|
|
196
|
-
return lines("Flow tables", value.map((f) => `${f.flow}: ${f.tables.join(", ") || "none"}`), "No tables configured.");
|
|
197
|
-
case "catalogue":
|
|
198
|
-
return lines(args.kind ?? "Capabilities", value.map((v) => `${v.id}${v.version ? "@" + v.version : ""}${v.description ? " " + v.description : ""}`), `No ${args.kind ?? "capabilities"} available.\nNext: ingestron plugin list`);
|
|
199
|
-
case "provider_commands":
|
|
200
|
-
return lines("Plugin operations", value.commands.map((c) => `${c.name} ${c.description}`), "No plugin operations available.");
|
|
201
|
-
case "plugin_command":
|
|
202
|
-
case "provider_command":
|
|
203
|
-
return "Plugin operation completed locally.\nUse --json, --verbose or --out to inspect its result.";
|
|
204
|
-
case "plan":
|
|
205
|
-
return `Local build plan ready (${value.nodes.length} nodes).\nUse --json or --verbose to inspect the plan.`;
|
|
206
|
-
case "diff":
|
|
207
|
-
return `Local differences: ${value.added.length} added, ${value.changed.length} changed, ${value.removed.length} removed.`;
|
|
208
|
-
case "config_explain":
|
|
209
|
-
return `Configuration: ${clean(value.path)} (${clean(value.environment)})\nUse --verbose to inspect declared and resolved values.`;
|
|
210
|
-
case "resolve":
|
|
211
|
-
return (`Project ${clean(value.project.id)} — resolved build configuration\n` +
|
|
212
|
-
`Providers: ${Object.keys(value.project.providers?.configurations ?? {})
|
|
213
|
-
.map(clean)
|
|
214
|
-
.join(", ") || "none"}\n` +
|
|
215
|
-
`Connections: ${Object.keys(value.project.connections ?? {})
|
|
216
|
-
.map(clean)
|
|
217
|
-
.join(", ") || "none"}\n` +
|
|
218
|
-
`Flows: ${value.flows.length}; unresolved inputs: ${value.pending.length}.\n` +
|
|
219
|
-
"Authored files: ingestron source list; ingestron contract list.\nUse --verbose for resolved configuration and input-file digests.");
|
|
220
|
-
case "read":
|
|
221
|
-
return value.content;
|
|
222
|
-
case "schema":
|
|
223
|
-
return "Schema available. Use --json for tools or --verbose to inspect it.";
|
|
224
|
-
}
|
|
225
|
-
return `${result.operation.replaceAll("_", " ")} completed.\nUse --json for structured data or --verbose for details.`;
|
|
226
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
interface Browser {
|
|
2
|
-
select(message: string, options: {
|
|
3
|
-
value: string;
|
|
4
|
-
label: string;
|
|
5
|
-
hint?: string;
|
|
6
|
-
}[]): Promise<string>;
|
|
7
|
-
search(): Promise<string>;
|
|
8
|
-
details(text: string): void;
|
|
9
|
-
}
|
|
10
|
-
/** Read-only navigation of installed plugin metadata. */
|
|
11
|
-
export declare function browsePlugins(ui: Browser, query?: string, initialKind?: string, filters?: {
|
|
12
|
-
engine?: string;
|
|
13
|
-
}, root?: string): Promise<void>;
|
|
14
|
-
export {};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { browseProviders, pluginKindLabel } from "@ingestron/core/adapter";
|
|
2
|
-
/** Read-only navigation of installed plugin metadata. */
|
|
3
|
-
export async function browsePlugins(ui, query = "", initialKind, filters = {}, root = process.cwd()) {
|
|
4
|
-
browseProviders(root, query, initialKind, filters); // Validate filters even when catalogue is empty.
|
|
5
|
-
let kind = initialKind;
|
|
6
|
-
let listing = !!query || !!kind;
|
|
7
|
-
let page = 0;
|
|
8
|
-
for (;;) {
|
|
9
|
-
if (!listing) {
|
|
10
|
-
const choice = await ui.select("Browse plugins", [
|
|
11
|
-
{ value: "all", label: "Browse all plugins" },
|
|
12
|
-
{ value: "search", label: "Search plugins" },
|
|
13
|
-
...["provider", "model-pack", "activity-pack", "report-pack"].map((value) => ({ value, label: pluginKindLabel(value) })),
|
|
14
|
-
{
|
|
15
|
-
value: "connector",
|
|
16
|
-
label: "Connectors",
|
|
17
|
-
hint: "Installed connector packages",
|
|
18
|
-
},
|
|
19
|
-
{ value: "exit", label: "Finish browsing" },
|
|
20
|
-
]);
|
|
21
|
-
if (choice === "exit")
|
|
22
|
-
return;
|
|
23
|
-
kind = ["all", "search"].includes(choice) ? undefined : choice;
|
|
24
|
-
query = choice === "search" ? await ui.search() : "";
|
|
25
|
-
listing = true;
|
|
26
|
-
page = 0;
|
|
27
|
-
}
|
|
28
|
-
const plugins = browseProviders(root, query, kind, filters);
|
|
29
|
-
const visible = plugins.slice(page * 25, (page + 1) * 25);
|
|
30
|
-
const selected = await ui.select(plugins.length
|
|
31
|
-
? `Select a plugin (${plugins.length} results, page ${page + 1})`
|
|
32
|
-
: "No plugins match; change category or search", [
|
|
33
|
-
...visible.map((p) => ({
|
|
34
|
-
value: p.reference,
|
|
35
|
-
label: `${p.name} [${p.kindLabel}]`,
|
|
36
|
-
hint: `${p.availability} · ${p.description}`,
|
|
37
|
-
})),
|
|
38
|
-
...(page > 0 ? [{ value: ":previous", label: "Previous page" }] : []),
|
|
39
|
-
...((page + 1) * 25 < plugins.length
|
|
40
|
-
? [{ value: ":next", label: "Next page" }]
|
|
41
|
-
: []),
|
|
42
|
-
{ value: ":search", label: "Search this category" },
|
|
43
|
-
{ value: ":back", label: "Change category / browse all" },
|
|
44
|
-
{ value: ":exit", label: "Finish browsing" },
|
|
45
|
-
]);
|
|
46
|
-
if (selected === ":next") {
|
|
47
|
-
page++;
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
if (selected === ":previous") {
|
|
51
|
-
page--;
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
if (selected === ":exit")
|
|
55
|
-
return;
|
|
56
|
-
if (selected === ":back") {
|
|
57
|
-
listing = false;
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
if (selected === ":search") {
|
|
61
|
-
query = await ui.search();
|
|
62
|
-
page = 0;
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const plugin = plugins.find((p) => p.reference === selected);
|
|
66
|
-
ui.details(`${plugin.name} (${plugin.id})\n${plugin.kindLabel} · ${plugin.availability}\n\n${plugin.description}\n${plugin.evidence}\n\nLicence: ${plugin.licence}\nDocumentation: ${plugin.documentation}\nSource and package documentation: ${plugin.url}\n\nExact-version licences/notices and provenance are saved to .ingestron/plugin-info/ during installation. Engine compatibility is package-specific; installed metadata is not runtime verification.`);
|
|
67
|
-
const action = await ui.select("Next step", [
|
|
68
|
-
{ value: "back", label: "Back to results" },
|
|
69
|
-
{ value: "exit", label: "Finish browsing" },
|
|
70
|
-
]);
|
|
71
|
-
if (action === "exit")
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/** Official-name convenience at the adapter boundary; core only receives exact references. */
|
|
2
|
-
import { type Context, type OperationName, type Result } from "@ingestron/core";
|
|
3
|
-
export declare const officialPlugins: {
|
|
4
|
-
readonly adf: {
|
|
5
|
-
readonly kind: "provider";
|
|
6
|
-
readonly repository: "ingestron/provider-adf";
|
|
7
|
-
readonly path: "plugin/provider.yaml";
|
|
8
|
-
readonly tagPrefix: "";
|
|
9
|
-
};
|
|
10
|
-
readonly "azure-blob": {
|
|
11
|
-
readonly kind: "connector";
|
|
12
|
-
readonly repository: "ingestron/connectors";
|
|
13
|
-
readonly path: "connectors/azure-blob/connector.yaml";
|
|
14
|
-
readonly tagPrefix: "azure-blob-";
|
|
15
|
-
};
|
|
16
|
-
readonly databricks: {
|
|
17
|
-
readonly kind: "provider";
|
|
18
|
-
readonly repository: "ingestron/provider-databricks";
|
|
19
|
-
readonly path: "plugin/provider.yaml";
|
|
20
|
-
readonly tagPrefix: "";
|
|
21
|
-
};
|
|
22
|
-
readonly files: {
|
|
23
|
-
readonly kind: "connector";
|
|
24
|
-
readonly repository: "ingestron/connectors";
|
|
25
|
-
readonly path: "connectors/files/connector.yaml";
|
|
26
|
-
readonly tagPrefix: "files-";
|
|
27
|
-
};
|
|
28
|
-
readonly github: {
|
|
29
|
-
readonly kind: "connector";
|
|
30
|
-
readonly repository: "ingestron/connectors";
|
|
31
|
-
readonly path: "connectors/github/connector.yaml";
|
|
32
|
-
readonly tagPrefix: "github-";
|
|
33
|
-
};
|
|
34
|
-
readonly local: {
|
|
35
|
-
readonly kind: "provider";
|
|
36
|
-
readonly repository: "ingestron/provider-local";
|
|
37
|
-
readonly path: "plugin/provider.yaml";
|
|
38
|
-
readonly tagPrefix: "";
|
|
39
|
-
};
|
|
40
|
-
readonly mysql: {
|
|
41
|
-
readonly kind: "connector";
|
|
42
|
-
readonly repository: "ingestron/connectors";
|
|
43
|
-
readonly path: "connectors/mysql/connector.yaml";
|
|
44
|
-
readonly tagPrefix: "mysql-";
|
|
45
|
-
};
|
|
46
|
-
readonly oracle: {
|
|
47
|
-
readonly kind: "connector";
|
|
48
|
-
readonly repository: "ingestron/connectors";
|
|
49
|
-
readonly path: "connectors/oracle/connector.yaml";
|
|
50
|
-
readonly tagPrefix: "oracle-";
|
|
51
|
-
};
|
|
52
|
-
readonly postgresql: {
|
|
53
|
-
readonly kind: "connector";
|
|
54
|
-
readonly repository: "ingestron/connectors";
|
|
55
|
-
readonly path: "connectors/postgresql/connector.yaml";
|
|
56
|
-
readonly tagPrefix: "postgresql-";
|
|
57
|
-
};
|
|
58
|
-
readonly "sql-server": {
|
|
59
|
-
readonly kind: "connector";
|
|
60
|
-
readonly repository: "ingestron/connectors";
|
|
61
|
-
readonly path: "connectors/sql-server/connector.yaml";
|
|
62
|
-
readonly tagPrefix: "sql-server-";
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
|
-
export declare function officialName(reference: string): {
|
|
66
|
-
name: keyof typeof officialPlugins;
|
|
67
|
-
version: string;
|
|
68
|
-
} | undefined;
|
|
69
|
-
export declare function catalogueReleases(value: any, name: keyof typeof officialPlugins, host?: string): string[];
|
|
70
|
-
export declare function fetchCatalogue(): Promise<unknown>;
|
|
71
|
-
export declare function resolvePluginArgs(context: Context, operation: OperationName, args: any, catalogue?: typeof fetchCatalogue): Promise<any>;
|
|
72
|
-
export declare function executePluginOperation(context: Context, operation: OperationName, args?: any): Promise<Result>;
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
/** Official-name convenience at the adapter boundary; core only receives exact references. */
|
|
2
|
-
import { executeAsync, operationSchemas, } from "@ingestron/core";
|
|
3
|
-
import { check, packageLock, Problem } from "@ingestron/core/adapter";
|
|
4
|
-
import { coreVersion } from "../version.js";
|
|
5
|
-
export const officialPlugins = {
|
|
6
|
-
adf: {
|
|
7
|
-
kind: "provider",
|
|
8
|
-
repository: "ingestron/provider-adf",
|
|
9
|
-
path: "plugin/provider.yaml",
|
|
10
|
-
tagPrefix: "",
|
|
11
|
-
},
|
|
12
|
-
"azure-blob": {
|
|
13
|
-
kind: "connector",
|
|
14
|
-
repository: "ingestron/connectors",
|
|
15
|
-
path: "connectors/azure-blob/connector.yaml",
|
|
16
|
-
tagPrefix: "azure-blob-",
|
|
17
|
-
},
|
|
18
|
-
databricks: {
|
|
19
|
-
kind: "provider",
|
|
20
|
-
repository: "ingestron/provider-databricks",
|
|
21
|
-
path: "plugin/provider.yaml",
|
|
22
|
-
tagPrefix: "",
|
|
23
|
-
},
|
|
24
|
-
files: {
|
|
25
|
-
kind: "connector",
|
|
26
|
-
repository: "ingestron/connectors",
|
|
27
|
-
path: "connectors/files/connector.yaml",
|
|
28
|
-
tagPrefix: "files-",
|
|
29
|
-
},
|
|
30
|
-
github: {
|
|
31
|
-
kind: "connector",
|
|
32
|
-
repository: "ingestron/connectors",
|
|
33
|
-
path: "connectors/github/connector.yaml",
|
|
34
|
-
tagPrefix: "github-",
|
|
35
|
-
},
|
|
36
|
-
local: {
|
|
37
|
-
kind: "provider",
|
|
38
|
-
repository: "ingestron/provider-local",
|
|
39
|
-
path: "plugin/provider.yaml",
|
|
40
|
-
tagPrefix: "",
|
|
41
|
-
},
|
|
42
|
-
mysql: {
|
|
43
|
-
kind: "connector",
|
|
44
|
-
repository: "ingestron/connectors",
|
|
45
|
-
path: "connectors/mysql/connector.yaml",
|
|
46
|
-
tagPrefix: "mysql-",
|
|
47
|
-
},
|
|
48
|
-
oracle: {
|
|
49
|
-
kind: "connector",
|
|
50
|
-
repository: "ingestron/connectors",
|
|
51
|
-
path: "connectors/oracle/connector.yaml",
|
|
52
|
-
tagPrefix: "oracle-",
|
|
53
|
-
},
|
|
54
|
-
postgresql: {
|
|
55
|
-
kind: "connector",
|
|
56
|
-
repository: "ingestron/connectors",
|
|
57
|
-
path: "connectors/postgresql/connector.yaml",
|
|
58
|
-
tagPrefix: "postgresql-",
|
|
59
|
-
},
|
|
60
|
-
"sql-server": {
|
|
61
|
-
kind: "connector",
|
|
62
|
-
repository: "ingestron/connectors",
|
|
63
|
-
path: "connectors/sql-server/connector.yaml",
|
|
64
|
-
tagPrefix: "sql-server-",
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
const catalogueUrl = "https://raw.githubusercontent.com/ingestron/connectors/main/catalogue.json";
|
|
68
|
-
const stable = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
69
|
-
const compare = (a, b) => {
|
|
70
|
-
const x = a.split(".").map(Number), y = b.split(".").map(Number);
|
|
71
|
-
return y[0] - x[0] || y[1] - x[1] || y[2] - x[2];
|
|
72
|
-
};
|
|
73
|
-
export function officialName(reference) {
|
|
74
|
-
if (reference.includes("/"))
|
|
75
|
-
return undefined;
|
|
76
|
-
const [name, version, extra] = reference.split("@");
|
|
77
|
-
check(Object.hasOwn(officialPlugins, name), "PACKAGE", `Unknown official plugin '${name}'. Use ${Object.keys(officialPlugins).join(", ")}, or an explicit owner/repository reference. Check ingestron --version and update the CLI if a documented name is missing.`);
|
|
78
|
-
check(extra === undefined &&
|
|
79
|
-
(version === undefined || version === "latest" || stable.test(version)), "PACKAGE", "Use a stable version, @latest, or omit the version for an official plugin");
|
|
80
|
-
return { name: name, version };
|
|
81
|
-
}
|
|
82
|
-
export function catalogueReleases(value, name, host = coreVersion) {
|
|
83
|
-
const identity = officialPlugins[name];
|
|
84
|
-
check(value?.apiVersion === "ingestron.catalogue/v1", "CATALOGUE", "Unsupported official catalogue format");
|
|
85
|
-
const entry = value.plugins?.[name];
|
|
86
|
-
check(entry &&
|
|
87
|
-
entry.repository === identity.repository &&
|
|
88
|
-
entry.path === identity.path &&
|
|
89
|
-
entry.tagPrefix === identity.tagPrefix &&
|
|
90
|
-
Array.isArray(entry.releases) &&
|
|
91
|
-
entry.releases.length <= 1000, "CATALOGUE", `Invalid official catalogue identity for ${name}`);
|
|
92
|
-
const seen = new Set();
|
|
93
|
-
for (const release of entry.releases) {
|
|
94
|
-
check(stable.test(release.version) &&
|
|
95
|
-
!seen.has(release.version) &&
|
|
96
|
-
Array.isArray(release.coreVersions) &&
|
|
97
|
-
release.coreVersions.length > 0 &&
|
|
98
|
-
release.coreVersions.every((v) => typeof v === "string" && stable.test(v)), "CATALOGUE", `Invalid qualified release for ${name}`);
|
|
99
|
-
seen.add(release.version);
|
|
100
|
-
}
|
|
101
|
-
return entry.releases
|
|
102
|
-
.filter((r) => r.coreVersions.includes(host))
|
|
103
|
-
.map((r) => r.version)
|
|
104
|
-
.sort(compare);
|
|
105
|
-
}
|
|
106
|
-
export async function fetchCatalogue() {
|
|
107
|
-
try {
|
|
108
|
-
const response = await fetch(catalogueUrl, {
|
|
109
|
-
signal: AbortSignal.timeout(10000),
|
|
110
|
-
redirect: "error",
|
|
111
|
-
});
|
|
112
|
-
check(response.ok && response.body, "CATALOGUE", "Official catalogue is unavailable; retry or install an explicit version");
|
|
113
|
-
const reader = response.body.getReader();
|
|
114
|
-
const chunks = [];
|
|
115
|
-
let size = 0;
|
|
116
|
-
try {
|
|
117
|
-
for (;;) {
|
|
118
|
-
const { value, done } = await reader.read();
|
|
119
|
-
if (done)
|
|
120
|
-
break;
|
|
121
|
-
size += value.length;
|
|
122
|
-
check(size <= 262144, "CATALOGUE", "Official catalogue exceeds the size limit");
|
|
123
|
-
chunks.push(value);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
finally {
|
|
127
|
-
await reader.cancel();
|
|
128
|
-
}
|
|
129
|
-
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
if (error instanceof Problem)
|
|
133
|
-
throw error;
|
|
134
|
-
throw new Problem("CATALOGUE", "Cannot read the official catalogue; retry or install an explicit version");
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
export async function resolvePluginArgs(context, operation, args, catalogue = fetchCatalogue) {
|
|
138
|
-
if (operation !== "packages_install" && operation !== "plugin_versions")
|
|
139
|
-
return args;
|
|
140
|
-
const field = operation === "packages_install" ? "reference" : "provider";
|
|
141
|
-
const alias = officialName(args[field]);
|
|
142
|
-
if (!alias)
|
|
143
|
-
return args;
|
|
144
|
-
const identity = officialPlugins[alias.name];
|
|
145
|
-
if (operation === "packages_install" && args.kind)
|
|
146
|
-
check(args.kind === identity.kind, "PACKAGE", `${alias.name} is a ${identity.kind}; use ingestron ${identity.kind} install ${alias.name}`);
|
|
147
|
-
check(args.tagPrefix === undefined || args.tagPrefix === identity.tagPrefix, "OPTION", "Official plugin tag prefixes cannot be overridden; use an explicit reference for custom tags");
|
|
148
|
-
if (operation === "plugin_versions")
|
|
149
|
-
return {
|
|
150
|
-
...args,
|
|
151
|
-
provider: identity.repository,
|
|
152
|
-
tagPrefix: identity.tagPrefix,
|
|
153
|
-
};
|
|
154
|
-
// Check permissions before catalogue network access, just as core does before install.
|
|
155
|
-
check(context.allowWrite, "PERMISSION", "Package installation requires write access");
|
|
156
|
-
check(!(args.update && args.frozen), "PACKAGE", "Frozen installation cannot update packages");
|
|
157
|
-
const base = `${identity.repository}/${identity.path}@`;
|
|
158
|
-
let version = alias.version;
|
|
159
|
-
if (version === undefined || version === "latest") {
|
|
160
|
-
const installed = Object.keys(packageLock(context.root).packages)
|
|
161
|
-
.filter((r) => r.startsWith(base) && stable.test(r.slice(base.length)))
|
|
162
|
-
.map((r) => r.slice(base.length))
|
|
163
|
-
.sort(compare);
|
|
164
|
-
if (!args.update && installed.length)
|
|
165
|
-
version = installed[0];
|
|
166
|
-
else {
|
|
167
|
-
check(!args.frozen, "PACKAGE", "Frozen installation requires an existing exact lock; install an exact version first");
|
|
168
|
-
check(context.allowNetwork, "PERMISSION", "Latest plugin resolution requires explicit package-network access");
|
|
169
|
-
check(!args.fromGit, "OPTION", "Use an exact version with --from-git; latest selects official qualified releases");
|
|
170
|
-
const versions = catalogueReleases(await catalogue(), alias.name);
|
|
171
|
-
check(versions.length, "COMPATIBILITY", `No qualified ${alias.name} release supports core ${coreVersion}; update the CLI or select an explicitly compatible version`);
|
|
172
|
-
version = [...versions, ...installed].sort(compare)[0];
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
// Even 'update' must never retarget an existing immutable version lock.
|
|
176
|
-
return {
|
|
177
|
-
...args,
|
|
178
|
-
reference: `${base}${version}`,
|
|
179
|
-
tagPrefix: identity.tagPrefix,
|
|
180
|
-
update: false,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
export async function executePluginOperation(context, operation, args = {}) {
|
|
184
|
-
try {
|
|
185
|
-
if (operation === "packages_install" || operation === "plugin_versions") {
|
|
186
|
-
const parsed = operationSchemas[operation].safeParse(args);
|
|
187
|
-
check(parsed.success, "SCHEMA", "Invalid plugin operation arguments");
|
|
188
|
-
if (operation === "packages_install")
|
|
189
|
-
check(context.allowWrite, "PERMISSION", "Package installation requires write access");
|
|
190
|
-
check(context.allowNetwork || parsed.data?.fromGit, "PERMISSION", "Package access requires explicit package-network access");
|
|
191
|
-
args = await resolvePluginArgs(context, operation, parsed.data);
|
|
192
|
-
}
|
|
193
|
-
const result = await executeAsync(context, operation, args);
|
|
194
|
-
// Keep custom manifest paths in every returned installable reference.
|
|
195
|
-
if (operation === "plugin_versions" && result.ok) {
|
|
196
|
-
const identity = Object.values(officialPlugins).find((p) => p.repository === args.provider && p.tagPrefix === args.tagPrefix);
|
|
197
|
-
if (identity)
|
|
198
|
-
result.result.versions = result.result.versions.map((v) => ({
|
|
199
|
-
...v,
|
|
200
|
-
reference: `${identity.repository}/${identity.path}@${v.version}`,
|
|
201
|
-
}));
|
|
202
|
-
}
|
|
203
|
-
return result;
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
const e = error instanceof Problem
|
|
207
|
-
? error
|
|
208
|
-
: new Problem("PACKAGE", "Plugin resolution failed; check the reference and catalogue");
|
|
209
|
-
return {
|
|
210
|
-
apiVersion: "ingestron.operation/v1",
|
|
211
|
-
operation,
|
|
212
|
-
ok: false,
|
|
213
|
-
diagnostics: [{ code: e.code, message: e.message }],
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Context, OperationName, Result } from "@ingestron/core";
|
|
2
|
-
export interface Presentation {
|
|
3
|
-
tty: boolean;
|
|
4
|
-
plain?: boolean;
|
|
5
|
-
colour?: boolean;
|
|
6
|
-
progress?: boolean;
|
|
7
|
-
json?: boolean;
|
|
8
|
-
}
|
|
9
|
-
export declare function richTerminal(options: Presentation, env?: NodeJS.ProcessEnv): boolean;
|
|
10
|
-
export declare function decorate(text: string, ok: boolean, options: Presentation): string;
|
|
11
|
-
export declare function banner(text: string, options: Presentation): string;
|
|
12
|
-
export declare function backgroundOperation(context: Context, operation: OperationName, args: unknown, label: string, options: Presentation): Promise<Result>;
|