@atls/raijin 0.2.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.
Files changed (42) hide show
  1. package/bin/raijin.mjs +3 -0
  2. package/dist/cli.d.ts +1 -0
  3. package/dist/cli.js +13 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +1 -0
  6. package/dist/initializer/exceptions/usage.d.ts +3 -0
  7. package/dist/initializer/exceptions/usage.js +7 -0
  8. package/dist/initializer/index.d.ts +2 -0
  9. package/dist/initializer/index.js +18 -0
  10. package/dist/initializer/interface.d.ts +8 -0
  11. package/dist/initializer/interface.js +1 -0
  12. package/dist/initializer/project.d.ts +5 -0
  13. package/dist/initializer/project.js +42 -0
  14. package/dist/runtime/bootstrap.d.ts +2 -0
  15. package/dist/runtime/bootstrap.js +33 -0
  16. package/dist/runtime/download.d.ts +4 -0
  17. package/dist/runtime/download.js +30 -0
  18. package/dist/runtime/exceptions/asset-download.d.ts +3 -0
  19. package/dist/runtime/exceptions/asset-download.js +7 -0
  20. package/dist/runtime/exceptions/digest-mismatch.d.ts +3 -0
  21. package/dist/runtime/exceptions/digest-mismatch.js +7 -0
  22. package/dist/runtime/exceptions/invalid-manifest.d.ts +10 -0
  23. package/dist/runtime/exceptions/invalid-manifest.js +30 -0
  24. package/dist/runtime/exceptions/manifest-download.d.ts +3 -0
  25. package/dist/runtime/exceptions/manifest-download.js +7 -0
  26. package/dist/runtime/index.d.ts +13 -0
  27. package/dist/runtime/index.js +10 -0
  28. package/dist/runtime/installer.d.ts +7 -0
  29. package/dist/runtime/installer.js +24 -0
  30. package/dist/runtime/manifest.d.ts +16 -0
  31. package/dist/runtime/manifest.js +46 -0
  32. package/dist/runtime.d.ts +8 -0
  33. package/dist/runtime.js +7 -0
  34. package/dist/yarn/command.d.ts +3 -0
  35. package/dist/yarn/command.js +22 -0
  36. package/dist/yarn/exceptions/command.d.ts +3 -0
  37. package/dist/yarn/exceptions/command.js +7 -0
  38. package/dist/yarn/index.d.ts +3 -0
  39. package/dist/yarn/index.js +2 -0
  40. package/dist/yarn/runner.d.ts +1 -0
  41. package/dist/yarn/runner.js +1 -0
  42. package/package.json +57 -0
package/bin/raijin.mjs ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import '../dist/cli.js'
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,13 @@
1
+ import { runRaijinInitializer } from './initializer/index.js';
2
+ try {
3
+ await runRaijinInitializer({ argv: process.argv.slice(2) });
4
+ }
5
+ catch (error) {
6
+ if (error instanceof Error) {
7
+ process.stderr.write(`${error.message}\n`);
8
+ }
9
+ else {
10
+ process.stderr.write(`${String(error)}\n`);
11
+ }
12
+ process.exitCode = 1;
13
+ }
@@ -0,0 +1,2 @@
1
+ export type { RunRaijinInitializerOptions } from './initializer/interface.js';
2
+ export { runRaijinInitializer } from './initializer/index.js';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { runRaijinInitializer } from "./initializer/index.js";
@@ -0,0 +1,3 @@
1
+ export declare class RaijinInitializerUsageException extends Error {
2
+ constructor();
3
+ }
@@ -0,0 +1,7 @@
1
+ const RAIJIN_INITIALIZER_USAGE_MESSAGE = 'Usage: yarn init @atls/raijin or yarn dlx @atls/raijin init';
2
+ export class RaijinInitializerUsageException extends Error {
3
+ constructor() {
4
+ super(RAIJIN_INITIALIZER_USAGE_MESSAGE);
5
+ this.name = 'RaijinInitializerUsageException';
6
+ }
7
+ }
@@ -0,0 +1,2 @@
1
+ import type { RunRaijinInitializerOptions } from './interface.js';
2
+ export declare const runRaijinInitializer: ({ argv, cwd, fetchImpl, runYarnCommand: runCommand, }?: RunRaijinInitializerOptions) => Promise<void>;
@@ -0,0 +1,18 @@
1
+ import { RaijinInitializerUsageException } from './exceptions/usage.js';
2
+ import { installRaijinRuntime } from '../runtime/installer.js';
3
+ import { runYarnCommand } from '../yarn/command.js';
4
+ import { ensurePackageJson } from './project.js';
5
+ import { ensureYarnLock } from './project.js';
6
+ const CODE_RUNTIME_PACKAGE = '@atls/code-runtime@latest';
7
+ export const runRaijinInitializer = async ({ argv = [], cwd = process.cwd(), fetchImpl = fetch, runYarnCommand: runCommand = runYarnCommand, } = {}) => {
8
+ const command = argv[0];
9
+ if (argv.length > 1 || (command && command !== 'init')) {
10
+ throw new RaijinInitializerUsageException();
11
+ }
12
+ await ensurePackageJson(cwd);
13
+ await ensureYarnLock(cwd);
14
+ await installRaijinRuntime({ cwd, fetchImpl });
15
+ await runCommand(['add', '-D', CODE_RUNTIME_PACKAGE], cwd);
16
+ await runCommand(['generate', 'project'], cwd);
17
+ await runCommand(['tools', 'sync'], cwd);
18
+ };
@@ -0,0 +1,8 @@
1
+ import type { FetchLike } from '../runtime/download.js';
2
+ import type { YarnCommandRunner } from '../yarn/runner.js';
3
+ export interface RunRaijinInitializerOptions {
4
+ argv?: Array<string>;
5
+ cwd?: string;
6
+ fetchImpl?: FetchLike;
7
+ runYarnCommand?: YarnCommandRunner;
8
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export declare const getPackageName: (cwd: string) => string;
2
+ export declare const hasPackageJson: (cwd: string) => Promise<boolean>;
3
+ export declare const hasYarnLock: (cwd: string) => Promise<boolean>;
4
+ export declare const ensurePackageJson: (cwd: string) => Promise<void>;
5
+ export declare const ensureYarnLock: (cwd: string) => Promise<void>;
@@ -0,0 +1,42 @@
1
+ import { access } from 'node:fs/promises';
2
+ import { writeFile } from 'node:fs/promises';
3
+ import { basename } from 'node:path';
4
+ import { join } from 'node:path';
5
+ const PACKAGE_JSON = 'package.json';
6
+ const YARN_LOCK = 'yarn.lock';
7
+ const FALLBACK_PACKAGE_NAME = 'raijin-project';
8
+ const INVALID_PACKAGE_NAME_CHARS_PATTERN = /[^a-z0-9._~-]+/g;
9
+ const PACKAGE_NAME_EDGE_DASHES_PATTERN = /^-+|-+$/g;
10
+ export const getPackageName = (cwd) => {
11
+ const packageName = basename(cwd)
12
+ .toLowerCase()
13
+ .replace(INVALID_PACKAGE_NAME_CHARS_PATTERN, '-')
14
+ .replace(PACKAGE_NAME_EDGE_DASHES_PATTERN, '');
15
+ return packageName || FALLBACK_PACKAGE_NAME;
16
+ };
17
+ const hasProjectFile = async (cwd, fileName) => {
18
+ try {
19
+ await access(join(cwd, fileName));
20
+ return true;
21
+ }
22
+ catch (error) {
23
+ if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
24
+ return false;
25
+ }
26
+ throw error;
27
+ }
28
+ };
29
+ export const hasPackageJson = async (cwd) => hasProjectFile(cwd, PACKAGE_JSON);
30
+ export const hasYarnLock = async (cwd) => hasProjectFile(cwd, YARN_LOCK);
31
+ export const ensurePackageJson = async (cwd) => {
32
+ if (await hasPackageJson(cwd)) {
33
+ return;
34
+ }
35
+ await writeFile(join(cwd, PACKAGE_JSON), `${JSON.stringify({ name: getPackageName(cwd) }, null, 2)}\n`);
36
+ };
37
+ export const ensureYarnLock = async (cwd) => {
38
+ if (await hasYarnLock(cwd)) {
39
+ return;
40
+ }
41
+ await writeFile(join(cwd, YARN_LOCK), '');
42
+ };
@@ -0,0 +1,2 @@
1
+ export declare const updateBootstrapConfiguration: (content: string, yarnPath: string) => string;
2
+ export declare const writeBootstrapConfiguration: (cwd: string, yarnPath: string) => Promise<void>;
@@ -0,0 +1,33 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { writeFile } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ const YARNRC_PATH = '.yarnrc.yml';
5
+ const RAIJIN_NODE_LINKER = 'pnp';
6
+ const TOP_LEVEL_NODE_LINKER_PATTERN = /^nodeLinker:.*$/gm;
7
+ const TOP_LEVEL_YARN_PATH_PATTERN = /^yarnPath:.*$/gm;
8
+ const readTextOrEmpty = async (path) => {
9
+ try {
10
+ return await readFile(path, 'utf-8');
11
+ }
12
+ catch (error) {
13
+ if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
14
+ return '';
15
+ }
16
+ throw error;
17
+ }
18
+ };
19
+ const removeTopLevelLine = (content, pattern) => content.replace(pattern, '').trim();
20
+ export const updateBootstrapConfiguration = (content, yarnPath) => {
21
+ const normalizedContent = content.trimEnd();
22
+ const preservedContent = removeTopLevelLine(removeTopLevelLine(normalizedContent, TOP_LEVEL_NODE_LINKER_PATTERN), TOP_LEVEL_YARN_PATH_PATTERN);
23
+ const configuration = [`nodeLinker: ${RAIJIN_NODE_LINKER}`, `yarnPath: ${yarnPath}`];
24
+ if (preservedContent.length === 0) {
25
+ return `${configuration.join('\n')}\n`;
26
+ }
27
+ return `${preservedContent}\n${configuration.join('\n')}\n`;
28
+ };
29
+ export const writeBootstrapConfiguration = async (cwd, yarnPath) => {
30
+ const yarnrcPath = join(cwd, YARNRC_PATH);
31
+ const yarnrc = await readTextOrEmpty(yarnrcPath);
32
+ await writeFile(yarnrcPath, updateBootstrapConfiguration(yarnrc, yarnPath));
33
+ };
@@ -0,0 +1,4 @@
1
+ import type { RaijinRuntimeManifest } from './manifest.js';
2
+ export type FetchLike = typeof fetch;
3
+ export declare const fetchRaijinRuntimeManifest: (fetchImpl: FetchLike) => Promise<RaijinRuntimeManifest>;
4
+ export declare const downloadRaijinRuntime: (fetchImpl: FetchLike, manifest: RaijinRuntimeManifest) => Promise<Buffer>;
@@ -0,0 +1,30 @@
1
+ import { RaijinRuntimeAssetDownloadException } from './exceptions/asset-download.js';
2
+ import { RaijinRuntimeManifestDownloadException } from './exceptions/manifest-download.js';
3
+ import { RAIJIN_RUNTIME_MANIFEST_URL } from './manifest.js';
4
+ import { parseRaijinRuntimeManifest } from './manifest.js';
5
+ const fetchJson = async (fetchImpl, url) => {
6
+ const response = await fetchImpl(url, {
7
+ headers: {
8
+ accept: 'application/json',
9
+ 'user-agent': 'raijin-initializer',
10
+ },
11
+ });
12
+ if (!response.ok) {
13
+ throw new RaijinRuntimeManifestDownloadException(response.status);
14
+ }
15
+ return response.json();
16
+ };
17
+ const fetchBuffer = async (fetchImpl, url) => {
18
+ const response = await fetchImpl(url, {
19
+ headers: {
20
+ accept: 'application/octet-stream',
21
+ 'user-agent': 'raijin-initializer',
22
+ },
23
+ });
24
+ if (!response.ok) {
25
+ throw new RaijinRuntimeAssetDownloadException(response.status);
26
+ }
27
+ return Buffer.from(await response.arrayBuffer());
28
+ };
29
+ export const fetchRaijinRuntimeManifest = async (fetchImpl) => parseRaijinRuntimeManifest(await fetchJson(fetchImpl, RAIJIN_RUNTIME_MANIFEST_URL));
30
+ export const downloadRaijinRuntime = async (fetchImpl, manifest) => fetchBuffer(fetchImpl, manifest.assetUrl);
@@ -0,0 +1,3 @@
1
+ export declare class RaijinRuntimeAssetDownloadException extends Error {
2
+ constructor(status: number);
3
+ }
@@ -0,0 +1,7 @@
1
+ const createRuntimeAssetDownloadFailureMessage = (status) => `Failed to download Raijin runtime asset: ${status}`;
2
+ export class RaijinRuntimeAssetDownloadException extends Error {
3
+ constructor(status) {
4
+ super(createRuntimeAssetDownloadFailureMessage(status));
5
+ this.name = 'RaijinRuntimeAssetDownloadException';
6
+ }
7
+ }
@@ -0,0 +1,3 @@
1
+ export declare class RaijinRuntimeDigestMismatchException extends Error {
2
+ constructor(expected: string, actual: string);
3
+ }
@@ -0,0 +1,7 @@
1
+ const createRuntimeDigestMismatchMessage = (expected, actual) => `Downloaded Raijin runtime digest mismatch: expected ${expected}, got ${actual}`;
2
+ export class RaijinRuntimeDigestMismatchException extends Error {
3
+ constructor(expected, actual) {
4
+ super(createRuntimeDigestMismatchMessage(expected, actual));
5
+ this.name = 'RaijinRuntimeDigestMismatchException';
6
+ }
7
+ }
@@ -0,0 +1,10 @@
1
+ import type { RaijinRuntimeManifest } from '../manifest.js';
2
+ export declare class InvalidRaijinRuntimeManifestException extends Error {
3
+ private constructor();
4
+ static expectedObject(): InvalidRaijinRuntimeManifestException;
5
+ static unsupportedSchemaVersion(): InvalidRaijinRuntimeManifestException;
6
+ static missingField(key: keyof RaijinRuntimeManifest): InvalidRaijinRuntimeManifestException;
7
+ static unexpectedPackage(packageName: string): InvalidRaijinRuntimeManifestException;
8
+ static unexpectedAsset(assetName: string): InvalidRaijinRuntimeManifestException;
9
+ static invalidSha256(): InvalidRaijinRuntimeManifestException;
10
+ }
@@ -0,0 +1,30 @@
1
+ const INVALID_RUNTIME_MANIFEST_OBJECT_MESSAGE = 'Invalid Raijin runtime manifest: expected object';
2
+ const INVALID_RUNTIME_MANIFEST_SCHEMA_VERSION_MESSAGE = 'Invalid Raijin runtime manifest: unsupported schemaVersion';
3
+ const INVALID_RUNTIME_MANIFEST_SHA256_MESSAGE = 'Invalid Raijin runtime manifest: invalid sha256';
4
+ const createInvalidRuntimeManifestFieldMessage = (key) => `Invalid Raijin runtime manifest: missing ${key}`;
5
+ const createInvalidRuntimeManifestPackageMessage = (packageName) => `Invalid Raijin runtime manifest: expected ${packageName}`;
6
+ const createInvalidRuntimeManifestAssetMessage = (assetName) => `Invalid Raijin runtime manifest: expected ${assetName}`;
7
+ export class InvalidRaijinRuntimeManifestException extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = 'InvalidRaijinRuntimeManifestException';
11
+ }
12
+ static expectedObject() {
13
+ return new InvalidRaijinRuntimeManifestException(INVALID_RUNTIME_MANIFEST_OBJECT_MESSAGE);
14
+ }
15
+ static unsupportedSchemaVersion() {
16
+ return new InvalidRaijinRuntimeManifestException(INVALID_RUNTIME_MANIFEST_SCHEMA_VERSION_MESSAGE);
17
+ }
18
+ static missingField(key) {
19
+ return new InvalidRaijinRuntimeManifestException(createInvalidRuntimeManifestFieldMessage(key));
20
+ }
21
+ static unexpectedPackage(packageName) {
22
+ return new InvalidRaijinRuntimeManifestException(createInvalidRuntimeManifestPackageMessage(packageName));
23
+ }
24
+ static unexpectedAsset(assetName) {
25
+ return new InvalidRaijinRuntimeManifestException(createInvalidRuntimeManifestAssetMessage(assetName));
26
+ }
27
+ static invalidSha256() {
28
+ return new InvalidRaijinRuntimeManifestException(INVALID_RUNTIME_MANIFEST_SHA256_MESSAGE);
29
+ }
30
+ }
@@ -0,0 +1,3 @@
1
+ export declare class RaijinRuntimeManifestDownloadException extends Error {
2
+ constructor(status: number);
3
+ }
@@ -0,0 +1,7 @@
1
+ const createRuntimeManifestDownloadFailureMessage = (status) => `Failed to download Raijin runtime manifest: ${status}`;
2
+ export class RaijinRuntimeManifestDownloadException extends Error {
3
+ constructor(status) {
4
+ super(createRuntimeManifestDownloadFailureMessage(status));
5
+ this.name = 'RaijinRuntimeManifestDownloadException';
6
+ }
7
+ }
@@ -0,0 +1,13 @@
1
+ export type { FetchLike } from './download.js';
2
+ export type { InstallRaijinRuntimeOptions } from './installer.js';
3
+ export type { RaijinRuntimeManifest } from './manifest.js';
4
+ export { createSha256Digest } from './manifest.js';
5
+ export { downloadRaijinRuntime } from './download.js';
6
+ export { fetchRaijinRuntimeManifest } from './download.js';
7
+ export { getRaijinRuntimeYarnPath } from './manifest.js';
8
+ export { installRaijinRuntime } from './installer.js';
9
+ export { parseRaijinRuntimeManifest } from './manifest.js';
10
+ export { RAIJIN_RUNTIME_ASSET_NAME } from './manifest.js';
11
+ export { RAIJIN_RUNTIME_MANIFEST_SCHEMA_VERSION } from './manifest.js';
12
+ export { RAIJIN_RUNTIME_MANIFEST_URL } from './manifest.js';
13
+ export { RAIJIN_RUNTIME_PACKAGE_NAME } from './manifest.js';
@@ -0,0 +1,10 @@
1
+ export { createSha256Digest } from "./manifest.js";
2
+ export { downloadRaijinRuntime } from "./download.js";
3
+ export { fetchRaijinRuntimeManifest } from "./download.js";
4
+ export { getRaijinRuntimeYarnPath } from "./manifest.js";
5
+ export { installRaijinRuntime } from "./installer.js";
6
+ export { parseRaijinRuntimeManifest } from "./manifest.js";
7
+ export { RAIJIN_RUNTIME_ASSET_NAME } from "./manifest.js";
8
+ export { RAIJIN_RUNTIME_MANIFEST_SCHEMA_VERSION } from "./manifest.js";
9
+ export { RAIJIN_RUNTIME_MANIFEST_URL } from "./manifest.js";
10
+ export { RAIJIN_RUNTIME_PACKAGE_NAME } from "./manifest.js";
@@ -0,0 +1,7 @@
1
+ import type { FetchLike } from './download.js';
2
+ import type { RaijinRuntimeManifest } from './manifest.js';
3
+ export interface InstallRaijinRuntimeOptions {
4
+ cwd: string;
5
+ fetchImpl: FetchLike;
6
+ }
7
+ export declare const installRaijinRuntime: ({ cwd, fetchImpl, }: InstallRaijinRuntimeOptions) => Promise<RaijinRuntimeManifest>;
@@ -0,0 +1,24 @@
1
+ import { mkdir } from 'node:fs/promises';
2
+ import { writeFile } from 'node:fs/promises';
3
+ import { dirname } from 'node:path';
4
+ import { join } from 'node:path';
5
+ import { RaijinRuntimeDigestMismatchException } from './exceptions/digest-mismatch.js';
6
+ import { writeBootstrapConfiguration } from './bootstrap.js';
7
+ import { downloadRaijinRuntime } from './download.js';
8
+ import { fetchRaijinRuntimeManifest } from './download.js';
9
+ import { createSha256Digest } from './manifest.js';
10
+ import { getRaijinRuntimeYarnPath } from './manifest.js';
11
+ export const installRaijinRuntime = async ({ cwd, fetchImpl, }) => {
12
+ const manifest = await fetchRaijinRuntimeManifest(fetchImpl);
13
+ const runtime = await downloadRaijinRuntime(fetchImpl, manifest);
14
+ const digest = createSha256Digest(runtime);
15
+ if (digest !== manifest.sha256) {
16
+ throw new RaijinRuntimeDigestMismatchException(manifest.sha256, digest);
17
+ }
18
+ const yarnPath = getRaijinRuntimeYarnPath(manifest);
19
+ const runtimePath = join(cwd, yarnPath);
20
+ await mkdir(dirname(runtimePath), { recursive: true });
21
+ await writeFile(runtimePath, runtime);
22
+ await writeBootstrapConfiguration(cwd, yarnPath);
23
+ return manifest;
24
+ };
@@ -0,0 +1,16 @@
1
+ export interface RaijinRuntimeManifest {
2
+ assetName: string;
3
+ assetUrl: string;
4
+ packageName: string;
5
+ schemaVersion: number;
6
+ sha256: string;
7
+ tagName: string;
8
+ version: string;
9
+ }
10
+ export declare const RAIJIN_RUNTIME_MANIFEST_URL = "https://raw.githubusercontent.com/atls/raijin/master/.yarn/releases/raijin-runtime.json";
11
+ export declare const RAIJIN_RUNTIME_PACKAGE_NAME = "@atls/yarn-cli";
12
+ export declare const RAIJIN_RUNTIME_ASSET_NAME = "yarn.mjs";
13
+ export declare const RAIJIN_RUNTIME_MANIFEST_SCHEMA_VERSION = 1;
14
+ export declare const parseRaijinRuntimeManifest: (value: unknown) => RaijinRuntimeManifest;
15
+ export declare const createSha256Digest: (data: Buffer) => string;
16
+ export declare const getRaijinRuntimeYarnPath: (manifest: RaijinRuntimeManifest) => string;
@@ -0,0 +1,46 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { InvalidRaijinRuntimeManifestException } from './exceptions/invalid-manifest.js';
3
+ export const RAIJIN_RUNTIME_MANIFEST_URL = 'https://raw.githubusercontent.com/atls/raijin/master/.yarn/releases/raijin-runtime.json';
4
+ export const RAIJIN_RUNTIME_PACKAGE_NAME = '@atls/yarn-cli';
5
+ export const RAIJIN_RUNTIME_ASSET_NAME = 'yarn.mjs';
6
+ export const RAIJIN_RUNTIME_MANIFEST_SCHEMA_VERSION = 1;
7
+ const SHA256_PATTERN = /^[a-f0-9]{64}$/;
8
+ const isRecord = (value) => typeof value === 'object' && value !== null;
9
+ const assertManifestString = (manifest, key) => {
10
+ const value = manifest[key];
11
+ if (typeof value !== 'string' || value.length === 0) {
12
+ throw InvalidRaijinRuntimeManifestException.missingField(key);
13
+ }
14
+ return value;
15
+ };
16
+ export const parseRaijinRuntimeManifest = (value) => {
17
+ if (!isRecord(value)) {
18
+ throw InvalidRaijinRuntimeManifestException.expectedObject();
19
+ }
20
+ if (value.schemaVersion !== RAIJIN_RUNTIME_MANIFEST_SCHEMA_VERSION) {
21
+ throw InvalidRaijinRuntimeManifestException.unsupportedSchemaVersion();
22
+ }
23
+ const packageName = assertManifestString(value, 'packageName');
24
+ const assetName = assertManifestString(value, 'assetName');
25
+ const sha256 = assertManifestString(value, 'sha256');
26
+ if (packageName !== RAIJIN_RUNTIME_PACKAGE_NAME) {
27
+ throw InvalidRaijinRuntimeManifestException.unexpectedPackage(RAIJIN_RUNTIME_PACKAGE_NAME);
28
+ }
29
+ if (assetName !== RAIJIN_RUNTIME_ASSET_NAME) {
30
+ throw InvalidRaijinRuntimeManifestException.unexpectedAsset(RAIJIN_RUNTIME_ASSET_NAME);
31
+ }
32
+ if (!SHA256_PATTERN.test(sha256)) {
33
+ throw InvalidRaijinRuntimeManifestException.invalidSha256();
34
+ }
35
+ return {
36
+ assetName,
37
+ assetUrl: assertManifestString(value, 'assetUrl'),
38
+ packageName,
39
+ schemaVersion: RAIJIN_RUNTIME_MANIFEST_SCHEMA_VERSION,
40
+ sha256,
41
+ tagName: assertManifestString(value, 'tagName'),
42
+ version: assertManifestString(value, 'version'),
43
+ };
44
+ };
45
+ export const createSha256Digest = (data) => createHash('sha256').update(data).digest('hex');
46
+ export const getRaijinRuntimeYarnPath = (manifest) => `.yarn/releases/raijin-yarn-${manifest.version}.mjs`;
@@ -0,0 +1,8 @@
1
+ export type { RaijinRuntimeManifest } from './runtime/manifest.js';
2
+ export { createSha256Digest } from './runtime/manifest.js';
3
+ export { getRaijinRuntimeYarnPath } from './runtime/manifest.js';
4
+ export { parseRaijinRuntimeManifest } from './runtime/manifest.js';
5
+ export { RAIJIN_RUNTIME_ASSET_NAME } from './runtime/manifest.js';
6
+ export { RAIJIN_RUNTIME_MANIFEST_SCHEMA_VERSION } from './runtime/manifest.js';
7
+ export { RAIJIN_RUNTIME_MANIFEST_URL } from './runtime/manifest.js';
8
+ export { RAIJIN_RUNTIME_PACKAGE_NAME } from './runtime/manifest.js';
@@ -0,0 +1,7 @@
1
+ export { createSha256Digest } from "./runtime/manifest.js";
2
+ export { getRaijinRuntimeYarnPath } from "./runtime/manifest.js";
3
+ export { parseRaijinRuntimeManifest } from "./runtime/manifest.js";
4
+ export { RAIJIN_RUNTIME_ASSET_NAME } from "./runtime/manifest.js";
5
+ export { RAIJIN_RUNTIME_MANIFEST_SCHEMA_VERSION } from "./runtime/manifest.js";
6
+ export { RAIJIN_RUNTIME_MANIFEST_URL } from "./runtime/manifest.js";
7
+ export { RAIJIN_RUNTIME_PACKAGE_NAME } from "./runtime/manifest.js";
@@ -0,0 +1,3 @@
1
+ import type { YarnCommandRunner } from './runner.js';
2
+ export declare const createYarnCommandEnvironment: (environment?: NodeJS.ProcessEnv) => NodeJS.ProcessEnv;
3
+ export declare const runYarnCommand: YarnCommandRunner;
@@ -0,0 +1,22 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { RaijinYarnCommandException } from './exceptions/command.js';
3
+ export const createYarnCommandEnvironment = (environment = process.env) => {
4
+ const yarnEnvironment = { ...environment };
5
+ delete yarnEnvironment.YARN_IGNORE_PATH;
6
+ return yarnEnvironment;
7
+ };
8
+ export const runYarnCommand = async (args, cwd) => {
9
+ const child = spawn('yarn', args, {
10
+ cwd,
11
+ env: createYarnCommandEnvironment(),
12
+ shell: process.platform === 'win32',
13
+ stdio: 'inherit',
14
+ });
15
+ const exitCode = await new Promise((resolve, reject) => {
16
+ child.once('error', reject);
17
+ child.once('exit', resolve);
18
+ });
19
+ if (exitCode !== 0) {
20
+ throw new RaijinYarnCommandException(args);
21
+ }
22
+ };
@@ -0,0 +1,3 @@
1
+ export declare class RaijinYarnCommandException extends Error {
2
+ constructor(args: Array<string>);
3
+ }
@@ -0,0 +1,7 @@
1
+ const createYarnCommandFailureMessage = (args) => `Command failed: yarn ${args.join(' ')}`;
2
+ export class RaijinYarnCommandException extends Error {
3
+ constructor(args) {
4
+ super(createYarnCommandFailureMessage(args));
5
+ this.name = 'RaijinYarnCommandException';
6
+ }
7
+ }
@@ -0,0 +1,3 @@
1
+ export type { YarnCommandRunner } from './runner.js';
2
+ export { createYarnCommandEnvironment } from './command.js';
3
+ export { runYarnCommand } from './command.js';
@@ -0,0 +1,2 @@
1
+ export { createYarnCommandEnvironment } from "./command.js";
2
+ export { runYarnCommand } from "./command.js";
@@ -0,0 +1 @@
1
+ export type YarnCommandRunner = (args: Array<string>, cwd: string) => Promise<void>;
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@atls/raijin",
3
+ "version": "0.2.0",
4
+ "license": "BSD-3-Clause",
5
+ "type": "module",
6
+ "exports": {
7
+ "./package.json": "./package.json",
8
+ "./runtime": {
9
+ "import": "./dist/runtime.js",
10
+ "types": "./dist/runtime.d.ts",
11
+ "default": "./dist/runtime.js"
12
+ },
13
+ ".": {
14
+ "import": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "main": "dist/index.js",
20
+ "bin": {
21
+ "raijin": "./bin/raijin.mjs"
22
+ },
23
+ "files": [
24
+ "bin",
25
+ "dist"
26
+ ],
27
+ "scripts": {
28
+ "build": "yarn library build",
29
+ "prepack": "yarn run build",
30
+ "postpack": "rm -rf dist"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "24.12.2"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public",
37
+ "bin": {
38
+ "raijin": "./bin/raijin.mjs"
39
+ },
40
+ "exports": {
41
+ "./package.json": "./package.json",
42
+ "./runtime": {
43
+ "import": "./dist/runtime.js",
44
+ "types": "./dist/runtime.d.ts",
45
+ "default": "./dist/runtime.js"
46
+ },
47
+ ".": {
48
+ "import": "./dist/index.js",
49
+ "types": "./dist/index.d.ts",
50
+ "default": "./dist/index.js"
51
+ }
52
+ },
53
+ "main": "dist/index.js",
54
+ "types": "dist/index.d.ts"
55
+ },
56
+ "types": "dist/index.d.ts"
57
+ }