lapeh 3.0.2 ā 3.0.3
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 +284 -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.3",
|
|
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,284 @@
|
|
|
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 => l && !l.startsWith('chore:') && !l.startsWith('Merge branch'));
|
|
47
|
+
} catch (e) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Helper to get npm version
|
|
53
|
+
function getNpmVersion() {
|
|
54
|
+
try {
|
|
55
|
+
return execSync('npm view lapeh version', { stdio: 'pipe' }).toString().trim();
|
|
56
|
+
} catch (e) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Helper to increment patch version
|
|
62
|
+
function incrementPatch(version) {
|
|
63
|
+
const parts = version.split('.').map(Number);
|
|
64
|
+
if (parts.length !== 3 || parts.some(isNaN)) return version; // Fallback
|
|
65
|
+
parts[2]++;
|
|
66
|
+
return parts.join('.');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function main() {
|
|
70
|
+
try {
|
|
71
|
+
// 1. Check versions and ask for new one
|
|
72
|
+
console.log('š Checking npm version...');
|
|
73
|
+
const npmVersion = getNpmVersion();
|
|
74
|
+
const baseVersion = npmVersion || currentVersion;
|
|
75
|
+
const suggestedVersion = incrementPatch(baseVersion);
|
|
76
|
+
|
|
77
|
+
console.log(`Latest npm version: ${npmVersion || 'Not found (using local)'}`);
|
|
78
|
+
console.log(`Current local version: ${currentVersion}`);
|
|
79
|
+
|
|
80
|
+
const newVersionInput = await question(`Enter new version (default: ${suggestedVersion}): `);
|
|
81
|
+
const newVersion = newVersionInput.trim() || suggestedVersion;
|
|
82
|
+
|
|
83
|
+
if (!newVersion) {
|
|
84
|
+
console.log('ā Version is required');
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Always update package.json locally first
|
|
89
|
+
console.log('\nš¦ Updating package.json files...');
|
|
90
|
+
updatePackageJson(packageJsonPath, newVersion);
|
|
91
|
+
updatePackageJson(websitePackageJsonPath, newVersion);
|
|
92
|
+
|
|
93
|
+
// 2. Question: Blog
|
|
94
|
+
const createBlog = await question('\n1. Apa Anda akan membuatkan blog untuk fitur baru ini? (y/n): ');
|
|
95
|
+
let blogTitleEN = '';
|
|
96
|
+
|
|
97
|
+
if (createBlog.toLowerCase() === 'y') {
|
|
98
|
+
console.log('\nš¤ Auto-detecting changes from Git...');
|
|
99
|
+
const changes = getGitChanges();
|
|
100
|
+
|
|
101
|
+
// Heuristics for defaults
|
|
102
|
+
const defaultTitle = changes.length > 0 ? changes[0] : 'Maintenance Release';
|
|
103
|
+
const defaultDesc = changes.length > 0 ? `Includes: ${changes.slice(0, 2).join(', ')}` : 'Routine maintenance and updates.';
|
|
104
|
+
const defaultFeatures = changes.join(', ');
|
|
105
|
+
|
|
106
|
+
console.log('\n--- š®š© Bahasa Indonesia Input ---');
|
|
107
|
+
const titleID = await question(`Judul Rilis (default: "${defaultTitle}"): `) || defaultTitle;
|
|
108
|
+
const descriptionID = await question(`Deskripsi Singkat (default: "${defaultDesc}"): `) || defaultDesc;
|
|
109
|
+
const featuresID = await question(`Fitur Utama (default: "${defaultFeatures}"): `) || defaultFeatures;
|
|
110
|
+
|
|
111
|
+
console.log('\n--- šŗšø English Input ---');
|
|
112
|
+
// Reuse ID inputs as defaults for EN if user just hits enter,
|
|
113
|
+
// but ideally they should type English. We show the same defaults.
|
|
114
|
+
const titleEN = await question(`Release Title (default: "${defaultTitle}"): `) || defaultTitle;
|
|
115
|
+
const descriptionEN = await question(`Short Description (default: "${defaultDesc}"): `) || defaultDesc;
|
|
116
|
+
const featuresEN = await question(`Key Features (default: "${defaultFeatures}"): `) || defaultFeatures;
|
|
117
|
+
|
|
118
|
+
blogTitleEN = titleEN; // Save for commit message
|
|
119
|
+
|
|
120
|
+
console.log('š Generating blog posts...');
|
|
121
|
+
const date = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
|
|
122
|
+
const dateString = new Date().toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric' });
|
|
123
|
+
const dateStringEn = new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
|
|
124
|
+
|
|
125
|
+
const blogFileName = `release-v${newVersion}.md`;
|
|
126
|
+
|
|
127
|
+
const featureListID = featuresID.split(',').map(f => `* **${f.trim()}**`).join('\n');
|
|
128
|
+
const featureListEN = featuresEN.split(',').map(f => `* **${f.trim()}**`).join('\n');
|
|
129
|
+
|
|
130
|
+
// Indonesian Blog Content
|
|
131
|
+
const idContent = `---
|
|
132
|
+
title: Rilis v${newVersion} - ${titleID}
|
|
133
|
+
date: ${date}
|
|
134
|
+
author: Tim Lapeh
|
|
135
|
+
description: ${descriptionID}
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
# Rilis v${newVersion}: ${titleID}
|
|
139
|
+
|
|
140
|
+
Kami dengan senang hati mengumumkan rilis **Lapeh Framework v${newVersion}**!
|
|
141
|
+
|
|
142
|
+
## Apa yang Baru?
|
|
143
|
+
|
|
144
|
+
${descriptionID}
|
|
145
|
+
|
|
146
|
+
### Fitur Utama š
|
|
147
|
+
|
|
148
|
+
${featureListID}
|
|
149
|
+
|
|
150
|
+
## Cara Update
|
|
151
|
+
|
|
152
|
+
\`\`\`bash
|
|
153
|
+
npm install lapeh@latest
|
|
154
|
+
\`\`\`
|
|
155
|
+
|
|
156
|
+
Terima kasih telah menggunakan Lapeh Framework!
|
|
157
|
+
`;
|
|
158
|
+
|
|
159
|
+
// English Blog Content
|
|
160
|
+
const enContent = `---
|
|
161
|
+
title: Release v${newVersion} - ${titleEN}
|
|
162
|
+
date: ${date}
|
|
163
|
+
author: Lapeh Team
|
|
164
|
+
description: ${descriptionEN}
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
# Release v${newVersion}: ${titleEN}
|
|
168
|
+
|
|
169
|
+
We are excited to announce the release of **Lapeh Framework v${newVersion}**!
|
|
170
|
+
|
|
171
|
+
## What's New?
|
|
172
|
+
|
|
173
|
+
${descriptionEN}
|
|
174
|
+
|
|
175
|
+
### Key Features š
|
|
176
|
+
|
|
177
|
+
${featureListEN}
|
|
178
|
+
|
|
179
|
+
## How to Update
|
|
180
|
+
|
|
181
|
+
\`\`\`bash
|
|
182
|
+
npm install lapeh@latest
|
|
183
|
+
\`\`\`
|
|
184
|
+
|
|
185
|
+
Thank you for using Lapeh Framework!
|
|
186
|
+
`;
|
|
187
|
+
|
|
188
|
+
fs.writeFileSync(path.join(websiteDir, 'blog', blogFileName), idContent);
|
|
189
|
+
fs.writeFileSync(path.join(websiteDir, 'en/blog', blogFileName), enContent);
|
|
190
|
+
|
|
191
|
+
console.log('š Updating blog indexes...');
|
|
192
|
+
updateBlogIndex(path.join(websiteDir, 'blog/index.md'), newVersion, titleID, dateString, descriptionID, blogFileName, 'id');
|
|
193
|
+
updateBlogIndex(path.join(websiteDir, 'en/blog/index.md'), newVersion, titleEN, dateStringEn, descriptionEN, blogFileName, 'en');
|
|
194
|
+
} else {
|
|
195
|
+
console.log('āļø Skipping blog generation.');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 3. Question: Documentation
|
|
199
|
+
const updateDocs = await question('\n2. Apa Anda ingin update dokumentasi? (y/n): ');
|
|
200
|
+
if (updateDocs.toLowerCase() === 'y') {
|
|
201
|
+
console.log('\nš Documentation Reminder:');
|
|
202
|
+
console.log('Jika ada package/method baru, silakan update file berikut secara manual sekarang:');
|
|
203
|
+
console.log(' - website/docs/packages.md');
|
|
204
|
+
console.log(' - website/docs/api.md');
|
|
205
|
+
|
|
206
|
+
await question('Tekan Enter jika Anda sudah selesai update manual (atau jika tidak diperlukan)...');
|
|
207
|
+
|
|
208
|
+
console.log('š Syncing documentation...');
|
|
209
|
+
execSync('node scripts/sync-docs.js', { cwd: websiteDir, stdio: 'inherit' });
|
|
210
|
+
} else {
|
|
211
|
+
console.log('āļø Skipping documentation sync.');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// 4. Question: Git
|
|
215
|
+
const pushGit = await question('\n3. Apa ingin publish ke Git? (y/n): ');
|
|
216
|
+
if (pushGit.toLowerCase() === 'y') {
|
|
217
|
+
const commitMsg = blogTitleEN
|
|
218
|
+
? `chore: release v${newVersion} - ${blogTitleEN}`
|
|
219
|
+
: `chore: release v${newVersion}`;
|
|
220
|
+
|
|
221
|
+
execSync('git add .', { stdio: 'inherit' });
|
|
222
|
+
execSync(`git commit -m "${commitMsg}"`, { stdio: 'inherit' });
|
|
223
|
+
execSync('git push', { stdio: 'inherit' });
|
|
224
|
+
console.log('ā
Git push complete');
|
|
225
|
+
} else {
|
|
226
|
+
console.log('āļø Skipping Git push.');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// 5. Question: NPM
|
|
230
|
+
const publishNpm = await question('\n4. Apa ingin publish ke NPM? (y/n): ');
|
|
231
|
+
if (publishNpm.toLowerCase() === 'y') {
|
|
232
|
+
execSync('npm publish', { stdio: 'inherit' });
|
|
233
|
+
console.log('ā
NPM publish complete');
|
|
234
|
+
} else {
|
|
235
|
+
console.log('āļø Skipping NPM publish.');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
console.log('\n⨠Proses selesai!');
|
|
239
|
+
|
|
240
|
+
} catch (error) {
|
|
241
|
+
console.error('ā Error:', error.message);
|
|
242
|
+
} finally {
|
|
243
|
+
rl.close();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function updatePackageJson(filePath, version) {
|
|
248
|
+
const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
249
|
+
json.version = version;
|
|
250
|
+
fs.writeFileSync(filePath, JSON.stringify(json, null, 2) + '\n');
|
|
251
|
+
console.log(`Updated ${path.basename(filePath)} to ${version}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function updateBlogIndex(filePath, version, title, date, description, fileName, lang) {
|
|
255
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
256
|
+
|
|
257
|
+
const readMore = lang === 'id' ? 'Baca selengkapnya' : 'Read more';
|
|
258
|
+
const releaseTag = lang === 'id' ? 'Rilis' : 'Release';
|
|
259
|
+
|
|
260
|
+
// Construct new entry
|
|
261
|
+
const newEntry = `## š [${releaseTag} v${version}: ${title}](./${fileName.replace('.md', '')})
|
|
262
|
+
|
|
263
|
+
_${date}_ ⢠š¤ Lapeh Team ⢠š·ļø _Release_
|
|
264
|
+
|
|
265
|
+
${description} [${readMore} ā](./${fileName.replace('.md', '')})
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
`;
|
|
270
|
+
|
|
271
|
+
const separator = '---';
|
|
272
|
+
const parts = content.split(separator);
|
|
273
|
+
|
|
274
|
+
if (parts.length >= 2) {
|
|
275
|
+
parts.splice(1, 0, '\n\n' + newEntry.trim() + '\n\n');
|
|
276
|
+
content = parts.join(separator);
|
|
277
|
+
} else {
|
|
278
|
+
content = content + '\n\n' + newEntry;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
fs.writeFileSync(filePath, content);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
main();
|