lapeh 3.0.2 → 3.0.4

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.
Files changed (2) hide show
  1. package/package.json +127 -126
  2. package/scripts/release.js +295 -0
package/package.json CHANGED
@@ -1,126 +1,127 @@
1
- {
2
- "name": "lapeh",
3
- "version": "3.0.2",
4
- "description": "Framework API Express yang siap pakai (Standardized)",
5
- "engines": {
6
- "node": ">=18.0.0",
7
- "npm": ">=9.0.0"
8
- },
9
- "main": "dist/lib/bootstrap.js",
10
- "bin": {
11
- "lapeh": "bin/index.js"
12
- },
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://github.com/robyajo/lapeh.git"
16
- },
17
- "homepage": "https://lapeh-doc.vercel.app",
18
- "bugs": {
19
- "url": "https://github.com/robyajo/lapeh/issues"
20
- },
21
- "types": "dist/src/index.d.ts",
22
- "files": [
23
- "bin",
24
- "dist",
25
- "lib",
26
- "scripts",
27
- "src",
28
- "storage",
29
- "doc",
30
- "README.md",
31
- "LICENSE",
32
- "tsconfig.json",
33
- "nodemon.json",
34
- "docker-compose.yml",
35
- ".env.example",
36
- "eslint.config.mjs",
37
- "gitignore.template",
38
- "ecosystem.config.js",
39
- "tsconfig.build.json"
40
- ],
41
- "scripts": {
42
- "dev": "node bin/index.js dev",
43
- "first": "node scripts/init-project.js",
44
- "build": "node bin/index.js build",
45
- "start": "node bin/index.js start",
46
- "start:prod": "node bin/index.js start",
47
- "typecheck": "tsc --noEmit",
48
- "lint": "eslint .",
49
- "lint:fix": "eslint . --fix",
50
- "test": "jest",
51
- "generate:jwt": "node scripts/generate-jwt-secret.js",
52
- "make:module": "node scripts/make-module.js",
53
- "make:modul": "node scripts/make-module.js",
54
- "config:clear": "node scripts/config-clear.js",
55
- "prepublishOnly": "npm run build"
56
- },
57
- "keywords": [
58
- "nodejs-framework",
59
- "typescript-framework",
60
- "express-framework",
61
- "backend-framework",
62
- "rest-api",
63
- "production-ready",
64
- "api-generator",
65
- "boilerplate",
66
- "starter-kit",
67
- "mvc",
68
- "cli",
69
- "lapeh",
70
- "roby-ajo",
71
- "ajo-roby",
72
- "robyajo",
73
- "lapeh"
74
- ],
75
- "author": "robyajo <robyfull.dev@gmail.com>",
76
- "license": "MIT",
77
- "type": "commonjs",
78
- "peerDependencies": {},
79
- "dependencies": {
80
- "@types/bcryptjs": "2.4.6",
81
- "@types/compression": "^1.8.1",
82
- "@types/cors": "2.8.19",
83
- "@types/express": "5.0.6",
84
- "@types/jsonwebtoken": "9.0.10",
85
- "@types/multer": "^2.0.0",
86
- "@types/node": "25.0.3",
87
- "@types/pg": "8.16.0",
88
- "@types/uuid": "10.0.0",
89
- "bcryptjs": "^2.4.3",
90
- "compression": "^1.8.1",
91
- "cors": "2.8.5",
92
- "dotenv": "17.2.3",
93
- "express": "5.2.1",
94
- "express-rate-limit": "8.2.1",
95
- "fast-json-stringify": "^6.1.1",
96
- "helmet": "8.1.0",
97
- "ioredis": "5.8.2",
98
- "ioredis-mock": "^8.13.1",
99
- "jsonwebtoken": "9.0.3",
100
- "module-alias": "^2.2.3",
101
- "multer": "2.0.2",
102
- "pg": "8.16.3",
103
- "slugify": "1.6.6",
104
- "socket.io": "4.8.3",
105
- "ts-node": "^10.9.2",
106
- "tsconfig-paths": "^4.2.0",
107
- "typescript": "^5.9.3",
108
- "uuid": "13.0.0",
109
- "winston": "^3.19.0",
110
- "winston-daily-rotate-file": "^5.0.0",
111
- "zod": "3.23.8"
112
- },
113
- "devDependencies": {
114
- "@eslint/js": "^9.39.2",
115
- "@types/bcrypt": "^5.0.2",
116
- "@types/jest": "^30.0.0",
117
- "@types/module-alias": "^2.0.4",
118
- "@types/supertest": "^6.0.3",
119
- "eslint": "^9.39.2",
120
- "globals": "^16.5.0",
121
- "jest": "^30.2.0",
122
- "supertest": "^7.1.4",
123
- "ts-jest": "^29.4.6",
124
- "typescript-eslint": "^8.50.1"
125
- }
126
- }
1
+ {
2
+ "name": "lapeh",
3
+ "version": "3.0.4",
4
+ "description": "Framework API Express yang siap pakai (Standardized)",
5
+ "engines": {
6
+ "node": ">=18.0.0",
7
+ "npm": ">=9.0.0"
8
+ },
9
+ "main": "dist/lib/bootstrap.js",
10
+ "bin": {
11
+ "lapeh": "bin/index.js"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/robyajo/lapeh.git"
16
+ },
17
+ "homepage": "https://lapeh-doc.vercel.app",
18
+ "bugs": {
19
+ "url": "https://github.com/robyajo/lapeh/issues"
20
+ },
21
+ "types": "dist/src/index.d.ts",
22
+ "files": [
23
+ "bin",
24
+ "dist",
25
+ "lib",
26
+ "scripts",
27
+ "src",
28
+ "storage",
29
+ "doc",
30
+ "README.md",
31
+ "LICENSE",
32
+ "tsconfig.json",
33
+ "nodemon.json",
34
+ "docker-compose.yml",
35
+ ".env.example",
36
+ "eslint.config.mjs",
37
+ "gitignore.template",
38
+ "ecosystem.config.js",
39
+ "tsconfig.build.json"
40
+ ],
41
+ "scripts": {
42
+ "dev": "node bin/index.js dev",
43
+ "first": "node scripts/init-project.js",
44
+ "build": "node bin/index.js build",
45
+ "start": "node bin/index.js start",
46
+ "start:prod": "node bin/index.js start",
47
+ "typecheck": "tsc --noEmit",
48
+ "lint": "eslint .",
49
+ "lint:fix": "eslint . --fix",
50
+ "test": "jest",
51
+ "generate:jwt": "node scripts/generate-jwt-secret.js",
52
+ "make:module": "node scripts/make-module.js",
53
+ "make:modul": "node scripts/make-module.js",
54
+ "config:clear": "node scripts/config-clear.js",
55
+ "release": "node scripts/release.js",
56
+ "prepublishOnly": "npm run build"
57
+ },
58
+ "keywords": [
59
+ "nodejs-framework",
60
+ "typescript-framework",
61
+ "express-framework",
62
+ "backend-framework",
63
+ "rest-api",
64
+ "production-ready",
65
+ "api-generator",
66
+ "boilerplate",
67
+ "starter-kit",
68
+ "mvc",
69
+ "cli",
70
+ "lapeh",
71
+ "roby-ajo",
72
+ "ajo-roby",
73
+ "robyajo",
74
+ "lapeh"
75
+ ],
76
+ "author": "robyajo <robyfull.dev@gmail.com>",
77
+ "license": "MIT",
78
+ "type": "commonjs",
79
+ "peerDependencies": {},
80
+ "dependencies": {
81
+ "@types/bcryptjs": "2.4.6",
82
+ "@types/compression": "^1.8.1",
83
+ "@types/cors": "2.8.19",
84
+ "@types/express": "5.0.6",
85
+ "@types/jsonwebtoken": "9.0.10",
86
+ "@types/multer": "^2.0.0",
87
+ "@types/node": "25.0.3",
88
+ "@types/pg": "8.16.0",
89
+ "@types/uuid": "10.0.0",
90
+ "bcryptjs": "^2.4.3",
91
+ "compression": "^1.8.1",
92
+ "cors": "2.8.5",
93
+ "dotenv": "17.2.3",
94
+ "express": "5.2.1",
95
+ "express-rate-limit": "8.2.1",
96
+ "fast-json-stringify": "^6.1.1",
97
+ "helmet": "8.1.0",
98
+ "ioredis": "5.8.2",
99
+ "ioredis-mock": "^8.13.1",
100
+ "jsonwebtoken": "9.0.3",
101
+ "module-alias": "^2.2.3",
102
+ "multer": "2.0.2",
103
+ "pg": "8.16.3",
104
+ "slugify": "1.6.6",
105
+ "socket.io": "4.8.3",
106
+ "ts-node": "^10.9.2",
107
+ "tsconfig-paths": "^4.2.0",
108
+ "typescript": "^5.9.3",
109
+ "uuid": "13.0.0",
110
+ "winston": "^3.19.0",
111
+ "winston-daily-rotate-file": "^5.0.0",
112
+ "zod": "3.23.8"
113
+ },
114
+ "devDependencies": {
115
+ "@eslint/js": "^9.39.2",
116
+ "@types/bcrypt": "^5.0.2",
117
+ "@types/jest": "^30.0.0",
118
+ "@types/module-alias": "^2.0.4",
119
+ "@types/supertest": "^6.0.3",
120
+ "eslint": "^9.39.2",
121
+ "globals": "^16.5.0",
122
+ "jest": "^30.2.0",
123
+ "supertest": "^7.1.4",
124
+ "ts-jest": "^29.4.6",
125
+ "typescript-eslint": "^8.50.1"
126
+ }
127
+ }
@@ -0,0 +1,295 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const readline = require('readline');
4
+ const { execSync } = require('child_process');
5
+
6
+ const rl = readline.createInterface({
7
+ input: process.stdin,
8
+ output: process.stdout
9
+ });
10
+
11
+ const question = (query) => new Promise((resolve) => rl.question(query, resolve));
12
+
13
+ // Paths
14
+ const rootDir = path.resolve(__dirname, '..');
15
+ const websiteDir = path.join(rootDir, 'website');
16
+ const packageJsonPath = path.join(rootDir, 'package.json');
17
+ const websitePackageJsonPath = path.join(websiteDir, 'package.json');
18
+
19
+ // Read current version
20
+ const pkg = require(packageJsonPath);
21
+ const currentVersion = pkg.version;
22
+
23
+ console.log(`\nšŸš€ Lapeh Release Automation Script`);
24
+ console.log(`Current Version: ${currentVersion}\n`);
25
+
26
+ // Helper to get git changes
27
+ function getGitChanges() {
28
+ try {
29
+ // Try to find the last tag
30
+ let lastTag = '';
31
+ try {
32
+ lastTag = execSync('git describe --tags --abbrev=0', { stdio: 'pipe' }).toString().trim();
33
+ } catch (e) {
34
+ // No tags found, maybe fetch all commits
35
+ lastTag = '';
36
+ }
37
+
38
+ const range = lastTag ? `${lastTag}..HEAD` : 'HEAD';
39
+ const logs = execSync(`git log ${range} --pretty=format:"%s"`, { stdio: 'pipe' }).toString().trim();
40
+
41
+ if (!logs) return [];
42
+
43
+ // Filter out chores, merges, etc. if desired, or keep everything
44
+ return logs.split('\n')
45
+ .map(l => l.trim())
46
+ .filter(l =>
47
+ l &&
48
+ !l.startsWith('chore:') &&
49
+ !l.startsWith('Merge branch') &&
50
+ !l.startsWith('docs: release') &&
51
+ !l.includes('release v') &&
52
+ !l.includes('Update version')
53
+ );
54
+ } catch (e) {
55
+ return [];
56
+ }
57
+ }
58
+
59
+ // Helper to get npm version
60
+ function getNpmVersion() {
61
+ try {
62
+ return execSync('npm view lapeh version', { stdio: 'pipe' }).toString().trim();
63
+ } catch (e) {
64
+ return null;
65
+ }
66
+ }
67
+
68
+ // Helper to increment patch version
69
+ function incrementPatch(version) {
70
+ const parts = version.split('.').map(Number);
71
+ if (parts.length !== 3 || parts.some(isNaN)) return version; // Fallback
72
+ parts[2]++;
73
+ return parts.join('.');
74
+ }
75
+
76
+ async function main() {
77
+ try {
78
+ // 1. Check versions and ask for new one
79
+ console.log('šŸ” Checking npm version...');
80
+ const npmVersion = getNpmVersion();
81
+ const baseVersion = npmVersion || currentVersion;
82
+ const suggestedVersion = incrementPatch(baseVersion);
83
+
84
+ console.log(`Latest npm version: ${npmVersion || 'Not found (using local)'}`);
85
+ console.log(`Current local version: ${currentVersion}`);
86
+
87
+ const newVersionInput = await question(`Enter new version (default: ${suggestedVersion}): `);
88
+ const newVersion = newVersionInput.trim() || suggestedVersion;
89
+
90
+ if (!newVersion) {
91
+ console.log('āŒ Version is required');
92
+ process.exit(1);
93
+ }
94
+
95
+ // Always update package.json locally first
96
+ console.log('\nšŸ“¦ Updating package.json files...');
97
+ updatePackageJson(packageJsonPath, newVersion);
98
+ updatePackageJson(websitePackageJsonPath, newVersion);
99
+
100
+ // 2. Question: Blog
101
+ const createBlog = await question('\n1. Apa Anda akan membuatkan blog untuk fitur baru ini? (y/n): ');
102
+ let blogTitleEN = '';
103
+
104
+ if (createBlog.toLowerCase() === 'y') {
105
+ console.log('\nšŸ¤– Auto-detecting changes from Git...');
106
+ const changes = getGitChanges();
107
+
108
+ // Heuristics for defaults
109
+ const defaultTitle = changes.length > 0 ? changes[0] : 'Maintenance Release';
110
+ const defaultDesc = changes.length > 0 ? `Includes: ${changes.slice(0, 2).join(', ')}` : 'Routine maintenance and updates.';
111
+ const defaultFeatures = changes.join(', ');
112
+
113
+ // Use defaults directly
114
+ const titleID = defaultTitle;
115
+ const descriptionID = defaultDesc;
116
+ const featuresID = defaultFeatures;
117
+
118
+ const titleEN = defaultTitle;
119
+ const descriptionEN = defaultDesc;
120
+ const featuresEN = defaultFeatures;
121
+
122
+ blogTitleEN = titleEN; // Save for commit message
123
+
124
+ console.log('šŸ“ Generating blog posts...');
125
+ const date = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
126
+ const dateString = new Date().toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric' });
127
+ const dateStringEn = new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
128
+
129
+ const blogFileName = `release-v${newVersion}.md`;
130
+
131
+ // Generate list items
132
+ const featureListID = changes.length > 0
133
+ ? changes.map(f => `* **${f.trim()}**`).join('\n')
134
+ : '* **Routine maintenance**';
135
+
136
+ const featureListEN = changes.length > 0
137
+ ? changes.map(f => `* **${f.trim()}**`).join('\n')
138
+ : '* **Routine maintenance**';
139
+
140
+ // Indonesian Blog Content
141
+ const idContent = `---
142
+ title: Rilis v${newVersion} - ${titleID}
143
+ date: ${date}
144
+ author: Tim Lapeh
145
+ description: ${descriptionID}
146
+ ---
147
+
148
+ # Rilis v${newVersion}: ${titleID}
149
+
150
+ Kami dengan senang hati mengumumkan rilis **Lapeh Framework v${newVersion}**!
151
+
152
+ ## Apa yang Baru?
153
+
154
+ ${descriptionID}
155
+
156
+ ### Fitur Utama šŸš€
157
+
158
+ ${featureListID}
159
+
160
+ ## Cara Update
161
+
162
+ \`\`\`bash
163
+ npm install lapeh@latest
164
+ \`\`\`
165
+
166
+ Terima kasih telah menggunakan Lapeh Framework!
167
+ `;
168
+
169
+ // English Blog Content
170
+ const enContent = `---
171
+ title: Release v${newVersion} - ${titleEN}
172
+ date: ${date}
173
+ author: Lapeh Team
174
+ description: ${descriptionEN}
175
+ ---
176
+
177
+ # Release v${newVersion}: ${titleEN}
178
+
179
+ We are excited to announce the release of **Lapeh Framework v${newVersion}**!
180
+
181
+ ## What's New?
182
+
183
+ ${descriptionEN}
184
+
185
+ ### Key Features šŸš€
186
+
187
+ ${featureListEN}
188
+
189
+ ## How to Update
190
+
191
+ \`\`\`bash
192
+ npm install lapeh@latest
193
+ \`\`\`
194
+
195
+ Thank you for using Lapeh Framework!
196
+ `;
197
+
198
+ fs.writeFileSync(path.join(websiteDir, 'blog', blogFileName), idContent);
199
+ fs.writeFileSync(path.join(websiteDir, 'en/blog', blogFileName), enContent);
200
+
201
+ console.log('šŸ“‘ Updating blog indexes...');
202
+ updateBlogIndex(path.join(websiteDir, 'blog/index.md'), newVersion, titleID, dateString, descriptionID, blogFileName, 'id');
203
+ updateBlogIndex(path.join(websiteDir, 'en/blog/index.md'), newVersion, titleEN, dateStringEn, descriptionEN, blogFileName, 'en');
204
+ } else {
205
+ console.log('ā­ļø Skipping blog generation.');
206
+ }
207
+
208
+ // 3. Question: Documentation
209
+ const updateDocs = await question('\n2. Apa Anda ingin update dokumentasi? (y/n): ');
210
+ if (updateDocs.toLowerCase() === 'y') {
211
+ console.log('\nšŸ“š Documentation Reminder:');
212
+ console.log('Jika ada package/method baru, silakan update file berikut secara manual sekarang:');
213
+ console.log(' - website/docs/packages.md');
214
+ console.log(' - website/docs/api.md');
215
+
216
+ await question('Tekan Enter jika Anda sudah selesai update manual (atau jika tidak diperlukan)...');
217
+
218
+ console.log('šŸ”„ Syncing documentation...');
219
+ execSync('node scripts/sync-docs.js', { cwd: websiteDir, stdio: 'inherit' });
220
+ } else {
221
+ console.log('ā­ļø Skipping documentation sync.');
222
+ }
223
+
224
+ // 4. Question: Git
225
+ const pushGit = await question('\n3. Apa ingin publish ke Git? (y/n): ');
226
+ if (pushGit.toLowerCase() === 'y') {
227
+ const commitMsg = blogTitleEN
228
+ ? `chore: release v${newVersion} - ${blogTitleEN}`
229
+ : `chore: release v${newVersion}`;
230
+
231
+ execSync('git add .', { stdio: 'inherit' });
232
+ execSync(`git commit -m "${commitMsg}"`, { stdio: 'inherit' });
233
+ execSync(`git tag v${newVersion}`, { stdio: 'inherit' });
234
+ execSync(`git push origin HEAD && git push origin v${newVersion}`, { stdio: 'inherit' });
235
+ console.log('āœ… Git push & tag complete');
236
+ } else {
237
+ console.log('ā­ļø Skipping Git push.');
238
+ }
239
+
240
+ // 5. Question: NPM
241
+ const publishNpm = await question('\n4. Apa ingin publish ke NPM? (y/n): ');
242
+ if (publishNpm.toLowerCase() === 'y') {
243
+ execSync('npm publish', { stdio: 'inherit' });
244
+ console.log('āœ… NPM publish complete');
245
+ } else {
246
+ console.log('ā­ļø Skipping NPM publish.');
247
+ }
248
+
249
+ console.log('\n✨ Proses selesai!');
250
+
251
+ } catch (error) {
252
+ console.error('āŒ Error:', error.message);
253
+ } finally {
254
+ rl.close();
255
+ }
256
+ }
257
+
258
+ function updatePackageJson(filePath, version) {
259
+ const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
260
+ json.version = version;
261
+ fs.writeFileSync(filePath, JSON.stringify(json, null, 2) + '\n');
262
+ console.log(`Updated ${path.basename(filePath)} to ${version}`);
263
+ }
264
+
265
+ function updateBlogIndex(filePath, version, title, date, description, fileName, lang) {
266
+ let content = fs.readFileSync(filePath, 'utf8');
267
+
268
+ const readMore = lang === 'id' ? 'Baca selengkapnya' : 'Read more';
269
+ const releaseTag = lang === 'id' ? 'Rilis' : 'Release';
270
+
271
+ // Construct new entry
272
+ const newEntry = `## šŸš€ [${releaseTag} v${version}: ${title}](./${fileName.replace('.md', '')})
273
+
274
+ _${date}_ • šŸ‘¤ Lapeh Team • šŸ·ļø _Release_
275
+
276
+ ${description} [${readMore} →](./${fileName.replace('.md', '')})
277
+
278
+ ---
279
+
280
+ `;
281
+
282
+ const separator = '---';
283
+ const parts = content.split(separator);
284
+
285
+ if (parts.length >= 2) {
286
+ parts.splice(1, 0, '\n\n' + newEntry.trim() + '\n\n');
287
+ content = parts.join(separator);
288
+ } else {
289
+ content = content + '\n\n' + newEntry;
290
+ }
291
+
292
+ fs.writeFileSync(filePath, content);
293
+ }
294
+
295
+ main();