@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.
- package/.clean-publish.hash +1 -0
- package/LICENSE +21 -0
- package/README.md +35 -0
- package/dist/index.cjs +5 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +20 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +20 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +5 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +38 -0
- package/plugin.json +9 -0
- package/template-files/.prettierrc +8 -0
- package/template-files/LICENSE +21 -0
- package/template-files/README.md +58 -0
- package/template-files/eslint.config.mjs +106 -0
- package/template-files/gitignore +146 -0
- package/template-files/package.json +64 -0
- package/template-files/src/index.ts +31 -0
- package/template-files/tests/helpers/use-temp-project.ts +29 -0
- package/template-files/tests/my.test.ts +44 -0
- package/template-files/tsconfig.json +23 -0
- package/template-files/tsconfig.test.json +8 -0
- package/template-files/tsdown.config.ts +12 -0
- package/template-files/vitest.config.ts +12 -0
|
@@ -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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"}
|
package/dist/index.d.cts
ADDED
|
@@ -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"}
|
package/dist/index.d.mts
ADDED
|
@@ -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":"0SAgBA,MAAM,EAAY,EAAK,QAAQ,EAAc,OAAO,KAAK,IAAI,CAAC,CACxD,EAAY,EAAK,QAAQ,EAAW,KAAM,iBAAiB,CAE3D,EAAY,EAAU,EAAK,CAEjC,IAAA,EAAe,EAA8C,CACzD,GAAI,yBACJ,KAAM,SACN,WAAY,EAEZ,MAAM,OAAO,EAAkB,CAC3B,MAAO,CACH,IAAK,CACD,SAAU,SACV,WAAY,KAAO,KACR,CACH,YAAa,CACT,MAAO,iBACP,YAAa,gBACb,aAAc,EAAY,KAC7B,CACD,YAAa,CACT,MAAO,gBACP,YAAa,eAChB,CACD,QAAS,CACL,MAAO,YACP,YAAa,WACb,aAAc,QACd,SAAU,GACb,CACD,OAAQ,CACJ,MAAO,WACP,YAAa,UAChB,CACD,WAAY,CACR,MAAO,gBACP,YAAa,kCAChB,CACD,QAAS,CACL,MAAO,aACP,YAAa,6BACb,aAAc,GACd,SAAU,GACb,CACD,eAAgB,CACZ,MAAO,oBACP,YAAa,mCACb,QAAS,CAAC,MAAO,OAAQ,OAAO,CAChC,aAAc,MACjB,CACD,QAAS,CACL,MAAO,YACP,YAAa,wBACb,aAAc,GACd,SAAU,GACb,CACJ,EAEL,QAAS,KAAM,IAAW,CACtB,MAAM,EAAgB,EAAQ,CAC9B,MAAM,EAAY,EAAQ,EAEjC,CACJ,EAER,CAAC,CAEF,eAAe,EAAgB,EAAiD,CAC5E,GAAM,CAAE,OAAM,SAAQ,SAAU,EAC1B,EAAY,EAAK,QAAQ,QAAQ,KAAK,CAAE,EAAK,CAG/C,MAAM,EAAG,WAAW,EAAU,GACzB,IACD,QAAQ,MAAM,cAAc,EAAK,6CAA6C,CAC9E,QAAQ,KAAK,EAAE,EAEf,EACA,QAAQ,IAAI,8CAA8C,IAAY,EAEtE,MAAM,EAAG,OAAO,EAAU,CAC1B,QAAQ,IAAI,+BAA+B,IAAY,GAK3D,EACA,QAAQ,IAAI,qCAAqC,IAAY,EAE7D,MAAM,EAAG,UAAU,EAAU,CAC7B,QAAQ,IAAI,sBAAsB,IAAY,EAKlD,MAAM,EAAY,EAAW,EADb,MAAM,EAAG,QAAQ,EAAW,CAAE,cAAe,GAAM,CAAC,CACnB,EAAO,CAEnD,GACD,MAAM,EAAoB,EAAW,CACjC,iBAAkB,EAAQ,KAC1B,iBAAkB,EAAQ,YAC1B,gBAAiB,EAAQ,YACzB,YAAa,EAAQ,QACrB,gBAAiB,EAAQ,WACzB,WAAY,EAAQ,OACvB,CAAC,CAGF,EACA,QAAQ,IAAI;2CAA8C,CAE1D,QAAQ,IAAI,cAAc,EAAK,yBAAyB,CAIhE,eAAe,EACX,EACA,EACA,EACA,EACa,CAEb,IAAM,EAAuC,CACzC,UAAW,aACd,CAED,IAAK,IAAM,KAAS,EAAS,CACzB,IAAM,EAAa,EAAK,KAAK,EAAW,EAAM,KAAK,CAC7C,EAAa,EAAa,EAAM,OAAS,EAAM,KAC/C,EAAa,EAAK,KAAK,EAAW,EAAW,CAE/C,EAAM,aAAa,EACf,EACA,QAAQ,IAAI,qCAAqC,IAAa,CAE9D,MAAM,EAAG,UAAU,EAAW,CAIlC,MAAM,EAAY,EAAY,EADX,MAAM,EAAG,QAAQ,EAAY,CAAE,cAAe,GAAM,CAAC,CAClB,EAAO,EACtD,EAAM,QAAQ,GACjB,EACA,QAAQ,IAAI,yBAAyB,EAAM,OAAO,EAElD,MAAM,EAAG,KAAK,EAAY,EAAW,CACrC,QAAQ,IAAI,WAAW,EAAM,OAAO,IAMpD,eAAe,EAAY,EAAiD,CACxE,GAAM,CAAE,OAAM,SAAQ,UAAS,UAAS,kBAAmB,EACrD,EAAY,EAAK,QAAQ,QAAQ,KAAK,CAAE,EAAK,CAEnD,GAAI,EAAQ,CACR,QAAQ,IAAI;wCAA2C,CACvD,OAGJ,GAAI,EACA,GAAI,CACA,QAAQ,IAAI,iCAAiC,CAC7C,MAAM,EAAU,WAAY,CAAE,IAAK,EAAW,CAAC,CAC/C,QAAQ,IAAI,8BAA8B,OACrC,EAAO,CACZ,QAAQ,MAAM,uCAAyC,EAAgB,QAAQ,CAIvF,GAAI,EACA,GAAI,CACA,QAAQ,IAAI,sDAAsD,CAElE,MAAM,EAAU,GAAG,EAAe,UAAW,CAAE,IAAK,EAAW,CAAC,CAChE,QAAQ,IAAI,uCAAuC,OAC9C,EAAO,CACZ,QAAQ,MAAM,kCAAoC,EAAgB,QAAQ,CAIlF,QAAQ,IAAI;kCAAqC,CACjD,QAAQ,IAAI,UAAU,IAAO,CACxB,GACD,QAAQ,IAAI,KAAK,EAAe,UAAU,CAE9C,QAAQ,IAAI,KAAK,EAAe,YAAY,CAC5C,QAAQ,IAAI,KAAK,EAAe,OAAO"}
|
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,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,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
|
+
});
|