@enspirit/emb 0.0.5 → 0.0.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 +61 -31
- package/dist/src/cli/commands/clean.d.ts +3 -1
- package/dist/src/cli/commands/clean.js +13 -2
- package/dist/src/cli/commands/components/build.d.ts +6 -2
- package/dist/src/cli/commands/components/build.js +16 -7
- package/dist/src/cli/commands/config/print.js +2 -3
- package/dist/src/cli/commands/down.d.ts +2 -2
- package/dist/src/cli/commands/down.js +5 -25
- package/dist/src/cli/commands/tasks/index.js +11 -5
- package/dist/src/cli/commands/tasks/run.d.ts +1 -3
- package/dist/src/cli/commands/tasks/run.js +11 -93
- package/dist/src/cli/commands/up.d.ts +1 -1
- package/dist/src/cli/commands/up.js +12 -34
- package/dist/src/config/convert.d.ts +2 -3
- package/dist/src/config/convert.js +4 -11
- package/dist/src/config/index.d.ts +1 -0
- package/dist/src/config/index.js +1 -0
- package/dist/src/config/schema.d.ts +36 -29
- package/dist/src/config/schema.json +42 -25
- package/dist/src/config/types.d.ts +11 -7
- package/dist/src/config/validation.d.ts +2 -0
- package/dist/src/config/validation.js +26 -1
- package/dist/src/docker/compose/index.d.ts +1 -7
- package/dist/src/docker/compose/index.js +1 -13
- package/dist/src/docker/compose/operations/ComposeDownOperation.d.ts +12 -0
- package/dist/src/docker/compose/operations/ComposeDownOperation.js +21 -0
- package/dist/src/docker/compose/operations/ComposeUpOperation.d.ts +13 -0
- package/dist/src/docker/compose/operations/ComposeUpOperation.js +39 -0
- package/dist/src/docker/compose/operations/index.d.ts +2 -0
- package/dist/src/docker/compose/operations/index.js +2 -0
- package/dist/src/docker/operations/containers/ExecContainerOperation.d.ts +22 -0
- package/dist/src/docker/operations/containers/ExecContainerOperation.js +78 -0
- package/dist/src/docker/operations/containers/index.d.ts +1 -0
- package/dist/src/docker/operations/containers/index.js +1 -0
- package/dist/src/monorepo/component.d.ts +2 -2
- package/dist/src/monorepo/component.js +6 -6
- package/dist/src/monorepo/config.d.ts +6 -3
- package/dist/src/monorepo/config.js +22 -4
- package/dist/src/monorepo/index.d.ts +2 -0
- package/dist/src/monorepo/index.js +2 -0
- package/dist/src/monorepo/monorepo.d.ts +4 -2
- package/dist/src/monorepo/monorepo.js +30 -6
- package/dist/src/monorepo/operations/components/BuildComponentsOperation.d.ts +11 -2
- package/dist/src/monorepo/operations/components/BuildComponentsOperation.js +45 -59
- package/dist/src/monorepo/operations/components/GetComponentContainerOperation.d.ts +6 -0
- package/dist/src/monorepo/operations/components/GetComponentContainerOperation.js +21 -0
- package/dist/src/monorepo/operations/components/index.d.ts +1 -0
- package/dist/src/monorepo/operations/components/index.js +1 -0
- package/dist/src/monorepo/operations/index.d.ts +2 -0
- package/dist/src/monorepo/operations/index.js +2 -0
- package/dist/src/monorepo/operations/shell/ExecuteLocalCommandOperation.d.ts +16 -0
- package/dist/src/monorepo/operations/shell/ExecuteLocalCommandOperation.js +30 -0
- package/dist/src/monorepo/operations/shell/index.d.ts +1 -0
- package/dist/src/monorepo/operations/shell/index.js +1 -0
- package/dist/src/monorepo/operations/tasks/RunTasksOperation.d.ts +21 -0
- package/dist/src/monorepo/operations/tasks/RunTasksOperation.js +84 -0
- package/dist/src/monorepo/operations/tasks/index.d.ts +1 -0
- package/dist/src/monorepo/operations/tasks/index.js +1 -0
- package/dist/src/monorepo/plugins/ComponentDiscoverPlugin.d.ts +15 -0
- package/dist/src/monorepo/plugins/{ComponentsDiscover.js → ComponentDiscoverPlugin.js} +16 -2
- package/dist/src/monorepo/plugins/EmbfileLoaderPlugin.d.ts +14 -0
- package/dist/src/monorepo/plugins/EmbfileLoaderPlugin.js +37 -0
- package/dist/src/monorepo/plugins/index.d.ts +3 -2
- package/dist/src/monorepo/plugins/index.js +5 -2
- package/dist/src/monorepo/store/index.js +5 -3
- package/dist/src/monorepo/taskManagerFactory.d.ts +3 -0
- package/dist/src/monorepo/taskManagerFactory.js +20 -0
- package/dist/src/monorepo/types.d.ts +2 -1
- package/dist/src/monorepo/utils/findRunOrder.d.ts +34 -0
- package/dist/src/monorepo/utils/findRunOrder.js +165 -0
- package/dist/src/monorepo/utils/index.d.ts +1 -1
- package/dist/src/monorepo/utils/index.js +1 -1
- package/dist/src/operations/abstract/AbstractOperation.d.ts +1 -1
- package/dist/src/utils/deepMergeArray.d.ts +3 -0
- package/dist/src/utils/deepMergeArray.js +1 -0
- package/oclif.manifest.json +63 -74
- package/package.json +4 -2
- package/dist/src/cli/commands/run/index.d.ts +0 -10
- package/dist/src/cli/commands/run/index.js +0 -49
- package/dist/src/executors/docker.d.ts +0 -6
- package/dist/src/executors/docker.js +0 -14
- package/dist/src/executors/index.d.ts +0 -6
- package/dist/src/executors/index.js +0 -7
- package/dist/src/executors/shell.d.ts +0 -2
- package/dist/src/executors/shell.js +0 -14
- package/dist/src/executors/types.d.ts +0 -8
- package/dist/src/executors/types.js +0 -1
- package/dist/src/monorepo/plugins/ComponentsDiscover.d.ts +0 -6
- package/dist/src/monorepo/utils/findBuildOrder.d.ts +0 -2
- package/dist/src/monorepo/utils/findBuildOrder.js +0 -41
|
@@ -3,18 +3,32 @@ import { glob } from 'glob';
|
|
|
3
3
|
import { dirname } from 'node:path';
|
|
4
4
|
import { MonorepoConfig } from '../index.js';
|
|
5
5
|
import { AbstractPlugin } from './plugin.js';
|
|
6
|
+
export const ComponentDiscoverPluginDefaultOptions = {
|
|
7
|
+
glob: '*/Dockerfile',
|
|
8
|
+
};
|
|
6
9
|
export class ComponentDiscoverPlugin extends AbstractPlugin {
|
|
10
|
+
monorepo;
|
|
7
11
|
static name = 'autodiscover';
|
|
12
|
+
constructor(config, monorepo) {
|
|
13
|
+
super({
|
|
14
|
+
...ComponentDiscoverPluginDefaultOptions,
|
|
15
|
+
...config,
|
|
16
|
+
}, monorepo);
|
|
17
|
+
this.monorepo = monorepo;
|
|
18
|
+
}
|
|
8
19
|
async extendConfig(config) {
|
|
9
|
-
const files = await glob(
|
|
20
|
+
const files = await glob(this.config.glob || ComponentDiscoverPluginDefaultOptions.glob, {
|
|
21
|
+
...this.config,
|
|
10
22
|
cwd: config.project.rootDir,
|
|
11
23
|
});
|
|
12
24
|
const overrides = files.map((path) => {
|
|
13
25
|
const name = dirname(path);
|
|
14
26
|
const component = config.components.find((cmp) => cmp.name === name);
|
|
15
27
|
const cfg = {
|
|
16
|
-
context: name,
|
|
17
28
|
name,
|
|
29
|
+
docker: {
|
|
30
|
+
context: name,
|
|
31
|
+
},
|
|
18
32
|
};
|
|
19
33
|
return component ? deepmerge()(component, cfg) : cfg;
|
|
20
34
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Monorepo, MonorepoConfig } from '../index.js';
|
|
2
|
+
import { AbstractPlugin } from './plugin.js';
|
|
3
|
+
export type EmbfileLoaderPluginOptions = {
|
|
4
|
+
glob?: string | string[];
|
|
5
|
+
};
|
|
6
|
+
export declare const EmbfileLoaderPluginDefaultOptions: {
|
|
7
|
+
glob: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class EmbfileLoaderPlugin extends AbstractPlugin<Required<EmbfileLoaderPluginOptions>> {
|
|
10
|
+
protected monorepo: Monorepo;
|
|
11
|
+
static name: string;
|
|
12
|
+
constructor(cfg: Partial<EmbfileLoaderPluginOptions>, monorepo: Monorepo);
|
|
13
|
+
extendConfig(config: MonorepoConfig): Promise<MonorepoConfig>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { glob } from 'glob';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { validateEmbfile } from '../../config/index.js';
|
|
4
|
+
import { AbstractPlugin } from './plugin.js';
|
|
5
|
+
export const EmbfileLoaderPluginDefaultOptions = {
|
|
6
|
+
glob: '*/Embfile.{yaml,yml}',
|
|
7
|
+
};
|
|
8
|
+
export class EmbfileLoaderPlugin extends AbstractPlugin {
|
|
9
|
+
monorepo;
|
|
10
|
+
static name = 'embfiles';
|
|
11
|
+
constructor(cfg, monorepo) {
|
|
12
|
+
const config = {
|
|
13
|
+
...EmbfileLoaderPluginDefaultOptions,
|
|
14
|
+
...cfg,
|
|
15
|
+
};
|
|
16
|
+
if (!Array.isArray(config.glob)) {
|
|
17
|
+
config.glob = [config.glob];
|
|
18
|
+
}
|
|
19
|
+
super(config, monorepo);
|
|
20
|
+
this.monorepo = monorepo;
|
|
21
|
+
}
|
|
22
|
+
async extendConfig(config) {
|
|
23
|
+
const files = await glob(this.config.glob, {
|
|
24
|
+
...this.config,
|
|
25
|
+
cwd: config.project.rootDir,
|
|
26
|
+
});
|
|
27
|
+
const newConfig = await files.reduce(async (pConfig, path) => {
|
|
28
|
+
const config = await pConfig;
|
|
29
|
+
const embfile = await join(config.project.rootDir, path);
|
|
30
|
+
const component = await validateEmbfile(embfile);
|
|
31
|
+
return config.with({
|
|
32
|
+
components: [component],
|
|
33
|
+
});
|
|
34
|
+
}, Promise.resolve(config));
|
|
35
|
+
return newConfig;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { AbstractPlugin } from './plugin.js';
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './ComponentDiscoverPlugin.js';
|
|
3
3
|
export * from './DotEnvPlugin.js';
|
|
4
|
-
|
|
4
|
+
export * from './EmbfileLoaderPlugin.js';
|
|
5
|
+
import { Monorepo } from '../index.js';
|
|
5
6
|
export type AbstractPluginConstructor = new <C, P extends AbstractPlugin<C>>(config: C, monorepo: Monorepo) => P;
|
|
6
7
|
export declare const registerPlugin: (plugin: AbstractPluginConstructor) => void;
|
|
7
8
|
export declare const getPlugin: (name: string) => AbstractPluginConstructor;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './ComponentDiscoverPlugin.js';
|
|
2
2
|
export * from './DotEnvPlugin.js';
|
|
3
|
-
|
|
3
|
+
export * from './EmbfileLoaderPlugin.js';
|
|
4
|
+
import { ComponentDiscoverPlugin } from './ComponentDiscoverPlugin.js';
|
|
4
5
|
import { DotEnvPlugin } from './DotEnvPlugin.js';
|
|
6
|
+
import { EmbfileLoaderPlugin } from './EmbfileLoaderPlugin.js';
|
|
5
7
|
const PluginRegistry = new Map();
|
|
6
8
|
export const registerPlugin = (plugin) => {
|
|
7
9
|
if (PluginRegistry.has(plugin.name)) {
|
|
@@ -18,3 +20,4 @@ export const getPlugin = (name) => {
|
|
|
18
20
|
/** Not sure why we need casting */
|
|
19
21
|
registerPlugin(ComponentDiscoverPlugin);
|
|
20
22
|
registerPlugin(DotEnvPlugin);
|
|
23
|
+
registerPlugin(EmbfileLoaderPlugin);
|
|
@@ -10,9 +10,11 @@ import { dirname, join, normalize } from 'node:path';
|
|
|
10
10
|
export class EMBStore {
|
|
11
11
|
monorepo;
|
|
12
12
|
path;
|
|
13
|
-
constructor(monorepo, dirname
|
|
13
|
+
constructor(monorepo, dirname) {
|
|
14
14
|
this.monorepo = monorepo;
|
|
15
|
-
|
|
15
|
+
// By default, we use the flavor name to build that root of the store
|
|
16
|
+
// so that logs and sentinel files for different flavors are keps separate
|
|
17
|
+
this.path = this.monorepo.join(dirname || '.emb');
|
|
16
18
|
}
|
|
17
19
|
async createReadStream(path) {
|
|
18
20
|
await this.mkdirp(dirname(path));
|
|
@@ -45,7 +47,7 @@ export class EMBStore {
|
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
join(path) {
|
|
48
|
-
return join(this.path, path);
|
|
50
|
+
return join(this.path, this.monorepo.currentFlavor, path);
|
|
49
51
|
}
|
|
50
52
|
async mkdirp(path) {
|
|
51
53
|
// Avoid getting out of the store by ensuring nothing goes past ../
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Manager } from '@listr2/manager';
|
|
2
|
+
import { ListrDefaultRendererLogLevels, PRESET_TIMER, } from 'listr2';
|
|
3
|
+
export function taskManagerFactory(override) {
|
|
4
|
+
return new Manager({
|
|
5
|
+
collectErrors: 'minimal',
|
|
6
|
+
concurrent: false,
|
|
7
|
+
exitOnError: true,
|
|
8
|
+
rendererOptions: {
|
|
9
|
+
collapseErrors: false,
|
|
10
|
+
collapseSubtasks: false,
|
|
11
|
+
icon: {
|
|
12
|
+
[ListrDefaultRendererLogLevels.SKIPPED_WITH_COLLAPSE]: '♺',
|
|
13
|
+
},
|
|
14
|
+
timer: {
|
|
15
|
+
...PRESET_TIMER,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
...override,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
type DepList = readonly string[] | string[] | undefined;
|
|
2
|
+
type CollectionConfig<IDK extends PropertyKey, DPK extends PropertyKey> = {
|
|
3
|
+
idField: IDK;
|
|
4
|
+
depField: DPK;
|
|
5
|
+
/** If true, throw when an item's id equals some other item's name (or vice versa). */
|
|
6
|
+
forbidIdNameCollision?: boolean;
|
|
7
|
+
};
|
|
8
|
+
type AmbiguityPolicy = 'error' | 'runAll';
|
|
9
|
+
export declare class EMBCollection<T extends Partial<Record<DPK, DepList>> & Record<IDK, string> & {
|
|
10
|
+
name: string;
|
|
11
|
+
}, IDK extends keyof T, DPK extends keyof T> {
|
|
12
|
+
private items;
|
|
13
|
+
readonly idField: IDK;
|
|
14
|
+
readonly depField: DPK;
|
|
15
|
+
private byId;
|
|
16
|
+
private byName;
|
|
17
|
+
constructor(items: Iterable<T>, cfg: CollectionConfig<IDK, DPK>);
|
|
18
|
+
/** All items (stable array iteration) */
|
|
19
|
+
get all(): Iterable<T>;
|
|
20
|
+
idOf(t: T): string;
|
|
21
|
+
depsOf(t: T): readonly string[];
|
|
22
|
+
matches(ref: string, opts?: {
|
|
23
|
+
multiple?: false;
|
|
24
|
+
}): T;
|
|
25
|
+
matches(ref: string, opts: {
|
|
26
|
+
multiple: true;
|
|
27
|
+
}): T[];
|
|
28
|
+
}
|
|
29
|
+
export declare function findRunOrder<T extends Partial<Record<DPK, DepList>> & Record<IDK, string> & {
|
|
30
|
+
name: string;
|
|
31
|
+
}, IDK extends keyof T, DPK extends keyof T>(selection: readonly string[], collection: EMBCollection<T, IDK, DPK>, { onAmbiguous }?: {
|
|
32
|
+
onAmbiguous?: AmbiguityPolicy | undefined;
|
|
33
|
+
}): T[];
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import graphlib from 'graphlib';
|
|
2
|
+
export class EMBCollection {
|
|
3
|
+
items;
|
|
4
|
+
idField;
|
|
5
|
+
depField;
|
|
6
|
+
byId;
|
|
7
|
+
byName;
|
|
8
|
+
constructor(items, cfg) {
|
|
9
|
+
this.items = [];
|
|
10
|
+
this.idField = cfg.idField;
|
|
11
|
+
this.depField = cfg.depField;
|
|
12
|
+
this.byId = new Map();
|
|
13
|
+
this.byName = new Map();
|
|
14
|
+
// single-pass validation state
|
|
15
|
+
const seenIds = new Set();
|
|
16
|
+
const seenNames = new Set();
|
|
17
|
+
const dupIdReports = [];
|
|
18
|
+
const collisions = [];
|
|
19
|
+
for (const t of items) {
|
|
20
|
+
const id = t[this.idField];
|
|
21
|
+
const { name } = t;
|
|
22
|
+
// duplicate id?
|
|
23
|
+
if (seenIds.has(id)) {
|
|
24
|
+
const firstOwner = this.byId.get(id); // first occurrence already stored
|
|
25
|
+
dupIdReports.push(`id "${id}" used by "${firstOwner.name}" and "${name}"`);
|
|
26
|
+
// keep the first owner in byId; do not overwrite
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.byId.set(id, t);
|
|
30
|
+
seenIds.add(id);
|
|
31
|
+
}
|
|
32
|
+
// --- Optional validation: forbid id <-> name collisions ---
|
|
33
|
+
const checkCollisions = cfg.forbidIdNameCollision && this.idField !== 'name';
|
|
34
|
+
if (checkCollisions) {
|
|
35
|
+
if (seenNames.has(id)) {
|
|
36
|
+
const nameOwners = this.byName.get(id) ?? [];
|
|
37
|
+
const ownerIds = nameOwners.map((o) => o[this.idField]).join(', ');
|
|
38
|
+
collisions.push(`value "${id}" is an id of "${name}" and also a name of item(s) with id(s): [${ownerIds}]`);
|
|
39
|
+
}
|
|
40
|
+
if (seenIds.has(name)) {
|
|
41
|
+
const idOwner = this.byId.get(name);
|
|
42
|
+
collisions.push(`value "${name}" is a name of "${t.name}" and also an id of "${idOwner.name}"`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// byName index
|
|
46
|
+
const list = this.byName.get(name);
|
|
47
|
+
if (list)
|
|
48
|
+
list.push(t);
|
|
49
|
+
else
|
|
50
|
+
this.byName.set(name, [t]);
|
|
51
|
+
// keep item list (stable order)
|
|
52
|
+
this.items.push(t);
|
|
53
|
+
// record name after checks so current name won’t collide with itself
|
|
54
|
+
seenNames.add(name);
|
|
55
|
+
}
|
|
56
|
+
if (dupIdReports.length > 0 || collisions.length > 0) {
|
|
57
|
+
const parts = [];
|
|
58
|
+
if (dupIdReports.length > 0) {
|
|
59
|
+
parts.push(`Duplicate ${String(this.idField)} values (${dupIdReports.length}):\n` +
|
|
60
|
+
dupIdReports.join('\n'));
|
|
61
|
+
}
|
|
62
|
+
if (collisions.length > 0) {
|
|
63
|
+
parts.push(`id↔name collisions (${collisions.length}):\n` +
|
|
64
|
+
collisions.join('\n'));
|
|
65
|
+
}
|
|
66
|
+
// eslint-disable-next-line unicorn/error-message
|
|
67
|
+
throw new Error(parts.join('\n\n'));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** All items (stable array iteration) */
|
|
71
|
+
get all() {
|
|
72
|
+
return this.items;
|
|
73
|
+
}
|
|
74
|
+
idOf(t) {
|
|
75
|
+
return t[this.idField];
|
|
76
|
+
}
|
|
77
|
+
depsOf(t) {
|
|
78
|
+
return (t[this.depField] ?? []);
|
|
79
|
+
}
|
|
80
|
+
matches(ref, opts) {
|
|
81
|
+
const idHit = this.byId.get(ref);
|
|
82
|
+
if (idHit)
|
|
83
|
+
return opts?.multiple ? [idHit] : idHit;
|
|
84
|
+
const nameHits = this.byName.get(ref) ?? [];
|
|
85
|
+
if (nameHits.length === 0) {
|
|
86
|
+
throw new Error(`Unknown reference "${ref}"`);
|
|
87
|
+
}
|
|
88
|
+
if (opts?.multiple)
|
|
89
|
+
return nameHits;
|
|
90
|
+
if (nameHits.length > 1) {
|
|
91
|
+
const ids = nameHits.map((t) => this.idOf(t)).join(', ');
|
|
92
|
+
throw new Error(`Ambiguous reference "${ref}" matches multiple ids: [${ids}]`);
|
|
93
|
+
}
|
|
94
|
+
return nameHits[0];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/* ----------------- run-order helpers unchanged (for completeness) ---------------- */
|
|
98
|
+
function resolveRefSet(col, ref, policy) {
|
|
99
|
+
if (policy === 'runAll')
|
|
100
|
+
return col.matches(ref, { multiple: true }).map((t) => col.idOf(t));
|
|
101
|
+
return [col.idOf(col.matches(ref))];
|
|
102
|
+
}
|
|
103
|
+
function collectPredecessorClosure(g, seeds) {
|
|
104
|
+
const seen = new Set();
|
|
105
|
+
const q = [];
|
|
106
|
+
for (const s of seeds) {
|
|
107
|
+
if (!seen.has(s)) {
|
|
108
|
+
seen.add(s);
|
|
109
|
+
q.push(s);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
while (q.length > 0) {
|
|
113
|
+
const cur = q.shift();
|
|
114
|
+
for (const p of g.predecessors(cur) ?? [])
|
|
115
|
+
if (!seen.has(p)) {
|
|
116
|
+
seen.add(p);
|
|
117
|
+
q.push(p);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return seen;
|
|
121
|
+
}
|
|
122
|
+
function buildGraph(col, policy) {
|
|
123
|
+
const g = new graphlib.Graph({ directed: true });
|
|
124
|
+
for (const t of col.all)
|
|
125
|
+
g.setNode(col.idOf(t));
|
|
126
|
+
for (const t of col.all) {
|
|
127
|
+
const toId = col.idOf(t);
|
|
128
|
+
for (const ref of col.depsOf(t)) {
|
|
129
|
+
for (const fromId of resolveRefSet(col, ref, policy))
|
|
130
|
+
g.setEdge(fromId, toId);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return g;
|
|
134
|
+
}
|
|
135
|
+
export function findRunOrder(selection, collection, { onAmbiguous = 'error' } = {}) {
|
|
136
|
+
const g = buildGraph(collection, onAmbiguous);
|
|
137
|
+
const cycles = graphlib.alg.findCycles(g);
|
|
138
|
+
if (cycles.length > 0) {
|
|
139
|
+
throw new Error(`Circular dependencies detected: ${JSON.stringify(cycles)}`);
|
|
140
|
+
}
|
|
141
|
+
const selectedIds = new Set();
|
|
142
|
+
for (const ref of selection)
|
|
143
|
+
for (const id of resolveRefSet(collection, ref, onAmbiguous))
|
|
144
|
+
selectedIds.add(id);
|
|
145
|
+
if (selectedIds.size === 0)
|
|
146
|
+
throw new Error('Selection resolved to no items.');
|
|
147
|
+
const include = collectPredecessorClosure(g, selectedIds.values());
|
|
148
|
+
const sub = new graphlib.Graph({ directed: true });
|
|
149
|
+
for (const id of include)
|
|
150
|
+
sub.setNode(id);
|
|
151
|
+
for (const id of include)
|
|
152
|
+
for (const p of g.predecessors(id) ?? [])
|
|
153
|
+
if (include.has(p))
|
|
154
|
+
sub.setEdge(p, id);
|
|
155
|
+
const ids = graphlib.alg.topsort(sub);
|
|
156
|
+
const byId = new Map();
|
|
157
|
+
for (const t of collection.all)
|
|
158
|
+
byId.set(collection.idOf(t), t);
|
|
159
|
+
return ids.map((id) => {
|
|
160
|
+
const t = byId.get(id);
|
|
161
|
+
if (!t)
|
|
162
|
+
throw new Error(`Internal error: missing item for id "${id}"`);
|
|
163
|
+
return t;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './findRunOrder.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './findRunOrder.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EmbContext } from '../../index.js';
|
|
2
2
|
import * as z from 'zod';
|
|
3
|
-
import { IOperation } from '../
|
|
3
|
+
import { IOperation } from '../index.js';
|
|
4
4
|
export declare abstract class AbstractOperation<S extends z.Schema, O = unknown> implements IOperation<z.infer<S>, O> {
|
|
5
5
|
protected inputSchema: S;
|
|
6
6
|
protected context: EmbContext;
|
package/oclif.manifest.json
CHANGED
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
"name": "json",
|
|
15
15
|
"allowNo": false,
|
|
16
16
|
"type": "boolean"
|
|
17
|
+
},
|
|
18
|
+
"force": {
|
|
19
|
+
"char": "f",
|
|
20
|
+
"description": "Force the deletion of containers & images",
|
|
21
|
+
"name": "force",
|
|
22
|
+
"allowNo": false,
|
|
23
|
+
"type": "boolean"
|
|
17
24
|
}
|
|
18
25
|
},
|
|
19
26
|
"hasDynamicHelp": false,
|
|
@@ -47,6 +54,14 @@
|
|
|
47
54
|
"name": "json",
|
|
48
55
|
"allowNo": false,
|
|
49
56
|
"type": "boolean"
|
|
57
|
+
},
|
|
58
|
+
"flavor": {
|
|
59
|
+
"description": "Specify the flavor to use.",
|
|
60
|
+
"name": "flavor",
|
|
61
|
+
"required": false,
|
|
62
|
+
"hasDynamicHelp": false,
|
|
63
|
+
"multiple": false,
|
|
64
|
+
"type": "option"
|
|
50
65
|
}
|
|
51
66
|
},
|
|
52
67
|
"hasDynamicHelp": false,
|
|
@@ -89,10 +104,10 @@
|
|
|
89
104
|
"multiple": false,
|
|
90
105
|
"type": "option"
|
|
91
106
|
},
|
|
92
|
-
"force
|
|
107
|
+
"force": {
|
|
93
108
|
"char": "f",
|
|
94
|
-
"description": "
|
|
95
|
-
"name": "force
|
|
109
|
+
"description": "Bypass caches, force the recreation of containers, etc",
|
|
110
|
+
"name": "force",
|
|
96
111
|
"allowNo": false,
|
|
97
112
|
"type": "boolean"
|
|
98
113
|
}
|
|
@@ -118,7 +133,7 @@
|
|
|
118
133
|
"aliases": [],
|
|
119
134
|
"args": {
|
|
120
135
|
"component": {
|
|
121
|
-
"description": "List of components to build",
|
|
136
|
+
"description": "List of components to build (defaults to all)",
|
|
122
137
|
"name": "component",
|
|
123
138
|
"required": false
|
|
124
139
|
}
|
|
@@ -142,6 +157,13 @@
|
|
|
142
157
|
"hasDynamicHelp": false,
|
|
143
158
|
"multiple": false,
|
|
144
159
|
"type": "option"
|
|
160
|
+
},
|
|
161
|
+
"dry-run": {
|
|
162
|
+
"description": "Do not build the components but only produce build meta information",
|
|
163
|
+
"name": "dry-run",
|
|
164
|
+
"required": false,
|
|
165
|
+
"allowNo": false,
|
|
166
|
+
"type": "boolean"
|
|
145
167
|
}
|
|
146
168
|
},
|
|
147
169
|
"hasDynamicHelp": false,
|
|
@@ -204,10 +226,12 @@
|
|
|
204
226
|
"index.js"
|
|
205
227
|
]
|
|
206
228
|
},
|
|
207
|
-
"
|
|
208
|
-
"aliases": [
|
|
229
|
+
"containers": {
|
|
230
|
+
"aliases": [
|
|
231
|
+
"ps"
|
|
232
|
+
],
|
|
209
233
|
"args": {},
|
|
210
|
-
"description": "
|
|
234
|
+
"description": "List docker containers.",
|
|
211
235
|
"examples": [
|
|
212
236
|
"<%= config.bin %> <%= command.id %>"
|
|
213
237
|
],
|
|
@@ -219,18 +243,18 @@
|
|
|
219
243
|
"allowNo": false,
|
|
220
244
|
"type": "boolean"
|
|
221
245
|
},
|
|
222
|
-
"
|
|
223
|
-
"
|
|
224
|
-
"
|
|
246
|
+
"all": {
|
|
247
|
+
"char": "a",
|
|
248
|
+
"description": "Retun all containers. By default, only running containers are shown",
|
|
249
|
+
"name": "all",
|
|
225
250
|
"required": false,
|
|
226
|
-
"
|
|
227
|
-
"
|
|
228
|
-
"type": "option"
|
|
251
|
+
"allowNo": false,
|
|
252
|
+
"type": "boolean"
|
|
229
253
|
}
|
|
230
254
|
},
|
|
231
255
|
"hasDynamicHelp": false,
|
|
232
256
|
"hiddenAliases": [],
|
|
233
|
-
"id": "
|
|
257
|
+
"id": "containers",
|
|
234
258
|
"pluginAlias": "@enspirit/emb",
|
|
235
259
|
"pluginName": "@enspirit/emb",
|
|
236
260
|
"pluginType": "core",
|
|
@@ -242,16 +266,14 @@
|
|
|
242
266
|
"src",
|
|
243
267
|
"cli",
|
|
244
268
|
"commands",
|
|
245
|
-
"
|
|
246
|
-
"
|
|
269
|
+
"containers",
|
|
270
|
+
"index.js"
|
|
247
271
|
]
|
|
248
272
|
},
|
|
249
|
-
"containers": {
|
|
250
|
-
"aliases": [
|
|
251
|
-
"ps"
|
|
252
|
-
],
|
|
273
|
+
"containers:prune": {
|
|
274
|
+
"aliases": [],
|
|
253
275
|
"args": {},
|
|
254
|
-
"description": "
|
|
276
|
+
"description": "Prune containers.",
|
|
255
277
|
"examples": [
|
|
256
278
|
"<%= config.bin %> <%= command.id %>"
|
|
257
279
|
],
|
|
@@ -262,19 +284,11 @@
|
|
|
262
284
|
"name": "json",
|
|
263
285
|
"allowNo": false,
|
|
264
286
|
"type": "boolean"
|
|
265
|
-
},
|
|
266
|
-
"all": {
|
|
267
|
-
"char": "a",
|
|
268
|
-
"description": "Retun all containers. By default, only running containers are shown",
|
|
269
|
-
"name": "all",
|
|
270
|
-
"required": false,
|
|
271
|
-
"allowNo": false,
|
|
272
|
-
"type": "boolean"
|
|
273
287
|
}
|
|
274
288
|
},
|
|
275
289
|
"hasDynamicHelp": false,
|
|
276
290
|
"hiddenAliases": [],
|
|
277
|
-
"id": "containers",
|
|
291
|
+
"id": "containers:prune",
|
|
278
292
|
"pluginAlias": "@enspirit/emb",
|
|
279
293
|
"pluginName": "@enspirit/emb",
|
|
280
294
|
"pluginType": "core",
|
|
@@ -287,13 +301,13 @@
|
|
|
287
301
|
"cli",
|
|
288
302
|
"commands",
|
|
289
303
|
"containers",
|
|
290
|
-
"
|
|
304
|
+
"prune.js"
|
|
291
305
|
]
|
|
292
306
|
},
|
|
293
|
-
"
|
|
307
|
+
"config:print": {
|
|
294
308
|
"aliases": [],
|
|
295
309
|
"args": {},
|
|
296
|
-
"description": "
|
|
310
|
+
"description": "Print the current config.",
|
|
297
311
|
"examples": [
|
|
298
312
|
"<%= config.bin %> <%= command.id %>"
|
|
299
313
|
],
|
|
@@ -304,11 +318,19 @@
|
|
|
304
318
|
"name": "json",
|
|
305
319
|
"allowNo": false,
|
|
306
320
|
"type": "boolean"
|
|
321
|
+
},
|
|
322
|
+
"flavor": {
|
|
323
|
+
"description": "Specify the flavor to use.",
|
|
324
|
+
"name": "flavor",
|
|
325
|
+
"required": false,
|
|
326
|
+
"hasDynamicHelp": false,
|
|
327
|
+
"multiple": false,
|
|
328
|
+
"type": "option"
|
|
307
329
|
}
|
|
308
330
|
},
|
|
309
331
|
"hasDynamicHelp": false,
|
|
310
332
|
"hiddenAliases": [],
|
|
311
|
-
"id": "
|
|
333
|
+
"id": "config:print",
|
|
312
334
|
"pluginAlias": "@enspirit/emb",
|
|
313
335
|
"pluginName": "@enspirit/emb",
|
|
314
336
|
"pluginType": "core",
|
|
@@ -320,8 +342,8 @@
|
|
|
320
342
|
"src",
|
|
321
343
|
"cli",
|
|
322
344
|
"commands",
|
|
323
|
-
"
|
|
324
|
-
"
|
|
345
|
+
"config",
|
|
346
|
+
"print.js"
|
|
325
347
|
]
|
|
326
348
|
},
|
|
327
349
|
"images:delete": {
|
|
@@ -450,40 +472,6 @@
|
|
|
450
472
|
"prune.js"
|
|
451
473
|
]
|
|
452
474
|
},
|
|
453
|
-
"run": {
|
|
454
|
-
"aliases": [],
|
|
455
|
-
"args": {
|
|
456
|
-
"component": {
|
|
457
|
-
"description": "Component name",
|
|
458
|
-
"name": "component",
|
|
459
|
-
"required": true
|
|
460
|
-
},
|
|
461
|
-
"script": {
|
|
462
|
-
"description": "NPM script to run",
|
|
463
|
-
"name": "script",
|
|
464
|
-
"required": true
|
|
465
|
-
}
|
|
466
|
-
},
|
|
467
|
-
"description": "Run an npm script from a component's package.json",
|
|
468
|
-
"flags": {},
|
|
469
|
-
"hasDynamicHelp": false,
|
|
470
|
-
"hiddenAliases": [],
|
|
471
|
-
"id": "run",
|
|
472
|
-
"pluginAlias": "@enspirit/emb",
|
|
473
|
-
"pluginName": "@enspirit/emb",
|
|
474
|
-
"pluginType": "core",
|
|
475
|
-
"strict": true,
|
|
476
|
-
"enableJsonFlag": false,
|
|
477
|
-
"isESM": true,
|
|
478
|
-
"relativePath": [
|
|
479
|
-
"dist",
|
|
480
|
-
"src",
|
|
481
|
-
"cli",
|
|
482
|
-
"commands",
|
|
483
|
-
"run",
|
|
484
|
-
"index.js"
|
|
485
|
-
]
|
|
486
|
-
},
|
|
487
475
|
"tasks": {
|
|
488
476
|
"aliases": [],
|
|
489
477
|
"args": {},
|
|
@@ -522,12 +510,12 @@
|
|
|
522
510
|
"aliases": [],
|
|
523
511
|
"args": {
|
|
524
512
|
"task": {
|
|
525
|
-
"description": "List of tasks
|
|
513
|
+
"description": "List of tasks to run. You can provide either ids or names (eg: component:task or task)",
|
|
526
514
|
"name": "task",
|
|
527
|
-
"required":
|
|
515
|
+
"required": true
|
|
528
516
|
}
|
|
529
517
|
},
|
|
530
|
-
"description": "Run
|
|
518
|
+
"description": "Run tasks.",
|
|
531
519
|
"examples": [
|
|
532
520
|
"<%= config.bin %> <%= command.id %>"
|
|
533
521
|
],
|
|
@@ -541,6 +529,7 @@
|
|
|
541
529
|
},
|
|
542
530
|
"executor": {
|
|
543
531
|
"char": "x",
|
|
532
|
+
"description": "Where to run the task. (experimental!)",
|
|
544
533
|
"name": "executor",
|
|
545
534
|
"hasDynamicHelp": false,
|
|
546
535
|
"multiple": false,
|
|
@@ -570,5 +559,5 @@
|
|
|
570
559
|
]
|
|
571
560
|
}
|
|
572
561
|
},
|
|
573
|
-
"version": "0.0.
|
|
562
|
+
"version": "0.0.7"
|
|
574
563
|
}
|