UNPKG

@lenne.tech/cli

Version:

lenne.Tech CLI: lt

168 lines (167 loc) 6.81 kB
"use strict"; /** * Framework-detection helpers for @lenne.tech/nest-server consumer projects. * * lenne.tech API projects can consume the framework in two modes: * * - **npm mode** (classic): `@lenne.tech/nest-server` is installed as an npm * dependency. Framework source lives in * `node_modules/@lenne.tech/nest-server/`. Generated code uses bare * specifiers (`from '@lenne.tech/nest-server'`). * * - **vendored mode**: The framework's `core/` directory is copied directly * into the project at `<api-root>/src/core/` as first-class project code. * There is **no** `@lenne.tech/nest-server` dependency in `package.json`. * Generated code uses relative imports (`from '../../../core'`, depth * varies by file location). * * The detection is driven by the presence of `<api-root>/src/core/VENDOR.md` * (a baseline + patch-log file written by the vendoring pilot). * * This module centralizes the detection logic so that every CLI command which * emits or patches nest-server-aware code can branch consistently. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.detectFrameworkMode = detectFrameworkMode; exports.findProjectDir = findProjectDir; exports.getFrameworkImportSpecifier = getFrameworkImportSpecifier; exports.getFrameworkRootPath = getFrameworkRootPath; exports.isVendoredProject = isVendoredProject; const node_fs_1 = require("node:fs"); const path = __importStar(require("node:path")); /** * Determines the current framework consumption mode of the given project. * * Returns `'vendor'` if `VENDOR.md` indicates vendored mode. Otherwise * returns `'npm'` (the classic mode where `@lenne.tech/nest-server` is an * npm dependency). */ function detectFrameworkMode(projectDir) { return isVendoredProject(projectDir) ? 'vendor' : 'npm'; } /** * Walks up from `startDir` looking for the nearest `package.json`, returning * the directory that contains it. Used by commands that are invoked from a * sub-directory of an API project and need to find the project root. * * Returns `undefined` if no `package.json` is found up to the filesystem root. */ function findProjectDir(startDir) { let current = path.resolve(startDir); const root = path.parse(current).root; while (current !== root) { if ((0, node_fs_1.existsSync)(path.join(current, 'package.json'))) { return current; } current = path.dirname(current); } return undefined; } /** * Returns the import specifier to use for `from '<framework>'` in generated * source code living at `sourceFilePath`. * * - npm mode: always `'@lenne.tech/nest-server'` (bare specifier). * - vendor mode: a relative path from `sourceFilePath`'s directory to * `<projectDir>/src/core`, normalized to forward slashes and * prefixed with `./` if needed. Example: for * `projectDir/src/server/modules/foo/foo.service.ts`, returns * `'../../../core'`. * * `sourceFilePath` is the absolute path of the file that WILL CONTAIN the * import — NOT the file being imported. Depth is calculated from this path. * * @example * // Project at /abs/api, file at src/server/modules/foo/foo.service.ts * getFrameworkImportSpecifier('/abs/api', * '/abs/api/src/server/modules/foo/foo.service.ts'); * // → '../../../core' (vendor mode) * // → '@lenne.tech/nest-server' (npm mode) */ function getFrameworkImportSpecifier(projectDir, sourceFilePath) { if (!isVendoredProject(projectDir)) { return '@lenne.tech/nest-server'; } const corePath = path.join(projectDir, 'src', 'core'); const fromDir = path.dirname(sourceFilePath); let rel = path.relative(fromDir, corePath); // Normalize to POSIX separators (import specifiers are always forward-slash) rel = rel.split(path.sep).join('/'); // Guarantee a relative prefix; sibling or descendant paths otherwise miss `./` if (!rel.startsWith('.')) { rel = `./${rel}`; } return rel; } /** * Returns the filesystem root of the framework source for the project. * * - npm mode: `<projectDir>/node_modules/@lenne.tech/nest-server` * - vendor mode: `<projectDir>/src/core` * * Consumers that need to introspect framework source files (e.g. permissions * scanner, CrudService lookup) should use this instead of hard-coding either * path. */ function getFrameworkRootPath(projectDir) { return isVendoredProject(projectDir) ? path.join(projectDir, 'src', 'core') : path.join(projectDir, 'node_modules', '@lenne.tech', 'nest-server'); } /** * Detects whether the given API project directory runs in vendored mode. * * A project is considered vendored when: * 1. `<projectDir>/src/core/VENDOR.md` exists, AND * 2. The VENDOR.md content references `@lenne.tech/nest-server` (guards * against coincidental unrelated `VENDOR.md` files). * * @param projectDir Absolute path to the api project (the directory that * contains `package.json` and `src/`). */ function isVendoredProject(projectDir) { const vendorMd = path.join(projectDir, 'src', 'core', 'VENDOR.md'); if (!(0, node_fs_1.existsSync)(vendorMd)) { return false; } try { const content = (0, node_fs_1.readFileSync)(vendorMd, 'utf-8'); return content.includes('@lenne.tech/nest-server'); } catch (_a) { return false; } }