UNPKG

@feature-sliced/filesystem

Version:

A set of utilities for locating and working with FSD roots in the file system.

233 lines (227 loc) 7.62 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { conventionalSegmentNames: () => conventionalSegmentNames, crossReferenceToken: () => crossReferenceToken, getAllSegments: () => getAllSegments, getAllSlices: () => getAllSlices, getIndexes: () => getIndexes, getLayers: () => getLayers, getSegments: () => getSegments, getSlices: () => getSlices, isCrossImportPublicApi: () => isCrossImportPublicApi, isIndex: () => isIndex, isSlice: () => isSlice, isSliced: () => isSliced, layerSequence: () => layerSequence, resolveImport: () => resolveImport, unslicedLayers: () => unslicedLayers }); module.exports = __toCommonJS(index_exports); // src/fsd-aware-traverse.ts var import_node_path = require("path"); // src/definitions.ts var layerSequence = [ "shared", "entities", "features", "widgets", "pages", "app" ]; var unslicedLayers = ["shared", "app"]; var conventionalSegmentNames = ["ui", "api", "lib", "model", "config"]; var crossReferenceToken = "@x"; // src/fsd-aware-traverse.ts function getLayers(fsdRoot) { return Object.fromEntries( fsdRoot.children.filter( (child) => child.type === "folder" && layerSequence.includes((0, import_node_path.basename)(child.path)) ).map((child) => [(0, import_node_path.basename)(child.path), child]) ); } function getSlices(slicedLayer, additionalSegmentNames = []) { const slices = {}; function traverse(folder, pathPrefix = "") { if (isSlice(folder, additionalSegmentNames)) { slices[(0, import_node_path.join)(pathPrefix, (0, import_node_path.basename)(folder.path))] = folder; } else { folder.children.forEach((child) => { if (child.type === "folder") { traverse(child, (0, import_node_path.join)(pathPrefix, (0, import_node_path.basename)(folder.path))); } }); } } for (const child of slicedLayer.children) { if (child.type === "folder") { traverse(child); } } return slices; } function getSegments(sliceOrUnslicedLayer) { return Object.fromEntries( sliceOrUnslicedLayer.children.filter((child) => !isIndex(child)).map((child) => [(0, import_node_path.parse)(child.path).name, child]) ); } function getAllSlices(fsdRoot, additionalSegmentNames = []) { return Object.values(getLayers(fsdRoot)).filter(isSliced).reduce((slices, layer) => { return { ...slices, ...Object.fromEntries( Object.entries(getSlices(layer, additionalSegmentNames)).map( ([name, slice]) => [ name, { ...slice, layerName: (0, import_node_path.basename)(layer.path) } ] ) ) }; }, {}); } function getAllSegments(fsdRoot) { return Object.entries(getLayers(fsdRoot)).flatMap(([layerName, layer]) => { if (isSliced(layer)) { return Object.entries(getSlices(layer)).flatMap( ([sliceName, slice]) => Object.entries(getSegments(slice)).map(([segmentName, segment]) => ({ segment, segmentName, sliceName, layerName })) ); } else { return Object.entries(getSegments(layer)).map( ([segmentName, segment]) => ({ segment, segmentName, sliceName: null, layerName }) ); } }); } function isSliced(layerOrName) { return !unslicedLayers.includes( (0, import_node_path.basename)(typeof layerOrName === "string" ? layerOrName : layerOrName.path) ); } function getIndexes(fileOrFolder) { if (fileOrFolder.type === "file") { return [fileOrFolder]; } return fileOrFolder.children.filter(isIndex); } function isIndex(fileOrFolder) { if (fileOrFolder.type === "file") { const separator = "."; const parsedFileName = (0, import_node_path.parse)(fileOrFolder.path).name; return parsedFileName.split(separator).at(0) === "index"; } return false; } function isCrossImportPublicApi(file, { inSlice, forSlice, layerPath }) { const { dir, name } = (0, import_node_path.parse)(file.path); if (isIndex(file)) { return dir === (0, import_node_path.join)(layerPath, inSlice, "@x", forSlice); } return name === forSlice && dir === (0, import_node_path.join)(layerPath, inSlice, "@x"); } function isSlice(folder, additionalSegmentNames = []) { return folder.children.some( (child) => conventionalSegmentNames.concat(additionalSegmentNames).includes((0, import_node_path.parse)(child.path).name) ); } // src/resolve-import.ts var import_node_path2 = require("path"); var import_typescript = __toESM(require("typescript"), 1); function resolveImport(importedPath, importerPath, tsCompilerOptions, fileExists, directoryExists) { return import_typescript.default.resolveModuleName( importedPath, importerPath, normalizeCompilerOptions(tsCompilerOptions), { ...import_typescript.default.sys, fileExists, directoryExists } ).resolvedModule?.resolvedFileName?.replaceAll("/", import_node_path2.sep) ?? null; } var imperfectKeys = { module: import_typescript.default.ModuleKind, moduleResolution: { ...import_typescript.default.ModuleResolutionKind, node: import_typescript.default.ModuleResolutionKind.Node10 }, moduleDetection: import_typescript.default.ModuleDetectionKind, newLine: import_typescript.default.NewLineKind, target: import_typescript.default.ScriptTarget }; function normalizeCompilerOptions(compilerOptions) { return Object.fromEntries( Object.entries(compilerOptions).map(([key, value]) => { if (Object.keys(imperfectKeys).includes(key) && typeof value === "string") { for (const [enumKey, enumValue] of Object.entries( imperfectKeys[key] )) { if (enumKey.toLowerCase() === value.toLowerCase()) { return [key, enumValue]; } } } return [key, value]; }) ); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { conventionalSegmentNames, crossReferenceToken, getAllSegments, getAllSlices, getIndexes, getLayers, getSegments, getSlices, isCrossImportPublicApi, isIndex, isSlice, isSliced, layerSequence, resolveImport, unslicedLayers });