apparel 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/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # Apparel
2
+
3
+ A powerful NPX script that fills templates with variables from configuration files. Supports multiple config formats and template engines.
4
+
5
+ ## Features
6
+
7
+ - **Multiple Config Formats**: JSON, JSON5, YAML, TOML, XML
8
+ - **Multiple Template Engines**: Handlebars, EJS, Liquid, Jinja/Nunjucks
9
+ - **Local and Remote Files**: Support for local files, URLs, and GitHub repos
10
+ - **GitHub Integration**: Use `@repo/file` format to fetch from n-p-x organization
11
+ - **Flexible Output**: Write to file or stdout
12
+
13
+ ## Installation
14
+
15
+ Install globally to use as an NPX command:
16
+
17
+ ```bash
18
+ npm install -g apparel
19
+ ```
20
+
21
+ Or use directly with npx:
22
+
23
+ ```bash
24
+ npx apparel <src> <tpl> [dst]
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```bash
30
+ apparel <src> <tpl> [dst]
31
+ ```
32
+
33
+ ### Arguments
34
+
35
+ - `src` (required): Config file path
36
+ - `tpl` (required): Template file path
37
+ - `dst` (optional): Output file path (defaults to stdout)
38
+
39
+ ### File Sources
40
+
41
+ Files can be loaded from:
42
+
43
+ 1. **Local files**: `./config.json`, `../templates/email.hbs`
44
+ 2. **URLs**: `https://example.com/config.json`
45
+ 3. **GitHub repos**: `@myrepo/config.json` (fetches from `n-p-x/myrepo`)
46
+
47
+ ## Supported Config Formats
48
+
49
+ | Extension | Format | Parser |
50
+ |-----------|--------|---------|
51
+ | `.json` | JSON | Native JSON.parse |
52
+ | `.json5` | JSON5 | json5 |
53
+ | `.yml`, `.yaml` | YAML | js-yaml |
54
+ | `.toml` | TOML | toml |
55
+ | `.xml` | XML | fast-xml-parser |
56
+
57
+ ## Supported Template Engines
58
+
59
+ | Extension | Engine | Library |
60
+ |-----------|--------|---------|
61
+ | `.hbs`, `.handlebars` | Handlebars | handlebars |
62
+ | `.ejs` | EJS | ejs |
63
+ | `.liquid` | Liquid | liquidjs |
64
+ | `.jinja`, `.j2` | Jinja | nunjucks |
65
+
66
+ ## Examples
67
+
68
+ ### Basic Usage
69
+
70
+ ```bash
71
+ # JSON config with Handlebars template
72
+ apparel config.json template.hbs output.txt
73
+
74
+ # YAML config with EJS template to stdout
75
+ apparel config.yml template.ejs
76
+
77
+ # Remote config with local template
78
+ apparel https://example.com/config.json template.hbs
79
+ ```
80
+
81
+ ### GitHub Integration
82
+
83
+ ```bash
84
+ # Fetch config from n-p-x/configs repo
85
+ apparel @configs/prod.json template.hbs
86
+
87
+ # Fetch both config and template from GitHub
88
+ apparel @configs/prod.json @templates/email.hbs output.html
89
+ ```
90
+
91
+ ### Example Files
92
+
93
+ #### Config (config.json)
94
+ ```json
95
+ {
96
+ "name": "John Doe",
97
+ "email": "john@example.com",
98
+ "role": "Developer",
99
+ "skills": ["JavaScript", "TypeScript", "Node.js"]
100
+ }
101
+ ```
102
+
103
+ #### Handlebars Template (template.hbs)
104
+ ```handlebars
105
+ Hello {{name}},
106
+
107
+ Your role: {{role}}
108
+ Skills: {{#each skills}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}
109
+ ```
110
+
111
+ #### Output
112
+ ```
113
+ Hello John Doe,
114
+
115
+ Your role: Developer
116
+ Skills: JavaScript, TypeScript, Node.js
117
+ ```
118
+
119
+ ## Template Syntax Examples
120
+
121
+ ### Handlebars
122
+ ```handlebars
123
+ {{name}} - {{email}}
124
+ {{#each skills}}
125
+ - {{this}}
126
+ {{/each}}
127
+ ```
128
+
129
+ ### EJS
130
+ ```ejs
131
+ <%= name %> - <%= email %>
132
+ <% skills.forEach(skill => { %>
133
+ - <%= skill %>
134
+ <% }); %>
135
+ ```
136
+
137
+ ### Liquid
138
+ ```liquid
139
+ {{ name }} - {{ email }}
140
+ {% for skill in skills %}
141
+ - {{ skill }}
142
+ {% endfor %}
143
+ ```
144
+
145
+ ### Jinja/Nunjucks
146
+ ```jinja
147
+ {{ name }} - {{ email }}
148
+ {% for skill in skills %}
149
+ - {{ skill }}
150
+ {% endfor %}
151
+ ```
152
+
153
+ ## Error Handling
154
+
155
+ The script provides detailed error messages for:
156
+ - File not found or network errors
157
+ - Invalid config file format
158
+ - Template rendering errors
159
+ - Missing required arguments
160
+
161
+ ## Development
162
+
163
+ ```bash
164
+ # Install dependencies
165
+ npm install
166
+
167
+ # Build the project
168
+ npm run build
169
+
170
+ # Test locally
171
+ node dist/index.js examples/config.json examples/template.hbs
172
+ ```
173
+
174
+ ## License
175
+
176
+ ISC
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{Command as h}from"commander";import{promises as f}from"fs";import m from"js-yaml";import*as d from"toml";import g from"json5";import{XMLParser as y}from"fast-xml-parser";import p from"handlebars";import{Liquid as $}from"liquidjs";import x from"ejs";import w from"nunjucks";import s from"path";import{fileURLToPath as b}from"url";var j=b(import.meta.url),U=s.dirname(j);w.configure({autoescape:!1});async function l(r){let e=await fetch(r);if(!e.ok)throw new Error(`Failed to fetch ${r}: ${e.status} ${e.statusText}`);return e.text()}async function u(r){if(r.startsWith("@")){let[,e,...t]=r.split("/"),o=t.join("/"),a=`https://raw.githubusercontent.com/n-p-x/${e}/main/${o}`;return l(a)}return r.startsWith("http://")||r.startsWith("https://")?l(r):f.readFile(r,"utf8")}function L(r,e){let t=s.extname(e).toLowerCase();try{switch(t){case".json":return JSON.parse(r);case".json5":return g.parse(r);case".yml":case".yaml":return m.load(r);case".toml":return d.parse(r);case".xml":return new y({ignoreAttributes:!1,attributeNamePrefix:"@_",parseAttributeValue:!0}).parse(r);default:try{return JSON.parse(r)}catch{return m.load(r)}}}catch(o){throw new Error(`Failed to parse config file ${e}: ${o.message}`)}}async function F(r,e,t){let o=s.extname(e).toLowerCase();try{switch(o){case".hbs":case".handlebars":return p.compile(r)(t);case".liquid":return new $().parseAndRender(r,t);case".ejs":return x.render(r,t);case".jinja":case".j2":return w.renderString(r,t);default:return p.compile(r)(t)}}catch(a){throw new Error(`Failed to render template ${e}: ${a.message}`)}}async function T(){let r=new h;r.name("apparel").description("Fill templates with variables from config files").version("0.0.1").argument("<src>","Config file path (local file, URL, or @repo/file format)").argument("<tpl>","Template file path (local file, URL, or @repo/file format)").argument("[dst]","Output file path (optional, defaults to stdout)").action(async(e,t,o)=>{try{console.error(`Loading config from: ${e}`);let a=await u(e),n=L(a,e);console.error(`Loading template from: ${t}`);let i=await u(t);console.error("Rendering template...");let c=await F(i,t,n);o?(await f.writeFile(o,c,"utf8"),console.error(`Output written to: ${o}`)):process.stdout.write(c)}catch(a){console.error(`Error: ${a.message}`),process.exit(1)}}),await r.parseAsync()}(async()=>await T())();
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "John Doe",
3
+ "email": "john.doe@example.com",
4
+ "role": "Software Engineer",
5
+ "company": "Tech Corp",
6
+ "skills": ["JavaScript", "TypeScript", "Node.js", "React"],
7
+ "experience": 5
8
+ }
@@ -0,0 +1,6 @@
1
+ name = "John Doe"
2
+ email = "john.doe@example.com"
3
+ role = "Software Engineer"
4
+ company = "Tech Corp"
5
+ skills = ["JavaScript", "TypeScript", "Node.js", "React"]
6
+ experience = 5
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <name>John Doe</name>
4
+ <email>john.doe@example.com</email>
5
+ <role>Software Engineer</role>
6
+ <company>Tech Corp</company>
7
+ <skills>
8
+ <skill>JavaScript</skill>
9
+ <skill>TypeScript</skill>
10
+ <skill>Node.js</skill>
11
+ <skill>React</skill>
12
+ </skills>
13
+ <experience>5</experience>
14
+ </config>
@@ -0,0 +1,10 @@
1
+ name: Jane Smith
2
+ email: jane.smith@example.com
3
+ role: Product Manager
4
+ company: Innovation Labs
5
+ skills:
6
+ - Product Strategy
7
+ - User Research
8
+ - Agile
9
+ - Data Analysis
10
+ experience: 7
@@ -0,0 +1,22 @@
1
+ name: John Doe
2
+ email: john.doe@example.com
3
+ role: Software Engineer
4
+ company: Tech Corp
5
+ experience: 5 years
6
+
7
+ Skills:
8
+ - JavaScript
9
+ - TypeScript
10
+ - Node.js
11
+ - React
12
+
13
+ ---
14
+
15
+ Hello John Doe,
16
+
17
+ Thank you for your interest in joining Tech Corp as a Software Engineer.
18
+ With 5 years of experience and your skills in JavaScript, TypeScript, Node.js, React,
19
+ you would be a great fit for our team.
20
+
21
+ Best regards,
22
+ HR Team
@@ -0,0 +1,15 @@
1
+ Hello <%= name %>,
2
+
3
+ Welcome to <%= company %>! We're excited to have you join our team as a <%= role %>.
4
+
5
+ Your profile:
6
+ - Email: <%= email %>
7
+ - Experience: <%= experience %> years
8
+ - Skills: <% skills.forEach((skill, index) => { %>
9
+ • <%= skill %><% if (index < skills.length - 1) { %>,<% } %>
10
+ <% }); %>
11
+
12
+ We look forward to working with you!
13
+
14
+ Best regards,
15
+ The <%= company %> Team
@@ -0,0 +1,21 @@
1
+ name: {{name}}
2
+ email: {{email}}
3
+ role: {{role}}
4
+ company: {{company}}
5
+ experience: {{experience}} years
6
+
7
+ Skills:
8
+ {{#each skills}}
9
+ - {{this}}
10
+ {{/each}}
11
+
12
+ ---
13
+
14
+ Hello {{name}},
15
+
16
+ Thank you for your interest in joining {{company}} as a {{role}}.
17
+ With {{experience}} years of experience and your skills in {{#each skills}}{{this}}{{#unless @last}}, {{/unless}}{{/each}},
18
+ you would be a great fit for our team.
19
+
20
+ Best regards,
21
+ HR Team
@@ -0,0 +1,21 @@
1
+ name: {{ name }}
2
+ email: {{ email }}
3
+ role: {{ role }}
4
+ company: {{ company }}
5
+ experience: {{ experience }} years
6
+
7
+ Skills:
8
+ {% for skill in skills %}
9
+ - {{ skill }}
10
+ {% endfor %}
11
+
12
+ ---
13
+
14
+ Hello {{ name }},
15
+
16
+ Thank you for your interest in joining {{ company }} as a {{ role }}.
17
+ With {{ experience }} years of experience and your skills in {% for skill in skills %}{{ skill }}{% if not loop.last %}, {% endif %}{% endfor %},
18
+ you would be a great fit for our team.
19
+
20
+ Best regards,
21
+ HR Team
@@ -0,0 +1,21 @@
1
+ name: {{ name }}
2
+ email: {{ email }}
3
+ role: {{ role }}
4
+ company: {{ company }}
5
+ experience: {{ experience }} years
6
+
7
+ Skills:
8
+ {% for skill in skills %}
9
+ - {{ skill }}
10
+ {% endfor %}
11
+
12
+ ---
13
+
14
+ Hello {{ name }},
15
+
16
+ Thank you for your interest in joining {{ company }} as a {{ role }}.
17
+ With {{ experience }} years of experience and your skills in {% for skill in skills %}{{ skill }}{% unless forloop.last %}, {% endunless %}{% endfor %},
18
+ you would be a great fit for our team.
19
+
20
+ Best regards,
21
+ HR Team
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "apparel",
3
+ "version": "0.0.1",
4
+ "description": "Dress templates with variables.",
5
+ "type": "module",
6
+ "bin": "./dist/index.js",
7
+ "main": "./dist/index.js",
8
+ "scripts": {
9
+ "build": "tsup"
10
+ },
11
+ "keywords": [],
12
+ "author": "Asfandyar Sheikh",
13
+ "license": "ISC",
14
+ "dependencies": {
15
+ "commander": "^14.0.3",
16
+ "ejs": "^4.0.1",
17
+ "fast-xml-parser": "^5.3.7",
18
+ "handlebars": "^4.7.8",
19
+ "js-yaml": "^4.1.1",
20
+ "json5": "^2.2.3",
21
+ "liquidjs": "^10.24.0",
22
+ "nunjucks": "^3.2.4",
23
+ "toml": "^3.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "tsup": "^8.5.1",
27
+ "typescript": "^5.9.3"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/asfandyarsheikh/apparel.git"
32
+ }
33
+ }
package/tsup.config.js ADDED
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: { index: 'src/index.js' },
5
+ format: ['esm'],
6
+ clean: false,
7
+ minify: true,
8
+ });