@ingestron/core 0.12.5 → 0.12.7

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/README.md CHANGED
@@ -67,3 +67,14 @@ points are ESM; importing internal `dist/` paths is unsupported.
67
67
 
68
68
  Licensed by Otrera Limited under [Apache-2.0](LICENSE). See [NOTICE](NOTICE) and
69
69
  [third-party notices](THIRD_PARTY_NOTICES.md) for attribution and upstream terms.
70
+
71
+ ### Execution profiles
72
+
73
+ An ingestion flow may declare `executionProfiles` keyed by profile name. Each
74
+ binding specifies `provider`, a complete `ingestion` implementation, and `source`
75
+ defaults for that runtime. Tables and contracts remain shared. Source binding
76
+ defaults replace the flow defaults for the selected profile; table settings win.
77
+ Profiles cannot replace dataset schema/table identities. Select one flow with a
78
+ profile in build, validate, plan or resolve operations. Environment is independent.
79
+ The build records the selection; execution rejects a different profile. Use a
80
+ separate output directory per profile. Local evidence does not qualify a cloud target.
@@ -5,7 +5,7 @@
5
5
  "dist/assets/schemas/provenance.json": "4b5eb1fd89b81223f7946113b651d5a3a18adaa28948e43c3615dd851fb6844e",
6
6
  "dist/core/authoring.js": "84d848f46e612c241b615d3bd6868563696ca1f6504b27b76440da9bb94036fc",
7
7
  "dist/core/config.js": "b7e7138f7cc4a7b4ec8f6d0f0616c8802f2d802ec29aa09b40c1fc5c9324e016",
8
- "dist/core/connections.js": "48a06440a2d82eee36ef8a22a9343b52194e567263a5062f06fddd5def2c3c3e",
8
+ "dist/core/connections.js": "d7425d4a3d3c2f39b84ce78b80af8ccbd0c731b4e1cbada6914b1b6c31a3f1ff",
9
9
  "dist/core/connector-package.js": "de9729e9e4b0cf05bd1ef347e57ffd489245bb68efce5c313ccba72b78409f41",
10
10
  "dist/core/contracts.js": "a4af0b29ef8277a19d6e0c1d5de3059e09cdd3d45baefe9841cab1fb60985ecc",
11
11
  "dist/core/deliveries.js": "a4d2cb1213bc4c02cffb962dcb943ba98e261d37cfb21041948ec637599db080",
@@ -13,7 +13,8 @@
13
13
  "dist/core/development.js": "2b55b15d545172e527cf66868d96d97c5ca081d0a83892ffd253eadaa3cc1b39",
14
14
  "dist/core/ecosystem-authoring.js": "4320560eac2d2060e9e20be6a097759512c709a04fb7dc0520147ecd5ff6655e",
15
15
  "dist/core/errors.js": "8117e35fba84ae34627cb7d3bef46aaf6d8718c512140fa0ab08ccbdeeeec8c3",
16
- "dist/core/execution.js": "496807e7428528e31e76d51144dfd84682d435467b30a35574310af525ddeca7",
16
+ "dist/core/execution-profiles.js": "8651283b3febb79ab1bb022c56e64b783a44a69ea4b6d1f44f38acbd54756caa",
17
+ "dist/core/execution.js": "9d93281e6b3759be8b128541d1ddbc2c3c3ea8b1b5d00133603e8b711da868be",
17
18
  "dist/core/extension-packs.js": "6b2aaa83e51f40e176cc4cfed574a4a17646bb3f526666fe8e0456d2912a8045",
18
19
  "dist/core/fingerprint.js": "0edb56b544171ac20cc97fd58850eda5acefd3c725114b9d8bcc15b4971c5a36",
19
20
  "dist/core/generate.js": "7f80617867186d216d49fcd91ebefb1807d7fe22c62b3b95ae311fe5096b08e8",
@@ -21,16 +22,16 @@
21
22
  "dist/core/installed-plugins.js": "817ed411aef6f5b966a1828893081406805d2c8764d2ca20fd7e250e8a2168a8",
22
23
  "dist/core/model-pack-schema.js": "e3eb7ff33ddc652643e3f896637de0034004cd0cf26b0e296a074f830ae0b870",
23
24
  "dist/core/model-packs.js": "fee776ea0804dc66c9f140e57d94a3922d69c52d03c72079842ec43417616b0d",
24
- "dist/core/operations.js": "c3d295df7450c6f0f730bf3ab05c223361fb4015f2e4cbffac7c09a16ef0f903",
25
+ "dist/core/operations.js": "e7490a950c1d8e9b18dfd6782374a1bf088fc66143a4d92e64ce3b2d417db420",
25
26
  "dist/core/package-references.js": "bd3085eb6dcdac399d79af109d0a9e710a0532eba61e5298dc842aec9c7ef10a",
26
27
  "dist/core/packages.js": "c6bcbc90aa3597fcd4205b27136221229d9efedc9bfa68a83a134cb5e8f51d2b",
27
- "dist/core/planner.js": "974c6bac5c533a32a7c45f797ef4d857c644448aa243a929caca5917fb9f3fb8",
28
- "dist/core/project-build.js": "18ffe962068967af255e77f1dc48fa4dd9161cd50659a8a3d9ac3b161856082e",
28
+ "dist/core/planner.js": "a0963994865b68f526e150319ada3199ef3150b32f58bb096b9dc911c016bcb8",
29
+ "dist/core/project-build.js": "f8fcacb8d04f80477889ca50a9f7a285248740a30b4df14ad53c75c2a86e2606",
29
30
  "dist/core/project-packages.js": "b031dd9e3c5c147e8e1ed589b5eab21b9067acbefc1d4cd1dc5b6b7018cc39cf",
30
31
  "dist/core/provider-commands.js": "4f9b1565b3252a8c9c49a19a69b92fb6a72cc800cadc3e97812bf88c7e808466",
31
32
  "dist/core/provider-starter.js": "69795c1b79360e48664e91db0768f813fe4efc91aede003e1bf032f71731754c",
32
33
  "dist/core/report-pack-schema.js": "fe8ecdc2b8deacd8b2a1e46588ee06744a7b6d8e7342786e320f74cc848665fa",
33
- "dist/core/schema.js": "821e79cfc56dbd8c206959c53c0cda6d81507ae78010da1ec614e204c17d96eb",
34
+ "dist/core/schema.js": "b1acd3a58367e77a09c8ea5a2950068a593dca3f9e88d4ee2793cf091ef52a4f",
34
35
  "dist/core/workflows.js": "6573e1a2fd5873947bcba2809b5a4fb93e05db9a97ee5e0c294d67dae5947ff1",
35
36
  "dist/plugins/authoring.js": "ff985a7173c7aeda4a431a8603a4ab8631dc5134486578ede7d1301ebc3e6a19",
36
37
  "dist/plugins/compatibility.js": "a6591cfa4ca5a324fd29856e51319e39be470d6ed835ee268b293727ce11f8b7",
@@ -45,7 +46,7 @@
45
46
  "sources": {
46
47
  "src/core/authoring.ts": "e01136d3b54410ea0f44302bb43eefe2c2431138bee47600f0c97680785b8cab",
47
48
  "src/core/config.ts": "f282eb246438608e1951556dfeab9372daf65330a15a9d159d36d1f940370344",
48
- "src/core/connections.ts": "608dd839421b08b612fb1e6f861bd934e2443dce72543b002f23b38b7dafc5b7",
49
+ "src/core/connections.ts": "7e3e327fc460e08066986e2c22b58001a480732dca5aa7ddc73e95341f2b7472",
49
50
  "src/core/connector-package.ts": "a36151f6ffb49836547984eae871023ad1ad69a136f33cd6ad608496f84c85f8",
50
51
  "src/core/contracts.ts": "f10e2d689709665d7aea27d0c8861ae6d8b7039676d361389bc59a8f00e86aa9",
51
52
  "src/core/deliveries.ts": "6be0a7059c057420ba22a5515703164a892fac9e79a5bdb0e0871ea0b92ddd15",
@@ -53,7 +54,8 @@
53
54
  "src/core/development.ts": "decd47d8f6ca3289fea45331f27b99b0feb7188ae0a9e152c6459cc00658e7bd",
54
55
  "src/core/ecosystem-authoring.ts": "61a44100843273e74b385704195b5e36a72afb9482f910eaacdcf3abda7be38e",
55
56
  "src/core/errors.ts": "55e7ec3239bb3bcae73cf37e700cd83b9ea3336bf5514062827a3627a606977d",
56
- "src/core/execution.ts": "44ebbe7b6f64e0c3c224dd6f419939e500de92b7e4e8b283b0b33266e1d1fbf1",
57
+ "src/core/execution-profiles.ts": "0312515ae221b382256a48f96c5c475d41d94e64d0e6399584648d3385d3563d",
58
+ "src/core/execution.ts": "dd7943baa74cac9f63cb628ed8c0b705d9d952768ee8cf2823f9f426ffa414c6",
57
59
  "src/core/extension-packs.ts": "76671a6971598212c9ec0bb0ce9b75feee13dec09565fa0adc9f050a6ae668ec",
58
60
  "src/core/fingerprint.ts": "f74ebb99800a07975ec16618fb5c70d2a7d33ab3d4bb6de37c4a8ba211e9847e",
59
61
  "src/core/generate.ts": "5efadcd0957f124f44fa1af082d8850da24956e6f802de2fea43b6cd4460ecd2",
@@ -61,16 +63,16 @@
61
63
  "src/core/installed-plugins.ts": "951d15cdd8ca4a2c7d97fb01a46838822fe1b2fcf083ff8cf4bdca20d0997a2d",
62
64
  "src/core/model-pack-schema.ts": "bc9b30ab257fd25766cba63aa2fb6891c05e4b3eccf56d820caaab2dcc4147b4",
63
65
  "src/core/model-packs.ts": "a110d319f6feeff22a2d0d3a99ce5e49e56817d0cc27ab77d831d04a945ddfd3",
64
- "src/core/operations.ts": "bdb6b3dfaa5acd8367853dbe2d08013f5d68f6443afaacbaec8973f3d96424f0",
66
+ "src/core/operations.ts": "c4dbcfbd3a17bd3ddc2e6fd1d53ba9a1f3ea54e6f91ccb80c48c5b98914e3e12",
65
67
  "src/core/package-references.ts": "5c5cee7e140158928e2e5a37f426520c7c2f042546a37eed4507d79326181f5a",
66
68
  "src/core/packages.ts": "8a9b6612325de68ab2610f540bd39e4f899b06d1cc1fbd54ecfd2abb8b4e9c40",
67
- "src/core/planner.ts": "2c6f0d53e21cbb60fc2433e7da1245707133336274c60b9a5678614dabf09bca",
68
- "src/core/project-build.ts": "7fa5038e7e2ff2625a30ffae282369954a5989347c6435849b72c95f2e52e247",
69
+ "src/core/planner.ts": "e656011fad6e7374ba9e4c24510f23b67634b5bbc228180aec26961d9b8ec2e1",
70
+ "src/core/project-build.ts": "beaa788c68fa689371a832d09f0439f98ba9124c70ffab3dc36e9a75ee0c23c8",
69
71
  "src/core/project-packages.ts": "4c5cb98aeb5030db7cf2c851cd9e40ed9aae038517fba2d8d7159e884f08b7a0",
70
72
  "src/core/provider-commands.ts": "195133079085aae57208bee607af439d0ea09456d526e27ec73bfdc9d727805f",
71
73
  "src/core/provider-starter.ts": "eeb504e347638bb933d204dd4d5a7e3e94ff45db136c5edd3fb457061342e405",
72
74
  "src/core/report-pack-schema.ts": "cf2c68f3725cef847627ce61acd0887f04d0067bc324841d8a552bcb12d274b0",
73
- "src/core/schema.ts": "a99a90e51be10ed56713573df6f238e6aca5b897a9679fe7bd2a8c0ad1e7f586",
75
+ "src/core/schema.ts": "9c696ffb37bb8745043bb115ceef58216cbf116198faca00deec896ac7422187",
74
76
  "src/core/workflows.ts": "52f755e429a80e3283be030af58469158fdd19a357981b653e879d97194ec59a",
75
77
  "src/plugins/authoring.ts": "a0d68d406b4569c0b48eec458407d24c3d4eeed5b7918c6c4fcb3828ada93fe5",
76
78
  "src/plugins/compatibility.ts": "b5d357a1dc2a972cf8209311602f9fd816ba0a59cbe747f86f1b5567754073ea",
@@ -1,4 +1,4 @@
1
- export declare function prepareConnection(root: string, environment: string, flowId: string, validateOnly?: boolean, reviewFile?: string, configureExecution?: (execution: Record<string, any>) => Record<string, any>): {
1
+ export declare function prepareConnection(root: string, environment: string, flowId: string, validateOnly?: boolean, reviewFile?: string, configureExecution?: (execution: Record<string, any>) => Record<string, any>, executionProfile?: string): {
2
2
  project: string;
3
3
  environment: string;
4
4
  configuration: string;
@@ -6,6 +6,7 @@ import { resolveModelContracts } from "./model-packs.js";
6
6
  /** Project-owned configuration; schemas and runtime assets remain plugin-owned. */
7
7
  import { Ajv2020 } from "ajv/dist/2020.js";
8
8
  import { Configuration } from "./config.js";
9
+ import { bindExecutionProfile } from "./execution-profiles.js";
9
10
  import { projectSchema, flowSchema } from "./schema.js";
10
11
  import { projectPackages } from "./project-packages.js";
11
12
  import { canonical, check, digest, isMap } from "./errors.js";
@@ -18,14 +19,17 @@ function validate(schema, value, label) {
18
19
  const fn = ajv.compile(schema);
19
20
  check(fn(value), "CONNECTION", `${label}: ${ajv.errorsText(fn.errors)}`);
20
21
  }
21
- export function prepareConnection(root, environment, flowId, validateOnly = false, reviewFile, configureExecution) {
22
+ export function prepareConnection(root, environment, flowId, validateOnly = false, reviewFile, configureExecution, executionProfile) {
22
23
  // Do not interpolate $env here: connection credentials must never enter compiler memory/output.
23
24
  const reader = new Configuration(root, {});
24
25
  const project = reader.parse(projectSchema, reader.load());
25
26
  const profile = project.environments[environment];
26
27
  check(profile, "ENVIRONMENT", `Unknown environment ${environment}`);
27
28
  check(!profile.environment || profile.environment === environment, "ENVIRONMENT", "Environment name differs from selected profile");
28
- const flows = project.flows.map((f) => reader.parse(flowSchema, f));
29
+ const flows = project.flows.map((f) => {
30
+ const flow = reader.parse(flowSchema, f);
31
+ return bindExecutionProfile(flow, flow.id === flowId ? executionProfile : undefined);
32
+ });
29
33
  resolveModelContracts(reader, project, flows);
30
34
  check(new Set(flows.map((f) => f.id)).size === flows.length, "FLOW", "Duplicate flow IDs");
31
35
  const flow = flows.find((f) => f.id === flowId);
@@ -90,14 +94,15 @@ export function prepareConnection(root, environment, flowId, validateOnly = fals
90
94
  check(flow.tables && Object.keys(flow.tables).length > 0, "CONNECTION", "Select at least one table with an ODCS contract");
91
95
  const streams = new Set();
92
96
  const tables = Object.fromEntries(Object.entries(flow.tables).map(([name, table]) => {
97
+ const tableSource = { ...flow.defaults.source, ...table.source };
93
98
  const source = descriptor.tableSourceSchema
94
- ? { ...table.source, stream: name }
95
- : table.source;
99
+ ? { ...tableSource, stream: name }
100
+ : tableSource;
96
101
  if (descriptor.tableSourceSchema)
97
- validate(descriptor.tableSourceSchema, table.source, `${name} source`);
102
+ validate(descriptor.tableSourceSchema, tableSource, `${name} source`);
98
103
  else
99
- check(Object.keys(table.source).length === 1 &&
100
- typeof table.source.stream === "string", "CONNECTION", `${name}: source must identify one connector stream`);
104
+ check(Object.keys(tableSource).length === 1 &&
105
+ typeof tableSource.stream === "string", "CONNECTION", `${name}: source must identify one connector stream`);
101
106
  check(typeof source.stream === "string", "CONNECTION", `${name}: invalid source stream`);
102
107
  check(!streams.has(source.stream), "CONNECTION", "Duplicate source stream");
103
108
  streams.add(source.stream);
@@ -0,0 +1,2 @@
1
+ import type { Flow } from "./schema.js";
2
+ export declare function bindExecutionProfile(flow: Flow, profile?: string): Flow;
@@ -0,0 +1,17 @@
1
+ /** Execution bindings never duplicate or replace dataset identities/contracts. */
2
+ import { check } from "./errors.js";
3
+ export function bindExecutionProfile(flow, profile) {
4
+ if (!profile)
5
+ return flow;
6
+ const binding = flow.executionProfiles[profile];
7
+ check(binding, "PROFILE", `${flow.id}: unknown execution profile ${profile}`);
8
+ check(flow.kind === "ingestion" && !flow.steps, "PROFILE", "Execution profiles currently support ingestion flows only");
9
+ check(!Object.hasOwn(binding.source, "schema") &&
10
+ !Object.hasOwn(binding.source, "table"), "PROFILE", "Execution source bindings cannot replace dataset schema or table identity");
11
+ return {
12
+ ...flow,
13
+ provider: binding.provider,
14
+ ingestion: binding.ingestion,
15
+ defaults: { ...flow.defaults, source: binding.source },
16
+ };
17
+ }
@@ -3,12 +3,14 @@ import type { Context } from "./operations.js";
3
3
  export declare const executionSchemas: {
4
4
  runtime_prepare: z.ZodObject<{
5
5
  from: z.ZodOptional<z.ZodString>;
6
+ profile: z.ZodOptional<z.ZodString>;
6
7
  provider: z.ZodOptional<z.ZodString>;
7
8
  flow: z.ZodOptional<z.ZodString>;
8
9
  python: z.ZodOptional<z.ZodString>;
9
10
  }, z.core.$strict>;
10
11
  run: z.ZodObject<{
11
12
  from: z.ZodOptional<z.ZodString>;
13
+ profile: z.ZodOptional<z.ZodString>;
12
14
  provider: z.ZodOptional<z.ZodString>;
13
15
  flow: z.ZodOptional<z.ZodString>;
14
16
  action: z.ZodDefault<z.ZodEnum<{
@@ -12,6 +12,7 @@ import { checkProviderCompatibility } from "../plugins/compatibility.js";
12
12
  const id = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,99}$/);
13
13
  const selection = {
14
14
  from: z.string().optional(),
15
+ profile: id.optional(),
15
16
  provider: id.optional(),
16
17
  flow: id.optional(),
17
18
  };
@@ -150,6 +151,7 @@ export async function performExecution(context, operation, args) {
150
151
  const build = JSON.parse(readFileSync(resolve(directory, "ingestron-project.json"), "utf8"));
151
152
  check(build.apiVersion === "ingestron.project-build/v1" &&
152
153
  build.environment === environment, "BUILD", "Build environment differs; rebuild for this environment");
154
+ check((args.profile ?? "") === (build.selection?.profile ?? ""), "PROFILE", "Build execution profile differs; select the matching profile and build directory");
153
155
  for (const [file, hash] of Object.entries(build.sourceFiles ?? {}))
154
156
  check(existsSync(fence(root, file)) &&
155
157
  digest(readFileSync(fence(root, file))) === hash, "STALE", `Project input changed: ${file}; rebuild before execution`);
@@ -210,6 +212,7 @@ export async function performExecution(context, operation, args) {
210
212
  status: "running",
211
213
  pid: process.pid,
212
214
  environment,
215
+ profile: args.profile,
213
216
  project: build.project,
214
217
  provider: pkg.reference,
215
218
  providerCommit: pkg.commit,
@@ -158,6 +158,7 @@ export declare const operationSchemas: {
158
158
  provider: z.ZodOptional<z.ZodString>;
159
159
  delivery: z.ZodDefault<z.ZodBoolean>;
160
160
  flow: z.ZodOptional<z.ZodString>;
161
+ profile: z.ZodOptional<z.ZodString>;
161
162
  table: z.ZodOptional<z.ZodString>;
162
163
  step: z.ZodOptional<z.ZodString>;
163
164
  out: z.ZodDefault<z.ZodString>;
@@ -202,12 +203,17 @@ export declare const operationSchemas: {
202
203
  strict: "strict";
203
204
  }>>;
204
205
  flow: z.ZodOptional<z.ZodString>;
206
+ profile: z.ZodOptional<z.ZodString>;
205
207
  table: z.ZodOptional<z.ZodString>;
206
208
  step: z.ZodOptional<z.ZodString>;
207
209
  }, z.core.$strict>;
208
- readonly resolve: z.ZodObject<{}, z.core.$strict>;
210
+ readonly resolve: z.ZodObject<{
211
+ flow: z.ZodOptional<z.ZodString>;
212
+ profile: z.ZodOptional<z.ZodString>;
213
+ }, z.core.$strict>;
209
214
  readonly plan: z.ZodObject<{
210
215
  flow: z.ZodOptional<z.ZodString>;
216
+ profile: z.ZodOptional<z.ZodString>;
211
217
  table: z.ZodOptional<z.ZodString>;
212
218
  step: z.ZodOptional<z.ZodString>;
213
219
  }, z.core.$strict>;
@@ -343,12 +349,14 @@ export declare const operationSchemas: {
343
349
  readonly doctor: z.ZodObject<{}, z.core.$strict>;
344
350
  readonly runtime_prepare: z.ZodObject<{
345
351
  from: z.ZodOptional<z.ZodString>;
352
+ profile: z.ZodOptional<z.ZodString>;
346
353
  provider: z.ZodOptional<z.ZodString>;
347
354
  flow: z.ZodOptional<z.ZodString>;
348
355
  python: z.ZodOptional<z.ZodString>;
349
356
  }, z.core.$strict>;
350
357
  readonly run: z.ZodObject<{
351
358
  from: z.ZodOptional<z.ZodString>;
359
+ profile: z.ZodOptional<z.ZodString>;
352
360
  provider: z.ZodOptional<z.ZodString>;
353
361
  flow: z.ZodOptional<z.ZodString>;
354
362
  action: z.ZodDefault<z.ZodEnum<{
@@ -184,6 +184,7 @@ export const operationSchemas = {
184
184
  provider: z.string().optional(),
185
185
  delivery: z.boolean().default(false),
186
186
  flow: z.string().optional(),
187
+ profile: workflows.identifier.optional(),
187
188
  table: z.string().optional(),
188
189
  step: z.string().optional(),
189
190
  out: z.string().default("build/generated"),
@@ -217,14 +218,21 @@ export const operationSchemas = {
217
218
  .object({
218
219
  mode: z.enum(["draft", "strict"]).default("strict"),
219
220
  flow: z.string().optional(),
221
+ profile: workflows.identifier.optional(),
220
222
  table: z.string().optional(),
221
223
  step: z.string().optional(),
222
224
  })
223
225
  .strict(),
224
- resolve: z.object({}).strict(),
226
+ resolve: z
227
+ .object({
228
+ flow: workflows.identifier.optional(),
229
+ profile: workflows.identifier.optional(),
230
+ })
231
+ .strict(),
225
232
  plan: z
226
233
  .object({
227
234
  flow: z.string().optional(),
235
+ profile: workflows.identifier.optional(),
228
236
  table: z.string().optional(),
229
237
  step: z.string().optional(),
230
238
  })
@@ -597,8 +605,11 @@ export function execute(context, operation, request = {}) {
597
605
  break;
598
606
  case "validate": {
599
607
  if (args.mode === "draft") {
600
- check(!args.flow && !args.table && !args.step, "OPTION", "Draft validation checks the whole project; use strict mode for flow/table/step selection");
601
- const state = inspectProject(root, environment, { draft: true });
608
+ check(!args.flow && !args.table && !args.step && !args.profile, "OPTION", "Draft validation checks the whole project; use strict mode for flow/table/step selection");
609
+ const state = inspectProject(root, environment, {
610
+ ...args,
611
+ draft: true,
612
+ });
602
613
  result = {
603
614
  mode: "draft",
604
615
  pending: state.reader.pending,
@@ -606,15 +617,21 @@ export function execute(context, operation, request = {}) {
606
617
  };
607
618
  }
608
619
  else {
609
- const state = inspectProject(root, environment, { draft: true });
620
+ const state = inspectProject(root, environment, {
621
+ ...args,
622
+ draft: true,
623
+ });
610
624
  const selected = state.flows.filter((f) => !args.flow || f.id === args.flow);
611
625
  check(selected.length > 0, "FLOW", "Unknown flow");
612
626
  const connected = selected.filter((f) => f.ingestion?.connection);
613
627
  if (connected.length) {
614
628
  check(!args.table && !args.step, "CONNECTION", "Validate connector flows as a whole");
615
- const checks = connected.map((f) => prepareConnection(root, environment, f.id, true));
616
- for (const flow of selected.filter((f) => !f.ingestion?.connection))
617
- planProject(root, environment, { ...args, flow: flow.id });
629
+ const checks = connected.map((f) => prepareConnection(root, environment, f.id, true, undefined, undefined, args.profile));
630
+ // Validate native flows as one complete target. Selecting each flow
631
+ // separately makes providers that own shared resources reject an
632
+ // otherwise valid full project as an unsafe partial deployment.
633
+ if (selected.some((f) => !f.ingestion?.connection))
634
+ planProject(root, environment, { ...args, nativeOnly: true });
618
635
  result = {
619
636
  mode: "strict",
620
637
  evidence: "offline",
@@ -633,7 +650,10 @@ export function execute(context, operation, request = {}) {
633
650
  break;
634
651
  }
635
652
  case "resolve": {
636
- const state = inspectProject(root, environment, { draft: true });
653
+ const state = inspectProject(root, environment, {
654
+ ...args,
655
+ draft: true,
656
+ });
637
657
  result = {
638
658
  project: state.project,
639
659
  flows: state.flows,
@@ -1,6 +1,7 @@
1
1
  import { Configuration } from "./config.js";
2
2
  import { type Plan } from "./schema.js";
3
3
  export interface Select {
4
+ profile?: string;
4
5
  nativeOnly?: boolean;
5
6
  flowIds?: string[];
6
7
  projectBuild?: boolean;
@@ -73,6 +74,11 @@ export declare function inspectProject(root: string, environment?: string, optio
73
74
  export?: string | undefined;
74
75
  product?: string | undefined;
75
76
  provider?: string | undefined;
77
+ executionProfiles: Record<string, {
78
+ provider: string;
79
+ ingestion: Record<string, unknown>;
80
+ source: Record<string, unknown>;
81
+ }>;
76
82
  defaults: {
77
83
  source: Record<string, unknown>;
78
84
  with: Record<string, unknown>;
@@ -1,3 +1,4 @@
1
+ import { bindExecutionProfile } from "./execution-profiles.js";
1
2
  import { resolveModelContracts } from "./model-packs.js";
2
3
  import { extensionActivities } from "./extension-packs.js";
3
4
  import { expandProvider } from "../plugins/provider-renderer.js";
@@ -40,6 +41,7 @@ const auditSecrets = (value, path) => {
40
41
  }
41
42
  };
42
43
  export function inspectProject(root, environment = "dev", options = {}) {
44
+ check(!options.profile || options.flow, "PROFILE", "Select one flow when choosing an execution profile");
43
45
  const reader = new Configuration(root, options.environmentVariables);
44
46
  const raw = reader.load();
45
47
  check(raw.apiVersion === "ingestron.project/v1", "VERSION", "Core accepts ingestron.project/v1 only; legacy project formats are not supported");
@@ -74,6 +76,11 @@ export function inspectProject(root, environment = "dev", options = {}) {
74
76
  values: resolvedProfile.values,
75
77
  flow: { id: rawFlow.id },
76
78
  }, { draft: true, table: true, runtime: true })));
79
+ if (options.profile) {
80
+ const index = flows.findIndex((f) => f.id === options.flow);
81
+ check(index >= 0, "PROFILE", `Unknown flow ${options.flow}`);
82
+ flows[index] = bindExecutionProfile(flows[index], options.profile);
83
+ }
77
84
  resolveModelContracts(reader, project, flows);
78
85
  const ids = new Set();
79
86
  for (const flow of flows) {
@@ -794,6 +801,7 @@ export function planProject(root, environment = "dev", options = {}) {
794
801
  inputDigests: reader.inputs,
795
802
  selection: {
796
803
  ...(options.flow ? { flow: options.flow } : {}),
804
+ ...(options.profile ? { profile: options.profile } : {}),
797
805
  ...(options.table ? { table: options.table } : {}),
798
806
  ...(options.step ? { step: options.step } : {}),
799
807
  ...(options.delivery ? { delivery: true } : {}),
@@ -7,6 +7,7 @@ export declare function buildProject(root: string, environment: string, args: an
7
7
  scope: {
8
8
  projectBuild: boolean;
9
9
  flow?: any;
10
+ profile?: any;
10
11
  provider?: any;
11
12
  };
12
13
  evidence: string;
@@ -14,7 +14,7 @@ import { compilerFingerprint } from "./fingerprint.js";
14
14
  import { version } from "../version.js";
15
15
  import { projectPackages } from "./project-packages.js";
16
16
  export function buildProject(root, environment, args) {
17
- const { project, flows, reader, profile } = inspectProject(root, environment);
17
+ const { project, flows, reader, profile } = inspectProject(root, environment, args);
18
18
  check(!(args.provider && args.flow), "SELECT", "Choose provider or flow, not both");
19
19
  check(!args.table && !args.step, "SELECT", "Project packages contain complete flows; select flow, not individual tables or steps");
20
20
  if (args.provider)
@@ -66,6 +66,8 @@ export function buildProject(root, environment, args) {
66
66
  };
67
67
  [...candidates].forEach((id) => addNativeParents(id));
68
68
  const nativePlan = planProject(root, environment, {
69
+ flow: args.profile ? args.flow : undefined,
70
+ profile: args.profile,
69
71
  nativeOnly: true,
70
72
  flowIds: [...candidates],
71
73
  delivery: true,
@@ -158,7 +160,7 @@ export function buildProject(root, environment, args) {
158
160
  });
159
161
  check(isMap(configured.result) && isMap(configured.result.execution), "PROVIDER", "Invalid project execution configuration");
160
162
  return configured.result.execution;
161
- });
163
+ }, args.profile);
162
164
  return {
163
165
  flow: f.id,
164
166
  artifacts: prepared.result.artifacts,
@@ -227,6 +229,7 @@ export function buildProject(root, environment, args) {
227
229
  const selection = {
228
230
  projectBuild: true,
229
231
  ...(args.flow ? { flow: args.flow } : {}),
232
+ ...(args.profile ? { profile: args.profile } : {}),
230
233
  ...(args.provider ? { provider: args.provider } : {}),
231
234
  };
232
235
  const metadata = {
@@ -94,6 +94,11 @@ export declare const flowSchema: z.ZodObject<{
94
94
  export: z.ZodOptional<z.ZodString>;
95
95
  product: z.ZodOptional<z.ZodString>;
96
96
  provider: z.ZodOptional<z.ZodString>;
97
+ executionProfiles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
98
+ provider: z.ZodString;
99
+ ingestion: z.ZodRecord<z.ZodString, z.ZodUnknown>;
100
+ source: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
101
+ }, z.core.$strict>>>;
97
102
  defaults: z.ZodDefault<z.ZodObject<{
98
103
  source: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
99
104
  with: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -236,6 +241,7 @@ export interface Plan {
236
241
  delivery?: boolean;
237
242
  projectBuild?: boolean;
238
243
  provider?: string;
244
+ profile?: string;
239
245
  };
240
246
  project: string;
241
247
  environment: string;
@@ -98,6 +98,15 @@ export const flowSchema = z
98
98
  export: id.optional(),
99
99
  product: id.optional(),
100
100
  provider: id.optional(),
101
+ executionProfiles: z
102
+ .record(id, z
103
+ .object({
104
+ provider: id,
105
+ ingestion: map,
106
+ source: map.default({}),
107
+ })
108
+ .strict())
109
+ .default({}),
101
110
  defaults: z
102
111
  .object({ source: map.default({}), with: map.default({}) })
103
112
  .strict()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingestron/core",
3
- "version": "0.12.5",
3
+ "version": "0.12.7",
4
4
  "type": "module",
5
5
  "description": "Shared Ingestron project compiler, operations and editor schemas",
6
6
  "license": "Apache-2.0",
@@ -45,16 +45,6 @@
45
45
  "type": "git",
46
46
  "url": "git+https://github.com/ingestron/core.git"
47
47
  },
48
- "devDependencies": {
49
- "@types/node": "22.20.1",
50
- "prettier": "3.9.8",
51
- "tsx": "4.23.13",
52
- "typescript": "7.0.2"
53
- },
54
- "homepage": "https://ingestron.io",
55
- "bugs": {
56
- "url": "https://github.com/ingestron/core/issues"
57
- },
58
48
  "scripts": {
59
49
  "build": "node scripts/build-assets.mjs && tsc && node scripts/compiler-fingerprint.mjs",
60
50
  "test": "tsx --test --test-concurrency=1 test/unit/*.test.ts test/providers/*.test.ts test/integration/*.test.ts",
@@ -64,6 +54,19 @@
64
54
  "release:check": "node scripts/release-check.mjs",
65
55
  "package:check": "tsx scripts/package-check.ts",
66
56
  "validate": "pnpm format:check && pnpm build && pnpm test && pnpm secrets:check && pnpm release:check && pnpm package:check",
57
+ "prepack": "npm run build",
58
+ "prepublishOnly": "node scripts/release-check.mjs --publish",
67
59
  "licences:inventory": "node scripts/licence-inventory.mjs"
60
+ },
61
+ "packageManager": "pnpm@10.15.0",
62
+ "devDependencies": {
63
+ "@types/node": "22.20.1",
64
+ "prettier": "3.9.8",
65
+ "tsx": "4.23.13",
66
+ "typescript": "7.0.2"
67
+ },
68
+ "homepage": "https://ingestron.io",
69
+ "bugs": {
70
+ "url": "https://github.com/ingestron/core/issues"
68
71
  }
69
- }
72
+ }