@journeyapps/cloudcode-build-agent 0.0.0-dev.8ebefb0 → 0.0.0-dev.9188dcc

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.
@@ -1,91 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.detectTasks = void 0;
27
- const fs = __importStar(require("node:fs"));
28
- const path = __importStar(require("node:path"));
29
- const jetpack = __importStar(require("fs-jetpack"));
30
- const semver = __importStar(require("semver"));
31
- const defs = __importStar(require("./defs"));
32
- // TODO: validations for cloudcode specific keys and structure?
33
- async function readPackage(path) {
34
- try {
35
- const content = await fs.promises.readFile(path, { encoding: 'utf-8' });
36
- return JSON.parse(content);
37
- }
38
- catch (err) {
39
- console.error(`ERROR: ${err}`);
40
- throw err;
41
- // todo: check for enoent and skip?
42
- // todo: if json error, throw a CC build error?
43
- }
44
- }
45
- async function detectTasks(project_path, only) {
46
- const package_files = await jetpack.findAsync(path.join(project_path, 'cloudcode'), { matching: '**/package.json' });
47
- const filtered_package_files = package_files.filter((pkg_path) => {
48
- // FIXME: this is kinda clunky.
49
- const pm = /^\/?cloudcode\/([^\/]+)\/package\.json$/.exec(pkg_path);
50
- if (!pm) {
51
- return false;
52
- }
53
- const taskName = pm[1];
54
- if (only != null && only != taskName) {
55
- // !(only.indexOf(taskName) >= 0) // TODO: support a specific list of tasks to build?
56
- return false;
57
- }
58
- return true;
59
- });
60
- return Promise.all(filtered_package_files.map(async (pkg_path) => {
61
- const task_package = await readPackage(pkg_path);
62
- const task_name = task_package.name; // CAVEAT: the pkg name _must_ match the dir.
63
- const task_version = task_package?.cloudcode?.runtime;
64
- // FIXME: Do we want to filter out disabled tasks from the build process?
65
- console.debug(`Detected task version ${task_version}`);
66
- const matching = defs.SUPPORTED_VERSIONS.find((v) => {
67
- return semver.satisfies(v.version, task_version);
68
- });
69
- if (!matching) {
70
- throw new Error('FIXME: unsupported version');
71
- }
72
- console.debug(`Matching versions: ${JSON.stringify(matching)}`);
73
- const running_node_version = process.versions.node;
74
- let required_node_version;
75
- // if (matching?.node && semver.major(matching.node) !== semver.major(running_node_version)) {
76
- if (matching?.node && semver.parse(matching.node) !== semver.parse(running_node_version)) {
77
- console.debug(`Task requires different node version: v${matching.node}`);
78
- required_node_version = matching.node;
79
- }
80
- return {
81
- pkg_path,
82
- task_name,
83
- task_version,
84
- required_node_version,
85
- builder_package: matching.builder_package,
86
- builder_script: matching.builder_script
87
- };
88
- }));
89
- }
90
- exports.detectTasks = detectTasks;
91
- //# sourceMappingURL=detect_tasks.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"detect_tasks.js","sourceRoot":"","sources":["../src/detect_tasks.ts"],"names":[],"mappings":"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"}
package/dist/run.d.ts DELETED
@@ -1,4 +0,0 @@
1
- /// <reference types="node" />
2
- import { SpawnStreamEvent } from './spawn-stream';
3
- import { SpawnOptions } from 'child_process';
4
- export declare function runCommand(command: string, args: string[], options?: Partial<SpawnOptions>): AsyncIterable<SpawnStreamEvent>;
package/dist/run.js DELETED
@@ -1,19 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runCommand = void 0;
4
- const spawn_stream_1 = require("./spawn-stream");
5
- async function* runCommand(command, args, options) {
6
- const { childProcess, stream } = (0, spawn_stream_1.spawnStream)(command, args, { cwd: options?.cwd, splitLines: true, ...options });
7
- let exitCode = null;
8
- for await (let event of stream) {
9
- yield event;
10
- if (event.exitCode != null) {
11
- exitCode = event.exitCode;
12
- }
13
- }
14
- if (exitCode != 0) {
15
- throw new Error(`Command failed with code ${exitCode}`);
16
- }
17
- }
18
- exports.runCommand = runCommand;
19
- //# sourceMappingURL=run.js.map
package/dist/run.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":";;;AAAA,iDAA+D;AAGxD,KAAK,SAAS,CAAC,CAAC,UAAU,CAC/B,OAAe,EACf,IAAc,EACd,OAA+B;IAE/B,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,IAAA,0BAAW,EAAC,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAEjH,IAAI,QAAQ,GAAkB,IAAI,CAAC;IAEnC,IAAI,KAAK,EAAE,IAAI,KAAK,IAAI,MAAM,EAAE;QAC9B,MAAM,KAAK,CAAC;QACZ,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE;YAC1B,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;SAC3B;KACF;IAED,IAAI,QAAQ,IAAI,CAAC,EAAE;QACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAC;KACzD;AACH,CAAC;AAnBD,gCAmBC"}
@@ -1,15 +0,0 @@
1
- /// <reference types="node" />
2
- import { SpawnOptions } from 'child_process';
3
- export interface StreamOptions {
4
- splitLines?: boolean;
5
- }
6
- export declare function spawnStream(command: string, args: string[], options: SpawnOptions & StreamOptions): {
7
- childProcess: import("child_process").ChildProcessWithoutNullStreams;
8
- stream: AsyncIterable<SpawnStreamEvent>;
9
- };
10
- export interface SpawnStreamEvent {
11
- event: 'stdout' | 'stderr' | 'exit';
12
- stdout?: string;
13
- stderr?: string;
14
- exitCode?: number;
15
- }
@@ -1,59 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.spawnStream = void 0;
4
- const child_process_1 = require("child_process");
5
- const stream_1 = require("stream");
6
- function spawnStream(command, args, options) {
7
- const process = (0, child_process_1.spawn)(command, args, {
8
- ...options,
9
- stdio: 'pipe'
10
- });
11
- return {
12
- childProcess: process,
13
- stream: processToStream(process, options)
14
- };
15
- }
16
- exports.spawnStream = spawnStream;
17
- function processToStream(process, options) {
18
- const combinedStream = new stream_1.PassThrough({ objectMode: true });
19
- async function* transform(stream, key) {
20
- stream.setEncoding('utf-8');
21
- let iterable = stream;
22
- if (options.splitLines) {
23
- iterable = splitLines(iterable);
24
- }
25
- for await (const chunk of iterable) {
26
- yield {
27
- event: key,
28
- [key]: chunk
29
- };
30
- }
31
- }
32
- if (process.stdout) {
33
- stream_1.Readable.from(transform(process.stdout, 'stdout')).pipe(combinedStream, { end: false });
34
- }
35
- if (process.stderr) {
36
- stream_1.Readable.from(transform(process.stderr, 'stderr')).pipe(combinedStream, { end: false });
37
- }
38
- process.on('exit', (code) => {
39
- combinedStream.write({ exitCode: code }, () => {
40
- combinedStream.end();
41
- });
42
- });
43
- return combinedStream;
44
- }
45
- async function* splitLines(stream) {
46
- let buffer = '';
47
- for await (const chunk of stream) {
48
- buffer += chunk;
49
- const lines = buffer.split('\n');
50
- buffer = lines.pop();
51
- for (let line of lines) {
52
- yield `${line}\n`;
53
- }
54
- }
55
- if (buffer) {
56
- yield buffer;
57
- }
58
- }
59
- //# sourceMappingURL=spawn-stream.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spawn-stream.js","sourceRoot":"","sources":["../src/spawn-stream.ts"],"names":[],"mappings":";;;AAAA,iDAAkE;AAClE,mCAA+C;AAM/C,SAAgB,WAAW,CAAC,OAAe,EAAE,IAAc,EAAE,OAAqC;IAChG,MAAM,OAAO,GAAG,IAAA,qBAAK,EAAC,OAAO,EAAE,IAAI,EAAE;QACnC,GAAG,OAAO;QACV,KAAK,EAAE,MAAM;KACd,CAAC,CAAC;IAEH,OAAO;QACL,YAAY,EAAE,OAAO;QACrB,MAAM,EAAE,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC;KAC1C,CAAC;AACJ,CAAC;AAVD,kCAUC;AASD,SAAS,eAAe,CAAC,OAAqB,EAAE,OAAsB;IACpE,MAAM,cAAc,GAAG,IAAI,oBAAW,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7D,KAAK,SAAS,CAAC,CAAC,SAAS,CAAC,MAAgB,EAAE,GAAwB;QAClE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,QAAQ,GAA0B,MAAM,CAAC;QAC7C,IAAI,OAAO,CAAC,UAAU,EAAE;YACtB,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;SACjC;QACD,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,EAAE;YAClC,MAAM;gBACJ,KAAK,EAAE,GAAG;gBACV,CAAC,GAAG,CAAC,EAAE,KAAK;aACb,CAAC;SACH;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,EAAE;QAClB,iBAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;KACzF;IACD,IAAI,OAAO,CAAC,MAAM,EAAE;QAClB,iBAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;KACzF;IAED,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAmB,EAAE,EAAE;QACzC,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE;YAC5C,cAAc,CAAC,GAAG,EAAE,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,KAAK,SAAS,CAAC,CAAC,UAAU,CAAC,MAA6B;IACtD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE;QAChC,MAAM,IAAI,KAAK,CAAC;QAChB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QACtB,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE;YACtB,MAAM,GAAG,IAAI,IAAI,CAAC;SACnB;KACF;IACD,IAAI,MAAM,EAAE;QACV,MAAM,MAAM,CAAC;KACd;AACH,CAAC"}
package/src/defs.ts DELETED
@@ -1,45 +0,0 @@
1
- // TODO: maybe publish (some of) this from the CC service?
2
- export const SUPPORTED_VERSIONS = [
3
- {
4
- // proposed
5
- version: '1.13.0',
6
- node: '16.19.1',
7
- builder_package: '@journeyapps/cloudcode-build@1.13.0',
8
- builder_script: 'cloudcode-build'
9
- },
10
- {
11
- version: '1.12.0',
12
- node: '16.19.1', // FIXME: maybe the very specific node version here is too brittle?
13
- // builder_package: '@journeyapps/cloudcode-build-legacy@1.12.0'
14
- // DEV HACK:
15
- builder_package: '~/src/journey-cloudcode/packages/cloudcode-build-legacy',
16
- builder_script: 'cloudcode-build-legacy'
17
- },
18
- {
19
- version: '1.11.2',
20
- // node: '14.21.3',
21
- // builder_package: '@journeyapps/cloudcode-build-legacy@1.12.0'
22
- // DEV HACK:
23
- node: '16.19.1', // because local dev on darwin/arm64 and there's no darwin-arm64 builds for node14 available.
24
- builder_package: '~/src/journey-cloudcode/packages/cloudcode-build-legacy',
25
- builder_script: 'cloudcode-build-legacy'
26
- },
27
- {
28
- version: '1.11.1',
29
- // node: '14.21.3',
30
- // builder_package: '@journeyapps/cloudcode-build-legacy@1.12.0'
31
- // DEV HACK:
32
- node: '16.19.1', // because local dev on darwin/arm64 and there's no darwin-arm64 builds for node14 available.
33
- builder_package: '~/src/journey-cloudcode/packages/cloudcode-build-legacy',
34
- builder_script: 'cloudcode-build-legacy'
35
- },
36
- {
37
- version: '1.11.0',
38
- // node: '14.21.3',
39
- // builder_package: '@journeyapps/cloudcode-build-legacy@1.12.0'
40
- // DEV HACK:
41
- node: '16.19.1', // because local dev on darwin/arm64 and there's no darwin-arm64 builds for node14 available.
42
- builder_package: '~/src/journey-cloudcode/packages/cloudcode-build-legacy',
43
- builder_script: 'cloudcode-build-legacy'
44
- }
45
- ];
@@ -1,74 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
- import * as jetpack from 'fs-jetpack';
4
- import * as semver from 'semver';
5
- import * as defs from './defs';
6
-
7
- // TODO: validations for cloudcode specific keys and structure?
8
- async function readPackage(path: string) {
9
- try {
10
- const content = await fs.promises.readFile(path, { encoding: 'utf-8' });
11
- return JSON.parse(content);
12
- } catch (err) {
13
- console.error(`ERROR: ${err}`);
14
- throw err;
15
- // todo: check for enoent and skip?
16
- // todo: if json error, throw a CC build error?
17
- }
18
- }
19
-
20
- export async function detectTasks(project_path: string, only?: string) {
21
- const package_files = await jetpack.findAsync(path.join(project_path, 'cloudcode'), { matching: '**/package.json' });
22
- const filtered_package_files = package_files.filter((pkg_path) => {
23
- // FIXME: this is kinda clunky.
24
- const pm = /^\/?cloudcode\/([^\/]+)\/package\.json$/.exec(pkg_path);
25
- if (!pm) {
26
- return false;
27
- }
28
- const taskName = pm[1];
29
-
30
- if (only != null && only != taskName) {
31
- // !(only.indexOf(taskName) >= 0) // TODO: support a specific list of tasks to build?
32
- return false;
33
- }
34
- return true;
35
- });
36
-
37
- return Promise.all(
38
- filtered_package_files.map(async (pkg_path) => {
39
- const task_package = await readPackage(pkg_path);
40
-
41
- const task_name = task_package.name; // CAVEAT: the pkg name _must_ match the dir.
42
- const task_version = task_package?.cloudcode?.runtime;
43
- // FIXME: Do we want to filter out disabled tasks from the build process?
44
-
45
- console.debug(`Detected task version ${task_version}`);
46
-
47
- const matching = defs.SUPPORTED_VERSIONS.find((v) => {
48
- return semver.satisfies(v.version, task_version);
49
- });
50
- if (!matching) {
51
- throw new Error('FIXME: unsupported version');
52
- }
53
-
54
- console.debug(`Matching versions: ${JSON.stringify(matching)}`);
55
-
56
- const running_node_version = process.versions.node;
57
- let required_node_version;
58
- // if (matching?.node && semver.major(matching.node) !== semver.major(running_node_version)) {
59
- if (matching?.node && semver.parse(matching.node) !== semver.parse(running_node_version)) {
60
- console.debug(`Task requires different node version: v${matching.node}`);
61
-
62
- required_node_version = matching.node;
63
- }
64
- return {
65
- pkg_path,
66
- task_name,
67
- task_version,
68
- required_node_version,
69
- builder_package: matching.builder_package,
70
- builder_script: matching.builder_script
71
- };
72
- })
73
- );
74
- }
package/src/run.ts DELETED
@@ -1,23 +0,0 @@
1
- import { spawnStream, SpawnStreamEvent } from './spawn-stream';
2
- import { SpawnOptions } from 'child_process';
3
-
4
- export async function* runCommand(
5
- command: string,
6
- args: string[],
7
- options?: Partial<SpawnOptions>
8
- ): AsyncIterable<SpawnStreamEvent> {
9
- const { childProcess, stream } = spawnStream(command, args, { cwd: options?.cwd, splitLines: true, ...options });
10
-
11
- let exitCode: number | null = null;
12
-
13
- for await (let event of stream) {
14
- yield event;
15
- if (event.exitCode != null) {
16
- exitCode = event.exitCode;
17
- }
18
- }
19
-
20
- if (exitCode != 0) {
21
- throw new Error(`Command failed with code ${exitCode}`);
22
- }
23
- }
@@ -1,73 +0,0 @@
1
- import { ChildProcess, spawn, SpawnOptions } from 'child_process';
2
- import { PassThrough, Readable } from 'stream';
3
-
4
- export interface StreamOptions {
5
- splitLines?: boolean;
6
- }
7
-
8
- export function spawnStream(command: string, args: string[], options: SpawnOptions & StreamOptions) {
9
- const process = spawn(command, args, {
10
- ...options,
11
- stdio: 'pipe'
12
- });
13
-
14
- return {
15
- childProcess: process,
16
- stream: processToStream(process, options)
17
- };
18
- }
19
-
20
- export interface SpawnStreamEvent {
21
- event: 'stdout' | 'stderr' | 'exit';
22
- stdout?: string;
23
- stderr?: string;
24
- exitCode?: number;
25
- }
26
-
27
- function processToStream(process: ChildProcess, options: StreamOptions): AsyncIterable<SpawnStreamEvent> {
28
- const combinedStream = new PassThrough({ objectMode: true });
29
-
30
- async function* transform(stream: Readable, key: 'stdout' | 'stderr'): AsyncIterable<SpawnStreamEvent> {
31
- stream.setEncoding('utf-8');
32
- let iterable: AsyncIterable<string> = stream;
33
- if (options.splitLines) {
34
- iterable = splitLines(iterable);
35
- }
36
- for await (const chunk of iterable) {
37
- yield {
38
- event: key,
39
- [key]: chunk
40
- };
41
- }
42
- }
43
-
44
- if (process.stdout) {
45
- Readable.from(transform(process.stdout, 'stdout')).pipe(combinedStream, { end: false });
46
- }
47
- if (process.stderr) {
48
- Readable.from(transform(process.stderr, 'stderr')).pipe(combinedStream, { end: false });
49
- }
50
-
51
- process.on('exit', (code: number | null) => {
52
- combinedStream.write({ exitCode: code }, () => {
53
- combinedStream.end();
54
- });
55
- });
56
-
57
- return combinedStream;
58
- }
59
-
60
- async function* splitLines(stream: AsyncIterable<string>): AsyncIterable<string> {
61
- let buffer = '';
62
- for await (const chunk of stream) {
63
- buffer += chunk;
64
- const lines = buffer.split('\n');
65
- buffer = lines.pop()!;
66
- for (let line of lines) {
67
- yield `${line}\n`;
68
- }
69
- }
70
- if (buffer) {
71
- yield buffer;
72
- }
73
- }