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
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Creator CLI (V0)
|
|
2
|
+
|
|
3
|
+
TypeScript-based CLI for creator workflows.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
em-challenge challenge init --slug <slug> --title <title> [--description <text>] [--constraints <text>] [--backend <url>] [--dir <path>]
|
|
9
|
+
em-challenge challenge validate [--dir <path>]
|
|
10
|
+
em-challenge challenge submit [--backend <url>] [--dir <path>]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## What Each Command Does
|
|
14
|
+
- `challenge init`: creates challenge metadata in backend (`draft`) and scaffolds local creator workspace.
|
|
15
|
+
- `challenge validate`: checks workspace against creator rules (metadata, required files, disallowed files, hidden test presence).
|
|
16
|
+
- `challenge submit`: validates workspace, requests signed R2 upload URLs, packs starter/tests as `tar.gz`, and uploads both artifacts.
|
|
17
|
+
|
|
18
|
+
## Test
|
|
19
|
+
```bash
|
|
20
|
+
npm run typecheck
|
|
21
|
+
npm test
|
|
22
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PackageDirectoryInput } from "./commands/challenge-submit.js";
|
|
2
|
+
import type { BackendClientContract, Logger } from "./types.js";
|
|
3
|
+
type CliContext = {
|
|
4
|
+
backendClient?: BackendClientContract;
|
|
5
|
+
cwd?: string;
|
|
6
|
+
log?: Logger;
|
|
7
|
+
packageDirectory?: (input: PackageDirectoryInput) => Promise<Buffer>;
|
|
8
|
+
};
|
|
9
|
+
export declare function runCli(rawArgv: string[], context?: CliContext): Promise<{
|
|
10
|
+
challengeId: string | null;
|
|
11
|
+
slug: string;
|
|
12
|
+
workspaceDir: string;
|
|
13
|
+
} | import("./commands/challenge-validate.js").ChallengeValidateResult | import("./commands/challenge-submit.js").ChallengeSubmitResult>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,EAAE,qBAAqB,EAAY,MAAM,EAAE,MAAM,YAAY,CAAC;AAE1E,KAAK,UAAU,GAAG;IAChB,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACtE,CAAC;AAuBF,wBAAsB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,UAAe;;;;yIA+CvE"}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { DEFAULT_BACKEND_BASE_URL } from "./constants.js";
|
|
2
|
+
import { runChallengeInit } from "./commands/challenge-init.js";
|
|
3
|
+
import { runChallengeSubmit } from "./commands/challenge-submit.js";
|
|
4
|
+
import { runChallengeValidate } from "./commands/challenge-validate.js";
|
|
5
|
+
import { BackendClient } from "./lib/backend-client.js";
|
|
6
|
+
import { parseArgs } from "./lib/args.js";
|
|
7
|
+
import { CliError } from "./lib/cli-error.js";
|
|
8
|
+
function resolveBackendBaseUrl(flags, command) {
|
|
9
|
+
if (flags.backend && flags.backend !== true) {
|
|
10
|
+
return String(flags.backend);
|
|
11
|
+
}
|
|
12
|
+
if (command === "challenge" && (flags.dir || flags.dir === "")) {
|
|
13
|
+
return process.env.BACKEND_BASE_URL ?? DEFAULT_BACKEND_BASE_URL;
|
|
14
|
+
}
|
|
15
|
+
return process.env.BACKEND_BASE_URL ?? DEFAULT_BACKEND_BASE_URL;
|
|
16
|
+
}
|
|
17
|
+
function usageText() {
|
|
18
|
+
return [
|
|
19
|
+
"Usage:",
|
|
20
|
+
" em-challenge challenge init --slug <slug> --title <title> [--description <text>] [--constraints <text>] [--backend <url>] [--dir <path>]",
|
|
21
|
+
" em-challenge challenge validate [--dir <path>]",
|
|
22
|
+
" em-challenge challenge submit [--backend <url>] [--dir <path>]",
|
|
23
|
+
].join("\n");
|
|
24
|
+
}
|
|
25
|
+
export async function runCli(rawArgv, context = {}) {
|
|
26
|
+
const argv = rawArgv.slice();
|
|
27
|
+
const { flags, positionals } = parseArgs(argv);
|
|
28
|
+
const log = context.log ?? console.log;
|
|
29
|
+
const cwd = context.cwd ?? process.cwd();
|
|
30
|
+
const [domain, command] = positionals;
|
|
31
|
+
if (!domain || !command) {
|
|
32
|
+
throw new CliError(usageText(), { code: "USAGE_ERROR" });
|
|
33
|
+
}
|
|
34
|
+
if (domain !== "challenge") {
|
|
35
|
+
throw new CliError(`Unsupported domain: ${domain}\n\n${usageText()}`, { code: "USAGE_ERROR" });
|
|
36
|
+
}
|
|
37
|
+
const backendBaseUrl = resolveBackendBaseUrl(flags, domain);
|
|
38
|
+
const backendClient = context.backendClient ?? new BackendClient(backendBaseUrl);
|
|
39
|
+
if (command === "init") {
|
|
40
|
+
return runChallengeInit({ backendClient, cwd, flags, log });
|
|
41
|
+
}
|
|
42
|
+
if (command === "validate") {
|
|
43
|
+
const result = await runChallengeValidate({ cwd, flags, log });
|
|
44
|
+
if (!result.ok) {
|
|
45
|
+
throw new CliError("Validation failed.", {
|
|
46
|
+
code: "VALIDATION_FAILED",
|
|
47
|
+
details: result.errors,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
if (command === "submit") {
|
|
53
|
+
return runChallengeSubmit({
|
|
54
|
+
backendClient,
|
|
55
|
+
cwd,
|
|
56
|
+
flags,
|
|
57
|
+
log,
|
|
58
|
+
packageDirectory: context.packageDirectory,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
throw new CliError(`Unsupported command: ${command}\n\n${usageText()}`, { code: "USAGE_ERROR" });
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BackendClientContract, CliFlags, Logger } from "../types.js";
|
|
2
|
+
type ChallengeInitInput = {
|
|
3
|
+
backendClient: BackendClientContract;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
flags: CliFlags;
|
|
6
|
+
log?: Logger;
|
|
7
|
+
};
|
|
8
|
+
type ChallengeInitResult = {
|
|
9
|
+
challengeId: string | null;
|
|
10
|
+
slug: string;
|
|
11
|
+
workspaceDir: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function runChallengeInit({ backendClient, cwd, flags, log, }: ChallengeInitInput): Promise<ChallengeInitResult>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=challenge-init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenge-init.d.ts","sourceRoot":"","sources":["../../../src/commands/challenge-init.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,qBAAqB,EAErB,QAAQ,EACR,MAAM,EACP,MAAM,aAAa,CAAC;AAErB,KAAK,kBAAkB,GAAG;IACxB,aAAa,EAAE,qBAAqB,CAAC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAyDF,wBAAsB,gBAAgB,CAAC,EACrC,aAAa,EACb,GAAmB,EACnB,KAAK,EACL,GAAiB,GAClB,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAqEnD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { CHALLENGE_CONFIG_FILE, CONSTRAINTS_PLACEHOLDER, DEFAULT_BACKEND_BASE_URL, DESCRIPTION_PLACEHOLDER, } from "../constants.js";
|
|
4
|
+
import { CliError } from "../lib/cli-error.js";
|
|
5
|
+
import { ensureDir, pathExists, writeJsonFile } from "../lib/fs-utils.js";
|
|
6
|
+
import { ensureValidSlug } from "../lib/workspace.js";
|
|
7
|
+
function resolveOption(flags, key, fallback) {
|
|
8
|
+
const value = flags[key];
|
|
9
|
+
if (value === undefined || value === true || value === "") {
|
|
10
|
+
return fallback;
|
|
11
|
+
}
|
|
12
|
+
return String(value);
|
|
13
|
+
}
|
|
14
|
+
async function createStarterTemplate(workspaceDir) {
|
|
15
|
+
const starterDir = path.join(workspaceDir, "starter");
|
|
16
|
+
await ensureDir(path.join(starterDir, "src"));
|
|
17
|
+
const starterPackage = {
|
|
18
|
+
name: "challenge-starter",
|
|
19
|
+
private: true,
|
|
20
|
+
scripts: {
|
|
21
|
+
start: "node src/index.js",
|
|
22
|
+
test: "node --test",
|
|
23
|
+
},
|
|
24
|
+
type: "module",
|
|
25
|
+
version: "1.0.0",
|
|
26
|
+
};
|
|
27
|
+
await writeJsonFile(path.join(starterDir, "package.json"), starterPackage);
|
|
28
|
+
await fs.writeFile(path.join(starterDir, "src", "index.js"), `export function createApp() {\n return "replace-with-solution";\n}\n`, "utf8");
|
|
29
|
+
await fs.writeFile(path.join(starterDir, ".env.example"), "PORT=3000\n", "utf8");
|
|
30
|
+
}
|
|
31
|
+
async function createHiddenTestsTemplate(workspaceDir) {
|
|
32
|
+
const testsDir = path.join(workspaceDir, "tests");
|
|
33
|
+
await ensureDir(path.join(testsDir, "spec"));
|
|
34
|
+
const testsPackage = {
|
|
35
|
+
name: "challenge-hidden-tests",
|
|
36
|
+
private: true,
|
|
37
|
+
scripts: {
|
|
38
|
+
test: "node --test \"spec/**/*.test.js\"",
|
|
39
|
+
},
|
|
40
|
+
type: "module",
|
|
41
|
+
version: "1.0.0",
|
|
42
|
+
};
|
|
43
|
+
await writeJsonFile(path.join(testsDir, "package.json"), testsPackage);
|
|
44
|
+
await fs.writeFile(path.join(testsDir, "spec", "placeholder.test.js"), `import test from "node:test";\nimport assert from "node:assert/strict";\n\ntest("replace with real hidden tests", () => {\n assert.equal(true, true);\n});\n`, "utf8");
|
|
45
|
+
}
|
|
46
|
+
export async function runChallengeInit({ backendClient, cwd = process.cwd(), flags, log = console.log, }) {
|
|
47
|
+
const slug = ensureValidSlug(flags.slug);
|
|
48
|
+
const title = resolveOption(flags, "title", "");
|
|
49
|
+
if (!title || title.length < 3) {
|
|
50
|
+
throw new CliError("`--title` is required and must be at least 3 characters.", {
|
|
51
|
+
code: "INVALID_TITLE",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const descriptionMd = resolveOption(flags, "description", DESCRIPTION_PLACEHOLDER);
|
|
55
|
+
const constraintsMd = resolveOption(flags, "constraints", CONSTRAINTS_PLACEHOLDER);
|
|
56
|
+
const backendBaseUrl = resolveOption(flags, "backend", process.env.BACKEND_BASE_URL ?? DEFAULT_BACKEND_BASE_URL);
|
|
57
|
+
const workspaceDir = path.resolve(cwd, resolveOption(flags, "dir", slug));
|
|
58
|
+
if (await pathExists(workspaceDir)) {
|
|
59
|
+
throw new CliError(`Target directory already exists: ${workspaceDir}`, {
|
|
60
|
+
code: "DIRECTORY_EXISTS",
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const payload = {
|
|
64
|
+
constraintsMd,
|
|
65
|
+
descriptionMd,
|
|
66
|
+
slug,
|
|
67
|
+
title,
|
|
68
|
+
type: "EXPRESS_NODE",
|
|
69
|
+
};
|
|
70
|
+
const createdChallenge = await backendClient.createChallengeDraft(payload);
|
|
71
|
+
await ensureDir(workspaceDir);
|
|
72
|
+
await createStarterTemplate(workspaceDir);
|
|
73
|
+
await createHiddenTestsTemplate(workspaceDir);
|
|
74
|
+
const config = {
|
|
75
|
+
backendBaseUrl,
|
|
76
|
+
challengeId: createdChallenge?.id ?? null,
|
|
77
|
+
constraintsMd,
|
|
78
|
+
createdAt: new Date().toISOString(),
|
|
79
|
+
descriptionMd,
|
|
80
|
+
slug,
|
|
81
|
+
title,
|
|
82
|
+
type: "EXPRESS_NODE",
|
|
83
|
+
version: 1,
|
|
84
|
+
};
|
|
85
|
+
await writeJsonFile(path.join(workspaceDir, CHALLENGE_CONFIG_FILE), config);
|
|
86
|
+
await fs.writeFile(path.join(workspaceDir, "README.md"), `# ${title}\n\n## Description\n${descriptionMd}\n\n## Constraints\n${constraintsMd}\n`, "utf8");
|
|
87
|
+
log(`Challenge workspace created: ${workspaceDir}`);
|
|
88
|
+
log(`Next steps:`);
|
|
89
|
+
log(`1) cd ${workspaceDir}`);
|
|
90
|
+
log(`2) em-challenge challenge validate`);
|
|
91
|
+
log(`3) em-challenge challenge submit`);
|
|
92
|
+
return {
|
|
93
|
+
challengeId: createdChallenge?.id ?? null,
|
|
94
|
+
slug,
|
|
95
|
+
workspaceDir,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=challenge-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenge-init.js","sourceRoot":"","sources":["../../../src/commands/challenge-init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BackendClientContract, CliFlags, Logger } from "../types.js";
|
|
2
|
+
export type PackageDirectoryInput = {
|
|
3
|
+
archiveNamePrefix: string;
|
|
4
|
+
sourceDir: string;
|
|
5
|
+
};
|
|
6
|
+
type ChallengeSubmitInput = {
|
|
7
|
+
backendClient: BackendClientContract;
|
|
8
|
+
cwd?: string;
|
|
9
|
+
flags: CliFlags;
|
|
10
|
+
log?: Logger;
|
|
11
|
+
packageDirectory?: (input: PackageDirectoryInput) => Promise<Buffer>;
|
|
12
|
+
};
|
|
13
|
+
export type ChallengeSubmitResult = {
|
|
14
|
+
slug: string;
|
|
15
|
+
starterArtifactKey: string;
|
|
16
|
+
testsArtifactKey: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function packageDirectoryToTarGz({ archiveNamePrefix, sourceDir, }: PackageDirectoryInput): Promise<Buffer>;
|
|
19
|
+
export declare function runChallengeSubmit({ backendClient, cwd, flags, log, packageDirectory, }: ChallengeSubmitInput): Promise<ChallengeSubmitResult>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=challenge-submit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenge-submit.d.ts","sourceRoot":"","sources":["../../../src/commands/challenge-submit.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE3E,MAAM,MAAM,qBAAqB,GAAG;IAClC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,aAAa,EAAE,qBAAqB,CAAC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACtE,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,wBAAsB,uBAAuB,CAAC,EAC5C,iBAAiB,EACjB,SAAS,GACV,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAezC;AAED,wBAAsB,kBAAkB,CAAC,EACvC,aAAa,EACb,GAAmB,EACnB,KAAK,EACL,GAAiB,EACjB,gBAA0C,GAC3C,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA2CvD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { CHALLENGE_CONFIG_FILE, EXCLUDED_ARTIFACT_PATTERNS } from "../constants.js";
|
|
5
|
+
import { CliError } from "../lib/cli-error.js";
|
|
6
|
+
import { readJsonFile } from "../lib/fs-utils.js";
|
|
7
|
+
import { createTarGzFromDirectory } from "../lib/tarball.js";
|
|
8
|
+
import { runChallengeValidate } from "./challenge-validate.js";
|
|
9
|
+
export async function packageDirectoryToTarGz({ archiveNamePrefix, sourceDir, }) {
|
|
10
|
+
const archivePath = path.join(os.tmpdir(), `${archiveNamePrefix}-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`);
|
|
11
|
+
createTarGzFromDirectory({
|
|
12
|
+
excludePatterns: EXCLUDED_ARTIFACT_PATTERNS,
|
|
13
|
+
outputFile: archivePath,
|
|
14
|
+
sourceDir,
|
|
15
|
+
});
|
|
16
|
+
const fileBuffer = await fs.readFile(archivePath);
|
|
17
|
+
await fs.rm(archivePath, { force: true });
|
|
18
|
+
return fileBuffer;
|
|
19
|
+
}
|
|
20
|
+
export async function runChallengeSubmit({ backendClient, cwd = process.cwd(), flags, log = console.log, packageDirectory = packageDirectoryToTarGz, }) {
|
|
21
|
+
const validation = await runChallengeValidate({ cwd, flags, log: () => { } });
|
|
22
|
+
if (!validation.ok) {
|
|
23
|
+
throw new CliError(`Cannot submit challenge. Validation failed. Fix ${CHALLENGE_CONFIG_FILE} and workspace files first.`, {
|
|
24
|
+
code: "VALIDATION_FAILED",
|
|
25
|
+
details: validation.errors,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
const workspaceDir = validation.workspaceDir;
|
|
29
|
+
const config = await readJsonFile(path.join(workspaceDir, CHALLENGE_CONFIG_FILE));
|
|
30
|
+
const slug = config.slug;
|
|
31
|
+
const starterUploadData = await backendClient.requestStarterUpload(slug);
|
|
32
|
+
const testsUploadData = await backendClient.requestTestsUpload(slug);
|
|
33
|
+
const starterBuffer = await packageDirectory({
|
|
34
|
+
archiveNamePrefix: `${slug}-starter`,
|
|
35
|
+
sourceDir: path.join(workspaceDir, "starter"),
|
|
36
|
+
});
|
|
37
|
+
const testsBuffer = await packageDirectory({
|
|
38
|
+
archiveNamePrefix: `${slug}-tests`,
|
|
39
|
+
sourceDir: path.join(workspaceDir, "tests"),
|
|
40
|
+
});
|
|
41
|
+
await backendClient.uploadArtifact(starterUploadData.upload, starterBuffer);
|
|
42
|
+
await backendClient.uploadArtifact(testsUploadData.upload, testsBuffer);
|
|
43
|
+
log(`Submitted challenge artifacts for ${slug}.`);
|
|
44
|
+
log(`Starter artifact key: ${starterUploadData.upload.key}`);
|
|
45
|
+
log(`Tests artifact key: ${testsUploadData.upload.key}`);
|
|
46
|
+
return {
|
|
47
|
+
slug,
|
|
48
|
+
starterArtifactKey: starterUploadData.upload.key,
|
|
49
|
+
testsArtifactKey: testsUploadData.upload.key,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=challenge-submit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenge-submit.js","sourceRoot":"","sources":["../../../src/commands/challenge-submit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CliFlags, Logger } from "../types.js";
|
|
2
|
+
import type { WorkspaceValidationResult } from "../lib/workspace.js";
|
|
3
|
+
type ChallengeValidateInput = {
|
|
4
|
+
cwd?: string;
|
|
5
|
+
flags: CliFlags;
|
|
6
|
+
log?: Logger;
|
|
7
|
+
};
|
|
8
|
+
export type ChallengeValidateResult = WorkspaceValidationResult & {
|
|
9
|
+
workspaceDir: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function runChallengeValidate({ cwd, flags, log, }: ChallengeValidateInput): Promise<ChallengeValidateResult>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=challenge-validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenge-validate.d.ts","sourceRoot":"","sources":["../../../src/commands/challenge-validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAErE,KAAK,sBAAsB,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,yBAAyB,GAAG;IAChE,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,EACzC,GAAmB,EACnB,KAAK,EACL,GAAiB,GAClB,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA2B3D"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { validateWorkspace } from "../lib/workspace.js";
|
|
3
|
+
export async function runChallengeValidate({ cwd = process.cwd(), flags, log = console.log, }) {
|
|
4
|
+
const workspaceDir = path.resolve(cwd, String(flags.dir || "."));
|
|
5
|
+
const result = await validateWorkspace(workspaceDir);
|
|
6
|
+
if (!result.ok) {
|
|
7
|
+
log(`Validation failed for workspace: ${workspaceDir}`);
|
|
8
|
+
for (const error of result.errors) {
|
|
9
|
+
log(`- ERROR: ${error}`);
|
|
10
|
+
}
|
|
11
|
+
for (const warning of result.warnings) {
|
|
12
|
+
log(`- WARNING: ${warning}`);
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
...result,
|
|
16
|
+
workspaceDir,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
log(`Validation passed for workspace: ${workspaceDir}`);
|
|
20
|
+
for (const warning of result.warnings) {
|
|
21
|
+
log(`- WARNING: ${warning}`);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
...result,
|
|
25
|
+
workspaceDir,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=challenge-validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenge-validate.js","sourceRoot":"","sources":["../../../src/commands/challenge-validate.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAcxD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EACzC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,EACnB,KAAK,EACL,GAAG,GAAG,OAAO,CAAC,GAAG,GACM;IACvB,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAErD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,GAAG,CAAC,oCAAoC,YAAY,EAAE,CAAC,CAAC;QACxD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,GAAG,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;QAC3B,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,GAAG,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO;YACL,GAAG,MAAM;YACT,YAAY;SACb,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,oCAAoC,YAAY,EAAE,CAAC,CAAC;IACxD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,GAAG,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO;QACL,GAAG,MAAM;QACT,YAAY;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const DEFAULT_BACKEND_BASE_URL = "http://localhost:3001";
|
|
2
|
+
export declare const CHALLENGE_CONFIG_FILE = "challenge.config.json";
|
|
3
|
+
export declare const DESCRIPTION_PLACEHOLDER = "REPLACE_WITH_CHALLENGE_DESCRIPTION";
|
|
4
|
+
export declare const CONSTRAINTS_PLACEHOLDER = "REPLACE_WITH_CHALLENGE_CONSTRAINTS";
|
|
5
|
+
export declare const EXCLUDED_ARTIFACT_PATTERNS: readonly ["node_modules", ".git", ".DS_Store", "*.log", ".env"];
|
|
6
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,0BAA0B,CAAC;AAChE,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,eAAO,MAAM,uBAAuB,uCAAuC,CAAC;AAC5E,eAAO,MAAM,uBAAuB,uCAAuC,CAAC;AAE5E,eAAO,MAAM,0BAA0B,iEAM7B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const DEFAULT_BACKEND_BASE_URL = "http://localhost:3001";
|
|
2
|
+
export const CHALLENGE_CONFIG_FILE = "challenge.config.json";
|
|
3
|
+
export const DESCRIPTION_PLACEHOLDER = "REPLACE_WITH_CHALLENGE_DESCRIPTION";
|
|
4
|
+
export const CONSTRAINTS_PLACEHOLDER = "REPLACE_WITH_CHALLENGE_CONSTRAINTS";
|
|
5
|
+
export const EXCLUDED_ARTIFACT_PATTERNS = [
|
|
6
|
+
"node_modules",
|
|
7
|
+
".git",
|
|
8
|
+
".DS_Store",
|
|
9
|
+
"*.log",
|
|
10
|
+
".env",
|
|
11
|
+
];
|
|
12
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,uBAAuB,CAAC;AAChE,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAE7D,MAAM,CAAC,MAAM,uBAAuB,GAAG,oCAAoC,CAAC;AAC5E,MAAM,CAAC,MAAM,uBAAuB,GAAG,oCAAoC,CAAC;AAE5E,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,cAAc;IACd,MAAM;IACN,WAAW;IACX,OAAO;IACP,MAAM;CACE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { CliError } from "./lib/cli-error.js";
|
|
3
|
+
import { runCli } from "./cli.js";
|
|
4
|
+
async function main() {
|
|
5
|
+
try {
|
|
6
|
+
await runCli(process.argv.slice(2));
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
if (error instanceof CliError) {
|
|
10
|
+
console.error(error.message);
|
|
11
|
+
process.exit(error.exitCode);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
console.error("Unexpected CLI error.");
|
|
15
|
+
console.error(error);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
void main();
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACvC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,KAAK,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../../src/lib/args.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA4BpD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function parseArgs(argv) {
|
|
2
|
+
const positionals = [];
|
|
3
|
+
const flags = {};
|
|
4
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
5
|
+
const token = argv[index];
|
|
6
|
+
if (!token) {
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
if (!token.startsWith("--")) {
|
|
10
|
+
positionals.push(token);
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
const key = token.slice(2);
|
|
14
|
+
const next = argv[index + 1];
|
|
15
|
+
if (!next || next.startsWith("--")) {
|
|
16
|
+
flags[key] = true;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
flags[key] = next;
|
|
20
|
+
index += 1;
|
|
21
|
+
}
|
|
22
|
+
return { flags, positionals };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../../src/lib/args.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,MAAM,KAAK,GAAwB,EAAE,CAAC;IAEtC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,SAAS;QACX,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxB,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAE7B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YAClB,SAAS;QACX,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QAClB,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ArtifactUploadResponse, ArtifactUploadTarget, BackendClientContract, ChallengeDraftPayload, ChallengeDraftResponse } from "../types.js";
|
|
2
|
+
export declare class BackendClient implements BackendClientContract {
|
|
3
|
+
private readonly baseUrl;
|
|
4
|
+
constructor(baseUrl: string);
|
|
5
|
+
createChallengeDraft(input: ChallengeDraftPayload): Promise<ChallengeDraftResponse>;
|
|
6
|
+
requestStarterUpload(slug: string): Promise<ArtifactUploadResponse>;
|
|
7
|
+
requestTestsUpload(slug: string): Promise<ArtifactUploadResponse>;
|
|
8
|
+
uploadArtifact(upload: ArtifactUploadTarget, fileBuffer: Buffer): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=backend-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-client.d.ts","sourceRoot":"","sources":["../../../src/lib/backend-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,aAAa,CAAC;AAyCrB,qBAAa,aAAc,YAAW,qBAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAEd,OAAO,EAAE,MAAM;IAIrB,oBAAoB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAoBnF,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAiBnE,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAiBjE,cAAc,CAAC,MAAM,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAmB7F"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { CliError } from "./cli-error.js";
|
|
2
|
+
async function parseJsonSafely(response) {
|
|
3
|
+
const text = await response.text();
|
|
4
|
+
if (!text) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(text);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function requestJson(url, options = {}) {
|
|
15
|
+
const response = await fetch(url, options);
|
|
16
|
+
const payload = await parseJsonSafely(response);
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
const apiMessage = payload?.error?.message;
|
|
19
|
+
throw new CliError(apiMessage ?? `Backend request failed (${response.status})`, {
|
|
20
|
+
code: payload?.error?.code ?? "BACKEND_REQUEST_FAILED",
|
|
21
|
+
details: payload,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return payload ?? {};
|
|
25
|
+
}
|
|
26
|
+
export class BackendClient {
|
|
27
|
+
baseUrl;
|
|
28
|
+
constructor(baseUrl) {
|
|
29
|
+
this.baseUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
30
|
+
}
|
|
31
|
+
async createChallengeDraft(input) {
|
|
32
|
+
const payload = await requestJson(`${this.baseUrl}/v1/creator/challenges/init`, {
|
|
33
|
+
body: JSON.stringify(input),
|
|
34
|
+
headers: {
|
|
35
|
+
"content-type": "application/json",
|
|
36
|
+
},
|
|
37
|
+
method: "POST",
|
|
38
|
+
});
|
|
39
|
+
const challenge = payload?.data?.challenge;
|
|
40
|
+
if (!challenge) {
|
|
41
|
+
throw new CliError("Backend did not return created challenge data.", {
|
|
42
|
+
code: "INVALID_BACKEND_RESPONSE",
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return challenge;
|
|
46
|
+
}
|
|
47
|
+
async requestStarterUpload(slug) {
|
|
48
|
+
const payload = await requestJson(`${this.baseUrl}/v1/creator/challenges/${encodeURIComponent(slug)}/artifacts/starter/upload-url`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
});
|
|
51
|
+
if (!payload.data || !("upload" in payload.data)) {
|
|
52
|
+
throw new CliError("Backend did not return starter upload target.", {
|
|
53
|
+
code: "INVALID_BACKEND_RESPONSE",
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return payload.data;
|
|
57
|
+
}
|
|
58
|
+
async requestTestsUpload(slug) {
|
|
59
|
+
const payload = await requestJson(`${this.baseUrl}/v1/creator/challenges/${encodeURIComponent(slug)}/artifacts/tests/upload-url`, {
|
|
60
|
+
method: "POST",
|
|
61
|
+
});
|
|
62
|
+
if (!payload.data || !("upload" in payload.data)) {
|
|
63
|
+
throw new CliError("Backend did not return tests upload target.", {
|
|
64
|
+
code: "INVALID_BACKEND_RESPONSE",
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return payload.data;
|
|
68
|
+
}
|
|
69
|
+
async uploadArtifact(upload, fileBuffer) {
|
|
70
|
+
const headers = new Headers(upload.headers ?? {});
|
|
71
|
+
if (!headers.has("content-type")) {
|
|
72
|
+
headers.set("content-type", "application/gzip");
|
|
73
|
+
}
|
|
74
|
+
const response = await fetch(upload.url, {
|
|
75
|
+
body: new Uint8Array(fileBuffer),
|
|
76
|
+
headers,
|
|
77
|
+
method: upload.method ?? "PUT",
|
|
78
|
+
});
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
throw new CliError(`Artifact upload failed (${response.status})`, {
|
|
81
|
+
code: "ARTIFACT_UPLOAD_FAILED",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=backend-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-client.js","sourceRoot":"","sources":["../../../src/lib/backend-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type CliErrorOptions = {
|
|
2
|
+
code?: string;
|
|
3
|
+
details?: unknown;
|
|
4
|
+
exitCode?: number;
|
|
5
|
+
};
|
|
6
|
+
export declare class CliError extends Error {
|
|
7
|
+
readonly code: string;
|
|
8
|
+
readonly details?: unknown;
|
|
9
|
+
readonly exitCode: number;
|
|
10
|
+
constructor(message: string, options?: CliErrorOptions);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=cli-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-error.d.ts","sourceRoot":"","sources":["../../../src/lib/cli-error.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClC,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAOlE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class CliError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
details;
|
|
4
|
+
exitCode;
|
|
5
|
+
constructor(message, options = {}) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "CliError";
|
|
8
|
+
this.code = options.code ?? "CLI_ERROR";
|
|
9
|
+
this.details = options.details;
|
|
10
|
+
this.exitCode = options.exitCode ?? 1;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=cli-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-error.js","sourceRoot":"","sources":["../../../src/lib/cli-error.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjB,IAAI,CAAS;IACb,OAAO,CAAW;IAClB,QAAQ,CAAS;IAEjC,YAAmB,OAAe,EAAE,UAA2B,EAAE;QAC/D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IACxC,CAAC;CACF"}
|