Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: dev script for mitosis cli #958

Closed
wants to merge 4 commits into from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ You can get more information by running `mitosis --help`
- transpiles them as-is to JS
- Performs necessary transformations to both Mitosis & non-Mitosis files so that the output folder is coherent and valid (like renaming all component imports in a Svelte target such that they match the output name, ending in `.svelte`)

## `mitosis dev`

**Warning: mitosis dev is still experimental.**

`mitosis dev` is meant to reflect changes in your mitosis components more quickly. It:

- Reads the config in `mitosis.config.js` (also could specify config file by option: `--config=<file>`)
- Identifies a source folder
- Starts with running mitosis build (see above)
- Recompiles components on change
- Recompiles other files on change
- Currently does NOT recompile on change in override file but reruns mitosis build when this happens.

### options

| Option | Description | Example |
Expand Down
1 change: 1 addition & 0 deletions examples/basic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"mitosis": "mitosis build",
"build": "yarn run mitosis",
"start": "watch 'yarn run mitosis' ./src ./overrides",
"dev": "mitosis dev",
"test": "jest"
},
"dependencies": {
Expand Down
3 changes: 2 additions & 1 deletion examples/talk/apps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"scripts": {
"start": "watch 'yarn run build' ./src",
"build": "mitosis build --c mitosis.config.cjs",
"lint": "eslint"
"lint": "eslint",
"dev": "mitosis dev"
},
"type": "module",
"exports": {
Expand Down
3 changes: 2 additions & 1 deletion examples/todo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"version": "0.0.1",
"scripts": {
"build": "mitosis build",
"lint": "eslint"
"lint": "eslint",
"dev": "mitosis dev"
},
"exports": {
"./react/*": "./dist/react/src/*",
Expand Down
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@vue/compiler-sfc": "^3.1.5",
"babel-preset-solid": "^1.3.13",
"chalk": "^4.1.0",
"chokidar": "^3.5.3",
"debug": "^4.3.4",
"dedent": "^0.7.0",
"esbuild": "^0.12.16",
Expand Down
26 changes: 15 additions & 11 deletions packages/cli/src/build/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import { getFileExtensionForTarget } from './helpers/extensions';
import {
checkIsMitosisComponentFilePath,
INPUT_EXTENSIONS,
INPUT_EXTENSIONS_ARRAY,
INPUT_EXTENSION_REGEX,
} from './helpers/inputs-extensions';
import { checkShouldOutputTypeScript } from './helpers/options';
Expand Down Expand Up @@ -64,7 +63,7 @@ const DEFAULT_CONFIG: Partial<MitosisConfig> = {
getTargetPath,
};

const getOptions = (config?: MitosisConfig): MitosisConfig => ({
export const getOptions = (config?: MitosisConfig): MitosisConfig => ({
...DEFAULT_CONFIG,
...config,
options: {
Expand All @@ -73,7 +72,7 @@ const getOptions = (config?: MitosisConfig): MitosisConfig => ({
},
});

async function clean(options: MitosisConfig) {
export async function clean(options: MitosisConfig) {
const patterns = options.targets.map(
(target) => `${options.dest}/${options.getTargetPath({ target })}/${options.files}`,
);
Expand Down Expand Up @@ -166,9 +165,14 @@ const parseSvelteComponent = async ({ path, file }: { path: string; file: string
return output;
};

const getMitosisComponentJSONs = async (options: MitosisConfig): Promise<ParsedMitosisJson[]> => {
const pattern = `**/*(${INPUT_EXTENSIONS_ARRAY.join('|')})`;
const paths = (await glob(options.files, { cwd })).filter(checkIsMitosisComponentFilePath);
export const getMitosisComponentJSONs = async (
options: MitosisConfig,
paths?: string[],
): Promise<ParsedMitosisJson[]> => {
if (!paths) {
paths = (await glob(options.files, { cwd })).filter(checkIsMitosisComponentFilePath);
}

return Promise.all(
paths.map(async (path): Promise<ParsedMitosisJson> => {
try {
Expand Down Expand Up @@ -196,7 +200,7 @@ interface TargetContextWithConfig extends TargetContext {
options: MitosisConfig;
}

const getTargetContexts = (options: MitosisConfig) =>
export const getTargetContexts = (options: MitosisConfig) =>
options.targets.map(
(target): TargetContext => ({
target,
Expand All @@ -205,7 +209,7 @@ const getTargetContexts = (options: MitosisConfig) =>
}),
);

const buildAndOutputNonComponentFiles = async (targetContext: TargetContextWithConfig) => {
export const buildAndOutputNonComponentFiles = async (targetContext: TargetContextWithConfig) => {
const files = await buildNonComponentFiles(targetContext);
return await outputNonComponentFiles({ ...targetContext, files });
};
Expand Down Expand Up @@ -304,7 +308,7 @@ const getComponentOutputFileName = ({
/**
* Transpiles and outputs Mitosis component files.
*/
async function buildAndOutputComponentFiles({
export async function buildAndOutputComponentFiles({
target,
files,
options,
Expand Down Expand Up @@ -380,7 +384,7 @@ const outputNonComponentFiles = async ({
);
};

async function buildContextFile({
export async function buildContextFile({
target,
options,
path,
Expand Down Expand Up @@ -409,7 +413,7 @@ async function buildContextFile({
/**
* Transpiles all non-component files, including Context files.
*/
async function buildNonComponentFiles(args: TargetContextWithConfig) {
export async function buildNonComponentFiles(args: TargetContextWithConfig) {
const { target, options } = args;
const nonComponentFiles = (await glob(options.files, { cwd })).filter(
(file) => file.endsWith('.ts') || file.endsWith('.js'),
Expand Down
56 changes: 56 additions & 0 deletions packages/cli/src/build/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { MitosisConfig, Target } from '@builder.io/mitosis';
import { fastClone } from '../helpers/fast-clone';
import {
getMitosisComponentJSONs,
getOptions,
getTargetContexts,
buildAndOutputNonComponentFiles,
buildAndOutputComponentFiles,
} from './build';
import { checkIsMitosisComponentFilePath } from './helpers/inputs-extensions';

export async function dev({ config, path }: { config: MitosisConfig; path: string }) {
const options = getOptions(config);
// if it's a component
if (checkIsMitosisComponentFilePath(path)) {
// get all mitosis component JSONs
const mitosisComponents = await getMitosisComponentJSONs(options, [path]);

const targetContexts = getTargetContexts(options);

const generated: { target: Target; components: number; files: number }[] = [];

await Promise.all(
targetContexts.map(async (targetContext) => {
// clone mitosis JSONs for each target, so we can modify them in each generator without affecting future runs.
// each generator also clones the JSON before manipulating it, but this is an extra safety measure.
const files = fastClone(mitosisComponents);

const x = await buildAndOutputComponentFiles({ ...targetContext, options, files });

generated.push({
target: targetContext.target,
components: x.length,
files: 0,
});
}),
);

return generated;
}
// it's a non component file
else {
const targetContexts = getTargetContexts(options);

const generated: { target: Target; components: number; files: number }[] = await Promise.all(
targetContexts.map(async (targetContext) => {
return {
files: (await buildAndOutputNonComponentFiles({ ...targetContext, options })).length,
components: 0,
target: targetContext.target,
};
}),
);
return generated;
}
}
19 changes: 2 additions & 17 deletions packages/cli/src/commands/build.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,7 @@
import { GluegunCommand, GluegunParameters } from 'gluegun';
import { MitosisConfig, Target } from '@builder.io/mitosis';
import { GluegunCommand } from 'gluegun';
import { build } from '../build/build';
import { getMitosisConfig } from '../helpers/get-mitosis-config';

const getTargets = (mitosisConfig: MitosisConfig, cliOpts: GluegunParameters['options']) => {
const targetsFromCli: Target[] = (cliOpts.targets || '').split(',');
const excludeTargetsMap: Record<Target, true> = (cliOpts.excludeTargets || '')
.split(',')
.reduce((accu, t) => {
accu[t] = true;
return accu;
}, {});

const targets = Array.from(new Set([...mitosisConfig.targets, ...targetsFromCli])).filter(
(t) => t && !excludeTargetsMap[t],
);
return targets;
};
import { getTargets } from '../helpers/get-targets';

const command: GluegunCommand = {
name: 'build',
Expand Down
85 changes: 85 additions & 0 deletions packages/cli/src/commands/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { GluegunCommand } from 'gluegun';
import { getMitosisConfig } from '../helpers/get-mitosis-config';
import { build, clean } from '../build/build';
import chokidar from 'chokidar';
import { dev } from '../build/dev';
import { getTargets } from '../helpers/get-targets';
import { Target } from '@builder.io/mitosis';

const command: GluegunCommand = {
name: 'dev',
alias: 'd',
run: async (toolbox) => {
const { parameters } = toolbox;
const opts = parameters.options;
const configRelPath = opts.config ?? opts.c;
const config = getMitosisConfig(configRelPath);
if (!config) {
throw new Error(`No config file found for Mitosis.`);
}
const targets = getTargets(config, opts);

let files: string[] = [];
if (typeof config.files === 'string') {
files.push(config.files);
} else {
files.push(...config.files);
}

console.log('mitosis dev server started. running build command...');

await build({
...config,
targets,
});

const watcher = chokidar.watch(files, {}).on('change', async (path) => {
const start = new Date();
console.log(`detected change in ${path}, rebuilding...`);
try {
const data = await dev({ config: { ...config, targets }, path: path });
const end = new Date();
const time = (end.getTime() - start.getTime()) / 1000;
log({ data, time });
} catch (e) {
console.log('error rebuilding');
}
});

const overrideWatcher = chokidar
.watch(config.overridesDir || 'overrides', {})
.on('change', async () => {
console.log(`detected change in override folder. Rerunning build command...`);

await clean({ ...config, targets });

await build({
...config,
targets,
});
});

process.on('beforeExit', () => {
watcher.close();
overrideWatcher.close();
});
},
};

export const log = ({
data,
time,
}: {
data: { target: Target; components: number; files: number }[];
time: number;
}) => {
const components = data.map((a) => a.components).reduce((a, b) => a + b, 0);
const files = data.map((a) => a.files).reduce((a, b) => a + b, 0);
const targets = data.map((a) => a.target).length;

console.log(
`Generated ${files} files and ${components} components in ${targets} languages in ${time}s`,
);
};

module.exports = command;
17 changes: 17 additions & 0 deletions packages/cli/src/helpers/get-targets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { MitosisConfig, Target } from '@builder.io/mitosis';
import { GluegunParameters } from 'gluegun';

export const getTargets = (mitosisConfig: MitosisConfig, cliOpts: GluegunParameters['options']) => {
const targetsFromCli: Target[] = (cliOpts.targets || '').split(',');
const excludeTargetsMap: Record<Target, true> = (cliOpts.excludeTargets || '')
.split(',')
.reduce((accu, t) => {
accu[t] = true;
return accu;
}, {});

const targets = Array.from(new Set([...mitosisConfig.targets, ...targetsFromCli])).filter(
(t) => t && !excludeTargetsMap[t],
);
return targets;
};
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2577,6 +2577,7 @@ __metadata:
"@vue/compiler-sfc": ^3.1.5
babel-preset-solid: ^1.3.13
chalk: ^4.1.0
chokidar: ^3.5.3
debug: ^4.3.4
dedent: ^0.7.0
esbuild: ^0.12.16
Expand Down