import { path, FileSystem, type Logger } from '@servicenow/sdk-build-core' import { getAttachmentContent } from '../source-artifact-utils' export type ProjectSourceFiles = { // Project-relative paths whose content is read from disk. sourceFiles: string[] } /** * Reads the source-file inputs from `_project.json` for the app source artifact. * * @returns an empty list when `_project.json` is absent. * @throws {Error} if `_project.json` is present but cannot be read or parsed — a corrupt file * fails hard rather than silently producing a build with no editable source, which would * otherwise look identical to the legitimate case where no source files exist. */ export function readProjectJsonSourceFiles(fs: FileSystem, metadataDir: string): ProjectSourceFiles { const projectJsonPath = path.join(metadataDir, '_project.json') if (!FileSystem.existsSync(fs, projectJsonPath)) { return { sourceFiles: [] } } const content = fs.readFileSync(projectJsonPath, { encoding: 'utf-8' }).toString() const parsed = JSON.parse(content) as { sourceFiles?: string[] } return { sourceFiles: parsed.sourceFiles ?? [], } } export type SourceArtifactFiles = { files: Map totalSize: number skippedFiles: string[] } /** * Assembles the set of files for the AIUX source artifact from _project.json. * * Reads `sourceFiles` (project-relative paths) from disk under `projectDir`. * * @returns the file map, total size, and skipped-file warnings — or `null` when there are * no source files to attach at all. * @throws {Error} if the combined size would exceed `MAX_TOTAL_SIZE`, or if `_project.json` is * present but cannot be read or parsed (see {@link readProjectJsonSourceFiles}). */ export async function collectSourceArtifactFiles( fs: FileSystem, { metadataDir, projectDir, useNowPackIgnore = false, logger, }: { metadataDir: string; projectDir: string; useNowPackIgnore?: boolean; logger?: Logger } ): Promise { const { sourceFiles } = readProjectJsonSourceFiles(fs, metadataDir) if (sourceFiles.length === 0) { return null } return getAttachmentContent(fs, projectDir, sourceFiles, useNowPackIgnore, logger) }