evolved-monkey 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/src/cli.d.ts +15 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +63 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/challenge-init.d.ts +15 -0
- package/dist/src/commands/challenge-init.d.ts.map +1 -0
- package/dist/src/commands/challenge-init.js +98 -0
- package/dist/src/commands/challenge-init.js.map +1 -0
- package/dist/src/commands/challenge-submit.d.ts +21 -0
- package/dist/src/commands/challenge-submit.d.ts.map +1 -0
- package/dist/src/commands/challenge-submit.js +52 -0
- package/dist/src/commands/challenge-submit.js.map +1 -0
- package/dist/src/commands/challenge-validate.d.ts +13 -0
- package/dist/src/commands/challenge-validate.d.ts.map +1 -0
- package/dist/src/commands/challenge-validate.js +28 -0
- package/dist/src/commands/challenge-validate.js.map +1 -0
- package/dist/src/constants.d.ts +6 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +12 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +20 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib/args.d.ts +3 -0
- package/dist/src/lib/args.d.ts.map +1 -0
- package/dist/src/lib/args.js +24 -0
- package/dist/src/lib/args.js.map +1 -0
- package/dist/src/lib/backend-client.d.ts +10 -0
- package/dist/src/lib/backend-client.d.ts.map +1 -0
- package/dist/src/lib/backend-client.js +86 -0
- package/dist/src/lib/backend-client.js.map +1 -0
- package/dist/src/lib/cli-error.d.ts +12 -0
- package/dist/src/lib/cli-error.d.ts.map +1 -0
- package/dist/src/lib/cli-error.js +13 -0
- package/dist/src/lib/cli-error.js.map +1 -0
- package/dist/src/lib/fs-utils.d.ts +6 -0
- package/dist/src/lib/fs-utils.d.ts.map +1 -0
- package/dist/src/lib/fs-utils.js +39 -0
- package/dist/src/lib/fs-utils.js.map +1 -0
- package/dist/src/lib/tarball.d.ts +7 -0
- package/dist/src/lib/tarball.d.ts.map +1 -0
- package/dist/src/lib/tarball.js +23 -0
- package/dist/src/lib/tarball.js.map +1 -0
- package/dist/src/lib/workspace.d.ts +21 -0
- package/dist/src/lib/workspace.d.ts.map +1 -0
- package/dist/src/lib/workspace.js +107 -0
- package/dist/src/lib/workspace.js.map +1 -0
- package/dist/src/types.d.ts +39 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/tests/helpers/test-utils.d.ts +5 -0
- package/dist/tests/helpers/test-utils.d.ts.map +1 -0
- package/dist/tests/helpers/test-utils.js +26 -0
- package/dist/tests/helpers/test-utils.js.map +1 -0
- package/dist/tests/integration/submit-flow.spec.d.ts +2 -0
- package/dist/tests/integration/submit-flow.spec.d.ts.map +1 -0
- package/dist/tests/integration/submit-flow.spec.js +172 -0
- package/dist/tests/integration/submit-flow.spec.js.map +1 -0
- package/dist/tests/run-tests.d.ts +2 -0
- package/dist/tests/run-tests.d.ts.map +1 -0
- package/dist/tests/run-tests.js +33 -0
- package/dist/tests/run-tests.js.map +1 -0
- package/dist/tests/unit/cli-commands.spec.d.ts +2 -0
- package/dist/tests/unit/cli-commands.spec.d.ts.map +1 -0
- package/dist/tests/unit/cli-commands.spec.js +73 -0
- package/dist/tests/unit/cli-commands.spec.js.map +1 -0
- package/docs/01.md +39 -0
- package/package.json +22 -0
- package/src/cli.ts +86 -0
- package/src/commands/challenge-init.ts +162 -0
- package/src/commands/challenge-submit.ts +101 -0
- package/src/commands/challenge-validate.ts +48 -0
- package/src/constants.ts +13 -0
- package/src/index.ts +21 -0
- package/src/lib/args.ts +31 -0
- package/src/lib/backend-client.ts +129 -0
- package/src/lib/cli-error.ts +19 -0
- package/src/lib/fs-utils.ts +47 -0
- package/src/lib/tarball.ts +42 -0
- package/src/lib/workspace.ts +168 -0
- package/src/types.ts +45 -0
- package/tests/fixtures/invalid-workspace/challenge.config.json +11 -0
- package/tests/fixtures/invalid-workspace/starter/package.json +5 -0
- package/tests/fixtures/invalid-workspace/starter/src/index.js +3 -0
- package/tests/fixtures/valid-workspace/challenge.config.json +11 -0
- package/tests/fixtures/valid-workspace/starter/package.json +9 -0
- package/tests/fixtures/valid-workspace/starter/src/index.js +3 -0
- package/tests/fixtures/valid-workspace/tests/package.json +8 -0
- package/tests/fixtures/valid-workspace/tests/spec/basic.test.js +6 -0
- package/tests/helpers/test-utils.ts +32 -0
- package/tests/integration/submit-flow.spec.ts +207 -0
- package/tests/run-tests.ts +42 -0
- package/tests/snapshots/init-result.json +5 -0
- package/tests/unit/cli-commands.spec.ts +105 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function ensureDir(dirPath: string): Promise<void>;
|
|
2
|
+
export declare function pathExists(targetPath: string): Promise<boolean>;
|
|
3
|
+
export declare function readJsonFile<T>(filePath: string): Promise<T>;
|
|
4
|
+
export declare function writeJsonFile(filePath: string, value: unknown): Promise<void>;
|
|
5
|
+
export declare function walkFilesRecursively(rootDir: string): Promise<string[]>;
|
|
6
|
+
//# sourceMappingURL=fs-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/fs-utils.ts"],"names":[],"mappings":"AAGA,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOrE;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAGlE;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnF;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoB7E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function ensureDir(dirPath) {
|
|
4
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
5
|
+
}
|
|
6
|
+
export async function pathExists(targetPath) {
|
|
7
|
+
try {
|
|
8
|
+
await fs.access(targetPath);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function readJsonFile(filePath) {
|
|
16
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
17
|
+
return JSON.parse(content);
|
|
18
|
+
}
|
|
19
|
+
export async function writeJsonFile(filePath, value) {
|
|
20
|
+
const content = JSON.stringify(value, null, 2);
|
|
21
|
+
await fs.writeFile(filePath, `${content}\n`, "utf8");
|
|
22
|
+
}
|
|
23
|
+
export async function walkFilesRecursively(rootDir) {
|
|
24
|
+
const files = [];
|
|
25
|
+
async function visit(currentDir) {
|
|
26
|
+
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
const absolutePath = path.join(currentDir, entry.name);
|
|
29
|
+
if (entry.isDirectory()) {
|
|
30
|
+
await visit(absolutePath);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
files.push(absolutePath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
await visit(rootDir);
|
|
37
|
+
return files;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=fs-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../../../src/lib/fs-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe;IAC7C,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB;IACjD,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,QAAgB;IACpD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,KAAc;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/C,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,OAAO,IAAI,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAe;IACxD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,UAAU,KAAK,CAAC,UAAkB;QACrC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAEtE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAEvD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC;gBAC1B,SAAS;YACX,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type CreateTarballInput = {
|
|
2
|
+
excludePatterns?: readonly string[];
|
|
3
|
+
outputFile: string;
|
|
4
|
+
sourceDir: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function createTarGzFromDirectory({ outputFile, sourceDir, excludePatterns, }: CreateTarballInput): void;
|
|
7
|
+
//# sourceMappingURL=tarball.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tarball.d.ts","sourceRoot":"","sources":["../../../src/lib/tarball.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,EACvC,UAAU,EACV,SAAS,EACT,eAAoB,GACrB,EAAE,kBAAkB,GAAG,IAAI,CA2B3B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { CliError } from "./cli-error.js";
|
|
3
|
+
export function createTarGzFromDirectory({ outputFile, sourceDir, excludePatterns = [], }) {
|
|
4
|
+
const args = ["-czf", outputFile];
|
|
5
|
+
for (const pattern of excludePatterns) {
|
|
6
|
+
args.push("--exclude", pattern);
|
|
7
|
+
}
|
|
8
|
+
args.push("-C", sourceDir, ".");
|
|
9
|
+
const result = spawnSync("tar", args, { encoding: "utf8" });
|
|
10
|
+
if (result.error) {
|
|
11
|
+
throw new CliError("Unable to create tar.gz archive. Ensure `tar` is installed and available in PATH.", {
|
|
12
|
+
code: "TAR_COMMAND_MISSING",
|
|
13
|
+
details: result.error.message,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
if (result.status !== 0) {
|
|
17
|
+
throw new CliError("Failed to create tar.gz archive.", {
|
|
18
|
+
code: "TAR_ARCHIVE_FAILED",
|
|
19
|
+
details: result.stderr || result.stdout,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=tarball.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tarball.js","sourceRoot":"","sources":["../../../src/lib/tarball.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAQ1C,MAAM,UAAU,wBAAwB,CAAC,EACvC,UAAU,EACV,SAAS,EACT,eAAe,GAAG,EAAE,GACD;IACnB,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAElC,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAE5D,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,QAAQ,CAChB,mFAAmF,EACnF;YACE,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO;SAC9B,CACF,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,QAAQ,CAAC,kCAAkC,EAAE;YACrD,IAAI,EAAE,oBAAoB;YAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM;SACxC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type ChallengeWorkspaceConfig = {
|
|
2
|
+
backendBaseUrl: string;
|
|
3
|
+
challengeId: string | null;
|
|
4
|
+
constraintsMd: string;
|
|
5
|
+
createdAt: string;
|
|
6
|
+
descriptionMd: string;
|
|
7
|
+
slug: string;
|
|
8
|
+
title: string;
|
|
9
|
+
type: "EXPRESS_NODE";
|
|
10
|
+
version: number;
|
|
11
|
+
};
|
|
12
|
+
export type WorkspaceValidationResult = {
|
|
13
|
+
errors: string[];
|
|
14
|
+
ok: boolean;
|
|
15
|
+
warnings: string[];
|
|
16
|
+
};
|
|
17
|
+
export declare function normalizeSlug(slug: unknown): string;
|
|
18
|
+
export declare function ensureValidSlug(slug: unknown): string;
|
|
19
|
+
export declare function loadChallengeConfig(workspaceDir: string): Promise<ChallengeWorkspaceConfig>;
|
|
20
|
+
export declare function validateWorkspace(workspaceDir: string): Promise<WorkspaceValidationResult>;
|
|
21
|
+
//# sourceMappingURL=workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../../src/lib/workspace.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,wBAAwB,GAAG;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAInD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAarD;AAED,wBAAsB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAUjG;AAED,wBAAsB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAuGhG"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { CHALLENGE_CONFIG_FILE, CONSTRAINTS_PLACEHOLDER, DESCRIPTION_PLACEHOLDER, } from "../constants.js";
|
|
4
|
+
import { CliError } from "./cli-error.js";
|
|
5
|
+
import { pathExists, readJsonFile, walkFilesRecursively } from "./fs-utils.js";
|
|
6
|
+
const challengeSlugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
7
|
+
export function normalizeSlug(slug) {
|
|
8
|
+
return String(slug ?? "")
|
|
9
|
+
.trim()
|
|
10
|
+
.toLowerCase();
|
|
11
|
+
}
|
|
12
|
+
export function ensureValidSlug(slug) {
|
|
13
|
+
const value = normalizeSlug(slug);
|
|
14
|
+
if (!challengeSlugRegex.test(value)) {
|
|
15
|
+
throw new CliError("Slug must be lowercase kebab-case (letters, numbers, and hyphens only).", {
|
|
16
|
+
code: "INVALID_SLUG",
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
export async function loadChallengeConfig(workspaceDir) {
|
|
22
|
+
const configPath = path.join(workspaceDir, CHALLENGE_CONFIG_FILE);
|
|
23
|
+
if (!(await pathExists(configPath))) {
|
|
24
|
+
throw new CliError(`Missing ${CHALLENGE_CONFIG_FILE} in ${workspaceDir}`, {
|
|
25
|
+
code: "MISSING_CONFIG_FILE",
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return readJsonFile(configPath);
|
|
29
|
+
}
|
|
30
|
+
export async function validateWorkspace(workspaceDir) {
|
|
31
|
+
const errors = [];
|
|
32
|
+
const warnings = [];
|
|
33
|
+
const configPath = path.join(workspaceDir, CHALLENGE_CONFIG_FILE);
|
|
34
|
+
if (!(await pathExists(configPath))) {
|
|
35
|
+
errors.push(`Missing ${CHALLENGE_CONFIG_FILE}.`);
|
|
36
|
+
return { errors, ok: false, warnings };
|
|
37
|
+
}
|
|
38
|
+
const config = await readJsonFile(configPath);
|
|
39
|
+
const slug = normalizeSlug(config.slug);
|
|
40
|
+
if (!challengeSlugRegex.test(slug)) {
|
|
41
|
+
errors.push("Config slug is invalid. Use lowercase kebab-case.");
|
|
42
|
+
}
|
|
43
|
+
if (!config.title || String(config.title).trim().length < 3) {
|
|
44
|
+
errors.push("Config title must be at least 3 characters.");
|
|
45
|
+
}
|
|
46
|
+
if (!config.descriptionMd || String(config.descriptionMd).trim().length < 20) {
|
|
47
|
+
errors.push("Config descriptionMd must be at least 20 characters.");
|
|
48
|
+
}
|
|
49
|
+
if (String(config.descriptionMd).includes(DESCRIPTION_PLACEHOLDER)) {
|
|
50
|
+
errors.push("Replace description placeholder in challenge.config.json.");
|
|
51
|
+
}
|
|
52
|
+
if (!config.constraintsMd || String(config.constraintsMd).trim().length < 20) {
|
|
53
|
+
errors.push("Config constraintsMd must be at least 20 characters.");
|
|
54
|
+
}
|
|
55
|
+
if (String(config.constraintsMd).includes(CONSTRAINTS_PLACEHOLDER)) {
|
|
56
|
+
errors.push("Replace constraints placeholder in challenge.config.json.");
|
|
57
|
+
}
|
|
58
|
+
if (config.type !== "EXPRESS_NODE") {
|
|
59
|
+
errors.push("Only EXPRESS_NODE challenges are supported in V0.");
|
|
60
|
+
}
|
|
61
|
+
const starterDir = path.join(workspaceDir, "starter");
|
|
62
|
+
const testsDir = path.join(workspaceDir, "tests");
|
|
63
|
+
if (!(await pathExists(path.join(starterDir, "package.json")))) {
|
|
64
|
+
errors.push("starter/package.json is required.");
|
|
65
|
+
}
|
|
66
|
+
if (!(await pathExists(path.join(testsDir, "package.json")))) {
|
|
67
|
+
errors.push("tests/package.json is required.");
|
|
68
|
+
}
|
|
69
|
+
const disallowedPaths = [
|
|
70
|
+
path.join(starterDir, "node_modules"),
|
|
71
|
+
path.join(testsDir, "node_modules"),
|
|
72
|
+
path.join(starterDir, ".env"),
|
|
73
|
+
path.join(testsDir, ".env"),
|
|
74
|
+
];
|
|
75
|
+
for (const targetPath of disallowedPaths) {
|
|
76
|
+
if (await pathExists(targetPath)) {
|
|
77
|
+
errors.push(`Disallowed path present: ${path.relative(workspaceDir, targetPath)}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (await pathExists(starterDir)) {
|
|
81
|
+
const starterFiles = await walkFilesRecursively(starterDir);
|
|
82
|
+
const hiddenTestsInStarter = starterFiles.filter((filePath) => path.basename(filePath).match(/\.test\.[jt]sx?$/));
|
|
83
|
+
if (hiddenTestsInStarter.length > 0) {
|
|
84
|
+
errors.push("Starter must not include hidden test files.");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (await pathExists(testsDir)) {
|
|
88
|
+
const testFiles = await walkFilesRecursively(testsDir);
|
|
89
|
+
const matchingTestFiles = testFiles.filter((filePath) => path.basename(filePath).match(/\.test\.[jt]sx?$/));
|
|
90
|
+
if (matchingTestFiles.length === 0) {
|
|
91
|
+
errors.push("Hidden tests package must include at least one *.test.js or *.test.ts file.");
|
|
92
|
+
}
|
|
93
|
+
const externalUrlRegex = /https?:\/\/(?!localhost|127\.0\.0\.1)/i;
|
|
94
|
+
for (const filePath of matchingTestFiles) {
|
|
95
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
96
|
+
if (externalUrlRegex.test(content)) {
|
|
97
|
+
warnings.push(`Potential external network usage found in tests file: ${path.relative(workspaceDir, filePath)}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
errors,
|
|
103
|
+
ok: errors.length === 0,
|
|
104
|
+
warnings,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/lib/workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type FlagValue = string | boolean;
|
|
2
|
+
export type CliFlags = Record<string, FlagValue | undefined>;
|
|
3
|
+
export type ParsedArgs = {
|
|
4
|
+
flags: CliFlags;
|
|
5
|
+
positionals: string[];
|
|
6
|
+
};
|
|
7
|
+
export type Logger = (...args: string[]) => void;
|
|
8
|
+
export type ChallengeDraftPayload = {
|
|
9
|
+
constraintsMd: string;
|
|
10
|
+
descriptionMd: string;
|
|
11
|
+
slug: string;
|
|
12
|
+
title: string;
|
|
13
|
+
type: "EXPRESS_NODE";
|
|
14
|
+
};
|
|
15
|
+
export type ChallengeDraftResponse = {
|
|
16
|
+
id: string;
|
|
17
|
+
slug: string;
|
|
18
|
+
title: string;
|
|
19
|
+
type: "EXPRESS_NODE";
|
|
20
|
+
};
|
|
21
|
+
export type ArtifactUploadTarget = {
|
|
22
|
+
expiresInSeconds: number;
|
|
23
|
+
headers: Record<string, string>;
|
|
24
|
+
key: string;
|
|
25
|
+
method: "PUT";
|
|
26
|
+
url: string;
|
|
27
|
+
};
|
|
28
|
+
export type ArtifactUploadResponse = {
|
|
29
|
+
challengeId: string;
|
|
30
|
+
challengeSlug: string;
|
|
31
|
+
upload: ArtifactUploadTarget;
|
|
32
|
+
};
|
|
33
|
+
export interface BackendClientContract {
|
|
34
|
+
createChallengeDraft(input: ChallengeDraftPayload): Promise<ChallengeDraftResponse>;
|
|
35
|
+
requestStarterUpload(slug: string): Promise<ArtifactUploadResponse>;
|
|
36
|
+
requestTestsUpload(slug: string): Promise<ArtifactUploadResponse>;
|
|
37
|
+
uploadArtifact(upload: ArtifactUploadTarget, fileBuffer: Buffer): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AACzC,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,CAAC;AAE7D,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAEjD,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,KAAK,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,oBAAoB,CAAC;CAC9B,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,oBAAoB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACpF,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACpE,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAClE,cAAc,CAAC,MAAM,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function createTempDir(prefix: string): Promise<string>;
|
|
2
|
+
export declare function copyDir(sourceDir: string, destinationDir: string): Promise<void>;
|
|
3
|
+
export declare function resolveFixturePath(relativePath: string): string;
|
|
4
|
+
export declare function resolveSnapshotPath(relativePath: string): string;
|
|
5
|
+
//# sourceMappingURL=test-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../tests/helpers/test-utils.ts"],"names":[],"mappings":"AAIA,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;AAED,wBAAsB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAetF;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export async function createTempDir(prefix) {
|
|
5
|
+
return fs.mkdtemp(path.join(os.tmpdir(), prefix));
|
|
6
|
+
}
|
|
7
|
+
export async function copyDir(sourceDir, destinationDir) {
|
|
8
|
+
await fs.mkdir(destinationDir, { recursive: true });
|
|
9
|
+
const entries = await fs.readdir(sourceDir, { withFileTypes: true });
|
|
10
|
+
for (const entry of entries) {
|
|
11
|
+
const sourcePath = path.join(sourceDir, entry.name);
|
|
12
|
+
const destinationPath = path.join(destinationDir, entry.name);
|
|
13
|
+
if (entry.isDirectory()) {
|
|
14
|
+
await copyDir(sourcePath, destinationPath);
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
await fs.copyFile(sourcePath, destinationPath);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function resolveFixturePath(relativePath) {
|
|
21
|
+
return path.resolve(process.cwd(), "tests", "fixtures", relativePath);
|
|
22
|
+
}
|
|
23
|
+
export function resolveSnapshotPath(relativePath) {
|
|
24
|
+
return path.resolve(process.cwd(), "tests", "snapshots", relativePath);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=test-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../../tests/helpers/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc;IAChD,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,SAAiB,EAAE,cAAsB;IACrE,MAAM,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAErE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE9D,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,OAAO,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;YAC3C,SAAS;QACX,CAAC;QAED,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,YAAoB;IACrD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submit-flow.spec.d.ts","sourceRoot":"","sources":["../../../tests/integration/submit-flow.spec.ts"],"names":[],"mappings":"AA6JA,wBAAsB,6BAA6B,kBAiDlD"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import http from "node:http";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { runCli } from "../../src/cli.js";
|
|
6
|
+
import { createTempDir } from "../helpers/test-utils.js";
|
|
7
|
+
function createTestBackendServer() {
|
|
8
|
+
const uploadStats = {
|
|
9
|
+
starterBytes: 0,
|
|
10
|
+
starterUploads: 0,
|
|
11
|
+
testsBytes: 0,
|
|
12
|
+
testsUploads: 0,
|
|
13
|
+
};
|
|
14
|
+
let server;
|
|
15
|
+
function sendJson(response, statusCode, body) {
|
|
16
|
+
response.writeHead(statusCode, { "content-type": "application/json" });
|
|
17
|
+
response.end(JSON.stringify(body));
|
|
18
|
+
}
|
|
19
|
+
function readBody(request) {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
const chunks = [];
|
|
22
|
+
request.on("data", (chunk) => chunks.push(chunk));
|
|
23
|
+
request.on("end", () => resolve(Buffer.concat(chunks)));
|
|
24
|
+
request.on("error", reject);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async function handler(request, response) {
|
|
28
|
+
const host = request.headers.host;
|
|
29
|
+
const baseUrl = `http://${host}`;
|
|
30
|
+
const pathname = new URL(request.url ?? "/", baseUrl).pathname;
|
|
31
|
+
if (request.method === "POST" && pathname === "/v1/creator/challenges/init") {
|
|
32
|
+
const bodyBuffer = await readBody(request);
|
|
33
|
+
const payload = JSON.parse(bodyBuffer.toString("utf8"));
|
|
34
|
+
sendJson(response, 201, {
|
|
35
|
+
data: {
|
|
36
|
+
challenge: {
|
|
37
|
+
id: "challenge-integration-id",
|
|
38
|
+
slug: payload.slug,
|
|
39
|
+
title: payload.title,
|
|
40
|
+
type: "EXPRESS_NODE",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
success: true,
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const starterUploadMatch = pathname.match(/^\/v1\/creator\/challenges\/([^/]+)\/artifacts\/starter\/upload-url$/);
|
|
48
|
+
if (request.method === "POST" && starterUploadMatch) {
|
|
49
|
+
const slug = decodeURIComponent(starterUploadMatch[1] ?? "");
|
|
50
|
+
sendJson(response, 200, {
|
|
51
|
+
data: {
|
|
52
|
+
challengeId: "challenge-integration-id",
|
|
53
|
+
challengeSlug: slug,
|
|
54
|
+
upload: {
|
|
55
|
+
expiresInSeconds: 900,
|
|
56
|
+
headers: { "content-type": "application/gzip" },
|
|
57
|
+
key: "challenges/challenge-integration-id/starter/mock.tar.gz",
|
|
58
|
+
method: "PUT",
|
|
59
|
+
url: `${baseUrl}/upload/starter`,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
success: true,
|
|
63
|
+
});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const testsUploadMatch = pathname.match(/^\/v1\/creator\/challenges\/([^/]+)\/artifacts\/tests\/upload-url$/);
|
|
67
|
+
if (request.method === "POST" && testsUploadMatch) {
|
|
68
|
+
const slug = decodeURIComponent(testsUploadMatch[1] ?? "");
|
|
69
|
+
sendJson(response, 200, {
|
|
70
|
+
data: {
|
|
71
|
+
challengeId: "challenge-integration-id",
|
|
72
|
+
challengeSlug: slug,
|
|
73
|
+
upload: {
|
|
74
|
+
expiresInSeconds: 900,
|
|
75
|
+
headers: { "content-type": "application/gzip" },
|
|
76
|
+
key: "challenges/challenge-integration-id/tests/mock.tar.gz",
|
|
77
|
+
method: "PUT",
|
|
78
|
+
url: `${baseUrl}/upload/tests`,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
success: true,
|
|
82
|
+
});
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (request.method === "PUT" && pathname === "/upload/starter") {
|
|
86
|
+
const bodyBuffer = await readBody(request);
|
|
87
|
+
uploadStats.starterUploads += 1;
|
|
88
|
+
uploadStats.starterBytes += bodyBuffer.byteLength;
|
|
89
|
+
response.writeHead(200);
|
|
90
|
+
response.end();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (request.method === "PUT" && pathname === "/upload/tests") {
|
|
94
|
+
const bodyBuffer = await readBody(request);
|
|
95
|
+
uploadStats.testsUploads += 1;
|
|
96
|
+
uploadStats.testsBytes += bodyBuffer.byteLength;
|
|
97
|
+
response.writeHead(200);
|
|
98
|
+
response.end();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
response.writeHead(404);
|
|
102
|
+
response.end();
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
async start() {
|
|
106
|
+
server = http.createServer((request, response) => {
|
|
107
|
+
void handler(request, response);
|
|
108
|
+
});
|
|
109
|
+
await new Promise((resolve) => {
|
|
110
|
+
server?.listen(0, "127.0.0.1", resolve);
|
|
111
|
+
});
|
|
112
|
+
const address = server?.address();
|
|
113
|
+
if (!address || typeof address === "string") {
|
|
114
|
+
throw new Error("Unable to read test server address.");
|
|
115
|
+
}
|
|
116
|
+
const info = address;
|
|
117
|
+
return {
|
|
118
|
+
baseUrl: `http://127.0.0.1:${info.port}`,
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
async stop() {
|
|
122
|
+
if (!server) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
await new Promise((resolve) => server?.close(() => resolve()));
|
|
126
|
+
server = undefined;
|
|
127
|
+
},
|
|
128
|
+
uploadStats,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export async function runSubmitFlowIntegrationTests() {
|
|
132
|
+
const tempRoot = await createTempDir("em-cli-integration-");
|
|
133
|
+
const server = createTestBackendServer();
|
|
134
|
+
try {
|
|
135
|
+
const { baseUrl } = await server.start();
|
|
136
|
+
const workspaceRelative = "integration-workspace";
|
|
137
|
+
const workspaceAbsolute = path.join(tempRoot, workspaceRelative);
|
|
138
|
+
await runCli([
|
|
139
|
+
"challenge",
|
|
140
|
+
"init",
|
|
141
|
+
"--slug",
|
|
142
|
+
"integration-challenge",
|
|
143
|
+
"--title",
|
|
144
|
+
"Integration Challenge",
|
|
145
|
+
"--description",
|
|
146
|
+
"Create a deterministic express middleware that validates query params and returns JSON.",
|
|
147
|
+
"--constraints",
|
|
148
|
+
"Use only express and built-in Node modules. Keep behavior deterministic and offline.",
|
|
149
|
+
"--backend",
|
|
150
|
+
baseUrl,
|
|
151
|
+
"--dir",
|
|
152
|
+
workspaceRelative,
|
|
153
|
+
], {
|
|
154
|
+
cwd: tempRoot,
|
|
155
|
+
log: () => { },
|
|
156
|
+
});
|
|
157
|
+
await runCli(["challenge", "submit", "--backend", baseUrl, "--dir", workspaceAbsolute], {
|
|
158
|
+
cwd: tempRoot,
|
|
159
|
+
log: () => { },
|
|
160
|
+
packageDirectory: async () => Buffer.from("fake-tar-gz-bytes"),
|
|
161
|
+
});
|
|
162
|
+
assert.equal(server.uploadStats.starterUploads, 1);
|
|
163
|
+
assert.equal(server.uploadStats.testsUploads, 1);
|
|
164
|
+
assert.equal(server.uploadStats.starterBytes > 0, true);
|
|
165
|
+
assert.equal(server.uploadStats.testsBytes > 0, true);
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
await server.stop();
|
|
169
|
+
await fs.rm(tempRoot, { force: true, recursive: true });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=submit-flow.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submit-flow.spec.js","sourceRoot":"","sources":["../../../tests/integration/submit-flow.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-tests.d.ts","sourceRoot":"","sources":["../../tests/run-tests.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { runSubmitFlowIntegrationTests } from "./integration/submit-flow.spec.js";
|
|
2
|
+
import { runCliCommandsUnitTests } from "./unit/cli-commands.spec.js";
|
|
3
|
+
const tests = [
|
|
4
|
+
{
|
|
5
|
+
name: "unit: cli-commands",
|
|
6
|
+
run: runCliCommandsUnitTests,
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
name: "integration: submit-flow",
|
|
10
|
+
run: runSubmitFlowIntegrationTests,
|
|
11
|
+
},
|
|
12
|
+
];
|
|
13
|
+
async function main() {
|
|
14
|
+
let failed = 0;
|
|
15
|
+
for (const test of tests) {
|
|
16
|
+
try {
|
|
17
|
+
await test.run();
|
|
18
|
+
console.log(`[PASS] ${test.name}`);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
failed += 1;
|
|
22
|
+
console.error(`[FAIL] ${test.name}`);
|
|
23
|
+
console.error(error);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (failed > 0) {
|
|
27
|
+
process.exit(1);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
console.log(`All tests passed (${tests.length}).`);
|
|
31
|
+
}
|
|
32
|
+
void main();
|
|
33
|
+
//# sourceMappingURL=run-tests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-tests.js","sourceRoot":"","sources":["../../tests/run-tests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,mCAAmC,CAAC;AAClF,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAOtE,MAAM,KAAK,GAAgB;IACzB;QACE,IAAI,EAAE,oBAAoB;QAC1B,GAAG,EAAE,uBAAuB;KAC7B;IACD;QACE,IAAI,EAAE,0BAA0B;QAChC,GAAG,EAAE,6BAA6B;KACnC;CACF,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;AACrD,CAAC;AAED,KAAK,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-commands.spec.d.ts","sourceRoot":"","sources":["../../../tests/unit/cli-commands.spec.ts"],"names":[],"mappings":"AA0CA,wBAAsB,uBAAuB,kBA8D5C"}
|