mango-cms 0.1.1 → 0.1.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/cli.js CHANGED
@@ -10,6 +10,64 @@ const AdmZip = require('adm-zip');
10
10
 
11
11
  const program = new Command();
12
12
 
13
+ // Helper function to download and extract src.zip
14
+ async function ensureSrcExists(mangoCmsRoot) {
15
+ const srcDir = path.join(mangoCmsRoot, 'src');
16
+ if (!fs.existsSync(srcDir)) {
17
+ console.log('Downloading Mango CMS source files...');
18
+ const response = await axios({
19
+ method: 'get',
20
+ url: 'https://mango-cms.s3.amazonaws.com/src.zip',
21
+ responseType: 'arraybuffer'
22
+ });
23
+
24
+ const tempZipPath = path.join(mangoCmsRoot, 'src.zip');
25
+ fs.writeFileSync(tempZipPath, response.data);
26
+
27
+ console.log('Extracting source files...');
28
+ const zip = new AdmZip(tempZipPath);
29
+ zip.extractAllTo(mangoCmsRoot, true);
30
+
31
+ // Clean up the zip file
32
+ fs.unlinkSync(tempZipPath);
33
+ console.log('Source files installed successfully.');
34
+ }
35
+ }
36
+
37
+ // Helper function to validate and prompt for license if needed
38
+ async function ensureLicenseExists(configPath) {
39
+ let settings = { license: null };
40
+
41
+ try {
42
+ if (fs.existsSync(configPath)) {
43
+ settings = JSON.parse(fs.readFileSync(configPath, 'utf8'));
44
+ }
45
+ } catch (error) {
46
+ console.log('Error reading settings file:', error.message);
47
+ }
48
+
49
+ if (!settings.license) {
50
+ const answer = await inquirer.prompt([
51
+ {
52
+ type: 'input',
53
+ name: 'license',
54
+ message: 'Enter your license key:',
55
+ validate: input => {
56
+ if (!input) return 'License key is required';
57
+ if (input !== 'admin') return 'Invalid license key';
58
+ return true;
59
+ }
60
+ }
61
+ ]);
62
+
63
+ settings.license = answer.license;
64
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
65
+ fs.writeFileSync(configPath, JSON.stringify(settings, null, 2));
66
+ }
67
+
68
+ return settings.license;
69
+ }
70
+
13
71
  program
14
72
  .name('mango')
15
73
  .description('Mango CMS CLI');
@@ -44,28 +102,7 @@ program
44
102
  ]);
45
103
 
46
104
  // First, handle the src.zip download if needed
47
- const mangoCmsRoot = __dirname;
48
- const srcDir = path.join(mangoCmsRoot, 'src');
49
-
50
- if (!fs.existsSync(srcDir)) {
51
- console.log('Downloading Mango CMS source files...');
52
- const response = await axios({
53
- method: 'get',
54
- url: 'https://mango-cms.s3.amazonaws.com/src.zip',
55
- responseType: 'arraybuffer'
56
- });
57
-
58
- const tempZipPath = path.join(mangoCmsRoot, 'src.zip');
59
- fs.writeFileSync(tempZipPath, response.data);
60
-
61
- console.log('Extracting source files...');
62
- const zip = new AdmZip(tempZipPath);
63
- zip.extractAllTo(mangoCmsRoot, true);
64
-
65
- // Clean up the zip file
66
- fs.unlinkSync(tempZipPath);
67
- console.log('Source files installed successfully.');
68
- }
105
+ await ensureSrcExists(__dirname);
69
106
 
70
107
  // Now handle the project creation
71
108
  const projectDir = path.join(process.cwd(), answers.projectName);
@@ -80,7 +117,7 @@ program
80
117
  const configDir = path.join(projectDir, 'config');
81
118
 
82
119
  // Create or update settings.json
83
- const settingsPath = path.join(configDir, 'settings.json');
120
+ const settingsPath = path.join(configDir, 'config/settings.json');
84
121
  const settings = {
85
122
  license: answers.license
86
123
  };
@@ -90,7 +127,8 @@ program
90
127
  ✨ Project ${answers.projectName} created successfully!
91
128
  To get started:
92
129
  cd ${answers.projectName}
93
- mango start
130
+ npm install
131
+ npm mango start
94
132
  `);
95
133
  } catch (error) {
96
134
  console.error('Error creating project:', error.message);
@@ -101,13 +139,20 @@ To get started:
101
139
  program
102
140
  .command('start')
103
141
  .description('Start the Mango CMS in watch mode')
104
- .action(() => {
142
+ .action(async () => {
105
143
  try {
144
+
145
+ // Check for license in settings.json
146
+ const settingsPath = path.join(process.cwd(), 'config/config/settings.json');
147
+ await ensureLicenseExists(settingsPath);
148
+
149
+ // Ensure src exists
150
+ await ensureSrcExists(__dirname);
151
+
106
152
  // Path to @mango-cms/core inside node_modules
107
153
  const cmsPackagePath = path.resolve(__dirname);
108
154
  // User's project root (where they run "mango start")
109
- // const userProjectRoot = '../../'
110
- const userProjectRoot = '/Users/coltonneifert/Sites/test-2'
155
+ const userProjectRoot = process.cwd();
111
156
 
112
157
  console.log(`Starting Mango CMS...`);
113
158
  console.log(`CMS package located at: ${cmsPackagePath}`);
@@ -122,8 +167,6 @@ program
122
167
  stdio: 'inherit',
123
168
  env: {
124
169
  ...process.env,
125
- // NODE_OPTIONS: '--trace-warnings',
126
- // PROJECT_CONFIG: configDir,
127
170
  NODE_PATH: path.resolve(cmsPackagePath, 'node_modules'),
128
171
  MANGO_ROOT: cmsPackagePath,
129
172
  PROJECT_ROOT: userProjectRoot
@@ -1,4 +1,4 @@
1
- import { readEntries, updateEntry } from "../../mango/src/cms/1. build/libraries/mongo"
1
+ import { readEntries, updateEntry } from "@cms/1. build/libraries/mongo"
2
2
 
3
3
  export default {
4
4
  fields: {
@@ -0,0 +1,8 @@
1
+ {
2
+ "scripts": {
3
+ "mango": "mango"
4
+ },
5
+ "dependencies": {
6
+ "mango-cms": "^0.1.1"
7
+ }
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mango-cms",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "main": "index.js",
5
5
  "author": "Colton Neifert",
6
6
  "license": "ISC",
@@ -1,206 +0,0 @@
1
- // import CMS from '../../../mango/src/cms' (for use like {address: CMS.fields.Address()})
2
- import fields from '@cms/1. build/fields'
3
- import { readEntries, readEntry } from '../../../mango/src/cms/1. build/libraries/mongo'
4
-
5
- const billing = {
6
- fields: {
7
- paymentId: String,
8
- firstName: { type: String, search: { enabled: true, weight: 5 } },
9
- lastName: { type: String, search: { enabled: true, weight: 5 } },
10
- phoneNumber: String,
11
- address: fields.Address(),
12
- payment: {
13
- fields: {
14
- creditCard: {
15
- fields: {
16
- cardNumber: String,
17
- cardType: String,
18
- expirationDate: String,
19
- }
20
- },
21
- bankAccount: {
22
- fields: {
23
- accountNumber: String,
24
- accountType: String,
25
- echeckType: String,
26
- nameOnAccount: String,
27
- routingNumber: String
28
- }
29
- }
30
- }
31
- }
32
- }
33
- }
34
-
35
- const Items = {
36
- name: 'items',
37
- singular: 'item',
38
- fields: {
39
- price: { type: 'Int' },
40
- stock: { type: 'Int' },
41
- description: fields.PlainText(),
42
- },
43
- hooks: {
44
- sold({ item }) {
45
- console.log('sold', item.title)
46
- },
47
- addedToCart({ item }) {
48
- console.log('addedToCart', item.title)
49
- },
50
- removedFromCart({ item }) {
51
- console.log('removedFromCart', item.title)
52
- }
53
- }
54
- }
55
-
56
- const Discounts = {
57
- name: 'discounts',
58
- singular: 'discount',
59
- permissions: {
60
- public: ['create', 'read']
61
- },
62
- fields: {
63
- type: fields.Select({ options: ['coupon', 'sale'], required: true }),
64
- code: { required: true, translateInput: i => i.toLowerCase() },
65
- limitations: {
66
- fields: {
67
- items: fields.Relationship({ collection: 'item' }),
68
- perCustomer: 'Int',
69
- totalUses: 'Int',
70
- perOrder: 'Int',
71
- quantity: 'Int',
72
- // remainingUses: {
73
- // computed: doc => doc.limitations.totalUses ? /* Get times used and subtract from total uses */ : null
74
- // }
75
- }
76
- },
77
- freeShipping: Boolean,
78
- discount: {
79
- inputExample: '$12.50 or 50% etc.',
80
- inputType: String,
81
- validate: input => ({ valid: (!!input.match(/\$[0-9]+/) || input.match(/[0-9]\%+/)) ? true : false, response: 'Should be formatted like `100%` or `$12.50`' }),
82
- translateInput: input => ({
83
- type: !!input.match(/\$[0-9]+/) ? 'fixed' : 'percentage',
84
- value: !!input.match(/\$[0-9]+/) ? input.match(/\$\d+(?:\.\d+)?/)[0].replace('$', '') : input.match(/(\d+|\d+[.,]\d{1,2})(?=\s*%)/)[0].replace('%', '')
85
- }),
86
- fields: {
87
- type: String,
88
- value: 'Float'
89
- }
90
- }
91
- }
92
- }
93
-
94
-
95
- const Carts = {
96
- name: 'carts',
97
- singular: 'cart',
98
- permissions: {
99
- public: ['create', 'read', 'update']
100
- },
101
- fields: {
102
-
103
- title: { required: false },
104
-
105
- transactionId: String,
106
- finalized: Boolean,
107
- completed: Boolean,
108
- completedDate: fields.Timestamp(),
109
- cartItems: [{
110
- fields: {
111
- quantity: 'Int',
112
- discount: 'Float',
113
- item: fields.Relationship({ collection: 'item', single: true }),
114
- }
115
- }],
116
- coupons: fields.Relationship({ collection: 'discount' }),
117
-
118
- customerId: String,
119
- billing,
120
- shipping: {
121
- fields: {
122
- method: String,
123
- price: String,
124
- addressId: String,
125
- firstName: String,
126
- lastName: String,
127
- phoneNumber: String,
128
- address: fields.Address(),
129
- free: { type: Boolean, computed: doc => doc?.coupons?.find(c => c.freeShipping) }
130
- }
131
- },
132
-
133
- price: {
134
- fields: {
135
- subtotal: 'Float',
136
- discount: 'Float',
137
- total: 'Float',
138
- },
139
- computed: async doc => {
140
-
141
- let subtotal = Number(doc.cartItems?.reduce((a, i) => a + ((i.item?.price || 0) * i.quantity), 0)) || 0
142
- let shipping = doc?.shipping?.price || 0
143
-
144
- let discount = 0
145
-
146
- if (doc?.coupons?.length) {
147
- let coupon = doc?.coupons?.[0]
148
- if (coupon?.limitations?.items) {
149
- for (let item of doc.cartItems) {
150
- if (coupon?.limitations?.items?.find(i => i.id == item.item?.id)) {
151
- if (coupon.discount.type == 'fixed') {
152
- discount += (item.quantity * coupon.discount.value)
153
- } else {
154
- discount += ((item.quantity * item.item.price) * (Number(coupon.discount.value) / 100))
155
- console.log('discount', discount)
156
- }
157
- }
158
- }
159
- } else {
160
- if (coupon.discount.type == 'fixed') {
161
- discount = Number(coupon.discount.value > subtotal ? subtotal : coupon.discount.value)
162
- } else {
163
- discount = Number(subtotal * (Number(coupon.discount.value) / 100))
164
- }
165
- }
166
- }
167
-
168
- let activeSales = await readEntries({ collection: 'discounts', search: { type: 'sale', startDate: { $lt: new Date() }, endDate: { $gt: new Date() } } })
169
-
170
- if (activeSales?.length) {
171
- for (let item of doc.cartItems) {
172
- for (let sale of activeSales.sort((a, b) => b.discount.value < a.discount.value ? 1 : -1)) {
173
- let saleApplies = sale?.limitations?.items?.some(i => i == item.item?.id) || !sale?.limitations?.items?.length
174
- if (saleApplies) {
175
- if (sale.discount.type == 'fixed') {
176
- item.discount = (item.quantity * sale.discount.value)
177
- } else {
178
- item.discount = Number((item.quantity * item.item.price) * (Number(sale.discount.value) / 100))
179
- }
180
- }
181
- }
182
- }
183
- discount = Number(doc.cartItems?.reduce((a, i) => a + i.discount, 0))
184
- }
185
-
186
- let total = (subtotal + shipping - discount) || 0
187
-
188
- return {
189
- subtotal,
190
- discount,
191
- total,
192
- }
193
- }
194
- }
195
-
196
- },
197
- }
198
-
199
- export default {
200
- name: 'mangoStand',
201
- collections: [
202
- Items,
203
- Carts,
204
- Discounts,
205
- ],
206
- }