Skip to content

Commit

Permalink
feat(deno): support copying of asset files on emit (#306)
Browse files Browse the repository at this point in the history
  • Loading branch information
charsleysa authored Jul 6, 2023
1 parent 2da80d1 commit 783ee91
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 5 deletions.
48 changes: 47 additions & 1 deletion e2e/deno-e2e/tests/deno-integrated.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
uniq,
updateFile,
} from '@nx/plugin/testing';
import { unlinkSync, writeFileSync } from 'fs';
import { mkdirSync, unlinkSync, writeFileSync } from 'fs';
import { join } from 'path';
import {
killPort,
Expand Down Expand Up @@ -66,6 +66,52 @@ describe('Deno integrated monorepo', () => {
expect(workspaceFileExists(`dist/apps/${appName}/main.js`)).toBeTruthy();
}, 120_000);

it('should build deno app w/assets', async () => {
// Workspace ignore files
writeFileSync(join(tmpProjPath(), '.gitignore'), `git-ignore.hbs`);
writeFileSync(join(tmpProjPath(), '.nxignore'), `nx-ignore.hbs`);

// Assets
mkdirSync(join(tmpProjPath(), 'apps', appName, 'assets/a/b'), { recursive: true });
writeFileSync(join(tmpProjPath(), 'LICENSE'), 'license');
writeFileSync(join(tmpProjPath(), 'apps', appName, 'README.md'), 'readme');
writeFileSync(join(tmpProjPath(), 'apps', appName, 'assets/test1.hbs'), 'test');
writeFileSync(join(tmpProjPath(), 'apps', appName, 'assets/test2.hbs'), 'test');
writeFileSync(join(tmpProjPath(), 'apps', appName, 'assets/ignore.hbs'), 'IGNORE ME');
writeFileSync(join(tmpProjPath(), 'apps', appName, 'assets/git-ignore.hbs'), 'IGNORE ME');
writeFileSync(join(tmpProjPath(), 'apps', appName, 'assets/nx-ignore.hbs'), 'IGNORE ME');
writeFileSync(join(tmpProjPath(), 'apps', appName, 'assets/a/b/nested-ignore.hbs'), 'IGNORE ME');

const project = readJson(`apps/${appName}/project.json`);
project.targets.build.options.assets = [
`apps/${appName}/*.md`,
{
input: `apps/${appName}/assets`,
glob: '**/*.hbs',
output: 'assets',
ignore: ['ignore.hbs', '**/nested-ignore.hbs'],
},
'LICENSE',
];
updateFile(`apps/${appName}/project.json`, JSON.stringify(project));

const result = await runNxCommandAsync(`build ${appName}`);
expect(result.stdout).toContain(
`Successfully ran target build for project ${appName}`
);
expect(() => checkFilesExist(
`dist/apps/${appName}/main.js`,
`dist/apps/${appName}/LICENSE`,
`dist/apps/${appName}/README.md`,
`dist/apps/${appName}/assets/test1.hbs`,
`dist/apps/${appName}/assets/test2.hbs`
)).not.toThrow();
expect(workspaceFileExists(`dist/apps/${appName}/assets/ignore.hbs`)).toBeFalsy();
expect(workspaceFileExists(`dist/apps/${appName}/assets/git-ignore.hbs`)).toBeFalsy();
expect(workspaceFileExists(`dist/apps/${appName}/assets/nx-ignore.hbs`)).toBeFalsy();
expect(workspaceFileExists(`dist/apps/${appName}/assets/a/b/nested-ignore.hbs`)).toBeFalsy();
}, 120_000);

it('should serve deno app', async () => {
const p = await runCommandUntil(`serve ${appName}`, (output) => {
return output.includes(`Listening on`);
Expand Down
48 changes: 47 additions & 1 deletion e2e/deno-e2e/tests/deno-standalone.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
uniq,
updateFile,
} from '@nx/plugin/testing';
import { unlinkSync, writeFileSync } from 'fs';
import { mkdirSync, unlinkSync, writeFileSync } from 'fs';
import { join } from 'path';
import {
killPort,
Expand Down Expand Up @@ -67,6 +67,52 @@ describe('Deno standalone app', () => {
expect(workspaceFileExists(`dist/${appName}/main.js`)).toBeTruthy();
}, 120_000);

it('should build deno app w/assets', async () => {
// Workspace ignore files
writeFileSync(join(tmpProjPath(), '.gitignore'), `git-ignore.hbs`);
writeFileSync(join(tmpProjPath(), '.nxignore'), `nx-ignore.hbs`);

// Assets
mkdirSync(join(tmpProjPath(), 'assets/a/b'), { recursive: true });
writeFileSync(join(tmpProjPath(), 'LICENSE'), 'license');
writeFileSync(join(tmpProjPath(), 'README.md'), 'readme');
writeFileSync(join(tmpProjPath(), 'assets/test1.hbs'), 'test');
writeFileSync(join(tmpProjPath(), 'assets/test2.hbs'), 'test');
writeFileSync(join(tmpProjPath(), 'assets/ignore.hbs'), 'IGNORE ME');
writeFileSync(join(tmpProjPath(), 'assets/git-ignore.hbs'), 'IGNORE ME');
writeFileSync(join(tmpProjPath(), 'assets/nx-ignore.hbs'), 'IGNORE ME');
writeFileSync(join(tmpProjPath(), 'assets/a/b/nested-ignore.hbs'), 'IGNORE ME');

const project = readJson(`project.json`);
project.targets.build.options.assets = [
`*.md`,
{
input: `assets`,
glob: '**/*.hbs',
output: 'assets',
ignore: ['ignore.hbs', '**/nested-ignore.hbs'],
},
'LICENSE',
];
updateFile(`project.json`, JSON.stringify(project));

const result = await runNxCommandAsync(`build ${appName}`);
expect(result.stdout).toContain(
`Successfully ran target build for project ${appName}`
);
expect(() => checkFilesExist(
`dist/${appName}/main.js`,
`dist/${appName}/LICENSE`,
`dist/${appName}/README.md`,
`dist/${appName}/assets/test1.hbs`,
`dist/${appName}/assets/test2.hbs`
)).not.toThrow();
expect(workspaceFileExists(`dist/${appName}/assets/ignore.hbs`)).toBeFalsy();
expect(workspaceFileExists(`dist/${appName}/assets/git-ignore.hbs`)).toBeFalsy();
expect(workspaceFileExists(`dist/${appName}/assets/nx-ignore.hbs`)).toBeFalsy();
expect(workspaceFileExists(`dist/${appName}/assets/a/b/nested-ignore.hbs`)).toBeFalsy();
}, 120_000);

it('should serve deno app', async () => {
const p = await runCommandUntil(`serve ${appName}`, (output) => {
return output.includes(`Listening on`);
Expand Down
29 changes: 27 additions & 2 deletions packages/deno/src/executors/emit/emit.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { dirname, join, resolve } from 'path';
import { BuildExecutorSchema } from './schema';

import { ensureDirSync, unlinkSync, writeFileSync } from 'fs-extra';
import { CopyAssetsHandler } from '@nx/js/src/utils/assets/copy-assets-handler'
import { processCommonArgs } from '../../utils/arg-utils';
import { assertDenoInstalled, runDeno } from '../../utils/run-deno';

Expand All @@ -26,13 +27,36 @@ export async function denoEmitExecutor(
)} (https://deno.land/x/emit)`
);

return new Promise((resolve) => {
const projectRoot = context.projectGraph.nodes[context.projectName].data.root;
const outputPath = dirname(opts.outputFile);

const assetHandler = new CopyAssetsHandler({
projectDir: projectRoot,
rootDir: context.root,
outputDir: outputPath,
assets: opts.assets,
});

const denoEmitResult = await new Promise<boolean>((resolve) => {
const runningDenoProcess = runDeno(args);

runningDenoProcess.on('exit', (code) => {
resolve({ success: code === 0 });
resolve(code === 0);
});
});

if (denoEmitResult !== true) {
return { success: false };
}

let copyAssetsResult = true;
try {
await assetHandler.processAllAssetsOnce();
} catch {
copyAssetsResult = false;
}

return { success: copyAssetsResult };
}

function normalizeOptions(
Expand All @@ -53,6 +77,7 @@ function normalizeOptions(
ensureDirSync(resolve(context.root, dirname(options.outputFile)));

options.bundle ??= true;
options.assets ??= [];

return options;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/deno/src/executors/emit/schema.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { AssetGlob } from '@nx/js/src/assets/assets';

export interface BuildExecutorSchema {
denoConfig: string;
main: string;
outputFile: string;
bundle?: boolean;
assets?: Array<AssetGlob | string>;
}
45 changes: 44 additions & 1 deletion packages/deno/src/executors/emit/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,50 @@
"type": "boolean",
"description": "Bundle all imports into a single JavaScript file.",
"default": true
},
"assets": {
"type": "array",
"description": "List of static assets.",
"default": [],
"items": {
"$ref": "#/definitions/assetPattern"
}
}
},
"required": ["main", "outputFile", "denoConfig"]
"required": ["main", "outputFile", "denoConfig"],
"definitions": {
"assetPattern": {
"oneOf": [
{
"type": "object",
"properties": {
"glob": {
"type": "string",
"description": "The pattern to match."
},
"input": {
"type": "string",
"description": "The input directory path in which to apply 'glob'. Defaults to the project root."
},
"ignore": {
"description": "An array of globs to ignore.",
"type": "array",
"items": {
"type": "string"
}
},
"output": {
"type": "string",
"description": "Absolute path within the output."
}
},
"additionalProperties": false,
"required": ["glob", "input", "output"]
},
{
"type": "string"
}
]
}
}
}

0 comments on commit 783ee91

Please sign in to comment.