From 5d03e4eb8a417d9843b1676f8144fe535276837f Mon Sep 17 00:00:00 2001 From: Joao Santos Date: Tue, 12 Mar 2024 14:56:44 +0000 Subject: [PATCH] feat: generating a shrinkwrap-ish on workspaces --- generators/packagePacker/inversify.config.ts | 2 + generators/packagePacker/packagePacker.ts | 12 +- .../processors/shrinkwrapGenerator.ts | 125 ++++++++++++++++++ generators/packagePacker/types.ts | 1 + package.json | 2 +- 5 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 generators/packagePacker/processors/shrinkwrapGenerator.ts diff --git a/generators/packagePacker/inversify.config.ts b/generators/packagePacker/inversify.config.ts index 3502c70..3b18207 100644 --- a/generators/packagePacker/inversify.config.ts +++ b/generators/packagePacker/inversify.config.ts @@ -5,6 +5,7 @@ import { Log } from "./processors/log"; import { Paths } from "./processors/paths"; import { DriverTemplatesProcessor } from "./processors/driverTemplates"; import { LibraryTemplatesProcessor } from "./processors/libraryTemplates"; +import { ShrinkwrapGenerator } from "./processors/shrinkwrapGenerator"; const container = new Container(); @@ -15,5 +16,6 @@ container.bind(TYPES.Paths).to(Paths).inSingletonScope(); container.bind(TYPES.Processors.DriverTemplates).to(DriverTemplatesProcessor).inSingletonScope(); container.bind(TYPES.Processors.LibraryTemplates).to(LibraryTemplatesProcessor).inSingletonScope(); +container.bind(TYPES.Processors.ShrinkwrapGenerator).to(ShrinkwrapGenerator).inSingletonScope(); export { container }; diff --git a/generators/packagePacker/packagePacker.ts b/generators/packagePacker/packagePacker.ts index c664517..8e8291a 100644 --- a/generators/packagePacker/packagePacker.ts +++ b/generators/packagePacker/packagePacker.ts @@ -8,6 +8,8 @@ import { DriverTemplatesProcessor } from "./processors/driverTemplates"; import { LibraryTemplatesProcessor } from "./processors/libraryTemplates"; import { TYPES } from "./types"; import { Paths } from "./processors/paths"; +import { Log } from "./processors/log"; +import { ShrinkwrapGenerator } from "./processors/shrinkwrapGenerator"; export class PackagePacker { @@ -23,6 +25,8 @@ export class PackagePacker { const debug: boolean = options.d || options.debug || false; // let mappedAddons: string | undefined = undefined; + const _logger: Log = container.get(TYPES.Logger); + console.log(`Using the following settings:`); console.log(` Source : ${source}`); console.log(` Destination : ${destination}`); @@ -121,7 +125,13 @@ export class PackagePacker { if (configuration.type !== ComponentType.TasksPackage) { // Copy necessary files to generate package - this.copyFile("npm-shrinkwrap.json", source, temp); + if (!io.existsSync("npm-shrinkwrap.json")) { + _logger.Warn("npm-shrinkwrap.json file not found. Trying to generate it..."); + container.get(TYPES.Processors.ShrinkwrapGenerator).process(source, "npm-shrinkwrap.json"); + this.copyFile("npm-shrinkwrap.json", source, temp); + } else { + this.copyFile("npm-shrinkwrap.json", source, temp); + } this.copyFile(".npmignore", source, temp); this.copyFile(".npmrc", source, temp); this.copyFile("README.md", source, temp); diff --git a/generators/packagePacker/processors/shrinkwrapGenerator.ts b/generators/packagePacker/processors/shrinkwrapGenerator.ts new file mode 100644 index 0000000..6d81720 --- /dev/null +++ b/generators/packagePacker/processors/shrinkwrapGenerator.ts @@ -0,0 +1,125 @@ +import { Log } from "./log"; +import * as io from "fs-extra"; +import * as path from "path"; +import { inject, injectable } from "inversify"; +import { TYPES } from "../types"; +import { Paths } from "./paths"; + +@injectable() +export class ShrinkwrapGenerator { + + @inject(TYPES.Logger) + private _logger: Log; + + public process(source: string , fileName: string): void { + let lockFilePath = path.join(source, "package-lock.json"); + let isWorkspaces = false; + if (!io.existsSync(lockFilePath)) { + this._logger.Warn(`Package Lock file not found. Assuming this environment is using workspaces`); + + // Search up to 3 levels up + for (let i = 0; i < 3; i++) { + const levels = []; + for (let j = 0; j <= i; j++) { + levels.push(".."); + } + + lockFilePath = path.resolve(source, ...levels, "package-lock.json") + if (io.existsSync(lockFilePath)) { + isWorkspaces = true; + break; + } + } + } + + if (!io.existsSync(lockFilePath)) { + this._logger.Error(`Unable to find a suitable package lock file in the directory tree!`); + } else { + if (!isWorkspaces) { + this._logger.Info(`Since this is not a workspace environment, copying package-lock.json file as ${fileName}`); + io.copyFileSync(lockFilePath, path.join(source, fileName)); + } else { + const packageJsonLocation = path.join(source, "package.json"); + this._logger.Info(`Reading original package from '${packageJsonLocation}'`); + const packageJson = io.readJSONSync(packageJsonLocation); + this._logger.Info(`Reading lock file from '${lockFilePath}'`); + const lockJson = io.readJSONSync(lockFilePath); + + // now, cleanup the file + const prefix = source.slice(path.dirname(lockFilePath).length + 1).replace("\\", "/"); + + let dependencies: string[] = []; + for (const key in packageJson.dependencies ?? {}) { + dependencies.push(key); + } + for (const key in packageJson.peerDependencies ?? {}) { + dependencies.push(key); + } + + // Reprocess the important packages (@criticalmanufacturing/); + for(const dep of dependencies) { + if (dep.startsWith("@criticalmanufacturing/")) { + const importantPack = this.searchImportantPackage(lockJson.packages ?? {}, dep); + for (const key in importantPack.dependencies ?? {}) { + dependencies.push(key); + } + for (const key in importantPack.peerDependencies ?? {}) { + dependencies.push(key); + } + } + } + + // Remove duplicates + dependencies = dependencies.filter((item, index) => dependencies.indexOf(item) === index); + + const result: any = {}; + + // First add all entries that match the same name of this path + for (const key in lockJson.packages) { + if (key.startsWith(prefix)) { + result[key] = lockJson.packages[key]; + } + } + + dependencies.forEach((pack) => { + this._logger.Info(` Adding resolved package information for '${pack}'`); + const results = this.searchPackage(lockJson.packages ?? {}, pack); + for (const key in results) { + result[key] = results[key]; + } + }); + + + this._logger.Info(`Generating '${fileName}' file with relevant dependencies information for this package`) + io.writeJSONSync(path.join(source, fileName), { + name: packageJson.name, + version: packageJson.version, + packages: result + }, { + spaces: 2 + }); + } + } + } + + private searchPackage(full: any, search: string): any { + const result: any = {}; + for (const key in full) { + if (key === ("node_modules/" + search) || key.startsWith("node_modules/" + search + "/") || full[key].name === search) { + result[key] = full[key] + } + } + + return (result); + } + + private searchImportantPackage(full: any, search: string): any { + for (const key in full) { + if (full[key].name === search) { + return (full[key]); + } + } + + return ({}); + } +} \ No newline at end of file diff --git a/generators/packagePacker/types.ts b/generators/packagePacker/types.ts index 8c428e0..135d083 100644 --- a/generators/packagePacker/types.ts +++ b/generators/packagePacker/types.ts @@ -7,5 +7,6 @@ export const TYPES = { Processors: { DriverTemplates: Symbol("DriverTemplatesProcessor"), LibraryTemplates: Symbol("LibraryTemplatesProcessor"), + ShrinkwrapGenerator: Symbol("ShrinkwrapGenerator"), } }; diff --git a/package.json b/package.json index 828250d..c3719b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@criticalmanufacturing/generator-iot", - "version": "10.2.7", + "version": "10.2.9", "description": "Connect IoT Scaffolding", "files": [ "generators/*.js",