Skip to content

Commit

Permalink
Adds dest availability for dev commands (#123)
Browse files Browse the repository at this point in the history
* add dest

* readme
  • Loading branch information
elliotBraem authored Jul 5, 2024
1 parent 1220359 commit a5d4bb9
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 53 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,11 @@ Options:
-h, --help display help for command

Commands:
dev [options] [src] Run the development server
dev [options] [src] [dest] Run the development server
build [options] [src] [dest] Build the project
workspace|ws [options] [command] [src] [dest] Work with multiple apps
init [options] [path] Initialize a new project
clone [account] [dest] Clone a SocialDB repository
pull [account] Pull updates from a SocialDB repository
deploy [options] [appName] Deploy the project
upload [string] Upload data to SocialDB (not implemented)
help [command] display help for command
Expand Down
22 changes: 6 additions & 16 deletions lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ async function run() {
.command("dev")
.description("Run the development server")
.argument("[src]", "path to the app source code", ".")
.argument("[dest]", "destination path", "build")
.option("-n, --network <network>", "network to build for", "mainnet")
.option("-l, --loglevel <loglevel>", "log level (ERROR, WARN, INFO, DEV, BUILD, DEBUG)", "DEV")
.option("-p, --port <port>", "Port to run the server on", "8080")
.option("-g, --gateway <gateway>", "Path to custom gateway dist", true)
.option("--no-gateway", "Disable the gateway")
.option("--no-hot", "Disable hot reloading")
.option("--no-open", "Disable opening the browser")
.action((src, opts) => {
.action((src, dest, opts) => {
global.log = new Logger(LogLevel[opts.loglevel.toUpperCase() as keyof typeof LogLevel]);
dev(src, opts).catch((e: Error) => {
dev(src, dest, opts).catch((e: Error) => {
log.error(e.stack || e.message);
})
});
Expand All @@ -42,11 +43,10 @@ async function run() {
.command("build")
.description("Build the project")
.argument("[src]", "path to the app source code", ".")
.argument("[dest]", "destination path")
.argument("[dest]", "destination path", "build")
.option("-n, --network <network>", "network to build for", "mainnet")
.option("-l, --loglevel <loglevel>", "log level (ERROR, WARN, INFO, DEV, BUILD, DEBUG)", "BUILD")
.action(async (src, dest, opts) => {
dest = dest || path.join(src, "dist")
global.log = new Logger(LogLevel[opts.loglevel.toUpperCase() as keyof typeof LogLevel]);
await buildApp(src, dest, opts.network).catch((e: Error) => {
log.error(e.stack || e.message);
Expand All @@ -59,7 +59,7 @@ async function run() {
.description("Work with multiple apps")
.argument("[command]", "command to run")
.argument("[src]", "path to the workspace", ".")
.argument("[dest]", "destination path")
.argument("[dest]", "destination path", "build")
.option("-n, --network <network>", "network to build for", "mainnet")
.option("-l, --loglevel <loglevel>", "log level (ERROR, WARN, INFO, DEV, BUILD, DEBUG)")
.option("-p, --port <port>", "Port to run the server on", "8080")
Expand All @@ -68,15 +68,14 @@ async function run() {
.option("--no-hot", "Disable hot reloading")
.option("--no-open", "Disable opening the browser")
.action(async (command, src, dest, opts) => {
dest = dest || path.join(src, "dist")
if (command === "build") {
global.log = new Logger(LogLevel?.[opts?.loglevel?.toUpperCase() as keyof typeof LogLevel] || LogLevel.BUILD);
await buildWorkspace(src, dest, opts.network).catch((e: Error) => {
log.error(e.stack || e.message);
});
} else if (command === "dev") {
global.log = new Logger(LogLevel?.[opts?.loglevel?.toUpperCase() as keyof typeof LogLevel] || LogLevel.DEV);
await devWorkspace(src, opts).catch((e: Error) => {
await devWorkspace(src, dest, opts).catch((e: Error) => {
log.error(e.stack || e.message);
});
} else {
Expand Down Expand Up @@ -107,15 +106,6 @@ async function run() {
cloneRepository(account, dest);
});

program
.command("pull")
.description("Pull updates from a SocialDB repository")
.argument("[account]", "accountId")
.action(async (account: string | undefined) => {
console.log("not yet supported");
// pullRepository(account);
});

program
.command("deploy")
.description("Deploy the project")
Expand Down
54 changes: 27 additions & 27 deletions lib/dev.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { readJson, writeJson } from "fs-extra";
import { Gaze } from "gaze";
import path from "path";
import { Server as IoServer } from "socket.io";
import { Gaze } from "gaze";
import { buildApp } from "./build";
import { BaseConfig, loadConfig, readConfig } from "./config";
import { BaseConfig, loadConfig } from "./config";
import { startDevServer } from "./server";
import { startSocket } from "./socket";
import { Network } from "./types";
import { loopThroughFiles, readFile } from "./utils/fs";
import { mergeDeep, substractDeep } from "./utils/objects";
import { startFileWatcher } from "./watcher";

const DEV_DIST_FOLDER = "build";

var appSrcs = [], appDists = [];
var appDevJsons = [];
var appDevJsonPath = "bos-loader.json";
Expand All @@ -33,12 +31,13 @@ export type DevOptions = {
* Build and watch app according to bos.config.json
*
* @param src path to app source code
* @param dest path to build output
* @param opts DevOptions
*/
export async function dev(src: string, opts: DevOptions) {
const dist = path.join(src, DEV_DIST_FOLDER);
export async function dev(src: string, dest: string, opts: DevOptions) {
const dist = path.join(src, dest);
const devJsonPath = path.join(dist, "bos-loader.json");

// Build the app for the first time
const config = await loadConfig(src, opts.network);
let devJson = await generateApp(src, dist, config, opts);
Expand Down Expand Up @@ -71,12 +70,12 @@ export async function dev(src: string, opts: DevOptions) {

// Watch for changes in the src folder and rebuild the app on changes
fileWatcher = startFileWatcher([
path.join(src, "widget/**/*"),
path.join(src, "module/**/*"),
path.join(src, "ipfs/**/*"),
path.join(src, "bos.config.json"),
path.join(src, "aliases.json")
],
path.join(src, "widget/**/*"),
path.join(src, "module/**/*"),
path.join(src, "ipfs/**/*"),
path.join(src, "bos.config.json"),
path.join(src, "aliases.json")
],
fileWatcherCallback
);
}
Expand All @@ -86,15 +85,16 @@ export async function dev(src: string, opts: DevOptions) {
*
* @param root bos.workspace.json root directory
* @param srcs apps to build and watch
* @param dest path to build output
* @param opts DevOptions
*/
export async function devMulti(root: string, srcs: string[], opts: DevOptions) {
const dist = path.join(root, DEV_DIST_FOLDER);
export async function devMulti(root: string, srcs: string[], dest: string, opts: DevOptions) {
const dist = path.join(root, dest);
const devJsonPath = path.join(dist, "bos-loader.json");

// Build all apps for the first time and merge devJson
let appDevJson = { components: {}, data: {} };

for (const src of srcs) {
const config = await loadConfig(src, opts.network);
const devJson = await generateApp(src, path.join(dist, path.relative(root, src)), config, opts);
Expand Down Expand Up @@ -138,7 +138,7 @@ export async function devMulti(root: string, srcs: string[], opts: DevOptions) {
export async function addApps(srcs: string[], dists: string[]) {
let appDevJson = await readJson(appDevJsonPath, { throws: false });

for (let i = 0; i < srcs.length; i ++) {
for (let i = 0; i < srcs.length; i++) {
const src = srcs[i];
const dist = dists[i];

Expand All @@ -157,19 +157,19 @@ export async function addApps(srcs: string[], dists: string[]) {

if (fileWatcher) {
fileWatcher.add(srcs.map((src) => [
path.join(src, "widget/**/*"),
path.join(src, "module/**/*"),
path.join(src, "ipfs/**/*"),
path.join(src, "bos.config.json"),
path.join(src, "aliases.json")
]).flat()
path.join(src, "widget/**/*"),
path.join(src, "module/**/*"),
path.join(src, "ipfs/**/*"),
path.join(src, "bos.config.json"),
path.join(src, "aliases.json")
]).flat()
);
}
}

async function fileWatcherCallback(action: string, file: string) {
let appDevJson = await readJson(appDevJsonPath, { throws: false });

// find which app this file belongs to
const index = appSrcs.findIndex((src) => file.includes(path.resolve(src)));
if (index == -1) {
Expand All @@ -178,15 +178,15 @@ async function fileWatcherCallback(action: string, file: string) {

const src = appSrcs[index];
const dist = appDists[index];

let devJson = appDevJsons[index];
substractDeep(appDevJson, devJson);

// rebuild app
log.info(`[${path.relative(src, file)}] changed: rebuilding app...`, LogLevels.DEV);
const config = await loadConfig(src, appDevOptions.network);
devJson = await generateApp(src, dist, config, appDevOptions);

// write to redirect map
await writeJson(appDevJsonPath, mergeDeep(appDevJson, devJson));
appDevJsons[index] = devJson;
Expand Down
4 changes: 2 additions & 2 deletions lib/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ export async function buildWorkspace(src: string, dest: string, network: string
loading.finish(`Built workspace ${path.resolve(src)} to ${path.resolve(dest)}`);
};

export async function devWorkspace(src: string, devOpts: DevOptions): Promise<any> {
export async function devWorkspace(src: string, dest: string, devOpts: DevOptions): Promise<any> {
const loading = log.loading(`Starting workspace ${src}`, LogLevels.BUILD);

const { apps } = await readWorkspace(src);

log.info(`Found ${apps.length} apps\n`);

await devMulti(src, apps.map((app) => path.join(src, app)), devOpts);
await devMulti(src, apps.map((app) => path.join(src, app)), dest, devOpts);

loading.finish(`Started workspace ${path.resolve(src)}`);
}
Expand Down
12 changes: 6 additions & 6 deletions tests/unit/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,31 +53,31 @@ describe("dev", () => {
});

it("should call loadConfig with src and opts.network", async () => {
await dev(mockSrc, mockOpts);
await dev(mockSrc, "build", mockOpts);
expect(loadConfig).toHaveBeenCalledWith(mockSrc, mockOpts.network);
});

it("should call generateApp with src, dist, config, opts, and devJsonPath", async () => {
await dev(mockSrc, mockOpts);
await dev(mockSrc, "build", mockOpts);
const mockDist = path.join(mockSrc, 'build');
const mockDevJsonPath = path.join(mockSrc, 'build', 'bos-loader.json');
expect(startDevServer).toHaveBeenCalledWith([mockSrc], [mockDist], mockDevJsonPath, mockOpts);
});

it("should start the socket server if hot reload is enabled", async () => {
const mockOpts: DevOptions = { hot: true };
await dev(mockSrc, mockOpts);
await dev(mockSrc, "build", mockOpts);
expect(startSocket).toHaveBeenCalled();
});

it("should not start the socket server if hot reload is disabled", async () => {
const mockOpts: DevOptions = { hot: false };
await dev(mockSrc, mockOpts);
await dev(mockSrc, "build", mockOpts);
expect(startSocket).not.toHaveBeenCalled();
});

it("should call startFileWatcher with correct watch paths", async () => {
await dev(mockSrc, mockOpts);
await dev(mockSrc, "build", mockOpts);
const expectedWatchPaths = [
path.join(mockSrc, 'widget', '**', '*'),
path.join(mockSrc, 'module', '**', '*'),
Expand All @@ -92,7 +92,7 @@ describe("dev", () => {
const mockedGazeAdd = jest.spyOn(Gaze.prototype, 'add');

const mockOpts: DevOptions = { hot: false };
await dev(mockSrc, mockOpts);
await dev(mockSrc, "build", mockOpts);

const mockSrc2 = "/app_example_2";
vol.fromJSON(app_example_2, mockSrc2);
Expand Down

0 comments on commit a5d4bb9

Please sign in to comment.