Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions packages/actor-core-cli/src/commands/deploy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,24 @@ export const deploy = new Command()
.addArgument(
new Argument("<platform>", "The platform to deploy to").choices(["rivet"]),
)
.addArgument(new Argument("[path]", "Location of the project").default("./"))
.addOption(new Option("-r, --root [path]", "Location of the project").default("./"))
.addOption(new Option("-p, --path [path]", "Location of the app.ts file"))
.addOption(new Option("--skip-manager", "Skip deploying ActorCore manager"))
.addOption(new Option("--env <env>", "Specify environment to deploy to"))
.addOption(new Option("-v [version]", "Specify version of actor-core"))
.addHelpText(
"afterAll",
"\nMissing your favorite platform?\nLet us know! https://github.com/rivet-gg/actor-core/issues/new",
)
.action(async (platform, wd, opts) => {
const cwd = path.join(process.cwd(), wd);
.action(async (platform, opts: {
root: string;
path?: string;
port?: string;
skipManager: boolean,
env?: string,
version?: string,
}) => {
const cwd = path.join(process.cwd(), opts.root);

const exec = $({
cwd,
Expand All @@ -46,7 +54,7 @@ export const deploy = new Command()
const { config, cli } = yield* ctx.task(
"Prepare",
async function* (ctx) {
const config = yield* validateConfigTask(ctx, cwd);
const config = yield* validateConfigTask(ctx, cwd, opts.path);

const cli = yield* ctx.task(
"Locale rivet-cli",
Expand Down
29 changes: 16 additions & 13 deletions packages/actor-core-cli/src/commands/dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ import { spawn } from "node:child_process";
export const dev = new Command()
.name("dev")
.description("Run locally your ActorCore project.")
.addArgument(new Argument("[path]", "Location of the project"))
.addOption(
new Option("-p, --port [port]", "Specify which platform to use").default(
new Option("-r, --root [path]", "Location of the project").default("./"),
)
.addOption(new Option("-p, --path [path]", "Location of the app.ts file"))
.addOption(
new Option("--port [port]", "Specify which platform to use").default(
"6420",
),
)
Expand All @@ -26,15 +29,15 @@ export const dev = new Command()
.option("--no-open", "Do not open the browser with ActorCore Studio")
.action(action);

export async function action(
cmdPath = ".",
opts: {
port?: string;
open?: boolean;
} = {},
) {
const cwd = path.join(process.cwd(), cmdPath);
await workflow("Run locally your ActorCore project", async function* (ctx) {
export async function action(opts: {
root: string;
path?: string;
port?: string;
open: boolean;
}) {
const cwd = path.join(process.cwd(), opts.root);

await workflow("Run locally your ActorCore project", async function*(ctx) {
if (opts.open) {
open(
process.env._ACTOR_CORE_CLI_DEV
Expand All @@ -58,7 +61,7 @@ export async function action(
"server-entry.js",
),
],
{ env: { ...process.env, PORT: opts.port }, cwd },
{ env: { ...process.env, PORT: opts.port, PATH: opts.path }, cwd },
);
}

Expand All @@ -79,7 +82,7 @@ export async function action(
});

while (true) {
yield* validateConfigTask(ctx, cwd);
yield* validateConfigTask(ctx, cwd, opts.path);
server = createServer();
createLock();

Expand Down
2 changes: 1 addition & 1 deletion packages/actor-core-cli/src/server-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { validateConfig } from "./utils/config";
import { serve } from "@actor-core/nodejs";

async function run() {
const config = await validateConfig(process.cwd());
const config = await validateConfig(process.cwd(), process.env.PATH);
config.app.config.inspector = {
enabled: true,
};
Expand Down
87 changes: 51 additions & 36 deletions packages/actor-core-cli/src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,49 +13,55 @@ const ActorCoreConfig = z.object({

export async function loadConfig(
cwd: string,
appPath?: string,
): Promise<{ path: string; data: z.infer<typeof ActorCoreConfig> } | null> {
const configJoycon = new JoyCon();

const configPath = await configJoycon.resolve({
files: [
"src/app.ts",
"src/app.tsx",
"src/app.mts",
"src/app.js",
"src/app.cjs",
"src/app.mjs",
],
cwd,
stopDir: path.parse(cwd).root,
});

if (configPath) {
try {
const config = await bundleRequire({
filepath: configPath,
});
return {
path: configPath,
data: config.mod.default || config.mod,
};
} catch (error) {
throw { isBundleError: true, details: error };
}
// Attempt to auto-resolve app path
let resolvedAppPath: string;
if (appPath) {
resolvedAppPath = appPath;
} else {
// Auto-resolve app path
const resolved = await configJoycon.resolve({
files: [
"src/app.ts",
"src/app.tsx",
"src/app.mts",
"src/app.js",
"src/app.cjs",
"src/app.mjs",
],
cwd,
stopDir: path.parse(cwd).root,
});
if (!resolved) return null;
resolvedAppPath = resolved;
}

return null;
try {
const config = await bundleRequire({
filepath: resolvedAppPath,
});
return {
path: resolvedAppPath,
data: config.mod.default || config.mod,
};
} catch (error) {
throw { isBundleError: true, path: resolvedAppPath, details: error };
}
}

export async function requireConfig(cwd: string) {
const config = await loadConfig(cwd);
export async function requireConfig(cwd: string, appPath?: string) {
const config = await loadConfig(cwd, appPath);
if (!config || !config.data) {
throw { isNotFoundError: true };
throw { isNotFoundError: true, cwd, appPath };
}
return config;
}

export async function validateConfig(cwd: string) {
const config = await requireConfig(cwd);
export async function validateConfig(cwd: string, appPath?: string) {
const config = await requireConfig(cwd, appPath);
return await ActorCoreConfig.parseAsync({
...config.data,
cwd: path.dirname(config.path),
Expand All @@ -64,15 +70,24 @@ export async function validateConfig(cwd: string) {

export const isNotFoundError = (
error: unknown,
): error is { isNotFoundError: true } => {
return z.object({ isNotFoundError: z.literal(true) }).safeParse(error)
.success;
): error is { isNotFoundError: true; cwd: string; path?: string } => {
return z
.object({
isNotFoundError: z.literal(true),
cwd: z.string(),
appPath: z.string().optional(),
})
.safeParse(error).success;
};

export const isBundleError = (
error: unknown,
): error is { isBundleError: true; details: unknown } => {
): error is { isBundleError: true; path: string; details: unknown } => {
return z
.object({ isBundleError: z.literal(true), details: z.any() })
.object({
isBundleError: z.literal(true),
path: z.string(),
details: z.any(),
})
.safeParse(error).success;
};
23 changes: 13 additions & 10 deletions packages/actor-core-cli/src/workflows/validate-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,29 @@ import {
import path from "node:path";
import type { Context } from "../workflow";

export function validateConfigTask(ctx: Context, cwd: string) {
export function validateConfigTask(
ctx: Context,
cwd: string,
appPath?: string,
) {
return ctx.task("Build project", async () => {
try {
return await validateConfig(cwd);
return await validateConfig(cwd, appPath);
} catch (error) {
const indexFile = path.relative(
process.cwd(),
path.join(cwd, "src", "index.ts"),
);
if (isBundleError(error)) {
throw ctx.error(
`Could not parse Actors index file (${indexFile})\n${error.details}`,
`Could not parse Actors index file (${error.path})\n${error.details}`,
{
hint: "Please make sure that the file exists and does not have any syntax errors.",
},
);
} else if (isNotFoundError(error)) {
throw ctx.error(`Could not find Actors index file (${indexFile})`, {
hint: "Please make sure that the file exists and not empty.",
});
throw ctx.error(
`Could not find Actors index file (${error.path ? error.path : path.join(error.cwd, "src/app.{ts,tsx,mts,js,cjs,mjs}")})`,
{
hint: "Please make sure that the file exists and not empty.",
},
);
} else {
console.error(error);
throw ctx.error("Failed to build project config.", {
Expand Down
Loading