diff --git a/CHANGELOG.md b/CHANGELOG.md index 49b562304..0503b5471 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Piral Changelog +## 1.7.0 (tbd) + +- Fixed issue in `piral-vue3` concerning reactivity of props (#720) +- Updated to latest version of `dets` +- Updated website emulator to contain scaffolding tarballs +- Updated pilets to automatically treat defined app shells as shared +- Added support for `shared` key in *piral.json* + ## 1.6.2 (September 27, 2024) - Fixed `registerBreadcrumbs` in `piral-breadcrumbs` failing when no matcher was specified diff --git a/docs/static/schemas/piral-v0.json b/docs/static/schemas/piral-v0.json index 6478a1704..eecbe5977 100644 --- a/docs/static/schemas/piral-v0.json +++ b/docs/static/schemas/piral-v0.json @@ -83,6 +83,14 @@ ], "description": "Defines what isolation / component wrapper is used for components of micro frontends. By default, the 'classic' isolation mode is used." }, + "shared": { + "type": "array", + "items": { + "type": "string", + "description": "Path to the file to consider for sharing from the app shell." + }, + "description": "Defines what files to share directly as exports from the app shell." + }, "pilets": { "type": "object", "description": "Determines the scaffolding and upgrading behavior of pilets using this Piral instance.", diff --git a/docs/tutorials/13-sharing-from-piral.md b/docs/tutorials/13-sharing-from-piral.md index 48088f933..21f46a9b6 100644 --- a/docs/tutorials/13-sharing-from-piral.md +++ b/docs/tutorials/13-sharing-from-piral.md @@ -157,6 +157,12 @@ The API can be much more dynamic and powerful (e.g., even coupling to the global This way is our recommendation for dynamic data and functions that require protection. Besides building convenience wrappers around the global state container it can also leverage pilet specific behavior. +## Extending the App Shell Exports + +Our recommendation is to only use the Piral instance from your pilets as a type construct / for development purposes. At runtime no significant exports should be used within a pilet. However, if you really want your pilet to strongly depend on the app shell you can also use full exports using the `shared` key in the *piral.json*. + +For more information on this look at the [documentation for sharing dependencies](./15-share-dependencies.md). + ## Conclusion Sharing information from the Piral instance can be done in multiple ways. Depending on the needs of the application and its pilets one way or another may be the best. Usually, an app shell uses all these ways to build an outstanding experience for both - users and developers. diff --git a/docs/tutorials/15-share-dependencies.md b/docs/tutorials/15-share-dependencies.md index 022535235..0006bca86 100644 --- a/docs/tutorials/15-share-dependencies.md +++ b/docs/tutorials/15-share-dependencies.md @@ -12,7 +12,9 @@ Sharing dependencies is one of the selling points of Piral. The key, however, is Our recommendation is to keep the sharing of dependencies from the app shell as practical as possible. -## Declarative Sharing from the App Shell +## Sharing from the App Shell + +### Declarative Sharing from the App Shell The easiest way to share dependencies from the app shell is to declare them in the `importmap` section of the *package.json*. @@ -58,7 +60,7 @@ you get automatically `tslib` as a shared dependency. If you would also add `pir You can remove inherited importmaps and replace them by explicit `imports` declarations, too. -## Imperative Sharing from the App Shell +### Imperative Sharing from the App Shell Dependencies can also be "defined" or explicitly mentioned in the program code of the app shell. The mechanism for this works via the `shareDependencies` option of the `createInstance` function. @@ -101,7 +103,7 @@ const instance = createInstance({ By default, we do not recommend exporting functionality from the app shell. A Piral instance should **only deliver types** to the pilets. However, sometimes having a dedicated package for extra functionality would either complicate things or is just not feasible. -## Type Declarations +### Type Declarations While the explicit way is great for gaining flexibility it comes with one caveat: For this kind of sharing types are not automatically inferred and generated. As a result, we need to place additional typings for our offerings. @@ -136,6 +138,18 @@ declare module 'my-app-shell' { The rule of thumb for sharing the type declarations is: Everything exported top-level will be associated with the app shell, and everything exported from an explicitly declared module will be associated with that module. +### Exported Modules + +To simplify the process illustrated in the previous two sections you can use a special key called `shared` in your *pilet.json*, e.g.: + +```json +{ + "shared": ["./src/externals.ts"] +} +``` + +This will use the exports from the given modules (in the previous example *./src/externals.ts*) to be available in pilets. Moreover, the given modules will be added to the types, i.e., work as if they had been defined as `extraTypes`, too. + ## Sharing from Pilets The mechanism to share dependencies used in pilets is called "import maps". Import maps are also on the way to becoming [an official standard](https://wicg.github.io/import-maps/). diff --git a/package.json b/package.json index 118c7d0be..51d55278b 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ }, "resolutions": { "chalk": "^4.0.0", + "cookie": "0.7.0", "node-fetch": "2.6.7", "postcss": "8.4.40" } diff --git a/src/converters/piral-vue-3/src/converter.ts b/src/converters/piral-vue-3/src/converter.ts index 257e0d3da..b0bf66ea6 100644 --- a/src/converters/piral-vue-3/src/converter.ts +++ b/src/converters/piral-vue-3/src/converter.ts @@ -35,12 +35,13 @@ export function createConverter(config: Vue3ConverterOptions = {}) { middlewares.forEach((middleware) => middleware(app)); app.component(selector, createExtension(rootName)); app.mount(el); - !app._props && (app._props = {}); locals.instance = app; }, update(parent, data, ctx, locals: Vue3State) { + const appInstance = locals.instance._instance; + for (const prop in data) { - locals.instance._props[prop] = data[prop]; + appInstance.props[prop] = data[prop]; } }, unmount(parent, locals: Vue3State) { diff --git a/src/converters/piral-vue-3/src/mount.ts b/src/converters/piral-vue-3/src/mount.ts index e81bcb23f..dbef52668 100644 --- a/src/converters/piral-vue-3/src/mount.ts +++ b/src/converters/piral-vue-3/src/mount.ts @@ -2,21 +2,25 @@ import type { BaseComponentProps, ComponentContext } from 'piral-core'; import { createApp, Component, h } from 'vue'; export function mountVue( - root: Component, + component: Component, props: T, ctx: ComponentContext, captured?: Record, ) { - return createApp({ + const data = { + ...captured, + ...props, + }; + const root: Component = { provide: { piral: props.piral, ...ctx, }, + props: Object.keys(data), render() { - return h(root as any, { - ...captured, - ...props, - }); + return h(component, this.$props); }, - }); + }; + + return createApp(root, data); } diff --git a/src/framework/piral-core/app.codegen b/src/framework/piral-core/app.codegen index 9e188e575..ba41b8a3f 100644 --- a/src/framework/piral-core/app.codegen +++ b/src/framework/piral-core/app.codegen @@ -23,6 +23,7 @@ module.exports = function () { publicPath: process.env.PIRAL_PUBLIC_PATH || '/', debug: debug && (cfg.debugSettings || {}), emulator: !!process.env.DEBUG_PILET, + shared: Array.isArray(cfg.shared) ? cfg.shared : [], isolation: cfg.isolation || 'classic', }; diff --git a/src/framework/piral-core/src/tools/codegen.ts b/src/framework/piral-core/src/tools/codegen.ts index 067162aa3..2962f1b25 100644 --- a/src/framework/piral-core/src/tools/codegen.ts +++ b/src/framework/piral-core/src/tools/codegen.ts @@ -82,6 +82,7 @@ interface CodegenOptions { origin: string; cat: string; appName: string; + shared: Array; externals: Array; publicPath: string; isolation: 'classic' | 'modern'; @@ -97,12 +98,23 @@ interface CodegenOptions { } export function createDependencies(imports: Array, exports: Array, opts: CodegenOptions) { - const { root, appName, externals, origin } = opts; + const { root, appName, externals, shared, origin } = opts; const assignments: Array = []; const asyncAssignments: Array = []; if (appName) { - assignments.push(`deps['${appName}']={}`); + const parts = []; + + for (const item of shared) { + if (typeof item === 'string') { + const path = getModulePathOrDefault(root, origin, item); + const ref = `_${imports.length}`; + parts.push(`...${ref}`); + imports.push(`import * as ${ref} from ${JSON.stringify(path)}`); + } + } + + assignments.push(`deps['${appName}']={${parts.join(',')}}`); } for (const external of externals) { diff --git a/src/tooling/piral-cli/package.json b/src/tooling/piral-cli/package.json index a2256a380..0f01c3cfe 100644 --- a/src/tooling/piral-cli/package.json +++ b/src/tooling/piral-cli/package.json @@ -75,7 +75,7 @@ }, "dependencies": { "css-conflict-inspector": "^0.2.1", - "dets": "^0.16.0", + "dets": "^0.16.4", "kras": "^0.17.0", "rimraf": "^3.0.0", "typescript": "^5.0.0", diff --git a/src/tooling/piral-cli/src/apps/add-piral-instance-pilet.ts b/src/tooling/piral-cli/src/apps/add-piral-instance-pilet.ts index 4385f396c..4445fe80a 100644 --- a/src/tooling/piral-cli/src/apps/add-piral-instance-pilet.ts +++ b/src/tooling/piral-cli/src/apps/add-piral-instance-pilet.ts @@ -12,6 +12,10 @@ import { findPiletRoot, piletJson, ensure, + readPiralPackage, + checkAppShellPackage, + ForceOverwrite, + copyPiralFiles, } from '../common'; export interface AddPiralInstancePiletOptions { @@ -76,7 +80,14 @@ export async function addPiralInstancePilet(baseDir = process.cwd(), options: Ad if (piletJsonPath) { const piletJsonDir = dirname(piletJsonPath); const root = await findPiletRoot(piletJsonDir); - await installPiralInstance(app, fullBase, root, npmClient, selected); + const packageName = await installPiralInstance(app, fullBase, root, npmClient, selected); + const piralInfo = await readPiralPackage(root, packageName); + const isEmulator = checkAppShellPackage(piralInfo); + + if (isEmulator) { + // in the emulator case we get the files (and files_once) from the contained tarballs + await copyPiralFiles(root, packageName, piralInfo, ForceOverwrite.yes, {}); + } } else { log('piletJsonNotAvailable_0180', targetDir); } diff --git a/src/tooling/piral-cli/src/common/declaration.ts b/src/tooling/piral-cli/src/common/declaration.ts index 7d3916c7c..155b16d84 100644 --- a/src/tooling/piral-cli/src/common/declaration.ts +++ b/src/tooling/piral-cli/src/common/declaration.ts @@ -69,24 +69,31 @@ function findPiralBaseApi(root: string, framework: string) { } } -function findDeclaredTypings(root: string) { +function isString(n: any) { + return typeof n === 'string'; +} + +function findDeclaredTypings(root: string, shared: Array = []) { + const types = shared.filter(isString).map((file) => resolve(root, file)); + try { const { typings, extraTypes } = require(resolve(root, 'package.json')); if (extraTypes) { - if (typeof extraTypes === 'string') { - return [resolve(root, extraTypes)]; + if (isString(extraTypes)) { + return [resolve(root, extraTypes), ...types]; } else if (Array.isArray(extraTypes)) { - return extraTypes.filter((types) => typeof types === 'string').map((types) => resolve(root, types)); + const items = extraTypes.filter(isString).map((file) => resolve(root, file)); + return [...items, ...types]; } } if (typings) { - return [resolve(root, typings)]; + return [resolve(root, typings), ...types]; } } catch {} - return []; + return types; } async function getAllFiles(entryModules: Array) { @@ -128,11 +135,7 @@ function createLogger(): Logger { }; } -async function createDeclarationFile( - options: DeclOptions, - target: string, - forceOverwrite: ForceOverwrite, -) { +async function createDeclarationFile(options: DeclOptions, target: string, forceOverwrite: ForceOverwrite) { progress('Bundling declaration file ...'); const result = await generateDeclaration(options); @@ -190,14 +193,14 @@ export async function createPiralDeclaration( ) { progress('Reading configuration ...'); const entryFiles = await retrievePiralRoot(baseDir, entry); - const { name, root, externals, framework } = await retrievePiletsInfo(entryFiles); + const { name, root, externals, framework, shared } = await retrievePiletsInfo(entryFiles); const entryModules = await getEntryModules(entryFiles); const files = await getAllFiles(entryModules); const options: DeclOptions = { name, root, files, - types: findDeclaredTypings(root), + types: findDeclaredTypings(root, shared), apis: findPiralBaseApi(root, framework), noModuleDeclaration: true, imports: flattenExternals(externals, true), diff --git a/src/tooling/piral-cli/src/common/emulator.ts b/src/tooling/piral-cli/src/common/emulator.ts index 520e3c1bd..269a0cc6c 100644 --- a/src/tooling/piral-cli/src/common/emulator.ts +++ b/src/tooling/piral-cli/src/common/emulator.ts @@ -1,4 +1,4 @@ -import { join, resolve, relative, basename } from 'path'; +import { join, resolve, relative, basename, extname } from 'path'; import { findDependencyVersion, copyScaffoldingFiles, isValidDependency, flattenExternals } from './package'; import { createPiralStubIndexIfNotExists } from './template'; import { filesTar, filesOnceTar, packageJson, piralJson, emulatorJson } from './constants'; @@ -11,25 +11,19 @@ import { createDirectory, removeDirectory, matchFiles, removeAny, getFileNames } import { updateExistingJson, readJson, writeJson, createFileIfNotExists } from './io'; import { EmulatorWebsiteManifest, LogLevels, SharedDependency, PiletsInfo, TemplateFileLocation } from '../types'; -export async function createEmulatorSources( - sourceDir: string, - externals: Array, - targetDir: string, - targetFile: string, - logLevel: LogLevels, -) { - const piralPkg = await readJson(sourceDir, packageJson); - const piralJsonPkg = await readJson(sourceDir, piralJson); - const pilets: PiletsInfo = { - ...piralPkg.pilets, - ...piralJsonPkg.pilets, - }; - const files: Array = pilets.files ?? []; - const allDeps = { - ...piralPkg.devDependencies, - ...piralPkg.dependencies, - }; +function makeFilesMap(files: Array = []): Array { + return files + .filter((file) => file && (typeof file === 'string' || typeof file === 'object')) + .map((file) => (typeof file === 'string' ? { from: file, to: file } : file)) + .filter((file) => typeof file.to === 'string' && typeof file.from === 'string') + .map((file) => ({ + ...file, + to: file.to.replace(/\\/g, '/'), + from: join('files', file.to).replace(/\\/g, '/'), + })); +} +async function makeExternals(sourceDir: string, piralPkg: any, externals: Array) { const externalPackages = await Promise.all( externals .filter((ext) => ext.type === 'local' && isValidDependency(ext.name)) @@ -63,20 +57,65 @@ export async function createEmulatorSources( return deps; }, {} as Record); + return [externalDependencies, importmapEntries, optionalDependencies] as const; +} + +async function createScaffoldingTarballs(sourceDir: string, targetDir: string, files: Array = []) { + const filesDir = resolve(targetDir, filesTar); + const filesOnceDir = resolve(targetDir, filesOnceTar); + + await Promise.all([createDirectory(filesDir), createDirectory(filesOnceDir)]); + + // for scaffolding we need to keep the files also available in the new package + await copyScaffoldingFiles( + sourceDir, + filesDir, + files.filter((m) => typeof m === 'string' || !m.once), + ); + + // also to avoid information loss we should store the once-only files separately + await copyScaffoldingFiles( + sourceDir, + filesOnceDir, + files.filter((m) => typeof m !== 'string' && m.once), + ); + + // since things like .gitignore are not properly treated by npm we pack the files (for standard and once only) + await Promise.all([ + createTarball(filesDir, targetDir, `${filesTar}.tar`), + createTarball(filesOnceDir, targetDir, `${filesOnceTar}.tar`), + ]); + + // ... and remove the directory + await Promise.all([removeDirectory(filesDir), removeDirectory(filesOnceDir)]); +} + +export async function createEmulatorSources( + sourceDir: string, + externals: Array, + targetDir: string, + targetFile: string, + logLevel: LogLevels, +) { + const piralPkg = await readJson(sourceDir, packageJson); + const piralJsonPkg = await readJson(sourceDir, piralJson); + const pilets: PiletsInfo = { + ...piralPkg.pilets, + ...piralJsonPkg.pilets, + }; + const allDeps = { + ...piralPkg.devDependencies, + ...piralPkg.dependencies, + }; + const rootDir = resolve(targetDir, '..'); const appDir = relative(rootDir, targetDir); - const filesDir = resolve(rootDir, filesTar); - const filesOnceDir = resolve(rootDir, filesOnceTar); - const filesMap = files - .filter((file) => file && (typeof file === 'string' || typeof file === 'object')) - .map((file) => (typeof file === 'string' ? { from: file, to: file } : file)) - .filter((file) => typeof file.to === 'string' && typeof file.from === 'string') - .map((file) => ({ - ...file, - to: file.to.replace(/\\/g, '/'), - from: join('files', file.to).replace(/\\/g, '/'), - })); + const [externalDependencies, importmapEntries, optionalDependencies] = await makeExternals( + sourceDir, + piralPkg, + externals, + ); // do not modify an existing JSON await createFileIfNotExists(rootDir, packageJson, '{}'); @@ -94,7 +133,7 @@ export async function createEmulatorSources( }, pilets: { ...pilets, - files: filesMap, + files: makeFilesMap(pilets.files), }, piralCLI: { version: cliVersion, @@ -119,22 +158,6 @@ export async function createEmulatorSources( publishConfig: piralPkg.publishConfig, }); - await Promise.all([createDirectory(filesDir), createDirectory(filesOnceDir)]); - - // for scaffolding we need to keep the files also available in the new package - await copyScaffoldingFiles( - sourceDir, - filesDir, - files.filter((m) => typeof m === 'string' || !m.once), - ); - - // also to avoid information loss we should store the once-only files separately - await copyScaffoldingFiles( - sourceDir, - filesOnceDir, - files.filter((m) => typeof m !== 'string' && m.once), - ); - // we just want to make sure that "files" mentioned in the original package.json are respected in the package await copyScaffoldingFiles(sourceDir, rootDir, piralPkg.files ?? []); @@ -147,14 +170,8 @@ export async function createEmulatorSources( // generate the associated index.d.ts await createPiralDeclaration(sourceDir, piralPkg.app ?? `./src/index.html`, targetDir, ForceOverwrite.yes, logLevel); - // since things like .gitignore are not properly treated by npm we pack the files (for standard and once only) - await Promise.all([ - createTarball(filesDir, rootDir, `${filesTar}.tar`), - createTarball(filesOnceDir, rootDir, `${filesOnceTar}.tar`), - ]); - - // ... and remove the directory - await Promise.all([removeDirectory(filesDir), removeDirectory(filesOnceDir)]); + // generate the files.tar and files_once.tar files + await createScaffoldingTarballs(sourceDir, rootDir, pilets.files); return rootDir; } @@ -177,38 +194,11 @@ export async function createEmulatorWebsite( ...piralPkg.dependencies, }; - const externalPackages = await Promise.all( - externals - .filter((ext) => ext.type === 'local' && isValidDependency(ext.name)) - .map(async (external) => ({ - name: external.name, - version: await findDependencyVersion(piralPkg, sourceDir, external), - optional: external.isAsync, - })), + const [externalDependencies, importmapEntries, optionalDependencies] = await makeExternals( + sourceDir, + piralPkg, + externals, ); - const externalDependencies = externalPackages.reduce((deps, dep) => { - if (!dep.optional) { - deps[dep.name] = dep.version; - } - - return deps; - }, {} as Record); - - const importmapEntries = externalPackages.reduce((deps, dep) => { - if (!dep.optional) { - deps[dep.name] = dep.name; - } - - return deps; - }, {} as Record); - - const optionalDependencies = externalPackages.reduce((deps, dep) => { - if (dep.optional) { - deps[dep.name] = dep.name; - } - - return deps; - }, {} as Record); const allFiles = await matchFiles(targetDir, '*'); const data: EmulatorWebsiteManifest = { @@ -217,13 +207,18 @@ export async function createEmulatorWebsite( version: piralPkg.version, timestamp: new Date().toISOString(), scaffolding: { - pilets, + pilets: { + ...pilets, + files: makeFilesMap(pilets.files), + }, cli: cliVersion, }, files: { typings: 'index.d.ts', main: basename(targetFile), app: 'index.html', + always: `${filesTar}.tar`, + once: `${filesOnceTar}.tar`, assets: allFiles.map((file) => relative(targetDir, file)), }, importmap: { @@ -243,6 +238,9 @@ export async function createEmulatorWebsite( // generate the associated index.d.ts await createPiralDeclaration(sourceDir, piralPkg.app ?? `./src/index.html`, targetDir, ForceOverwrite.yes, logLevel); + // generate the files.tar and files_once.tar files + await createScaffoldingTarballs(sourceDir, targetDir, pilets.files); + return targetDir; } diff --git a/src/tooling/piral-cli/src/common/package.ts b/src/tooling/piral-cli/src/common/package.ts index 3ea7159b1..b7c2f93af 100644 --- a/src/tooling/piral-cli/src/common/package.ts +++ b/src/tooling/piral-cli/src/common/package.ts @@ -284,7 +284,6 @@ async function getAvailableFiles( root: string, name: string, dirName: string, - fileMap: Array, ): Promise> { const source = getPiralPath(root, name); const tgz = `${dirName}.tar`; @@ -305,8 +304,8 @@ async function getAvailableFiles( })); } -export async function getFileStats(root: string, name: string, fileMap: Array = []) { - const files = await getAvailableFiles(root, name, filesTar, fileMap); +export async function getFileStats(root: string, name: string) { + const files = await getAvailableFiles(root, name, filesTar); return await Promise.all( files.map(async (file) => { @@ -414,12 +413,10 @@ export async function copyPiralFiles( originalFiles?: Array, ) { log('generalDebug_0003', `Copying the Piral files ...`); - const { files: _files } = getPiletsInfo(piralInfo); - const fileMap = _files.filter(isTemplateFileLocation); - const files = await getAvailableFiles(root, name, filesTar, fileMap); + const files = await getAvailableFiles(root, name, filesTar); if (originalFiles === undefined) { - const initialFiles = await getAvailableFiles(root, name, filesOnceTar, fileMap); + const initialFiles = await getAvailableFiles(root, name, filesOnceTar); files.push(...initialFiles); originalFiles = []; } @@ -614,6 +611,7 @@ export async function retrievePiletsInfo(entryFile: string) { name: packageInfo.name, version: packageInfo.version, emulator: piralJsonPkg.emulator, + shared: piralJsonPkg.shared, framework, dependencies, scripts: packageInfo.scripts, @@ -750,7 +748,7 @@ export function combinePiletExternals( peerModules: Array, importmap: Array, ) { - const externals = [...Object.keys(peerDependencies), ...peerModules]; + const externals = [...Object.keys(peerDependencies), ...peerModules, ...appShells]; for (let i = importmap.length; i--; ) { const entry = importmap[i]; diff --git a/src/tooling/piral-cli/src/common/website.ts b/src/tooling/piral-cli/src/common/website.ts index 47a5ace28..98ef3af0a 100644 --- a/src/tooling/piral-cli/src/common/website.ts +++ b/src/tooling/piral-cli/src/common/website.ts @@ -33,21 +33,31 @@ async function requestManifest(url: string, interactive: boolean, httpsAgent?: A async function downloadEmulatorFiles( manifestUrl: string, - target: string, + targetDir: string, + appDir: string, files: EmulatorWebsiteManifestFiles, httpsAgent?: Agent, ) { const requiredFiles = [files.typings, files.main, files.app]; - const opts = getAxiosOptions(manifestUrl); + const optionalFiles = [files.always, files.once]; + const opts = { + ...getAxiosOptions(manifestUrl), + httpsAgent, + responseType: 'arraybuffer' as const, + }; - await Promise.all( - requiredFiles.map(async (file) => { - const url = new URL(file, manifestUrl); - const res = await axios.default.get(url.href, { ...opts, httpsAgent, responseType: 'arraybuffer' }); - const data: Buffer = res.data; - await writeBinary(target, file, data); - }), - ); + const downloadFiles = (files: Array, target: string) => { + return files + .filter((file) => file && typeof file === 'string') + .map(async (file) => { + const url = new URL(file, manifestUrl); + const res = await axios.default.get(url.href, opts); + const data: Buffer = res.data; + await writeBinary(target, file, data); + }); + }; + + await Promise.all([...downloadFiles(requiredFiles, appDir), ...downloadFiles(optionalFiles, targetDir)]); } async function createEmulatorFiles( @@ -92,7 +102,7 @@ async function createEmulatorFiles( outFile: emulatorJson.files.main, }); - await downloadEmulatorFiles(manifestUrl, appDir, emulatorJson.files, httpsAgent); + await downloadEmulatorFiles(manifestUrl, targetDir, appDir, emulatorJson.files, httpsAgent); } export async function updateFromEmulatorWebsite(targetDir: string, manifestUrl: string, interactive: boolean) { diff --git a/src/tooling/piral-cli/src/types/common.ts b/src/tooling/piral-cli/src/types/common.ts index bf0c3750d..5f94b6021 100644 --- a/src/tooling/piral-cli/src/types/common.ts +++ b/src/tooling/piral-cli/src/types/common.ts @@ -9,6 +9,8 @@ export interface EmulatorWebsiteManifestFiles { main: string; app: string; assets: Array; + always?: string; + once?: string; } export interface EmulatorWebsiteManifest { diff --git a/yarn.lock b/yarn.lock index 5407e6191..20dcda4cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4751,10 +4751,10 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +cookie@0.6.0, cookie@0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.0.tgz#2148f68a77245d5c2c0005d264bc3e08cfa0655d" + integrity sha512-qCf+V4dtlNhSRXGAZatc1TasyFO6GjohcOul807YOb5ik3+kQSnb4d7iajeCL8QHaJ4uZEjCgiCJerKXwdRVlQ== core-js-compat@^3.31.0, core-js-compat@^3.32.2: version "3.33.0" @@ -5179,10 +5179,10 @@ detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== -dets@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/dets/-/dets-0.16.0.tgz#f0fbc7955e90ef602e3ee42b49f10fd27542ad70" - integrity sha512-sqnrRoOHnexPnXY596j89DHu1BEfCD7WBWYKsahdpT85ajWbuJzpWl9HGtwgHmG94dLszSvBp4DvFuRAuuh25Q== +dets@^0.16.4: + version "0.16.4" + resolved "https://registry.yarnpkg.com/dets/-/dets-0.16.4.tgz#53531ebe800ede19238b80df601712b60bcc9ab0" + integrity sha512-2ZQ6qA3cBLZTzmmSud1qrbc1vARfPTpYcHwWOo1bYISYUuobSr3xDBESUKvTY2+rMxyMj2rDeSslrZJo1FvFJw== diff-sequences@^29.6.3: version "29.6.3"