@quadnix/octo-build 0.0.4

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 ADDED
@@ -0,0 +1,11 @@
1
+ # Octo
2
+ The open-source infrastructure management and CICD tool.
3
+
4
+ > Disclaimer,
5
+ > This library is currently in development.
6
+ > We will post a new release when it is ready for production.
7
+
8
+ # Local Setup
9
+ > npm install
10
+
11
+ > npm run prepare
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ import chalk from 'chalk';
3
+ import { accessSync, constants, existsSync, readFileSync } from 'fs';
4
+ import { load } from 'js-yaml';
5
+ import { join, resolve, sep } from 'path';
6
+ import * as process from 'process';
7
+ import yargs from 'yargs/yargs';
8
+ import { Main } from './main.js';
9
+ import { BuildFileParser } from './parsers/build-file.parser.js';
10
+ const PROGRAM_NAME = 'octob';
11
+ const USAGE = 'Usage: $0 ' +
12
+ '-b build.yml -s ~/path/to/my_project ' +
13
+ '[--concurrency 5]' +
14
+ '[--dryRun]' +
15
+ '[--logsDir /new/path]' +
16
+ '[--timeout 10000]';
17
+ const parser = yargs(process.argv.slice(2))
18
+ .scriptName(PROGRAM_NAME)
19
+ .options({
20
+ b: {
21
+ alias: 'buildFilePath',
22
+ demandOption: true,
23
+ description: 'The path to build file from sourcePath',
24
+ type: 'string',
25
+ },
26
+ s: { alias: 'sourcePath', demandOption: true, description: 'The path to source of project', type: 'string' },
27
+ })
28
+ .option('concurrency', {
29
+ default: 5,
30
+ description: 'The number of concurrent jobs to run. Defaults to 5',
31
+ type: 'number',
32
+ })
33
+ .option('dryRun', {
34
+ default: false,
35
+ description: 'Runs the program without actually executing any of the jobs. Defaults to FALSE',
36
+ type: 'boolean',
37
+ })
38
+ .option('logsDir', {
39
+ default: 'false',
40
+ description: 'Enables writing logs to files in the directory specified. Defaults to no write',
41
+ type: 'string',
42
+ })
43
+ .option('timeout', {
44
+ default: 0,
45
+ description: 'Defines the maximum amount of time (in minutes) this program can run. Defaults to INFINITE (0)',
46
+ type: 'number',
47
+ })
48
+ .usage(chalk.green(USAGE));
49
+ const argv = await parser.argv;
50
+ let { b: buildFilePath, s: sourcePath } = argv;
51
+ if (sourcePath.endsWith(sep)) {
52
+ sourcePath = sourcePath.substring(0, sourcePath.length - 1);
53
+ }
54
+ sourcePath = resolve(sourcePath);
55
+ if (buildFilePath.startsWith(sep)) {
56
+ buildFilePath = buildFilePath.substring(1);
57
+ }
58
+ buildFilePath = resolve(join(sourcePath, buildFilePath));
59
+ const logsDir = !argv.logsDir || argv.logsDir.toLowerCase() === 'false' ? undefined : resolve(argv.logsDir);
60
+ if (!existsSync(buildFilePath)) {
61
+ console.log(chalk.red('Cannot find build file: ' + buildFilePath));
62
+ process.exit(1);
63
+ }
64
+ try {
65
+ if (logsDir) {
66
+ accessSync(logsDir, constants.W_OK);
67
+ }
68
+ }
69
+ catch (error) {
70
+ console.log(chalk.red("Logs directory doesn't exist, or is not writable: " + logsDir));
71
+ process.exit(1);
72
+ }
73
+ const args = {
74
+ buildFilePath,
75
+ concurrency: argv.concurrency,
76
+ dryRun: argv.dryRun,
77
+ logsDir,
78
+ sourcePath,
79
+ timeout: argv.timeout,
80
+ };
81
+ let json;
82
+ try {
83
+ json = load(readFileSync(buildFilePath, 'utf-8'));
84
+ }
85
+ catch (error) {
86
+ console.log(chalk.red('Unable to parse build file: ' + error.message));
87
+ throw error;
88
+ }
89
+ const buildConfiguration = BuildFileParser.parse(json);
90
+ try {
91
+ const main = new Main(args, buildConfiguration);
92
+ await main.start();
93
+ console.log(chalk.green('Success'));
94
+ }
95
+ catch (error) {
96
+ console.log(chalk.red(error));
97
+ }
98
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { ChildProcessWithoutNullStreams } from 'child_process';
3
+ import { IBuildConfiguration } from './models/build-configuration.interface.js';
4
+ import { IRunArguments } from './models/run-arguments.interface.js';
5
+ export declare class Main {
6
+ private readonly args;
7
+ private readonly configuration;
8
+ constructor(args: IRunArguments, configuration: IBuildConfiguration);
9
+ runCommand(command: string, options: {
10
+ env: {
11
+ [key: string]: string;
12
+ };
13
+ sourcePath: string;
14
+ }): [ChildProcessWithoutNullStreams, Promise<void>];
15
+ scheduleJobs(): Promise<void>[];
16
+ start(): Promise<void>;
17
+ }
package/dist/main.js ADDED
@@ -0,0 +1,129 @@
1
+ import { mkdirSync } from 'fs';
2
+ import pLimit from 'p-limit';
3
+ import { join, resolve } from 'path';
4
+ import { StreamManager } from './streams/stream-manager.js';
5
+ import { ProcessUtility } from './utilities/process/process.utility.js';
6
+ export class Main {
7
+ args;
8
+ configuration;
9
+ constructor(args, configuration) {
10
+ this.args = args;
11
+ this.configuration = configuration;
12
+ }
13
+ runCommand(command, options) {
14
+ const spawnProcessOptions = { cwd: options.sourcePath, env: options.env, shell: true };
15
+ const runner = ProcessUtility.runDetachedProcess(command, spawnProcessOptions, 'pipe');
16
+ const promiseToFinishCommand = new Promise((resolve, reject) => {
17
+ runner.stderr.on('error', (error) => {
18
+ runner.kill();
19
+ reject(error);
20
+ });
21
+ runner.on('close', (exitCode) => {
22
+ runner.removeAllListeners();
23
+ if (exitCode === 0) {
24
+ resolve();
25
+ }
26
+ else {
27
+ const error = new Error('Command returned non-zero exit code!');
28
+ error['data'] = {
29
+ command,
30
+ exitCode,
31
+ };
32
+ reject(error);
33
+ }
34
+ });
35
+ });
36
+ return [runner, promiseToFinishCommand];
37
+ }
38
+ scheduleJobs() {
39
+ const streamManager = new StreamManager();
40
+ const timestamp = Date.now();
41
+ const logsPathPrefix = this.args.logsDir ? resolve(join(this.args.logsDir, `${timestamp}`)) : undefined;
42
+ if (logsPathPrefix) {
43
+ mkdirSync(logsPathPrefix, '0744');
44
+ }
45
+ const env = this.configuration.env;
46
+ const jobList = Object.keys(this.configuration.jobs);
47
+ const jobPromises = {};
48
+ const limit = pLimit(this.args.concurrency);
49
+ let i = 0;
50
+ let jobsScheduled = 0;
51
+ while (jobsScheduled !== jobList.length && i < jobList.length) {
52
+ for (const jobName of jobList) {
53
+ if (jobName in jobPromises) {
54
+ continue;
55
+ }
56
+ const job = this.configuration.jobs[jobName];
57
+ if (job.dependsOn.every((j) => j in jobPromises)) {
58
+ jobPromises[jobName] = limit(() => new Promise(async (resolve, reject) => {
59
+ try {
60
+ await Promise.all(job.dependsOn.map((j) => jobPromises[j]));
61
+ }
62
+ catch (error) {
63
+ reject(error);
64
+ return;
65
+ }
66
+ for (let i = 0; i <= job.retry; i++) {
67
+ const timeout = job.timeout > 0
68
+ ? setTimeout(() => {
69
+ job.onError === 'throw' ? reject(new Error('Job timed out! ' + jobName)) : resolve();
70
+ }, job.timeout)
71
+ : undefined;
72
+ try {
73
+ if (!this.args.dryRun) {
74
+ const [stream, promiseToFinishCommand] = this.runCommand(job.command, {
75
+ env,
76
+ sourcePath: this.args.sourcePath,
77
+ });
78
+ streamManager.registerStream(jobName, stream, { logsPathPrefix });
79
+ await promiseToFinishCommand;
80
+ }
81
+ resolve();
82
+ break;
83
+ }
84
+ catch (error) {
85
+ if (i === job.retry) {
86
+ job.onError === 'throw' ? reject(error) : resolve();
87
+ }
88
+ }
89
+ finally {
90
+ if (timeout) {
91
+ clearTimeout(timeout);
92
+ }
93
+ }
94
+ }
95
+ }));
96
+ jobsScheduled += 1;
97
+ }
98
+ }
99
+ i += 1;
100
+ }
101
+ if (jobsScheduled !== jobList.length) {
102
+ throw new Error('Unable to schedule all jobs. Possible circular dependency!');
103
+ }
104
+ return Object.values(jobPromises);
105
+ }
106
+ start() {
107
+ return new Promise(async (resolve, reject) => {
108
+ const timeout = this.args.timeout > 0
109
+ ? setTimeout(() => {
110
+ reject(new Error(`Reached timeout of ${this.args.timeout} ms!`));
111
+ }, this.args.timeout)
112
+ : undefined;
113
+ try {
114
+ const jobPromises = this.scheduleJobs();
115
+ await Promise.all(jobPromises);
116
+ resolve();
117
+ }
118
+ catch (error) {
119
+ reject(error);
120
+ }
121
+ finally {
122
+ if (timeout) {
123
+ clearTimeout(timeout);
124
+ }
125
+ }
126
+ });
127
+ }
128
+ }
129
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface IJob {
2
+ command: string;
3
+ dependsOn: string[];
4
+ onError: 'ignore' | 'throw';
5
+ retry: number;
6
+ timeout: number;
7
+ }
8
+ export interface IBuildConfiguration {
9
+ dist: string;
10
+ env: {
11
+ [key: string]: string;
12
+ };
13
+ jobs: {
14
+ [key: string]: IJob;
15
+ };
16
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=build-configuration.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-configuration.interface.js","sourceRoot":"","sources":["../../src/models/build-configuration.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export interface IRunArguments {
2
+ buildFilePath: string;
3
+ concurrency: number;
4
+ dryRun: boolean;
5
+ logsDir?: string | undefined;
6
+ sourcePath: string;
7
+ timeout: number;
8
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=run-arguments.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-arguments.interface.js","sourceRoot":"","sources":["../../src/models/run-arguments.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import { IBuildConfiguration } from '../models/build-configuration.interface.js';
2
+ export declare class BuildFileParser {
3
+ static parse(content: any): IBuildConfiguration;
4
+ }
@@ -0,0 +1,28 @@
1
+ export class BuildFileParser {
2
+ static parse(content) {
3
+ const jobs = {};
4
+ for (const jobName of Object.keys(content?.jobs || {})) {
5
+ const job = content.jobs[jobName];
6
+ if (!job.command) {
7
+ throw new Error('Missing required property - jobs > command');
8
+ }
9
+ jobs[jobName] = {
10
+ command: job.command,
11
+ dependsOn: job.dependsOn || [],
12
+ onError: job.onError?.toLowerCase() || 'throw',
13
+ retry: Number(job.retry) || 0,
14
+ timeout: Number(job.timeout) || 0,
15
+ };
16
+ }
17
+ return {
18
+ dist: content?.dist || '',
19
+ env: content?.env?.variables &&
20
+ typeof content.env.variables === 'object' &&
21
+ Object.keys(content.env.variables).length > 0
22
+ ? content.env.variables
23
+ : {},
24
+ jobs,
25
+ };
26
+ }
27
+ }
28
+ //# sourceMappingURL=build-file.parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-file.parser.js","sourceRoot":"","sources":["../../src/parsers/build-file.parser.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAe;IAC1B,MAAM,CAAC,KAAK,CAAC,OAAY;QACvB,MAAM,IAAI,GAA4B,EAAE,CAAC;QACzC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;YACvD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAChE,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,GAAG;gBACd,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE;gBAC9B,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,OAAO;gBAC9C,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC7B,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;aAClC,CAAC;QACJ,CAAC;QAED,OAAO;YACL,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE;YACzB,GAAG,EACD,OAAO,EAAE,GAAG,EAAE,SAAS;gBACvB,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,QAAQ;gBACzC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC;gBAC3C,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS;gBACvB,CAAC,CAAC,EAAE;YACR,IAAI;SACL,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { ChildProcessWithoutNullStreams } from 'child_process';
3
+ export declare class StreamManager {
4
+ private colors;
5
+ registerStream(jobName: string, stream: ChildProcessWithoutNullStreams, options: {
6
+ logsPathPrefix?: string;
7
+ }): void;
8
+ }
@@ -0,0 +1,33 @@
1
+ import chalk from 'chalk';
2
+ import { createWriteStream } from 'fs';
3
+ import { join, resolve } from 'path';
4
+ export class StreamManager {
5
+ colors = {
6
+ BLUE: chalk.blue,
7
+ CYAN: chalk.cyan,
8
+ GREEN: chalk.green,
9
+ MAGENTA: chalk.magenta,
10
+ YELLOW: chalk.yellow,
11
+ };
12
+ registerStream(jobName, stream, options) {
13
+ const colorKeys = Object.keys(this.colors);
14
+ const randomColor = this.colors[colorKeys[(colorKeys.length * Math.random()) << 0]];
15
+ stream.stdout.on('data', (data) => {
16
+ console.log(randomColor(data.toString()));
17
+ });
18
+ stream.stderr.on('error', (error) => {
19
+ console.log(chalk.red(error));
20
+ });
21
+ stream.on('close', () => {
22
+ stream.removeAllListeners();
23
+ });
24
+ if (options.logsPathPrefix) {
25
+ const writeStream = createWriteStream(resolve(join(options.logsPathPrefix, `${jobName}.log`)), {
26
+ flags: 'w',
27
+ });
28
+ stream.stdout.pipe(writeStream);
29
+ stream.stderr.pipe(writeStream);
30
+ }
31
+ }
32
+ }
33
+ //# sourceMappingURL=stream-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-manager.js","sourceRoot":"","sources":["../../src/streams/stream-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAwB,MAAM,OAAO,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,OAAO,aAAa;IAChB,MAAM,GAAG;QACf,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC;IAEF,cAAc,CAAC,OAAe,EAAE,MAAsC,EAAE,OAAoC;QAC1G,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,WAAW,GAAkB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEnG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;YAC3B,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,GAAG,OAAO,MAAM,CAAC,CAAC,EAAE;gBAC7F,KAAK,EAAE,GAAG;aACX,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { ChildProcessWithoutNullStreams, SpawnOptionsWithoutStdio } from 'child_process';
3
+ export declare class ProcessUtility {
4
+ static runDetachedProcess(command: string, options: SpawnOptionsWithoutStdio, outputWriter: any): ChildProcessWithoutNullStreams;
5
+ }
@@ -0,0 +1,15 @@
1
+ import { spawn } from 'child_process';
2
+ export class ProcessUtility {
3
+ static runDetachedProcess(command, options, outputWriter) {
4
+ options = options || {};
5
+ options.detached = true;
6
+ options.stdio = ['ignore', outputWriter, outputWriter];
7
+ options.env = options.env || {};
8
+ let firstSpaceIndex = command.indexOf(' ');
9
+ firstSpaceIndex = firstSpaceIndex === -1 ? command.length : firstSpaceIndex;
10
+ const program = command.substring(0, firstSpaceIndex);
11
+ const parameters = [command.substring(firstSpaceIndex + 1)];
12
+ return spawn(program, parameters, options);
13
+ }
14
+ }
15
+ //# sourceMappingURL=process.utility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.utility.js","sourceRoot":"","sources":["../../../src/utilities/process/process.utility.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4D,KAAK,EAAE,MAAM,eAAe,CAAC;AAEhG,MAAM,OAAO,cAAc;IACzB,MAAM,CAAC,kBAAkB,CACvB,OAAe,EACf,OAAiC,EACjC,YAAiB;QAEjB,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;QACxB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;QACxB,OAAO,CAAC,KAAK,GAAG,CAAC,QAAQ,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;QAEhC,IAAI,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3C,eAAe,GAAG,eAAe,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC;QAE5E,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;QACtD,MAAM,UAAU,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5D,OAAO,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "bin": {
3
+ "octob": "./dist/index.js"
4
+ },
5
+ "bugs": {
6
+ "url": "https://github.com/quadnix/octo/issues"
7
+ },
8
+ "dependencies": {
9
+ "chalk": "~5.3.0",
10
+ "js-yaml": "~4.1.0",
11
+ "p-limit": "~4.0.0",
12
+ "yargs": "~17.7.2"
13
+ },
14
+ "description": "Octo-Build is a CLI tool to build Octo projects.",
15
+ "devDependencies": {
16
+ "@types/js-yaml": "~4.0.8",
17
+ "@types/yargs": "~17.0.29"
18
+ },
19
+ "engines": {
20
+ "node": ">=16"
21
+ },
22
+ "exports": "./dist/index.js",
23
+ "files": [
24
+ "dist",
25
+ "!dist/tsconfig.build.tsbuildinfo",
26
+ "package.json"
27
+ ],
28
+ "homepage": "https://github.com/quadnix/octo#readme",
29
+ "jest": {
30
+ "coverageDirectory": "./coverage",
31
+ "extensionsToTreatAsEsm": [
32
+ ".ts"
33
+ ],
34
+ "moduleFileExtensions": [
35
+ "js",
36
+ "json",
37
+ "ts"
38
+ ],
39
+ "moduleNameMapper": {
40
+ "(.+)\\.js": "$1"
41
+ },
42
+ "preset": "ts-jest/presets/default-esm",
43
+ "rootDir": ".",
44
+ "testEnvironment": "node",
45
+ "testRegex": ".*spec\\.ts$",
46
+ "transform": {
47
+ "^.+\\.ts$": [
48
+ "ts-jest",
49
+ {
50
+ "useESM": true
51
+ }
52
+ ]
53
+ }
54
+ },
55
+ "keywords": [
56
+ "cdk",
57
+ "cicd",
58
+ "infrastructure",
59
+ "octo"
60
+ ],
61
+ "license": "MIT",
62
+ "main": "./dist/index.js",
63
+ "name": "@quadnix/octo-build",
64
+ "nx": {
65
+ "tags": [
66
+ "scope:octo-build"
67
+ ]
68
+ },
69
+ "publishConfig": {
70
+ "access": "public"
71
+ },
72
+ "repository": {
73
+ "type": "git",
74
+ "url": "git+https://github.com/quadnix/octo.git"
75
+ },
76
+ "scripts": {
77
+ "build": "rimraf dist && tsc -p tsconfig.build.json && chmod +x ./dist/index.js",
78
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
79
+ "lint": "eslint .",
80
+ "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
81
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest --testRegex=\"\\.spec.ts$\"",
82
+ "test:cov": "jest --coverage --testRegex=\"\\.spec.ts$\"",
83
+ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
84
+ "test:e2e": "jest --testRegex=\"\\.e2e-spec.ts$\"",
85
+ "test:integration": "jest --testRegex=\"\\.ispec.ts$\"",
86
+ "test:watch": "jest --watch"
87
+ },
88
+ "type": "module",
89
+ "types": "./dist/index.d.ts",
90
+ "version": "0.0.4"
91
+ }