diff --git a/crates/atlaspack_napi_helpers/src/js_callable/js_callable.rs b/crates/atlaspack_napi_helpers/src/js_callable/js_callable.rs index 8879c2a93..70c69653c 100644 --- a/crates/atlaspack_napi_helpers/src/js_callable/js_callable.rs +++ b/crates/atlaspack_napi_helpers/src/js_callable/js_callable.rs @@ -10,6 +10,7 @@ use napi::Env; use napi::JsFunction; use napi::JsObject; use napi::JsUnknown; +use napi::ValueType; use serde::de::DeserializeOwned; use serde::Serialize; @@ -18,7 +19,7 @@ use super::map_return_serde; use super::JsValue; pub type MapJsParams = Box napi::Result> + 'static>; -pub type MapJsReturn = Box napi::Result + 'static>; +pub type MapJsReturn = Box anyhow::Result + 'static>; /// JsCallable provides a Send + Sync wrapper around callable JavaScript functions /// @@ -78,90 +79,73 @@ impl JsCallable { Ok(self) } - /// Call JavaScript function and discard return value - pub fn call( - &self, - map_params: impl FnOnce(&Env) -> napi::Result> + 'static, - ) -> napi::Result<()> { - #[cfg(debug_assertions)] - if self.initial_thread == std::thread::current().id() { - return Err(napi::Error::from_reason(format!( - "Cannot run threadsafe function {} on main thread", - self.name - ))); - } - - self - .threadsafe_function - .call(Box::new(map_params), ThreadsafeFunctionCallMode::Blocking); - - Ok(()) - } - - pub fn call_serde(&self, params: Params) -> napi::Result<()> - where - Params: Serialize + Send + Sync + 'static, - { - self.call(map_params_serde(params)) - } - /// Call JavaScript function and handle the return value - pub fn call_with_return( + pub fn call( &self, map_params: impl FnOnce(&Env) -> napi::Result> + 'static, - map_return: impl Fn(&Env, JsUnknown) -> napi::Result + 'static, - ) -> napi::Result + map_return: impl Fn(&Env, JsUnknown) -> anyhow::Result + 'static, + ) -> anyhow::Result where Return: Send + 'static, { #[cfg(debug_assertions)] if self.initial_thread == std::thread::current().id() { - return Err(napi::Error::from_reason(format!( + anyhow::bail!( "Cannot run threadsafe function {} on main thread", self.name - ))); + ); } - let (tx, rx) = channel(); + let (tx, rx) = channel::>(); self.threadsafe_function.call_with_return_value( Box::new(map_params), ThreadsafeFunctionCallMode::NonBlocking, move |JsValue(value, env)| { - if value.is_promise()? { - let result: JsObject = value.try_into()?; - let then: JsFunction = result.get_named_property("then")?; - - let tx2 = tx.clone(); - let cb = env.create_function_from_closure("callback", move |ctx| { - tx.send(map_return(&env, ctx.get::(0)?)).unwrap(); - ctx.env.get_undefined() - })?; - - let eb = env.create_function_from_closure("error_callback", move |ctx| { - let err = napi::Error::from(ctx.get::(0)?); - tx2.send(Err(err)).expect("send failure"); - ctx.env.get_undefined() - })?; - - then.call(Some(&result), &[cb, eb])?; - } else if value.is_error()? { - tx.send(Err(napi::Error::from(value))).unwrap(); - } else { - tx.send(map_return(&env, value)).unwrap(); - } + let container: JsObject = value.try_into()?; + let then_fn: JsFunction = match container.get_named_property("then") { + Ok(then_fn) => then_fn, + Err(error) => { + tx.send(Err(anyhow::anyhow!(error))).unwrap(); + return Ok(()); + } + }; + + let then_callback = env.create_function_from_closure("callback", move |ctx| { + // Return + // [error, null] + // [null, value] + let result = ctx.get::(0)?; + let error = result.get_element::(0)?; + + if let ValueType::Null = error.get_type()? { + let value = result.get_element::(1)?; + tx.send(map_return(&env, value)).unwrap(); + } else { + let error_value = env.from_js_value::(error)?; + tx.send(Err(anyhow::anyhow!(error_value))).unwrap(); + } + + ctx.env.get_undefined() + })?; + + then_fn.call(Some(&container), &[then_callback])?; Ok(()) }, ); - rx.recv().unwrap() + let result = rx.recv().unwrap(); + match result { + Ok(value) => Ok(value), + Err(error) => Err(anyhow::anyhow!("{} {}", self.name, error)), + } } - pub fn call_with_return_serde(&self, params: Params) -> napi::Result + pub fn call_serde(&self, params: Params) -> anyhow::Result where Params: Serialize + Send + Sync + 'static, Return: Send + DeserializeOwned + 'static, { - self.call_with_return(map_params_serde(params), map_return_serde()) + self.call(map_params_serde(params), map_return_serde()) } } diff --git a/crates/atlaspack_napi_helpers/src/js_callable/serde.rs b/crates/atlaspack_napi_helpers/src/js_callable/serde.rs index 8daaeacab..16354ff7f 100644 --- a/crates/atlaspack_napi_helpers/src/js_callable/serde.rs +++ b/crates/atlaspack_napi_helpers/src/js_callable/serde.rs @@ -35,5 +35,8 @@ pub fn map_return_serde() -> MapJsReturn where Return: Send + DeserializeOwned + 'static, { - Box::new(move |env, value| env.from_js_value(&value)) + Box::new(move |env, value| match env.from_js_value(&value) { + Ok(result) => Ok(result), + Err(err) => Err(anyhow::anyhow!(err.to_string())), + }) } diff --git a/crates/atlaspack_plugin_rpc/src/nodejs/rpc_conn_nodejs.rs b/crates/atlaspack_plugin_rpc/src/nodejs/rpc_conn_nodejs.rs index 0fa48e970..32a9a9e38 100644 --- a/crates/atlaspack_plugin_rpc/src/nodejs/rpc_conn_nodejs.rs +++ b/crates/atlaspack_plugin_rpc/src/nodejs/rpc_conn_nodejs.rs @@ -1,5 +1,4 @@ use atlaspack_core::plugin::Resolved; -use atlaspack_napi_helpers::anyhow_from_napi; use atlaspack_napi_helpers::js_callable::JsCallable; use napi::{JsObject, JsUnknown}; @@ -32,34 +31,22 @@ impl NodejsWorker { impl RpcWorker for NodejsWorker { fn ping(&self) -> anyhow::Result<()> { - self - .ping_fn - .call_with_return( - |_env| Ok(Vec::::new()), - |_env, _| Ok(Vec::<()>::new()), - ) - .map_err(anyhow_from_napi)?; + self.ping_fn.call( + |_env| Ok(Vec::::new()), + |_env, _| Ok(Vec::<()>::new()), + )?; Ok(()) } fn load_plugin(&self, opts: LoadPluginOptions) -> anyhow::Result<()> { - self - .load_plugin_fn - .call_with_return_serde(opts) - .map_err(anyhow_from_napi) + self.load_plugin_fn.call_serde(opts) } fn run_resolver_resolve(&self, opts: RunResolverResolve) -> anyhow::Result { - self - .run_resolver_resolve_fn - .call_with_return_serde(opts) - .map_err(anyhow_from_napi) + self.run_resolver_resolve_fn.call_serde(opts) } fn run_transformer(&self, opts: RpcTransformerOpts) -> anyhow::Result { - self - .transformer_register_fn - .call_with_return_serde(opts) - .map_err(anyhow_from_napi) + self.transformer_register_fn.call_serde(opts) } } diff --git a/crates/node-bindings/src/atlaspack/file_system_napi.rs b/crates/node-bindings/src/atlaspack/file_system_napi.rs index f75fe5000..324e125ac 100644 --- a/crates/node-bindings/src/atlaspack/file_system_napi.rs +++ b/crates/node-bindings/src/atlaspack/file_system_napi.rs @@ -40,28 +40,28 @@ impl FileSystem for FileSystemNapi { fn canonicalize_base(&self, path: &Path) -> io::Result { self .canonicalize_fn - .call_with_return_serde(path.to_path_buf()) + .call_serde(path.to_path_buf()) .map_err(|e| io::Error::other(e)) } fn create_directory(&self, path: &Path) -> std::io::Result<()> { self .create_directory_fn - .call_with_return_serde(path.to_path_buf()) + .call_serde(path.to_path_buf()) .map_err(|e| io::Error::other(e)) } fn cwd(&self) -> io::Result { self .cwd_fn - .call_with_return_serde(None::) + .call_serde(None::) .map_err(|e| io::Error::other(e)) } fn read(&self, path: &Path) -> std::io::Result> { let result = self .read_file_fn - .call_with_return_serde(path.to_path_buf()) + .call_serde(path.to_path_buf()) .map_err(|e| io::Error::other(e)); result @@ -70,21 +70,21 @@ impl FileSystem for FileSystemNapi { fn read_to_string(&self, path: &Path) -> io::Result { self .read_file_fn - .call_with_return_serde((path.to_path_buf(), "utf8")) + .call_serde((path.to_path_buf(), "utf8")) .map_err(|e| io::Error::other(e)) } fn is_file(&self, path: &Path) -> bool { self .is_file_fn - .call_with_return_serde(path.to_path_buf()) + .call_serde(path.to_path_buf()) .expect("TODO handle error case") } fn is_dir(&self, path: &Path) -> bool { self .is_dir_fn - .call_with_return_serde(path.to_path_buf()) + .call_serde(path.to_path_buf()) .expect("TODO handle error case") } } diff --git a/crates/node-bindings/src/atlaspack/package_manager_napi.rs b/crates/node-bindings/src/atlaspack/package_manager_napi.rs index ce141daaa..9d13741e7 100644 --- a/crates/node-bindings/src/atlaspack/package_manager_napi.rs +++ b/crates/node-bindings/src/atlaspack/package_manager_napi.rs @@ -1,6 +1,5 @@ use std::path::Path; -use anyhow::anyhow; use napi::{Env, JsObject}; use atlaspack_napi_helpers::js_callable::JsCallable; @@ -13,7 +12,7 @@ pub struct PackageManagerNapi { impl PackageManagerNapi { pub fn new(env: &Env, js_file_system: &JsObject) -> napi::Result { Ok(Self { - resolve_fn: JsCallable::new_from_object_prop_bound("resolveSync", &js_file_system)? + resolve_fn: JsCallable::new_from_object_prop_bound("resolve", &js_file_system)? .into_unref(env)?, }) } @@ -23,7 +22,6 @@ impl PackageManager for PackageManagerNapi { fn resolve(&self, specifier: &str, from: &Path) -> anyhow::Result { self .resolve_fn - .call_with_return_serde((specifier.to_owned(), from.to_path_buf())) - .map_err(|e| anyhow!(e)) + .call_serde((specifier.to_owned(), from.to_path_buf())) } } diff --git a/packages/core/core/src/Atlaspack.js b/packages/core/core/src/Atlaspack.js index bdbfe985f..389f93740 100644 --- a/packages/core/core/src/Atlaspack.js +++ b/packages/core/core/src/Atlaspack.js @@ -58,7 +58,7 @@ import { } from './projectPath'; import {tracer} from '@atlaspack/profiler'; import {setFeatureFlags} from '@atlaspack/feature-flags'; -import {AtlaspackV3, toFileSystemV3} from './atlaspack-v3'; +import {AtlaspackV3} from './atlaspack-v3'; registerCoreWithSerializer(); @@ -137,7 +137,7 @@ export default class Atlaspack { ? undefined : [entries], env: resolvedOptions.env, - fs: inputFS && toFileSystemV3(inputFS), + fs: inputFS, defaultTargetOptions: { // $FlowFixMe projectPath is just a string distDir: resolvedOptions.defaultTargetOptions.distDir, diff --git a/packages/core/core/src/atlaspack-v3/AtlaspackV3.js b/packages/core/core/src/atlaspack-v3/AtlaspackV3.js index 3340619f1..8a708c583 100644 --- a/packages/core/core/src/atlaspack-v3/AtlaspackV3.js +++ b/packages/core/core/src/atlaspack-v3/AtlaspackV3.js @@ -3,13 +3,17 @@ import path from 'path'; import {Worker} from 'worker_threads'; import {AtlaspackNapi, type AtlaspackNapiOptions} from '@atlaspack/rust'; +import {NativePackageManager} from './package-manager'; +import type {FileSystem as ClassicFileSystem} from '@atlaspack/fs'; +import {NativeFileSystem} from './fs'; +import type {PackageManager as ClassicPackageManager} from '@atlaspack/types'; const WORKER_PATH = path.join(__dirname, 'worker', 'index.js'); export type AtlaspackV3Options = {| - fs?: AtlaspackNapiOptions['fs'], + fs?: ClassicFileSystem, nodeWorkers?: number, - packageManager?: AtlaspackNapiOptions['packageManager'], + packageManager?: ClassicPackageManager, threads?: number, ...AtlaspackNapiOptions['options'], |}; @@ -33,9 +37,10 @@ export class AtlaspackV3 { }; this._internal = new AtlaspackNapi({ - fs, + fs: fs && new NativeFileSystem(fs), nodeWorkers, - packageManager, + packageManager: + packageManager && new NativePackageManager(packageManager), threads, options, }); diff --git a/packages/core/core/src/atlaspack-v3/fs.js b/packages/core/core/src/atlaspack-v3/fs.js index 9751288d3..c203d57ea 100644 --- a/packages/core/core/src/atlaspack-v3/fs.js +++ b/packages/core/core/src/atlaspack-v3/fs.js @@ -5,37 +5,49 @@ import type { Encoding, FilePath, FileSystem as ClassicFileSystem, -} from '@atlaspack/types-internal'; - +} from '@atlaspack/types'; +import type {JsCallable} from './jsCallable'; import {jsCallable} from './jsCallable'; -// Move to @atlaspack/utils or a dedicated v3 / migration package later -export function toFileSystemV3(fs: ClassicFileSystem): FileSystem { - return { - canonicalize: jsCallable((path: FilePath) => fs.realpathSync(path)), - createDirectory: jsCallable((path: FilePath) => fs.mkdirp(path)), - cwd: jsCallable(() => fs.cwd()), - readFile: jsCallable((path: string, encoding?: Encoding) => { +export class NativeFileSystem implements FileSystem { + #fs: ClassicFileSystem; + + constructor(fs: ClassicFileSystem) { + this.#fs = fs; + } + + canonicalize: JsCallable<[FilePath], FilePath> = jsCallable(path => + this.#fs.realpathSync(path), + ); + + createDirectory: JsCallable<[FilePath], Promise> = jsCallable(path => + this.#fs.mkdirp(path), + ); + + cwd: JsCallable<[], FilePath> = jsCallable(() => this.#fs.cwd()); + + isDir: JsCallable<[FilePath], boolean> = jsCallable((path: string) => { + try { + return this.#fs.statSync(path).isDirectory(); + } catch { + return false; + } + }); + + isFile: JsCallable<[FilePath], boolean> = jsCallable(path => { + try { + return this.#fs.statSync(path).isDirectory(); + } catch { + return false; + } + }); + + readFile: JsCallable<[FilePath, Encoding | void], string | Array> = + jsCallable((path, encoding) => { if (!encoding) { // $FlowFixMe - return [...fs.readFileSync(path)]; - } else { - return fs.readFileSync(path, encoding); - } - }), - isFile: (path: string) => { - try { - return fs.statSync(path).isFile(); - } catch { - return false; - } - }, - isDir: (path: string) => { - try { - return fs.statSync(path).isDirectory(); - } catch { - return false; + return [...this.#fs.readFileSync(path)]; } - }, - }; + return this.#fs.readFileSync(path, encoding); + }); } diff --git a/packages/core/core/src/atlaspack-v3/index.js b/packages/core/core/src/atlaspack-v3/index.js index 44a7ade6b..77565be21 100644 --- a/packages/core/core/src/atlaspack-v3/index.js +++ b/packages/core/core/src/atlaspack-v3/index.js @@ -1,5 +1,6 @@ // @flow -export {toFileSystemV3} from './fs'; +export * from './fs'; export {AtlaspackV3} from './AtlaspackV3'; +export * from './package-manager'; export type * from './AtlaspackV3'; diff --git a/packages/core/core/src/atlaspack-v3/jsCallable.js b/packages/core/core/src/atlaspack-v3/jsCallable.js index 3d2714a39..e7bac277f 100644 --- a/packages/core/core/src/atlaspack-v3/jsCallable.js +++ b/packages/core/core/src/atlaspack-v3/jsCallable.js @@ -2,16 +2,22 @@ export type JsCallable, Return> = ( ...Args -) => Return; +) => Promise<[string | null, Return | null]>; export function jsCallable, Return>( - fn: (...Args) => Return, -): (...Args) => Return { - return (...args: Args) => { + fn: (...Args) => Return | Promise, +): JsCallable { + return async (...args) => { try { - return fn(...args); + const result = await fn(...args); + return [null, result]; } catch (err) { - return err; + if (err instanceof Error) { + return [err.stack, null]; + } + // $FlowFixMe migrate to TypeScript + let errStr = `${err}`; + return [`${errStr}`, null]; } }; } diff --git a/packages/core/core/src/atlaspack-v3/package-manager.js b/packages/core/core/src/atlaspack-v3/package-manager.js new file mode 100644 index 000000000..b12222562 --- /dev/null +++ b/packages/core/core/src/atlaspack-v3/package-manager.js @@ -0,0 +1,25 @@ +// @flow + +import type {PackageManager} from '@atlaspack/rust'; +import type { + PackageManager as ClassicPackageManager, + PackageManagerResolveResult, + DependencySpecifier, + FilePath, + PackageManagerPackageOptions, +} from '@atlaspack/types'; +import type {JsCallable} from './jsCallable'; +import {jsCallable} from './jsCallable'; + +export class NativePackageManager implements PackageManager { + #packageManager: ClassicPackageManager; + + constructor(packageManager: ClassicPackageManager) { + this.#packageManager = packageManager; + } + + resolve: JsCallable< + [DependencySpecifier, FilePath, ?PackageManagerPackageOptions], + Promise, + > = jsCallable((...args) => this.#packageManager.resolve(...args)); +} diff --git a/packages/core/core/src/atlaspack-v3/worker/worker.js b/packages/core/core/src/atlaspack-v3/worker/worker.js index 493a176ea..fbaf32c85 100644 --- a/packages/core/core/src/atlaspack-v3/worker/worker.js +++ b/packages/core/core/src/atlaspack-v3/worker/worker.js @@ -96,17 +96,10 @@ export class AtlaspackWorker { // console.log('Hi'); } - async runTransformer({ - resolveFrom, - specifier, - options, - asset, - }: {| - resolveFrom: string, - specifier: string, - options: PluginOptions, - asset: InnerAsset, - |}): any { + runTransformer: JsCallable< + [RunTransformerOptions], + Promise, + > = jsCallable(async ({resolveFrom, specifier, options, asset}) => { const customRequire = module.createRequire(resolveFrom); const resolvedPath = customRequire.resolve(specifier); // $FlowFixMe @@ -116,59 +109,63 @@ export class AtlaspackWorker { let assetCompat = new AssetCompat(asset, options); - try { - if (transformer.parse) { - // $FlowFixMe - const ast = await transformer.parse({asset: assetCompat}); // missing "config" - // $FlowFixMe - assetCompat.setAST(ast); - } + if (transformer.parse) { + // $FlowFixMe + const ast = await transformer.parse({asset: assetCompat}); // missing "config" + // $FlowFixMe + assetCompat.setAST(ast); + } + // $FlowFixMe + const result = await transformer.transform({ // $FlowFixMe - const result = await transformer.transform({ - // $FlowFixMe - asset: assetCompat, - options, - config: null, - }); + asset: assetCompat, + options, + config: null, + }); - if (transformer.generate) { + if (transformer.generate) { + // $FlowFixMe + let output = await transformer.generate({ // $FlowFixMe - let output = await transformer.generate({ - // $FlowFixMe - asset: assetCompat, - // $FlowFixMe - ast: assetCompat.getAST(), - }); + asset: assetCompat, // $FlowFixMe - assetCompat.setCode(output.content); - } + ast: assetCompat.getAST(), + }); + // $FlowFixMe + assetCompat.setCode(output.content); + } - assert( - result.length === 1, - '[V3] Unimplemented: Multiple asset return from Node transformer', - ); - assert( - result[0] === assetCompat, - '[V3] Unimplemented: New asset returned from Node transformer', - ); + assert( + result.length === 1, + '[V3] Unimplemented: Multiple asset return from Node transformer', + ); + assert( + result[0] === assetCompat, + '[V3] Unimplemented: New asset returned from Node transformer', + ); - return { - asset, - dependencies: assetCompat._dependencies, - }; - } catch (e) { - // TODO: Improve error logging from JS plugins. Without this you currently - // only see the error message, no stack trace. - // eslint-disable-next-line no-console - console.error(e); - throw e; - } - } + return { + asset, + dependencies: assetCompat._dependencies, + }; + }); } napi.registerWorker(workerData.tx_worker, new AtlaspackWorker()); +type RunTransformerOptions = {| + resolveFrom: string, + specifier: string, + options: PluginOptions, + asset: InnerAsset, +|}; + +type RunTransformerResult = {| + asset: mixed, + dependencies: mixed, +|}; + type LoadPluginOptions = {| kind: 'resolver', specifier: string, diff --git a/packages/core/core/test/Dependency.test.js b/packages/core/core/test/Dependency.test.js index a7083fcde..0bc0189b5 100644 --- a/packages/core/core/test/Dependency.test.js +++ b/packages/core/core/test/Dependency.test.js @@ -1,4 +1,4 @@ -import expect from 'expect'; +import assert from 'assert'; import {createDependencyId} from '../src/Dependency'; import {createEnvironment} from '../src/Environment'; @@ -15,7 +15,7 @@ describe('Dependency', () => { env: createEnvironment(), specifierType: 'esm', }); - expect(id1).toEqual(id2); + assert.equal(id1, id2); }); }); }); diff --git a/packages/core/core/test/Environment.test.js b/packages/core/core/test/Environment.test.js index b214b8e9c..d6304fdee 100644 --- a/packages/core/core/test/Environment.test.js +++ b/packages/core/core/test/Environment.test.js @@ -1,8 +1,6 @@ // @flow strict-local import assert from 'assert'; -// $FlowFixMe -import expect from 'expect'; import {createEnvironment} from '../src/Environment'; import {initializeMonitoring} from '../../rust'; @@ -105,6 +103,6 @@ describe('createEnvironment', function () { it('returns a stable hash', () => { initializeMonitoring(); const environment = createEnvironment({}); - expect(environment.id).toEqual('d821e85f6b50315e'); + assert.equal(environment.id, 'd821e85f6b50315e'); }); }); diff --git a/packages/core/integration-tests/test/atlaspack-v3.js b/packages/core/integration-tests/test/atlaspack-v3.js index 694585123..d26d51f5e 100644 --- a/packages/core/integration-tests/test/atlaspack-v3.js +++ b/packages/core/integration-tests/test/atlaspack-v3.js @@ -2,7 +2,7 @@ import {join} from 'path'; -import {AtlaspackV3, toFileSystemV3} from '@atlaspack/core'; +import {AtlaspackV3} from '@atlaspack/core'; import {NodePackageManager} from '@atlaspack/package-manager'; import { describe, @@ -32,7 +32,7 @@ describe('AtlaspackV3', function () { let atlaspack = new AtlaspackV3({ corePath: '', entries: [join(__dirname, 'index.js')], - fs: toFileSystemV3(overlayFS), + fs: overlayFS, nodeWorkers: 1, packageManager: new NodePackageManager(inputFS, __dirname), }); diff --git a/packages/core/rust/index.js.flow b/packages/core/rust/index.js.flow index 88e605d28..742c66aea 100644 --- a/packages/core/rust/index.js.flow +++ b/packages/core/rust/index.js.flow @@ -4,7 +4,9 @@ import type { FileCreateInvalidation, FilePath, InitialAtlaspackOptions, - PackageManager, + PackageManagerResolveResult, + DependencySpecifier, + PackageManagerPackageOptions, } from '@atlaspack/types'; declare export var init: void | (() => void); @@ -24,12 +26,26 @@ export interface ConfigRequest { } export interface RequestOptions {} +export type IsOk = boolean; + +export type JsCallable, Return> = ( + ...Args +) => Promise<[string | null, Return | null]>; + export interface FileSystem { - canonicalize(path: FilePath): FilePath; - cwd(): FilePath; - isDir(path: FilePath): boolean; - isFile(path: FilePath): boolean; - readFile(path: FilePath, encoding?: Encoding): string; + canonicalize: JsCallable<[FilePath], FilePath>; + createDirectory: JsCallable<[FilePath], Promise>; + cwd: JsCallable<[], FilePath>; + isDir: JsCallable<[FilePath], boolean>; + isFile: JsCallable<[FilePath], boolean>; + readFile: JsCallable<[FilePath, Encoding | void], string | Array>; +} + +export interface PackageManager { + resolve: JsCallable< + [DependencySpecifier, FilePath, ?PackageManagerPackageOptions], + Promise, +> } export type AtlaspackNapiOptions = {| diff --git a/packages/core/types-internal/src/PackageManager.js b/packages/core/types-internal/src/PackageManager.js index 87bc06565..d7e87919d 100644 --- a/packages/core/types-internal/src/PackageManager.js +++ b/packages/core/types-internal/src/PackageManager.js @@ -43,17 +43,23 @@ export interface PackageManager { require( id: DependencySpecifier, from: FilePath, - ?{|range?: ?SemverRange, shouldAutoInstall?: boolean, saveDev?: boolean|}, + options: ?PackageManagerPackageOptions, ): Promise; resolve( id: DependencySpecifier, from: FilePath, - ?{|range?: ?SemverRange, shouldAutoInstall?: boolean, saveDev?: boolean|}, + options: ?PackageManagerPackageOptions, ): Promise; getInvalidations(id: DependencySpecifier, from: FilePath): Invalidations; invalidate(id: DependencySpecifier, from: FilePath): void; } +export type PackageManagerPackageOptions = {| + range?: ?SemverRange, + shouldAutoInstall?: boolean, + saveDev?: boolean, +|}; + export type ModuleRequest = {| +name: string, +range: ?SemverRange, diff --git a/packages/core/types-internal/src/index.js b/packages/core/types-internal/src/index.js index 2f4026022..532b98180 100644 --- a/packages/core/types-internal/src/index.js +++ b/packages/core/types-internal/src/index.js @@ -25,6 +25,7 @@ import type {Glob} from './Glob'; import type {PackageName} from './PackageName'; import type { PackageManager, + PackageManagerPackageOptions, PackageManagerResolveResult, Invalidations, PackageInstaller, @@ -62,6 +63,7 @@ export type { FileInvalidation, FileAboveInvalidation, PackageManager, + PackageManagerPackageOptions, PackageManagerResolveResult, Invalidations, PackageInstaller,