@libria/scaffold-plugin-ts-lib 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ af0da0b1616a134a27f1dade7e24291d5aff575a2f023e12a1d63524155fd13d
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CinemaCove
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # @libria/scaffold-ts-lib
2
+
3
+ TypeScript library template for [@libria/scaffold](https://github.com/LibriaForge/scaffold).
4
+
5
+ This plugin scaffolds new TypeScript library projects with a pre-configured build setup, testing, linting, and publishing workflow.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @libria/scaffold-ts-lib
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ # Interactive — prompts for all options
17
+ scaffold new ts-lib my-lib
18
+
19
+ # Non-interactive
20
+ scaffold new ts-lib my-lib --author "John Doe" --license MIT
21
+ ```
22
+
23
+ ## What You Get
24
+
25
+ A ready-to-use TypeScript library project with:
26
+
27
+ - TypeScript configuration (strict mode)
28
+ - Build setup with dual CJS/ESM output
29
+ - Vitest for testing
30
+ - ESLint + Prettier for code quality
31
+ - Package.json with proper exports map
32
+
33
+ ## License
34
+
35
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,5 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`child_process`),l=require(`path`);l=s(l);let u=require(`url`),d=require(`util`),f=require(`@libria/plugin-loader`),p=require(`@libria/scaffold-core`),m=require(`fs-extra`);m=s(m);const h=l.default.dirname((0,u.fileURLToPath)(require(`url`).pathToFileURL(__filename).href)),g=l.default.resolve(h,`..`,`template-files`),_=(0,d.promisify)(c.exec);var v=(0,f.definePlugin)({id:`libria:scaffold:ts-lib`,name:`ts-lib`,pluginType:p.SCAFFOLD_TEMPLATE_PLUGIN_TYPE,async create(e){return{api:{argument:`ts-lib`,getOptions:async e=>({packageName:{flags:`--package-name`,description:`Package name:`,defaultValue:e.name},description:{flags:`--description`,description:`Description:`},version:{flags:`--version`,description:`Version:`,defaultValue:`0.0.0`,required:!0},author:{flags:`--author`,description:`Author:`},githubRepo:{flags:`--github-repo`,description:`GitHub repository (owner/repo):`},gitInit:{flags:`--git-init`,description:`Initialize git repository?`,defaultValue:!0,required:!1},packageManager:{flags:`--package-manager`,description:`Package Manager (npm/yarn/pnpm):`,choices:[`npm`,`yarn`,`pnpm`],defaultValue:`npm`},install:{flags:`--install`,description:`Install dependencies?`,defaultValue:!0,required:!1}}),execute:async e=>{await y(e),await x(e)}}}}});async function y(e){let{name:t,dryRun:n,force:r}=e,i=l.default.resolve(process.cwd(),t);await m.default.pathExists(i)&&(r||(console.error(`Directory '${t}' already exists. Use --force to overwrite.`),process.exit(1)),n?console.log(`[dry-run] Would remove existing directory: ${i}`):(await m.default.remove(i),console.log(`Removed existing directory: ${i}`))),n?console.log(`[dry-run] Would create directory: ${i}`):(await m.default.ensureDir(i),console.log(`Created directory: ${i}`)),await b(g,i,await m.default.readdir(g,{withFileTypes:!0}),n),n||await(0,p.replacePlaceholders)(i,{"{PROJECT_NAME}":e.name,"{PACKAGE_NAME}":e.packageName,"{DESCRIPTION}":e.description,"{VERSION}":e.version,"{GITHUB_REPO}":e.githubRepo,"{AUTHOR}":e.author}),n?console.log(`
2
+ [dry-run] No files were actually created.`):console.log(`\nProject '${t}' created successfully!`)}async function b(e,t,n,r){let i={gitignore:`.gitignore`};for(let a of n){let n=l.default.join(e,a.name),o=i[a.name]??a.name,s=l.default.join(t,o);a.isDirectory()?(r?console.log(`[dry-run] Would create directory: ${s}`):await m.default.ensureDir(s),await b(n,s,await m.default.readdir(n,{withFileTypes:!0}),r)):a.isFile()&&(r?console.log(`[dry-run] Would copy: ${a.name}`):(await m.default.copy(n,s),console.log(`Copied: ${a.name}`)))}}async function x(e){let{name:t,dryRun:n,gitInit:r,install:i,packageManager:a}=e,o=l.default.resolve(process.cwd(),t);if(n){console.log(`
3
+ [dry-run] Skipping post-process steps.`);return}if(r)try{console.log(`Initializing git repository...`),await _(`git init`,{cwd:o}),console.log(`Git repository initialized.`)}catch(e){console.error(`Failed to initialize git repository:`,e.message)}if(i)try{console.log(`Installing dependencies (this may take a moment)...`),await _(`${a} install`,{cwd:o}),console.log(`Dependencies installed successfully.`)}catch(e){console.error(`Failed to install dependencies:`,e.message)}console.log(`
4
+ All done! Your project is ready.`),console.log(`\n cd ${t}`),i||console.log(` ${a} install`),console.log(` ${a} run build`),console.log(` ${a} test`)}module.exports=v;
5
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["__dirname","exec","SCAFFOLD_TEMPLATE_PLUGIN_TYPE","fs"],"sources":["../src/ts-lib.ts"],"sourcesContent":["import { exec } from 'child_process';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { promisify } from 'util';\n\nimport { definePlugin, PluginContext } from '@libria/plugin-loader';\nimport {\n ExecuteOptions,\n replacePlaceholders,\n SCAFFOLD_TEMPLATE_PLUGIN_TYPE,\n ScaffoldTemplatePlugin,\n} from '@libria/scaffold-core';\nimport fs from 'fs-extra';\n\nimport { Options } from './types';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst FILES_DIR = path.resolve(__dirname, '..', 'template-files');\n\nconst execAsync = promisify(exec);\n\nexport default definePlugin<ScaffoldTemplatePlugin<Options>>({\n id: 'libria:scaffold:ts-lib',\n name: 'ts-lib',\n pluginType: SCAFFOLD_TEMPLATE_PLUGIN_TYPE,\n\n async create(_: PluginContext) {\n return {\n api: {\n argument: 'ts-lib',\n getOptions: async (initOptions): Promise<Options> => {\n return {\n packageName: {\n flags: '--package-name',\n description: 'Package name:',\n defaultValue: initOptions.name,\n },\n description: {\n flags: '--description',\n description: 'Description:',\n },\n version: {\n flags: '--version',\n description: 'Version:',\n defaultValue: '0.0.0',\n required: true,\n },\n author: {\n flags: '--author',\n description: 'Author:',\n },\n githubRepo: {\n flags: '--github-repo',\n description: 'GitHub repository (owner/repo):',\n },\n gitInit: {\n flags: '--git-init',\n description: 'Initialize git repository?',\n defaultValue: true,\n required: false,\n },\n packageManager: {\n flags: '--package-manager',\n description: 'Package Manager (npm/yarn/pnpm):',\n choices: ['npm', 'yarn', 'pnpm'],\n defaultValue: 'npm',\n },\n install: {\n flags: '--install',\n description: 'Install dependencies?',\n defaultValue: true,\n required: false,\n },\n };\n },\n execute: async options => {\n await generateProject(options);\n await postProcess(options);\n },\n },\n };\n },\n});\n\nasync function generateProject(options: ExecuteOptions<Options>): Promise<void> {\n const { name, dryRun, force } = options;\n const targetDir = path.resolve(process.cwd(), name);\n\n // Check if target directory exists\n if (await fs.pathExists(targetDir)) {\n if (!force) {\n console.error(`Directory '${name}' already exists. Use --force to overwrite.`);\n process.exit(1);\n }\n if (dryRun) {\n console.log(`[dry-run] Would remove existing directory: ${targetDir}`);\n } else {\n await fs.remove(targetDir);\n console.log(`Removed existing directory: ${targetDir}`);\n }\n }\n\n // Create target directory\n if (dryRun) {\n console.log(`[dry-run] Would create directory: ${targetDir}`);\n } else {\n await fs.ensureDir(targetDir);\n console.log(`Created directory: ${targetDir}`);\n }\n\n // Copy all files from files directory to target\n const entries = await fs.readdir(FILES_DIR, { withFileTypes: true });\n await copyEntries(FILES_DIR, targetDir, entries, dryRun);\n\n if (!dryRun) {\n await replacePlaceholders(targetDir, {\n '{PROJECT_NAME}': options.name,\n '{PACKAGE_NAME}': options.packageName,\n '{DESCRIPTION}': options.description,\n '{VERSION}': options.version,\n '{GITHUB_REPO}': options.githubRepo,\n '{AUTHOR}': options.author,\n });\n }\n\n if (dryRun) {\n console.log('\\n[dry-run] No files were actually created.');\n } else {\n console.log(`\\nProject '${name}' created successfully!`);\n }\n}\n\nasync function copyEntries(\n sourceDir: string,\n targetDir: string,\n entries: fs.Dirent[],\n dryRun?: boolean\n): Promise<void> {\n // Files that need to be renamed when copying (npm strips dotfiles like .gitignore)\n const RENAME_FILES: Record<string, string> = {\n gitignore: '.gitignore',\n };\n\n for (const entry of entries) {\n const sourcePath = path.join(sourceDir, entry.name);\n const targetName = RENAME_FILES[entry.name] ?? entry.name;\n const targetPath = path.join(targetDir, targetName);\n\n if (entry.isDirectory()) {\n if (dryRun) {\n console.log(`[dry-run] Would create directory: ${targetPath}`);\n } else {\n await fs.ensureDir(targetPath);\n }\n // Recursively copy directory contents\n const subEntries = await fs.readdir(sourcePath, { withFileTypes: true });\n await copyEntries(sourcePath, targetPath, subEntries, dryRun);\n } else if (entry.isFile()) {\n if (dryRun) {\n console.log(`[dry-run] Would copy: ${entry.name}`);\n } else {\n await fs.copy(sourcePath, targetPath);\n console.log(`Copied: ${entry.name}`);\n }\n }\n }\n}\n\nasync function postProcess(options: ExecuteOptions<Options>): Promise<void> {\n const { name, dryRun, gitInit, install, packageManager } = options;\n const targetDir = path.resolve(process.cwd(), name);\n\n if (dryRun) {\n console.log('\\n[dry-run] Skipping post-process steps.');\n return;\n }\n\n if (gitInit) {\n try {\n console.log('Initializing git repository...');\n await execAsync('git init', { cwd: targetDir });\n console.log('Git repository initialized.');\n } catch (error) {\n console.error('Failed to initialize git repository:', (error as Error).message);\n }\n }\n\n if (install) {\n try {\n console.log('Installing dependencies (this may take a moment)...');\n\n await execAsync(`${packageManager} install`, { cwd: targetDir });\n console.log('Dependencies installed successfully.');\n } catch (error) {\n console.error('Failed to install dependencies:', (error as Error).message);\n }\n }\n\n console.log('\\nAll done! Your project is ready.');\n console.log(`\\n cd ${name}`);\n if (!install) {\n console.log(` ${packageManager} install`);\n }\n console.log(` ${packageManager} run build`);\n console.log(` ${packageManager} test`);\n}\n"],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import * as _libria_plugin_loader0 from "@libria/plugin-loader";
2
+ import { ScaffoldTemplatePlugin, ScaffoldTemplatePluginOption } from "@libria/scaffold-core";
3
+
4
+ //#region src/types.d.ts
5
+ interface Options {
6
+ packageName: ScaffoldTemplatePluginOption<string>;
7
+ description: ScaffoldTemplatePluginOption<string>;
8
+ version: ScaffoldTemplatePluginOption<string>;
9
+ author: ScaffoldTemplatePluginOption<string>;
10
+ githubRepo: ScaffoldTemplatePluginOption<string>;
11
+ gitInit: ScaffoldTemplatePluginOption<boolean>;
12
+ install: ScaffoldTemplatePluginOption<boolean>;
13
+ packageManager: ScaffoldTemplatePluginOption<string>;
14
+ }
15
+ //#endregion
16
+ //#region src/ts-lib.d.ts
17
+ declare const _default: _libria_plugin_loader0.PluginFactory<ScaffoldTemplatePlugin<Options>>;
18
+ //#endregion
19
+ export { Options, _default as default };
20
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/ts-lib.ts"],"mappings":";;;;UAEiB,OAAA;EACb,WAAA,EAAa,4BAAA;EACb,WAAA,EAAa,4BAAA;EACb,OAAA,EAAS,4BAAA;EACT,MAAA,EAAQ,4BAAA;EACR,UAAA,EAAY,4BAAA;EACZ,OAAA,EAAS,4BAAA;EACT,OAAA,EAAS,4BAAA;EACT,cAAA,EAAgB,4BAAA;AAAA;;;cCIc,QAAA"}
@@ -0,0 +1,20 @@
1
+ import * as _libria_plugin_loader0 from "@libria/plugin-loader";
2
+ import { ScaffoldTemplatePlugin, ScaffoldTemplatePluginOption } from "@libria/scaffold-core";
3
+
4
+ //#region src/types.d.ts
5
+ interface Options {
6
+ packageName: ScaffoldTemplatePluginOption<string>;
7
+ description: ScaffoldTemplatePluginOption<string>;
8
+ version: ScaffoldTemplatePluginOption<string>;
9
+ author: ScaffoldTemplatePluginOption<string>;
10
+ githubRepo: ScaffoldTemplatePluginOption<string>;
11
+ gitInit: ScaffoldTemplatePluginOption<boolean>;
12
+ install: ScaffoldTemplatePluginOption<boolean>;
13
+ packageManager: ScaffoldTemplatePluginOption<string>;
14
+ }
15
+ //#endregion
16
+ //#region src/ts-lib.d.ts
17
+ declare const _default: _libria_plugin_loader0.PluginFactory<ScaffoldTemplatePlugin<Options>>;
18
+ //#endregion
19
+ export { Options, _default as default };
20
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/ts-lib.ts"],"mappings":";;;;UAEiB,OAAA;EACb,WAAA,EAAa,4BAAA;EACb,WAAA,EAAa,4BAAA;EACb,OAAA,EAAS,4BAAA;EACT,MAAA,EAAQ,4BAAA;EACR,UAAA,EAAY,4BAAA;EACZ,OAAA,EAAS,4BAAA;EACT,OAAA,EAAS,4BAAA;EACT,cAAA,EAAgB,4BAAA;AAAA;;;cCIc,QAAA"}
package/dist/index.mjs ADDED
@@ -0,0 +1,5 @@
1
+ import{exec as e}from"child_process";import t from"path";import{fileURLToPath as n}from"url";import{promisify as r}from"util";import{definePlugin as i}from"@libria/plugin-loader";import{SCAFFOLD_TEMPLATE_PLUGIN_TYPE as a,replacePlaceholders as o}from"@libria/scaffold-core";import s from"fs-extra";const c=t.dirname(n(import.meta.url)),l=t.resolve(c,`..`,`template-files`),u=r(e);var d=i({id:`libria:scaffold:ts-lib`,name:`ts-lib`,pluginType:a,async create(e){return{api:{argument:`ts-lib`,getOptions:async e=>({packageName:{flags:`--package-name`,description:`Package name:`,defaultValue:e.name},description:{flags:`--description`,description:`Description:`},version:{flags:`--version`,description:`Version:`,defaultValue:`0.0.0`,required:!0},author:{flags:`--author`,description:`Author:`},githubRepo:{flags:`--github-repo`,description:`GitHub repository (owner/repo):`},gitInit:{flags:`--git-init`,description:`Initialize git repository?`,defaultValue:!0,required:!1},packageManager:{flags:`--package-manager`,description:`Package Manager (npm/yarn/pnpm):`,choices:[`npm`,`yarn`,`pnpm`],defaultValue:`npm`},install:{flags:`--install`,description:`Install dependencies?`,defaultValue:!0,required:!1}}),execute:async e=>{await f(e),await m(e)}}}}});async function f(e){let{name:n,dryRun:r,force:i}=e,a=t.resolve(process.cwd(),n);await s.pathExists(a)&&(i||(console.error(`Directory '${n}' already exists. Use --force to overwrite.`),process.exit(1)),r?console.log(`[dry-run] Would remove existing directory: ${a}`):(await s.remove(a),console.log(`Removed existing directory: ${a}`))),r?console.log(`[dry-run] Would create directory: ${a}`):(await s.ensureDir(a),console.log(`Created directory: ${a}`)),await p(l,a,await s.readdir(l,{withFileTypes:!0}),r),r||await o(a,{"{PROJECT_NAME}":e.name,"{PACKAGE_NAME}":e.packageName,"{DESCRIPTION}":e.description,"{VERSION}":e.version,"{GITHUB_REPO}":e.githubRepo,"{AUTHOR}":e.author}),r?console.log(`
2
+ [dry-run] No files were actually created.`):console.log(`\nProject '${n}' created successfully!`)}async function p(e,n,r,i){let a={gitignore:`.gitignore`};for(let o of r){let r=t.join(e,o.name),c=a[o.name]??o.name,l=t.join(n,c);o.isDirectory()?(i?console.log(`[dry-run] Would create directory: ${l}`):await s.ensureDir(l),await p(r,l,await s.readdir(r,{withFileTypes:!0}),i)):o.isFile()&&(i?console.log(`[dry-run] Would copy: ${o.name}`):(await s.copy(r,l),console.log(`Copied: ${o.name}`)))}}async function m(e){let{name:n,dryRun:r,gitInit:i,install:a,packageManager:o}=e,s=t.resolve(process.cwd(),n);if(r){console.log(`
3
+ [dry-run] Skipping post-process steps.`);return}if(i)try{console.log(`Initializing git repository...`),await u(`git init`,{cwd:s}),console.log(`Git repository initialized.`)}catch(e){console.error(`Failed to initialize git repository:`,e.message)}if(a)try{console.log(`Installing dependencies (this may take a moment)...`),await u(`${o} install`,{cwd:s}),console.log(`Dependencies installed successfully.`)}catch(e){console.error(`Failed to install dependencies:`,e.message)}console.log(`
4
+ All done! Your project is ready.`),console.log(`\n cd ${n}`),a||console.log(` ${o} install`),console.log(` ${o} run build`),console.log(` ${o} test`)}export{d as default};
5
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/ts-lib.ts"],"sourcesContent":["import { exec } from 'child_process';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { promisify } from 'util';\n\nimport { definePlugin, PluginContext } from '@libria/plugin-loader';\nimport {\n ExecuteOptions,\n replacePlaceholders,\n SCAFFOLD_TEMPLATE_PLUGIN_TYPE,\n ScaffoldTemplatePlugin,\n} from '@libria/scaffold-core';\nimport fs from 'fs-extra';\n\nimport { Options } from './types';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst FILES_DIR = path.resolve(__dirname, '..', 'template-files');\n\nconst execAsync = promisify(exec);\n\nexport default definePlugin<ScaffoldTemplatePlugin<Options>>({\n id: 'libria:scaffold:ts-lib',\n name: 'ts-lib',\n pluginType: SCAFFOLD_TEMPLATE_PLUGIN_TYPE,\n\n async create(_: PluginContext) {\n return {\n api: {\n argument: 'ts-lib',\n getOptions: async (initOptions): Promise<Options> => {\n return {\n packageName: {\n flags: '--package-name',\n description: 'Package name:',\n defaultValue: initOptions.name,\n },\n description: {\n flags: '--description',\n description: 'Description:',\n },\n version: {\n flags: '--version',\n description: 'Version:',\n defaultValue: '0.0.0',\n required: true,\n },\n author: {\n flags: '--author',\n description: 'Author:',\n },\n githubRepo: {\n flags: '--github-repo',\n description: 'GitHub repository (owner/repo):',\n },\n gitInit: {\n flags: '--git-init',\n description: 'Initialize git repository?',\n defaultValue: true,\n required: false,\n },\n packageManager: {\n flags: '--package-manager',\n description: 'Package Manager (npm/yarn/pnpm):',\n choices: ['npm', 'yarn', 'pnpm'],\n defaultValue: 'npm',\n },\n install: {\n flags: '--install',\n description: 'Install dependencies?',\n defaultValue: true,\n required: false,\n },\n };\n },\n execute: async options => {\n await generateProject(options);\n await postProcess(options);\n },\n },\n };\n },\n});\n\nasync function generateProject(options: ExecuteOptions<Options>): Promise<void> {\n const { name, dryRun, force } = options;\n const targetDir = path.resolve(process.cwd(), name);\n\n // Check if target directory exists\n if (await fs.pathExists(targetDir)) {\n if (!force) {\n console.error(`Directory '${name}' already exists. Use --force to overwrite.`);\n process.exit(1);\n }\n if (dryRun) {\n console.log(`[dry-run] Would remove existing directory: ${targetDir}`);\n } else {\n await fs.remove(targetDir);\n console.log(`Removed existing directory: ${targetDir}`);\n }\n }\n\n // Create target directory\n if (dryRun) {\n console.log(`[dry-run] Would create directory: ${targetDir}`);\n } else {\n await fs.ensureDir(targetDir);\n console.log(`Created directory: ${targetDir}`);\n }\n\n // Copy all files from files directory to target\n const entries = await fs.readdir(FILES_DIR, { withFileTypes: true });\n await copyEntries(FILES_DIR, targetDir, entries, dryRun);\n\n if (!dryRun) {\n await replacePlaceholders(targetDir, {\n '{PROJECT_NAME}': options.name,\n '{PACKAGE_NAME}': options.packageName,\n '{DESCRIPTION}': options.description,\n '{VERSION}': options.version,\n '{GITHUB_REPO}': options.githubRepo,\n '{AUTHOR}': options.author,\n });\n }\n\n if (dryRun) {\n console.log('\\n[dry-run] No files were actually created.');\n } else {\n console.log(`\\nProject '${name}' created successfully!`);\n }\n}\n\nasync function copyEntries(\n sourceDir: string,\n targetDir: string,\n entries: fs.Dirent[],\n dryRun?: boolean\n): Promise<void> {\n // Files that need to be renamed when copying (npm strips dotfiles like .gitignore)\n const RENAME_FILES: Record<string, string> = {\n gitignore: '.gitignore',\n };\n\n for (const entry of entries) {\n const sourcePath = path.join(sourceDir, entry.name);\n const targetName = RENAME_FILES[entry.name] ?? entry.name;\n const targetPath = path.join(targetDir, targetName);\n\n if (entry.isDirectory()) {\n if (dryRun) {\n console.log(`[dry-run] Would create directory: ${targetPath}`);\n } else {\n await fs.ensureDir(targetPath);\n }\n // Recursively copy directory contents\n const subEntries = await fs.readdir(sourcePath, { withFileTypes: true });\n await copyEntries(sourcePath, targetPath, subEntries, dryRun);\n } else if (entry.isFile()) {\n if (dryRun) {\n console.log(`[dry-run] Would copy: ${entry.name}`);\n } else {\n await fs.copy(sourcePath, targetPath);\n console.log(`Copied: ${entry.name}`);\n }\n }\n }\n}\n\nasync function postProcess(options: ExecuteOptions<Options>): Promise<void> {\n const { name, dryRun, gitInit, install, packageManager } = options;\n const targetDir = path.resolve(process.cwd(), name);\n\n if (dryRun) {\n console.log('\\n[dry-run] Skipping post-process steps.');\n return;\n }\n\n if (gitInit) {\n try {\n console.log('Initializing git repository...');\n await execAsync('git init', { cwd: targetDir });\n console.log('Git repository initialized.');\n } catch (error) {\n console.error('Failed to initialize git repository:', (error as Error).message);\n }\n }\n\n if (install) {\n try {\n console.log('Installing dependencies (this may take a moment)...');\n\n await execAsync(`${packageManager} install`, { cwd: targetDir });\n console.log('Dependencies installed successfully.');\n } catch (error) {\n console.error('Failed to install dependencies:', (error as Error).message);\n }\n }\n\n console.log('\\nAll done! Your project is ready.');\n console.log(`\\n cd ${name}`);\n if (!install) {\n console.log(` ${packageManager} install`);\n }\n console.log(` ${packageManager} run build`);\n console.log(` ${packageManager} test`);\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@libria/scaffold-plugin-ts-lib",
3
+ "version": "0.0.1",
4
+ "description": "Typescript library template for @libria/scaffold",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.mjs",
7
+ "exports": {
8
+ ".": {
9
+ "require": {
10
+ "types": "./dist/index.d.cts",
11
+ "default": "./dist/index.cjs"
12
+ },
13
+ "import": {
14
+ "types": "./dist/index.d.mts",
15
+ "default": "./dist/index.mjs"
16
+ }
17
+ }
18
+ },
19
+ "type": "module",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/LibriaForge/scaffold-starters.git"
23
+ },
24
+ "keywords": [
25
+ "typescript"
26
+ ],
27
+ "author": "LibriaForge",
28
+ "license": "MIT",
29
+ "bugs": {
30
+ "url": "https://github.com/LibriaForge/scaffold-starters/issues"
31
+ },
32
+ "homepage": "https://github.com/LibriaForge/scaffold-starters#readme",
33
+ "dependencies": {
34
+ "@libria/plugin-loader": "^2.0.0-alpha",
35
+ "@libria/scaffold-core": "^0.3.1",
36
+ "fs-extra": "^11.3.3"
37
+ }
38
+ }
package/plugin.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "id": "libria:scaffold:ts-lib",
3
+ "name": "ts-lib",
4
+ "pluginType": "scaffold-template",
5
+ "version": "1.0.0",
6
+ "description": "TypeScript library scaffold template",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts"
9
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "es5",
5
+ "printWidth": 100,
6
+ "tabWidth": 4,
7
+ "arrowParens": "avoid"
8
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CinemaCove
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,58 @@
1
+ # {PACKAGE_NAME}
2
+
3
+ {DESCRIPTION}
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install {PACKAGE_NAME}
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { add, subtract, multiply, divide } from '{PACKAGE_NAME}';
15
+
16
+ console.log(add(2, 3)); // 5
17
+ console.log(subtract(5, 3)); // 2
18
+ console.log(multiply(4, 5)); // 20
19
+ console.log(divide(10, 2)); // 5
20
+ ```
21
+
22
+ ## API
23
+
24
+ ### `add(a: number, b: number): number`
25
+
26
+ Adds two numbers together.
27
+
28
+ ### `subtract(a: number, b: number): number`
29
+
30
+ Subtracts the second number from the first.
31
+
32
+ ### `multiply(a: number, b: number): number`
33
+
34
+ Multiplies two numbers together.
35
+
36
+ ### `divide(a: number, b: number): number`
37
+
38
+ Divides the first number by the second. Throws an error if the divisor is zero.
39
+
40
+ ## Development
41
+
42
+ ```bash
43
+ # Install dependencies
44
+ npm install
45
+
46
+ # Run tests
47
+ npm test
48
+
49
+ # Build
50
+ npm run build
51
+
52
+ # Lint
53
+ npm run lint
54
+ ```
55
+
56
+ ## License
57
+
58
+ MIT
@@ -0,0 +1,106 @@
1
+ import eslint from '@eslint/js';
2
+ import tseslint from 'typescript-eslint';
3
+ import prettierConfig from 'eslint-config-prettier';
4
+ import prettierPlugin from 'eslint-plugin-prettier';
5
+ import unusedImports from 'eslint-plugin-unused-imports';
6
+ import importPlugin from 'eslint-plugin-import';
7
+
8
+ export default tseslint.config(
9
+ eslint.configs.recommended,
10
+ ...tseslint.configs.recommended,
11
+ prettierConfig,
12
+ {
13
+ files: ['src/**/*.ts', 'src/**/*.tsx'], // Only lint src folder
14
+ languageOptions: {
15
+ parser: tseslint.parser,
16
+ parserOptions: {
17
+ project: './tsconfig.json',
18
+ tsconfigRootDir: import.meta.dirname,
19
+ },
20
+ },
21
+ plugins: {
22
+ import: importPlugin,
23
+ prettier: prettierPlugin,
24
+ 'unused-imports': unusedImports,
25
+ },
26
+ rules: {
27
+ // Prettier integration
28
+ 'prettier/prettier': 'error',
29
+
30
+ // Unused variables and imports
31
+ 'unused-imports/no-unused-imports': 'error',
32
+ 'unused-imports/no-unused-vars': [
33
+ 'warn',
34
+ {
35
+ vars: 'all',
36
+ varsIgnorePattern: '^_',
37
+ args: 'after-used',
38
+ argsIgnorePattern: '^_',
39
+ },
40
+ ],
41
+ '@typescript-eslint/no-unused-vars': [
42
+ 'error',
43
+ {
44
+ argsIgnorePattern: '^_',
45
+ varsIgnorePattern: '^_',
46
+ caughtErrorsIgnorePattern: '^_',
47
+ },
48
+ ],
49
+
50
+ // Explicit member accessibility (public, private, protected)
51
+ '@typescript-eslint/explicit-member-accessibility': [
52
+ 'error',
53
+ {
54
+ accessibility: 'explicit',
55
+ overrides: {
56
+ constructors: 'off', // constructors default to public, no need to specify
57
+ },
58
+ },
59
+ ],
60
+
61
+ // Explicit function return types
62
+ '@typescript-eslint/explicit-function-return-type': [
63
+ 'warn',
64
+ {
65
+ allowExpressions: true,
66
+ allowTypedFunctionExpressions: true,
67
+ },
68
+ ],
69
+
70
+ // Sort imports alphabetically
71
+ 'import/order': [
72
+ 'error',
73
+ {
74
+ groups: [
75
+ 'builtin', // Node.js built-in modules
76
+ 'external', // npm packages
77
+ 'internal', // Your own modules
78
+ 'parent', // Parent directories
79
+ 'sibling', // Same directory
80
+ 'index', // Index files
81
+ ],
82
+ 'newlines-between': 'always',
83
+ alphabetize: {
84
+ order: 'asc',
85
+ caseInsensitive: true,
86
+ },
87
+ },
88
+ ],
89
+
90
+ // No unused imports
91
+ 'no-unused-vars': 'off', // Turn off base rule (using TS version)
92
+ // 'import/no-unused-modules': ['warn', { unusedExports: true }],
93
+
94
+ // Additional helpful rules
95
+ 'no-console': ['warn', { allow: ['log', 'warn', 'error'] }],
96
+ '@typescript-eslint/no-explicit-any': 'warn',
97
+ '@typescript-eslint/no-non-null-assertion': 'warn',
98
+ 'prefer-const': 'error',
99
+ 'no-var': 'error',
100
+ },
101
+ },
102
+ {
103
+ // Ignore patterns (replaces .eslintignore)
104
+ ignores: ['node_modules/**', 'dist/**', 'build/**', '*.config.js', 'coverage/**', 'scripts/**', '.tmp/**', '.tmp-clean-publish/**'],
105
+ }
106
+ );
@@ -0,0 +1,146 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ lerna-debug.log*
8
+
9
+ # Diagnostic reports (https://nodejs.org/api/report.html)
10
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11
+
12
+ # Runtime data
13
+ pids
14
+ *.pid
15
+ *.seed
16
+ *.pid.lock
17
+
18
+ # Directory for instrumented libs generated by jscoverage/JSCover
19
+ lib-cov
20
+
21
+ # Coverage directory used by tools like istanbul
22
+ coverage
23
+ *.lcov
24
+
25
+ # nyc test coverage
26
+ .nyc_output
27
+
28
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29
+ .grunt
30
+
31
+ # Bower dependency directory (https://bower.io/)
32
+ bower_components
33
+
34
+ # node-waf configuration
35
+ .lock-wscript
36
+
37
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
38
+ build/Release
39
+
40
+ # Dependency directories
41
+ node_modules/
42
+ jspm_packages/
43
+
44
+ # Snowpack dependency directory (https://snowpack.dev/)
45
+ web_modules/
46
+
47
+ # TypeScript cache
48
+ *.tsbuildinfo
49
+
50
+ # Optional npm cache directory
51
+ .npm
52
+
53
+ # Optional eslint cache
54
+ .eslintcache
55
+
56
+ # Optional stylelint cache
57
+ .stylelintcache
58
+
59
+ # Optional REPL history
60
+ .node_repl_history
61
+
62
+ # Output of 'npm pack'
63
+ *.tgz
64
+
65
+ # Yarn Integrity file
66
+ .yarn-integrity
67
+
68
+ # dotenv environment variable files
69
+ .env
70
+ .env.*
71
+ !.env.example
72
+
73
+ # parcel-bundler cache (https://parceljs.org/)
74
+ .cache
75
+ .parcel-cache
76
+
77
+ # Next.js build output
78
+ .next
79
+ out
80
+
81
+ # Nuxt.js build / generate output
82
+ .nuxt
83
+ dist
84
+
85
+ # Gatsby files
86
+ .cache/
87
+ # Comment in the public line in if your project uses Gatsby and not Next.js
88
+ # https://nextjs.org/blog/next-9-1#public-directory-support
89
+ # public
90
+
91
+ # vuepress build output
92
+ .vuepress/dist
93
+
94
+ # vuepress v2.x temp and cache directory
95
+ .temp
96
+ .cache
97
+
98
+ # Sveltekit cache directory
99
+ .svelte-kit/
100
+
101
+ # vitepress build output
102
+ **/.vitepress/dist
103
+
104
+ # vitepress cache directory
105
+ **/.vitepress/cache
106
+
107
+ # Docusaurus cache and generated files
108
+ .docusaurus
109
+
110
+ # Serverless directories
111
+ .serverless/
112
+
113
+ # FuseBox cache
114
+ .fusebox/
115
+
116
+ # DynamoDB Local files
117
+ .dynamodb/
118
+
119
+ # Firebase cache directory
120
+ .firebase/
121
+
122
+ # TernJS port file
123
+ .tern-port
124
+
125
+ # Stores VSCode versions used for testing VSCode extensions
126
+ .vscode-test
127
+
128
+ # yarn v3
129
+ .pnp.*
130
+ .yarn/*
131
+ !.yarn/patches
132
+ !.yarn/plugins
133
+ !.yarn/releases
134
+ !.yarn/sdks
135
+ !.yarn/versions
136
+
137
+ # Vite logs files
138
+ vite.config.js.timestamp-*
139
+ vite.config.ts.timestamp-*
140
+
141
+ .idea
142
+ .DS_Store
143
+ /.claude/
144
+ /.tmp-clean-publish/
145
+ /.clean-publish.last-hash
146
+ /.tmp/
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "{PACKAGE_NAME}",
3
+ "version": "{VERSION}",
4
+ "description": "{DESCRIPTION}",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.mjs",
7
+ "exports": {
8
+ ".": {
9
+ "require": {
10
+ "types": "./dist/index.d.cts",
11
+ "default": "./dist/index.cjs"
12
+ },
13
+ "import": {
14
+ "types": "./dist/index.d.mts",
15
+ "default": "./dist/index.mjs"
16
+ }
17
+ }
18
+ },
19
+ "type": "module",
20
+ "scripts": {
21
+ "build": "cross-env NODE_ENV=production tsdown",
22
+ "build:dev": "tsdown",
23
+ "test": "vitest",
24
+ "lint": "eslint . --ext .ts",
25
+ "lint:fix": "eslint . --ext .ts --fix",
26
+ "format": "prettier --write .",
27
+ "test:coverage": "vitest --coverage",
28
+ "clean": "npm run lint:fix && npm run format",
29
+ "build-and-publish": "npm run build && npx @libria/clean-publish build && npx @libria/clean-publish publish"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/{GITHUB_REPO}.git"
34
+ },
35
+ "keywords": [
36
+ "typescript"
37
+ ],
38
+ "author": "{AUTHOR}",
39
+ "license": "MIT",
40
+ "bugs": {
41
+ "url": "https://github.com/{GITHUB_REPO}/issues"
42
+ },
43
+ "homepage": "https://github.com/{GITHUB_REPO}#readme",
44
+ "devDependencies": {
45
+ "@eslint/eslintrc": "^3.3.3",
46
+ "@eslint/js": "^9.39.2",
47
+ "@libria/clean-publish": "^1.0.0",
48
+ "@types/node": "^22.0.0",
49
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
50
+ "@typescript-eslint/parser": "^8.0.0",
51
+ "@vitest/coverage-v8": "^2.0.0",
52
+ "cross-env": "^10.1.0",
53
+ "eslint": "^9.0.0",
54
+ "eslint-config-prettier": "^10.0.0",
55
+ "eslint-plugin-import": "^2.30.0",
56
+ "eslint-plugin-prettier": "^5.0.0",
57
+ "eslint-plugin-unused-imports": "^4.0.0",
58
+ "prettier": "^3.0.0",
59
+ "tsdown": "^0.20.0",
60
+ "typescript": "^5.0.0",
61
+ "typescript-eslint": "^8.0.0",
62
+ "vitest": "^2.0.0"
63
+ }
64
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Adds two numbers together.
3
+ */
4
+ export function add(a: number, b: number): number {
5
+ return a + b;
6
+ }
7
+
8
+ /**
9
+ * Subtracts the second number from the first.
10
+ */
11
+ export function subtract(a: number, b: number): number {
12
+ return a - b;
13
+ }
14
+
15
+ /**
16
+ * Multiplies two numbers together.
17
+ */
18
+ export function multiply(a: number, b: number): number {
19
+ return a * b;
20
+ }
21
+
22
+ /**
23
+ * Divides the first number by the second.
24
+ * @throws Error if divisor is zero.
25
+ */
26
+ export function divide(a: number, b: number): number {
27
+ if (b === 0) {
28
+ throw new Error('Cannot divide by zero');
29
+ }
30
+ return a / b;
31
+ }
@@ -0,0 +1,29 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+
4
+ const PROJECT_ROOT = path.resolve(import.meta.dirname, '../..');
5
+ const TMP_DIR = path.join(PROJECT_ROOT, '.tmp');
6
+
7
+ interface TempProjectResult {
8
+ tmp: string;
9
+ cleanup: () => Promise<void>;
10
+ }
11
+
12
+ export async function useTempProject(name?: string): Promise<TempProjectResult> {
13
+ await fs.ensureDir(TMP_DIR);
14
+ const timestamp = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14);
15
+ const tmp = await fs.mkdtemp(path.join(TMP_DIR, `{PROJECT_NAME}-${timestamp}-${name ? name + '-' : ''}`));
16
+
17
+ const originalCwd = process.cwd();
18
+ process.chdir(tmp);
19
+
20
+ return {
21
+ tmp,
22
+ cleanup: async () => {
23
+ process.chdir(originalCwd);
24
+ if (await fs.pathExists(tmp)) {
25
+ await fs.remove(tmp);
26
+ }
27
+ },
28
+ };
29
+ }
@@ -0,0 +1,44 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { add, subtract, multiply, divide } from '../src';
3
+
4
+ describe('Math functions', () => {
5
+ describe('add', () => {
6
+ it('should add two positive numbers', () => {
7
+ expect(add(2, 3)).toBe(5);
8
+ });
9
+
10
+ it('should handle negative numbers', () => {
11
+ expect(add(-1, 1)).toBe(0);
12
+ });
13
+ });
14
+
15
+ describe('subtract', () => {
16
+ it('should subtract two numbers', () => {
17
+ expect(subtract(5, 3)).toBe(2);
18
+ });
19
+
20
+ it('should return negative when second is larger', () => {
21
+ expect(subtract(3, 5)).toBe(-2);
22
+ });
23
+ });
24
+
25
+ describe('multiply', () => {
26
+ it('should multiply two numbers', () => {
27
+ expect(multiply(4, 5)).toBe(20);
28
+ });
29
+
30
+ it('should return zero when multiplied by zero', () => {
31
+ expect(multiply(5, 0)).toBe(0);
32
+ });
33
+ });
34
+
35
+ describe('divide', () => {
36
+ it('should divide two numbers', () => {
37
+ expect(divide(10, 2)).toBe(5);
38
+ });
39
+
40
+ it('should throw when dividing by zero', () => {
41
+ expect(() => divide(5, 0)).toThrow('Cannot divide by zero');
42
+ });
43
+ });
44
+ });
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2021",
4
+ "lib": ["ES2021"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "node",
7
+ "declaration": true,
8
+ // Generate .d.ts files
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "outDir": "./dist",
13
+ "rootDir": "./src"
14
+ },
15
+ "include": [
16
+ "src/**/*"
17
+ ],
18
+ "exclude": [
19
+ "node_modules",
20
+ "dist",
21
+ "tests"
22
+ ]
23
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["src/**/*", "tests/**/*"],
4
+ "compilerOptions": {
5
+ "rootDir": ".",
6
+ "types": ["vitest/globals"]
7
+ }
8
+ }
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from 'tsdown';
2
+
3
+ const isDebug = process.env.NODE_ENV !== 'production';
4
+
5
+ export default defineConfig({
6
+ entry: { index: 'src/index.ts' },
7
+ format: ['cjs', 'esm'],
8
+ dts: true,
9
+ sourcemap: true,
10
+ clean: true,
11
+ minify: !isDebug,
12
+ });
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: 'node',
7
+ coverage: {
8
+ provider: 'v8',
9
+ reporter: ['text', 'html'],
10
+ },
11
+ },
12
+ });