From 45d1c3d004bdba69cc2ce98e2fee423a1bf536b8 Mon Sep 17 00:00:00 2001 From: Jan Vennemann Date: Thu, 16 Nov 2023 22:52:10 +0100 Subject: [PATCH] fix: handle optional alloy component files --- package.json | 2 +- src/node/plugins/alloy/component.ts | 64 ++++++++++++++++++++++------- src/node/plugins/alloy/widget.ts | 2 +- src/node/plugins/index.ts | 2 +- src/node/plugins/resolve.ts | 6 +++ yarn.lock | 16 -------- 6 files changed, 58 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 3f72467..fab10cc 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@rollup/plugin-node-resolve": "^15.0.1", "acorn": "^8.2.4", "alloy-compiler": "0.2.7", - "alloy-utils": "^0.2.5", + "alloy-utils": "^0.2.7", "chalk": "^4.1.2", "debug": "^4.3.1", "esbuild": "^0.11.12", diff --git a/src/node/plugins/alloy/component.ts b/src/node/plugins/alloy/component.ts index 9b16e3f..8c9435b 100644 --- a/src/node/plugins/alloy/component.ts +++ b/src/node/plugins/alloy/component.ts @@ -1,15 +1,17 @@ import path from 'path'; import qs from 'querystring'; +import fs from 'fs-extra'; import { createFilter } from '@rollup/pluginutils'; import { ResolvedId } from 'rollup'; import { ModuleNode, Plugin, ResolvedConfig, ViteDevServer } from 'vite'; -import { stripBase } from '../../utils/vite.js'; +import { cleanUrl, stripBase } from '../../utils/vite.js'; import { AlloyContext } from './context'; const controllerRE = /(?:[/\\]widgets[/\\]([^/\\]+))?[/\\](?:controllers)[/\\](.*)/; const EMPTY_EXPORT = 'export default {}'; +const VIEW_ONLY_PREFIX = '\0alloyview:'; interface AlloyQuery { alloy?: boolean; @@ -70,6 +72,20 @@ export function componentPlugin(ctx: AlloyContext): Plugin { importer, { skipSelf: true } ); + if (!result) { + // No controller found, but maybe there is a view only + const view = await this.resolve( + path.join(appDir, 'views', `${componentId}.xml`), + importer, + { skipSelf: true } + ); + if (view) { + return ( + VIEW_ONLY_PREFIX + + view.id.replace('/app/views/', '/app/controllers/') + ); + } + } } if (result) { return result.id; @@ -78,6 +94,11 @@ export function componentPlugin(ctx: AlloyContext): Plugin { }, async load(id) { + if (id.startsWith(VIEW_ONLY_PREFIX)) { + console.log('Load view only controller'); + return ''; + } + const { filename, query } = parseAlloyRequest(id); // select corresponding block for sub-part virtual modules if (query.alloy) { @@ -93,34 +114,47 @@ export function componentPlugin(ctx: AlloyContext): Plugin { }, async transform(code, id) { + if (id.startsWith(VIEW_ONLY_PREFIX)) { + // Map virtual view only id back to controller id + id = id + .replace(VIEW_ONLY_PREFIX, '') + .replace('/app/views/', '/app/controllers/') + .replace(/\.xml/, '.js'); + } + const { filename, query } = parseAlloyRequest(id); if (!query.alloy && !filter(filename)) { return; } + const cleanId = cleanUrl(id); + if (!query.alloy) { - ctx.compiler.purgeStyleCache(id); + ctx.compiler.purgeStyleCache(cleanId); const { code: controllerCode, map, dependencies } = ctx.compiler.compileComponent({ controllerContent: code, - file: id + file: cleanId }); - const deps = dependencies.map((dep) => { - // Make sure changes to view and style files trigger a controller rebuild - this.addWatchFile(dep); - - if (dep.endsWith('.tss')) { - return dep + '?alloy&type=style'; - } else if (dep.endsWith('.xml')) { - return dep + '?alloy&type=template'; - } else { - throw new Error(`Unknown Alloy component dependency: ${dep}`); - } - }); + const deps = dependencies + // Only consider deps that actually exist + .filter((d) => fs.pathExistsSync(d)) + .map((dep) => { + // Make sure changes to view and style files trigger a controller rebuild + this.addWatchFile(dep); + + if (dep.endsWith('.tss')) { + return dep + '?alloy&type=style'; + } else if (dep.endsWith('.xml')) { + return dep + '?alloy&type=template'; + } else { + throw new Error(`Unknown Alloy component dependency: ${dep}`); + } + }); if (server) { // server only handling for view and style dependency hmr diff --git a/src/node/plugins/alloy/widget.ts b/src/node/plugins/alloy/widget.ts index 62f0ecf..6a45aab 100644 --- a/src/node/plugins/alloy/widget.ts +++ b/src/node/plugins/alloy/widget.ts @@ -14,7 +14,7 @@ export function widgetPlugin(appDir: string): Plugin { * @todo: Support Widgets from `node_modules`. */ async resolveId(id, importer) { - if (id.startsWith('/')) { + if (id.startsWith('/') && !id.startsWith(appDir)) { // check WPATH generated url `//` const secondSlashIndex = id.indexOf('/', 1); if (secondSlashIndex !== -1) { diff --git a/src/node/plugins/index.ts b/src/node/plugins/index.ts index 92abe83..f9b7df5 100644 --- a/src/node/plugins/index.ts +++ b/src/node/plugins/index.ts @@ -28,7 +28,7 @@ export async function resolvePlugins({ clientInjectionsPlugin(), nativeModulesPlugin(nativeModules), nodeBuiltinsPlugin(), - resolvePlugin(type, platform), + resolvePlugin(projectDir, type, platform), i18nPlugin(projectDir, type) ]; if (nativeModules.includes('hyperloop')) { diff --git a/src/node/plugins/resolve.ts b/src/node/plugins/resolve.ts index c486174..eedc254 100644 --- a/src/node/plugins/resolve.ts +++ b/src/node/plugins/resolve.ts @@ -12,6 +12,7 @@ import { FS_PREFIX } from '../constants.js'; * - Support bare module and absolute ids as relative to source root */ export function resolvePlugin( + projectDir: string, projectType: ProjectType, platform: Platform ): Plugin { @@ -39,6 +40,11 @@ export function resolvePlugin( return; } + // prevent nested full path resolving + if (id.startsWith(projectDir)) { + return; + } + const platformResolve = async (id: string, base: string) => { const result = await this.resolve(path.join(base, id), importer, { skipSelf: true diff --git a/yarn.lock b/yarn.lock index 2269564..c12a662 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1741,22 +1741,6 @@ alloy-compiler@0.2.7: walk-sync "^2.0.2" xmldom "^0.6.0" -alloy-utils@^0.2.5: - version "0.2.5" - resolved "https://registry.npmjs.org/alloy-utils/-/alloy-utils-0.2.5.tgz" - integrity sha512-fzktykZU5Niny/mVNNx07bJcrAfG9paaPA2oYF2vGhuuipgUrnWDvpNnXc7ADWiKUKcBIgQJ2I1paHIrRoI+mA== - dependencies: - "@babel/code-frame" "^7.8.3" - chmodr "^1.2.0" - colors "^1.4.0" - fs-extra "^9.0.0" - global-paths "^1.0.0" - jsonlint "^1.6.3" - lodash "^4.17.15" - moment "^2.24.0" - resolve "^1.12.0" - xmldom "^0.3.0" - alloy-utils@^0.2.7: version "0.2.7" resolved "https://registry.npmjs.org/alloy-utils/-/alloy-utils-0.2.7.tgz"