create-jinmankn-app 1.0.0

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 (117) hide show
  1. package/bin/index.js +76 -0
  2. package/package.json +20 -0
  3. package/templates/blueprint/BLUEPRINT_REPRODUCTION_PROMPT.md +996 -0
  4. package/templates/blueprint/HOW_IT_WORKS.md +286 -0
  5. package/templates/blueprint/README.md +123 -0
  6. package/templates/blueprint/backend/config/db.js +12 -0
  7. package/templates/blueprint/backend/controllers/authController.js +90 -0
  8. package/templates/blueprint/backend/controllers/itemController.js +74 -0
  9. package/templates/blueprint/backend/middleware/auth.js +32 -0
  10. package/templates/blueprint/backend/middleware/errorHandler.js +23 -0
  11. package/templates/blueprint/backend/models/Item.js +26 -0
  12. package/templates/blueprint/backend/models/User.js +28 -0
  13. package/templates/blueprint/backend/package-lock.json +2190 -0
  14. package/templates/blueprint/backend/package.json +23 -0
  15. package/templates/blueprint/backend/routes/authRoutes.js +11 -0
  16. package/templates/blueprint/backend/routes/healthRoutes.js +9 -0
  17. package/templates/blueprint/backend/routes/itemRoutes.js +21 -0
  18. package/templates/blueprint/backend/server.js +29 -0
  19. package/templates/blueprint/frontend/.env.example +1 -0
  20. package/templates/blueprint/frontend/index.html +13 -0
  21. package/templates/blueprint/frontend/package-lock.json +2844 -0
  22. package/templates/blueprint/frontend/package.json +23 -0
  23. package/templates/blueprint/frontend/public/favicon.svg +4 -0
  24. package/templates/blueprint/frontend/src/App.jsx +78 -0
  25. package/templates/blueprint/frontend/src/assets/logo.svg +4 -0
  26. package/templates/blueprint/frontend/src/components/DashboardLayout.jsx +103 -0
  27. package/templates/blueprint/frontend/src/components/ProtectedRoute.jsx +18 -0
  28. package/templates/blueprint/frontend/src/index.css +1 -0
  29. package/templates/blueprint/frontend/src/main.jsx +13 -0
  30. package/templates/blueprint/frontend/src/pages/DashboardHome.jsx +74 -0
  31. package/templates/blueprint/frontend/src/pages/Items.jsx +243 -0
  32. package/templates/blueprint/frontend/src/pages/Login.jsx +101 -0
  33. package/templates/blueprint/frontend/src/pages/Profile.jsx +79 -0
  34. package/templates/blueprint/frontend/src/pages/Register.jsx +122 -0
  35. package/templates/blueprint/frontend/src/pages/Report.jsx +124 -0
  36. package/templates/blueprint/frontend/vite.config.js +10 -0
  37. package/templates/blueprint/package.json +13 -0
  38. package/templates/blueprint/scripts/pack-blueprint.ps1 +18 -0
  39. package/templates/chom/Backend/app.js +25 -0
  40. package/templates/chom/Backend/package-lock.json +1551 -0
  41. package/templates/chom/Backend/package.json +23 -0
  42. package/templates/chom/Backend/seedAdmin.js +21 -0
  43. package/templates/chom/Backend/src/controllers/payment.c.js +57 -0
  44. package/templates/chom/Backend/src/controllers/students.c.js +58 -0
  45. package/templates/chom/Backend/src/controllers/users.c.js +62 -0
  46. package/templates/chom/Backend/src/middleware/authentication.js +18 -0
  47. package/templates/chom/Backend/src/models/payment.m.js +13 -0
  48. package/templates/chom/Backend/src/models/students.m.js +10 -0
  49. package/templates/chom/Backend/src/models/users.m.js +11 -0
  50. package/templates/chom/Backend/src/routes/users.r.js +21 -0
  51. package/templates/chom/Frontend/README.md +16 -0
  52. package/templates/chom/Frontend/eslint.config.js +21 -0
  53. package/templates/chom/Frontend/index.html +13 -0
  54. package/templates/chom/Frontend/package-lock.json +3075 -0
  55. package/templates/chom/Frontend/package.json +31 -0
  56. package/templates/chom/Frontend/public/favicon.svg +1 -0
  57. package/templates/chom/Frontend/public/icons.svg +24 -0
  58. package/templates/chom/Frontend/src/App.css +189 -0
  59. package/templates/chom/Frontend/src/App.jsx +28 -0
  60. package/templates/chom/Frontend/src/api/api.jsx +27 -0
  61. package/templates/chom/Frontend/src/assets/hero.png +0 -0
  62. package/templates/chom/Frontend/src/assets/react.svg +1 -0
  63. package/templates/chom/Frontend/src/assets/vite.svg +1 -0
  64. package/templates/chom/Frontend/src/components/Navbar.jsx +21 -0
  65. package/templates/chom/Frontend/src/index.css +8 -0
  66. package/templates/chom/Frontend/src/main.jsx +10 -0
  67. package/templates/chom/Frontend/src/pages/Dashboard.jsx +21 -0
  68. package/templates/chom/Frontend/src/pages/Landing.jsx +39 -0
  69. package/templates/chom/Frontend/src/pages/Login.jsx +49 -0
  70. package/templates/chom/Frontend/src/pages/Overview.jsx +42 -0
  71. package/templates/chom/Frontend/src/pages/Register.jsx +76 -0
  72. package/templates/chom/Frontend/src/pages/Students.jsx +14 -0
  73. package/templates/chom/Frontend/vite.config.js +8 -0
  74. package/templates/chom/package.json +13 -0
  75. package/templates/hospital-faisal/backend/.env.example +9 -0
  76. package/templates/hospital-faisal/backend/config/db.js +96 -0
  77. package/templates/hospital-faisal/backend/controllers/appointmentController.js +164 -0
  78. package/templates/hospital-faisal/backend/controllers/authController.js +106 -0
  79. package/templates/hospital-faisal/backend/controllers/hospitalReportController.js +72 -0
  80. package/templates/hospital-faisal/backend/controllers/medicalReportController.js +105 -0
  81. package/templates/hospital-faisal/backend/controllers/patientController.js +98 -0
  82. package/templates/hospital-faisal/backend/database/schema.sql +47 -0
  83. package/templates/hospital-faisal/backend/middleware/auth.js +30 -0
  84. package/templates/hospital-faisal/backend/middleware/errorHandler.js +23 -0
  85. package/templates/hospital-faisal/backend/middleware/role.js +6 -0
  86. package/templates/hospital-faisal/backend/package-lock.json +2092 -0
  87. package/templates/hospital-faisal/backend/package.json +23 -0
  88. package/templates/hospital-faisal/backend/routes/appointmentRoutes.js +25 -0
  89. package/templates/hospital-faisal/backend/routes/authRoutes.js +12 -0
  90. package/templates/hospital-faisal/backend/routes/healthRoutes.js +9 -0
  91. package/templates/hospital-faisal/backend/routes/hospitalReportRoutes.js +10 -0
  92. package/templates/hospital-faisal/backend/routes/medicalReportRoutes.js +16 -0
  93. package/templates/hospital-faisal/backend/routes/patientRoutes.js +22 -0
  94. package/templates/hospital-faisal/backend/server.js +46 -0
  95. package/templates/hospital-faisal/frontend/.env.example +1 -0
  96. package/templates/hospital-faisal/frontend/index.html +10 -0
  97. package/templates/hospital-faisal/frontend/package-lock.json +2844 -0
  98. package/templates/hospital-faisal/frontend/package.json +23 -0
  99. package/templates/hospital-faisal/frontend/public/favicon.svg +4 -0
  100. package/templates/hospital-faisal/frontend/src/App.jsx +56 -0
  101. package/templates/hospital-faisal/frontend/src/api.js +20 -0
  102. package/templates/hospital-faisal/frontend/src/assets/logo.svg +4 -0
  103. package/templates/hospital-faisal/frontend/src/components/DashboardLayout.jsx +114 -0
  104. package/templates/hospital-faisal/frontend/src/components/ProtectedRoute.jsx +18 -0
  105. package/templates/hospital-faisal/frontend/src/components/RoleRoute.jsx +14 -0
  106. package/templates/hospital-faisal/frontend/src/index.css +1 -0
  107. package/templates/hospital-faisal/frontend/src/main.jsx +13 -0
  108. package/templates/hospital-faisal/frontend/src/pages/Appointments.jsx +305 -0
  109. package/templates/hospital-faisal/frontend/src/pages/DashboardHome.jsx +105 -0
  110. package/templates/hospital-faisal/frontend/src/pages/Login.jsx +98 -0
  111. package/templates/hospital-faisal/frontend/src/pages/MedicalReports.jsx +182 -0
  112. package/templates/hospital-faisal/frontend/src/pages/Patients.jsx +237 -0
  113. package/templates/hospital-faisal/frontend/src/pages/Profile.jsx +78 -0
  114. package/templates/hospital-faisal/frontend/src/pages/Register.jsx +133 -0
  115. package/templates/hospital-faisal/frontend/src/pages/Report.jsx +167 -0
  116. package/templates/hospital-faisal/frontend/vite.config.js +10 -0
  117. package/templates/hospital-faisal/package.json +13 -0
@@ -0,0 +1,78 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { api } from '../api';
3
+
4
+ function Profile() {
5
+ const [user, setUser] = useState(null);
6
+ const [error, setError] = useState('');
7
+ const [loading, setLoading] = useState(true);
8
+
9
+ const handleRetrieve = async () => {
10
+ try {
11
+ const response = await api.get('/auth/me');
12
+ setUser(response.data.user);
13
+ localStorage.setItem('user', JSON.stringify(response.data.user));
14
+ } catch (err) {
15
+ const storedUser = localStorage.getItem('user');
16
+ if (storedUser) {
17
+ setUser(JSON.parse(storedUser));
18
+ } else {
19
+ setError(err.response?.data?.message || 'Failed to load profile');
20
+ }
21
+ } finally {
22
+ setLoading(false);
23
+ }
24
+ };
25
+
26
+ useEffect(() => {
27
+ handleRetrieve();
28
+ }, []);
29
+
30
+ if (loading) {
31
+ return <p className="text-slate-500">Loading profile...</p>;
32
+ }
33
+
34
+ if (!user) {
35
+ return (
36
+ <p className="text-slate-600">
37
+ {error || 'No profile data found. Try signing in again.'}
38
+ </p>
39
+ );
40
+ }
41
+
42
+ return (
43
+ <div className="max-w-lg">
44
+ <h1 className="text-2xl font-bold text-slate-800 mb-6">Profile</h1>
45
+
46
+ {error && (
47
+ <p className="mb-4 text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2">
48
+ {error}
49
+ </p>
50
+ )}
51
+
52
+ <div className="bg-white rounded-lg shadow-sm border border-slate-200 divide-y divide-slate-200">
53
+ <div className="px-6 py-4 flex justify-between gap-4">
54
+ <span className="text-sm font-medium text-slate-500">Name</span>
55
+ <span className="text-sm text-slate-800">{user.name}</span>
56
+ </div>
57
+ <div className="px-6 py-4 flex justify-between gap-4">
58
+ <span className="text-sm font-medium text-slate-500">Email</span>
59
+ <span className="text-sm text-slate-800">{user.email}</span>
60
+ </div>
61
+ <div className="px-6 py-4 flex justify-between gap-4">
62
+ <span className="text-sm font-medium text-slate-500">Role</span>
63
+ <span className="text-sm text-slate-800 capitalize">{user.role}</span>
64
+ </div>
65
+ {user.id && (
66
+ <div className="px-6 py-4 flex justify-between gap-4">
67
+ <span className="text-sm font-medium text-slate-500">User ID</span>
68
+ <span className="text-sm text-slate-800 font-mono truncate max-w-[200px]">
69
+ {user.id}
70
+ </span>
71
+ </div>
72
+ )}
73
+ </div>
74
+ </div>
75
+ );
76
+ }
77
+
78
+ export default Profile;
@@ -0,0 +1,133 @@
1
+ import { useState } from 'react';
2
+ import { Link, useNavigate } from 'react-router-dom';
3
+ import { api } from '../api';
4
+
5
+ function Register() {
6
+ const navigate = useNavigate();
7
+ const [name, setName] = useState('');
8
+ const [email, setEmail] = useState('');
9
+ const [password, setPassword] = useState('');
10
+ const [role, setRole] = useState('receptionist');
11
+ const [error, setError] = useState('');
12
+ const [message, setMessage] = useState('');
13
+ const [loading, setLoading] = useState(false);
14
+
15
+ const handleSubmit = async (e) => {
16
+ e.preventDefault();
17
+ setError('');
18
+ setMessage('');
19
+ setLoading(true);
20
+
21
+ try {
22
+ const response = await api.post('/auth/register', {
23
+ name,
24
+ email,
25
+ password,
26
+ role,
27
+ });
28
+ localStorage.setItem('token', response.data.token);
29
+ localStorage.setItem('user', JSON.stringify(response.data.user));
30
+ setMessage('Account created successfully');
31
+ navigate('/dashboard');
32
+ } catch (err) {
33
+ setError(err.response?.data?.message || 'Registration failed');
34
+ } finally {
35
+ setLoading(false);
36
+ }
37
+ };
38
+
39
+ return (
40
+ <div className="min-h-screen flex items-center justify-center px-4 bg-slate-100">
41
+ <div className="w-full max-w-md bg-white rounded-lg shadow-md p-8">
42
+ <p className="text-xs font-semibold uppercase tracking-wider text-teal-600">
43
+ King Faisal Hospital Rwanda
44
+ </p>
45
+ <h1 className="text-2xl font-bold text-slate-800 mb-6 mt-1">Staff registration</h1>
46
+
47
+ {message && (
48
+ <p className="mb-4 text-sm text-green-700 bg-green-50 border border-green-200 rounded px-3 py-2">
49
+ {message}
50
+ </p>
51
+ )}
52
+ {error && (
53
+ <p className="mb-4 text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2">
54
+ {error}
55
+ </p>
56
+ )}
57
+
58
+ <form onSubmit={handleSubmit} className="space-y-4">
59
+ <div>
60
+ <label htmlFor="name" className="block text-sm font-medium text-slate-700 mb-1">
61
+ Full name
62
+ </label>
63
+ <input
64
+ id="name"
65
+ type="text"
66
+ required
67
+ value={name}
68
+ onChange={(e) => setName(e.target.value)}
69
+ className="w-full border border-slate-300 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-teal-500"
70
+ />
71
+ </div>
72
+ <div>
73
+ <label htmlFor="email" className="block text-sm font-medium text-slate-700 mb-1">
74
+ Email
75
+ </label>
76
+ <input
77
+ id="email"
78
+ type="email"
79
+ required
80
+ value={email}
81
+ onChange={(e) => setEmail(e.target.value)}
82
+ className="w-full border border-slate-300 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-teal-500"
83
+ />
84
+ </div>
85
+ <div>
86
+ <label htmlFor="role" className="block text-sm font-medium text-slate-700 mb-1">
87
+ Role
88
+ </label>
89
+ <select
90
+ id="role"
91
+ value={role}
92
+ onChange={(e) => setRole(e.target.value)}
93
+ className="w-full border border-slate-300 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-teal-500"
94
+ >
95
+ <option value="receptionist">Receptionist</option>
96
+ <option value="doctor">Doctor</option>
97
+ </select>
98
+ </div>
99
+ <div>
100
+ <label htmlFor="password" className="block text-sm font-medium text-slate-700 mb-1">
101
+ Password
102
+ </label>
103
+ <input
104
+ id="password"
105
+ type="password"
106
+ required
107
+ minLength={6}
108
+ value={password}
109
+ onChange={(e) => setPassword(e.target.value)}
110
+ className="w-full border border-slate-300 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-teal-500"
111
+ />
112
+ </div>
113
+ <button
114
+ type="submit"
115
+ disabled={loading}
116
+ className="w-full bg-teal-600 text-white font-medium py-2 rounded hover:bg-teal-700 disabled:opacity-50"
117
+ >
118
+ {loading ? 'Creating account...' : 'Register'}
119
+ </button>
120
+ </form>
121
+
122
+ <p className="mt-4 text-sm text-slate-600 text-center">
123
+ Already have an account?{' '}
124
+ <Link to="/login" className="text-teal-600 hover:underline">
125
+ Sign in
126
+ </Link>
127
+ </p>
128
+ </div>
129
+ </div>
130
+ );
131
+ }
132
+
133
+ export default Register;
@@ -0,0 +1,167 @@
1
+ import { useState } from 'react';
2
+ import { api } from '../api';
3
+
4
+ function Report() {
5
+ const [startDate, setStartDate] = useState('');
6
+ const [endDate, setEndDate] = useState('');
7
+ const [data, setData] = useState(null);
8
+ const [error, setError] = useState('');
9
+ const [loading, setLoading] = useState(false);
10
+
11
+ const handleGenerate = async (e) => {
12
+ e.preventDefault();
13
+ setError('');
14
+ setLoading(true);
15
+ setData(null);
16
+
17
+ try {
18
+ const response = await api.get('/reports', {
19
+ params: { startDate, endDate },
20
+ });
21
+ setData(response.data);
22
+ } catch (err) {
23
+ setError(err.response?.data?.message || 'Failed to generate report');
24
+ } finally {
25
+ setLoading(false);
26
+ }
27
+ };
28
+
29
+ return (
30
+ <div className="max-w-6xl">
31
+ <h1 className="text-2xl font-bold text-slate-800 mb-2">Hospital Reports</h1>
32
+ <p className="text-slate-600 mb-6">
33
+ Filter appointments and patients attended between selected dates.
34
+ </p>
35
+
36
+ <form onSubmit={handleGenerate} className="bg-white rounded-lg shadow-md p-6 mb-8 flex flex-wrap gap-4 items-end">
37
+ <div>
38
+ <label className="block text-sm font-medium text-slate-700 mb-1">Start date</label>
39
+ <input
40
+ type="date"
41
+ required
42
+ value={startDate}
43
+ onChange={(e) => setStartDate(e.target.value)}
44
+ className="border border-slate-300 rounded px-3 py-2"
45
+ />
46
+ </div>
47
+ <div>
48
+ <label className="block text-sm font-medium text-slate-700 mb-1">End date</label>
49
+ <input
50
+ type="date"
51
+ required
52
+ value={endDate}
53
+ onChange={(e) => setEndDate(e.target.value)}
54
+ className="border border-slate-300 rounded px-3 py-2"
55
+ />
56
+ </div>
57
+ <button
58
+ type="submit"
59
+ disabled={loading}
60
+ className="bg-teal-600 text-white font-medium px-5 py-2 rounded hover:bg-teal-700 disabled:opacity-50"
61
+ >
62
+ {loading ? 'Generating...' : 'Generate report'}
63
+ </button>
64
+ </form>
65
+
66
+ {error && (
67
+ <p className="mb-4 text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2">
68
+ {error}
69
+ </p>
70
+ )}
71
+
72
+ {data && (
73
+ <div className="space-y-8">
74
+ <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
75
+ <div className="bg-white rounded-lg border border-slate-200 p-5">
76
+ <p className="text-sm text-slate-500">Total appointments</p>
77
+ <p className="text-3xl font-bold text-slate-800 mt-1">{data.summary.totalAppointments}</p>
78
+ </div>
79
+ <div className="bg-white rounded-lg border border-slate-200 p-5">
80
+ <p className="text-sm text-slate-500">Completed</p>
81
+ <p className="text-3xl font-bold text-green-700 mt-1">{data.summary.totalCompleted}</p>
82
+ </div>
83
+ <div className="bg-white rounded-lg border border-slate-200 p-5">
84
+ <p className="text-sm text-slate-500">Cancelled</p>
85
+ <p className="text-3xl font-bold text-red-700 mt-1">{data.summary.totalCancelled}</p>
86
+ </div>
87
+ <div className="bg-white rounded-lg border border-slate-200 p-5">
88
+ <p className="text-sm text-slate-500">Patients attended</p>
89
+ <p className="text-3xl font-bold text-teal-700 mt-1">{data.summary.patientsAttended}</p>
90
+ </div>
91
+ </div>
92
+
93
+ <section>
94
+ <h2 className="text-lg font-semibold text-slate-800 mb-3">
95
+ Appointments ({data.startDate} to {data.endDate})
96
+ </h2>
97
+ {data.appointments.length === 0 ? (
98
+ <p className="text-slate-500 text-sm">No appointments in this period.</p>
99
+ ) : (
100
+ <div className="overflow-x-auto bg-white rounded-lg border border-slate-200">
101
+ <table className="w-full text-sm text-left">
102
+ <thead className="bg-slate-50 text-slate-600">
103
+ <tr>
104
+ <th className="px-4 py-2">Patient</th>
105
+ <th className="px-4 py-2">Doctor</th>
106
+ <th className="px-4 py-2">Date</th>
107
+ <th className="px-4 py-2">Time</th>
108
+ <th className="px-4 py-2">Status</th>
109
+ </tr>
110
+ </thead>
111
+ <tbody className="divide-y divide-slate-200">
112
+ {data.appointments.map((a) => (
113
+ <tr key={a.id}>
114
+ <td className="px-4 py-2">{a.patient_name}</td>
115
+ <td className="px-4 py-2">{a.doctor_name}</td>
116
+ <td className="px-4 py-2">{a.appointment_date}</td>
117
+ <td className="px-4 py-2">{String(a.appointment_time).slice(0, 5)}</td>
118
+ <td className="px-4 py-2 capitalize">{a.status}</td>
119
+ </tr>
120
+ ))}
121
+ </tbody>
122
+ </table>
123
+ </div>
124
+ )}
125
+ </section>
126
+
127
+ <section>
128
+ <h2 className="text-lg font-semibold text-slate-800 mb-3">Patients attended</h2>
129
+ {data.patientsAttended.length === 0 ? (
130
+ <p className="text-slate-500 text-sm">No completed visits in this period.</p>
131
+ ) : (
132
+ <ul className="bg-white rounded-lg border border-slate-200 divide-y divide-slate-200">
133
+ {data.patientsAttended.map((p) => (
134
+ <li key={p.id} className="px-4 py-3 text-sm flex justify-between">
135
+ <span className="font-medium text-slate-800">{p.patient_name}</span>
136
+ <span className="text-slate-500">{p.phone}</span>
137
+ </li>
138
+ ))}
139
+ </ul>
140
+ )}
141
+ </section>
142
+
143
+ <section>
144
+ <h2 className="text-lg font-semibold text-slate-800 mb-3">Medical reports</h2>
145
+ {data.medicalReports.length === 0 ? (
146
+ <p className="text-slate-500 text-sm">No medical reports in this period.</p>
147
+ ) : (
148
+ <div className="space-y-3">
149
+ {data.medicalReports.map((r) => (
150
+ <article key={r.id} className="bg-white rounded-lg border border-slate-200 p-4 text-sm">
151
+ <p className="font-medium text-slate-800">
152
+ {r.patient_name} — Dr. {r.doctor_name} ({r.report_date})
153
+ </p>
154
+ <p className="mt-1 text-slate-600">Diagnosis: {r.diagnosis}</p>
155
+ <p className="mt-1 text-slate-600">Prescription: {r.prescription}</p>
156
+ </article>
157
+ ))}
158
+ </div>
159
+ )}
160
+ </section>
161
+ </div>
162
+ )}
163
+ </div>
164
+ );
165
+ }
166
+
167
+ export default Report;
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+ import tailwindcss from '@tailwindcss/vite';
4
+
5
+ export default defineConfig({
6
+ plugins: [react(), tailwindcss()],
7
+ server: {
8
+ port: 5173,
9
+ },
10
+ });
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "hospital-faisal",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "type": "commonjs"
13
+ }