From 46936baaaeb11969275831f2e9866563d4e652da Mon Sep 17 00:00:00 2001 From: fraxken Date: Wed, 4 Jun 2025 00:11:11 +0200 Subject: [PATCH] feat(mama): implement optional ManifestManager location dirname --- .changeset/eight-cows-ask.md | 5 ++++ workspaces/mama/README.md | 25 +++++++++++++++++++- workspaces/mama/src/ManifestManager.class.ts | 22 ++++++++++++++--- workspaces/mama/test/ManifestManager.spec.ts | 22 +++++++++++++++++ 4 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 .changeset/eight-cows-ask.md diff --git a/.changeset/eight-cows-ask.md b/.changeset/eight-cows-ask.md new file mode 100644 index 00000000..34c1df5a --- /dev/null +++ b/.changeset/eight-cows-ask.md @@ -0,0 +1,5 @@ +--- +"@nodesecure/mama": patch +--- + +Add optional ManifestManager dirname location diff --git a/workspaces/mama/README.md b/workspaces/mama/README.md index 9dacc283..c8f453de 100644 --- a/workspaces/mama/README.md +++ b/workspaces/mama/README.md @@ -39,15 +39,38 @@ Load a new instance using a `package.json` from the filesystem. The **location** parameter can either be a full path or the path to the directory where the `package.json` is located. -### constructor(document: ManifestManagerDocument) +> [!NOTE] +> `location` is automatically dispatched to the ManifestManager constructor options. + +### constructor(document: ManifestManagerDocument, options?: ManifestManagerOptions) +document is described by the following type: ```ts +import type { + PackumentVersion, + PackageJSON, + WorkspacesPackageJSON +} from "@nodesecure/npm-types"; + type ManifestManagerDocument = PackageJSON | WorkspacesPackageJSON | PackumentVersion; ``` +And the `options` interface + +```ts +export interface ManifestManagerOptions { + /** + * Optional absolute location (directory) to the manifest + */ + location?: string; +} +``` + +--- + Default values are injected if they are not present in the document. This behavior is necessary for the correct operation of certain functions, such as integrity recovery. ```js diff --git a/workspaces/mama/src/ManifestManager.class.ts b/workspaces/mama/src/ManifestManager.class.ts index 49a4516d..ac0dc8df 100644 --- a/workspaces/mama/src/ManifestManager.class.ts +++ b/workspaces/mama/src/ManifestManager.class.ts @@ -48,6 +48,13 @@ export type ManifestManagerDefaultProperties = Required< Pick >; +export interface ManifestManagerOptions { + /** + * Optional absolute location (directory) to the manifest + */ + location?: string; +} + export type ManifestManagerDocument = PackageJSON | WorkspacesPackageJSON | @@ -68,19 +75,27 @@ export class ManifestManager< ManifestManagerDocument, NonOptionalPackageJSONProperties >; - + public location: string | undefined; public flags = Object.seal({ hasUnsafeScripts: false, isNative: false }); constructor( - document: ManifestManagerDocument + document: ManifestManagerDocument, + options: ManifestManagerOptions = {} ) { + const { location } = options; + this.document = Object.assign( { ...ManifestManager.Default }, structuredClone(document) ); + if (location) { + this.location = path.extname(location) || path.basename(location).startsWith(".") ? + path.dirname(location) : + location; + } this.flags.isNative = [ ...this.dependencies, @@ -218,7 +233,8 @@ export class ManifestManager< ) as PackageJSON | WorkspacesPackageJSON; return new ManifestManager( - packageJSON + packageJSON, + { location } ); } catch (cause) { diff --git a/workspaces/mama/test/ManifestManager.spec.ts b/workspaces/mama/test/ManifestManager.spec.ts index f2df8daa..a0cb5603 100644 --- a/workspaces/mama/test/ManifestManager.spec.ts +++ b/workspaces/mama/test/ManifestManager.spec.ts @@ -46,6 +46,7 @@ describe("ManifestManager", () => { location ); + assert.equal(mama.location, location); assert.equal(readfile.mock.callCount(), 1); assert.ok(mama instanceof ManifestManager); @@ -68,6 +69,7 @@ describe("ManifestManager", () => { location ); + assert.equal(mama.location, path.dirname(location)); assert.equal(readFile.mock.callCount(), 1); assert.ok(mama instanceof ManifestManager); @@ -136,6 +138,26 @@ describe("ManifestManager", () => { } ); }); + + it("Should store location as it if that's not a file", () => { + for (const location of ["/tmp/path", "./tmp/path"]) { + const mama = new ManifestManager(kMinimalPackageJSON, { location }); + assert.strictEqual(mama.location, location); + } + }); + + it("Should store location dirname if provided with a filename", () => { + for (const fileName of ["package.json", ".gitignore"]) { + const location = `/tmp/path/${fileName}`; + const mama = new ManifestManager(kMinimalPackageJSON, { location }); + assert.strictEqual(mama.location, path.dirname(location)); + } + }); + + it("Should have location undefined if not provided", () => { + const mama = new ManifestManager(kMinimalPackageJSON); + assert.strictEqual(mama.location, undefined); + }); }); describe("get moduleType", () => {