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.
- package/package.json +127 -126
- package/scripts/release.js +295 -0
package/package.json
CHANGED
|
@@ -1,126 +1,127 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "lapeh",
|
|
3
|
-
"version": "3.0.
|
|
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
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"ajo
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
|
|
81
|
-
"@types/
|
|
82
|
-
"@types/
|
|
83
|
-
"@types/
|
|
84
|
-
"@types/
|
|
85
|
-
"@types/
|
|
86
|
-
"@types/
|
|
87
|
-
"@types/
|
|
88
|
-
"@types/
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"express
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"ioredis
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"winston
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"@
|
|
116
|
-
"@types/
|
|
117
|
-
"@types/
|
|
118
|
-
"@types/
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
"
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
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();
|