@jspreadsheet/install 1.0.1 → 1.1.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.
- package/index.js +459 -326
- package/package.json +23 -21
package/index.js
CHANGED
|
@@ -1,326 +1,459 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const { execSync } = require('child_process');
|
|
5
|
-
const https = require('https');
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
{
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
console.log(
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
console.
|
|
298
|
-
console.
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
console.
|
|
312
|
-
console.
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { select, input, Separator } = require('@inquirer/prompts');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
5
|
+
const https = require('https');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
// Colors — use yoctocolors-cjs (transitive dep of @inquirer)
|
|
10
|
+
let c;
|
|
11
|
+
try {
|
|
12
|
+
c = require('yoctocolors-cjs');
|
|
13
|
+
} catch {
|
|
14
|
+
const esc = (code) => (s) => `\x1b[${code[0]}m${s}\x1b[${code[1]}m`;
|
|
15
|
+
c = {
|
|
16
|
+
bold: esc([1, 22]), dim: esc([2, 22]), italic: esc([3, 23]),
|
|
17
|
+
green: esc([32, 39]), red: esc([31, 39]), yellow: esc([33, 39]),
|
|
18
|
+
blue: esc([34, 39]), cyan: esc([36, 39]), gray: esc([90, 39]),
|
|
19
|
+
magenta: esc([35, 39]),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ─── Constants ───────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
const PACKAGES = {
|
|
26
|
+
pro: {
|
|
27
|
+
vanilla: 'jspreadsheet',
|
|
28
|
+
react: '@jspreadsheet/react',
|
|
29
|
+
vue: '@jspreadsheet/vue',
|
|
30
|
+
angular: 'jspreadsheet',
|
|
31
|
+
},
|
|
32
|
+
ce: {
|
|
33
|
+
vanilla: 'jspreadsheet-ce',
|
|
34
|
+
react: '@jspreadsheet-ce/react',
|
|
35
|
+
vue: '@jspreadsheet-ce/vue',
|
|
36
|
+
angular: 'jspreadsheet-ce',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const VALID_EDITIONS = ['pro', 'ce'];
|
|
41
|
+
const VALID_FRAMEWORKS = ['react', 'vue', 'angular', 'vanilla'];
|
|
42
|
+
|
|
43
|
+
// ─── Arg Parsing ─────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
function parseArgs() {
|
|
46
|
+
const args = process.argv.slice(2);
|
|
47
|
+
const flags = {};
|
|
48
|
+
for (let i = 0; i < args.length; i++) {
|
|
49
|
+
const arg = args[i];
|
|
50
|
+
if ((arg === '--edition' || arg === '-e') && args[i + 1]) {
|
|
51
|
+
flags.edition = args[++i].toLowerCase();
|
|
52
|
+
} else if ((arg === '--framework' || arg === '-f') && args[i + 1]) {
|
|
53
|
+
flags.framework = args[++i].toLowerCase();
|
|
54
|
+
} else if (arg === '--email' && args[i + 1]) {
|
|
55
|
+
flags.email = args[++i];
|
|
56
|
+
} else if (arg === '--skip-registration' || arg === '--no-register') {
|
|
57
|
+
flags.skipRegistration = true;
|
|
58
|
+
} else if (arg === '--dry-run') {
|
|
59
|
+
flags.dryRun = true;
|
|
60
|
+
} else if (arg === '--help' || arg === '-h') {
|
|
61
|
+
flags.help = true;
|
|
62
|
+
} else if (arg === '--version' || arg === '-v') {
|
|
63
|
+
flags.version = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return flags;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function printHelp() {
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log(` ${c.bold('Jspreadsheet Installer')}`);
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log(' Usage:');
|
|
74
|
+
console.log(` ${c.dim('$')} npx @jspreadsheet/install ${c.dim('[options]')}`);
|
|
75
|
+
console.log('');
|
|
76
|
+
console.log(' Options:');
|
|
77
|
+
console.log(` ${c.cyan('--edition, -e')} ${c.dim('<pro|ce>')} Edition to install`);
|
|
78
|
+
console.log(` ${c.cyan('--framework, -f')} ${c.dim('<name>')} Framework: react, vue, angular, vanilla`);
|
|
79
|
+
console.log(` ${c.cyan('--email')} ${c.dim('<email>')} Register for free trial (Pro only)`);
|
|
80
|
+
console.log(` ${c.cyan('--skip-registration')} Skip registration prompt (Pro only)`);
|
|
81
|
+
console.log(` ${c.cyan('--dry-run')} Preview the flow without installing`);
|
|
82
|
+
console.log(` ${c.cyan('--version, -v')} Show version number`);
|
|
83
|
+
console.log(` ${c.cyan('--help, -h')} Show this help message`);
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log(' Examples:');
|
|
86
|
+
console.log(` ${c.dim('$')} npx @jspreadsheet/install --edition pro --framework react`);
|
|
87
|
+
console.log(` ${c.dim('$')} npx @jspreadsheet/install -e ce -f vanilla`);
|
|
88
|
+
console.log(` ${c.dim('$')} npx @jspreadsheet/install --edition pro --email dev@co.com`);
|
|
89
|
+
console.log('');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ─── Display Helpers ─────────────────────────────────────────────────
|
|
93
|
+
|
|
94
|
+
function printBanner() {
|
|
95
|
+
console.log('');
|
|
96
|
+
console.log(` ${c.cyan('┌')} ${c.bold('Jspreadsheet Installer')}`);
|
|
97
|
+
console.log(` ${c.cyan('│')}`);
|
|
98
|
+
console.log(` ${c.cyan('│')} The JavaScript data grid for building`);
|
|
99
|
+
console.log(` ${c.cyan('│')} enterprise-grade spreadsheet applications.`);
|
|
100
|
+
console.log(` ${c.cyan('└')}`);
|
|
101
|
+
console.log('');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function printFeatureComparison() {
|
|
105
|
+
const W = 52;
|
|
106
|
+
const b = c.gray('│');
|
|
107
|
+
const strip = (s) => s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
108
|
+
const row = (content) => {
|
|
109
|
+
const visible = strip(content).length;
|
|
110
|
+
const pad = Math.max(0, W - visible);
|
|
111
|
+
return ` ${b}${content}${' '.repeat(pad)}${b}`;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const lines = [
|
|
115
|
+
c.gray(` ┌${'─'.repeat(W)}┐`),
|
|
116
|
+
row(''),
|
|
117
|
+
row(` ${c.bold('Pro')} ${c.dim('— Full-featured commercial spreadsheet')}`),
|
|
118
|
+
row(` ${c.green('✓')} 500+ Excel-compatible formulas`),
|
|
119
|
+
row(` ${c.green('✓')} XLSX, CSV & clipboard import/export`),
|
|
120
|
+
row(` ${c.green('✓')} AI integration & real-time collaboration`),
|
|
121
|
+
row(` ${c.green('✓')} Toolbar, context menu & 30+ plugins`),
|
|
122
|
+
row(` ${c.green('✓')} Persistence, history & cross-sheet refs`),
|
|
123
|
+
row(` ${c.green('✓')} Priority support & regular updates`),
|
|
124
|
+
row(` ${c.dim('Free on localhost · 30-day free trial')}`),
|
|
125
|
+
row(''),
|
|
126
|
+
row(` ${c.bold('CE')} ${c.dim('— Community Edition (MIT license)')}`),
|
|
127
|
+
row(` ${c.green('✓')} Core spreadsheet rendering & editing`),
|
|
128
|
+
row(` ${c.green('✓')} Basic formulas (SUM, AVG, etc.)`),
|
|
129
|
+
row(` ${c.green('✓')} CSV import/export`),
|
|
130
|
+
row(` ${c.green('✓')} Fully open-source, no watermark`),
|
|
131
|
+
row(` ${c.dim('Community support via GitHub issues')}`),
|
|
132
|
+
row(''),
|
|
133
|
+
c.gray(` └${'─'.repeat(W)}┘`),
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
for (const line of lines) {
|
|
137
|
+
console.log(line);
|
|
138
|
+
}
|
|
139
|
+
console.log('');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function printSummary(edition, framework, license, dryRun) {
|
|
143
|
+
const isPro = edition === 'pro';
|
|
144
|
+
const mainPkg = isPro ? 'jspreadsheet' : 'jspreadsheet-ce';
|
|
145
|
+
|
|
146
|
+
console.log('');
|
|
147
|
+
const label = dryRun ? 'ready to install' : 'installed';
|
|
148
|
+
console.log(` ${c.green('◇')} ${isPro ? 'Jspreadsheet Pro' : 'Jspreadsheet CE'} ${label}`);
|
|
149
|
+
console.log(` ${c.dim('│')}`);
|
|
150
|
+
console.log(` ${c.dim('│')} Edition: ${c.bold(isPro ? 'Pro' : 'Community (MIT)')}`);
|
|
151
|
+
|
|
152
|
+
if (isPro) {
|
|
153
|
+
if (license) {
|
|
154
|
+
console.log(` ${c.dim('│')} License: ${c.green(license)}`);
|
|
155
|
+
} else {
|
|
156
|
+
console.log(` ${c.dim('│')} Mode: ${c.dim('evaluation — free on localhost')}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
console.log(` ${c.dim('│')}`);
|
|
161
|
+
console.log(` ${c.dim('│')} ${c.bold('Getting started:')}`);
|
|
162
|
+
console.log(` ${c.dim('│')}`);
|
|
163
|
+
|
|
164
|
+
if (isPro) {
|
|
165
|
+
if (framework === 'react') {
|
|
166
|
+
console.log(` ${c.dim('│')} ${c.cyan("import { Spreadsheet, Worksheet } from '@jspreadsheet/react';")}`);
|
|
167
|
+
console.log(` ${c.dim('│')} ${c.cyan(`import jspreadsheet from '${mainPkg}';`)}`);
|
|
168
|
+
console.log(` ${c.dim('│')}`);
|
|
169
|
+
console.log(` ${c.dim('│')} ${c.cyan(`jspreadsheet.setLicense('${license || 'evaluation'}');`)}`);
|
|
170
|
+
} else if (framework === 'vue') {
|
|
171
|
+
console.log(` ${c.dim('│')} ${c.cyan("import { Spreadsheet, Worksheet } from '@jspreadsheet/vue';")}`);
|
|
172
|
+
console.log(` ${c.dim('│')} ${c.cyan(`import jspreadsheet from '${mainPkg}';`)}`);
|
|
173
|
+
console.log(` ${c.dim('│')}`);
|
|
174
|
+
console.log(` ${c.dim('│')} ${c.cyan(`jspreadsheet.setLicense('${license || 'evaluation'}');`)}`);
|
|
175
|
+
} else if (framework === 'angular') {
|
|
176
|
+
console.log(` ${c.dim('│')} ${c.cyan(`import jspreadsheet from '${mainPkg}';`)}`);
|
|
177
|
+
console.log(` ${c.dim('│')}`);
|
|
178
|
+
console.log(` ${c.dim('│')} ${c.cyan(`jspreadsheet.setLicense('${license || 'evaluation'}');`)}`);
|
|
179
|
+
console.log(` ${c.dim('│')} ${c.cyan(`jspreadsheet(divRef, { worksheets: [{ minDimensions: [10, 10] }] });`)}`);
|
|
180
|
+
console.log(` ${c.dim('│')}`);
|
|
181
|
+
console.log(` ${c.dim('│')} ${c.dim('Use CUSTOM_ELEMENTS_SCHEMA or call jspreadsheet in ngAfterViewInit')}`);
|
|
182
|
+
} else {
|
|
183
|
+
console.log(` ${c.dim('│')} ${c.cyan(`import jspreadsheet from '${mainPkg}';`)}`);
|
|
184
|
+
console.log(` ${c.dim('│')}`);
|
|
185
|
+
console.log(` ${c.dim('│')} ${c.cyan(`jspreadsheet.setLicense('${license || 'evaluation'}');`)}`);
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
if (framework === 'react') {
|
|
189
|
+
console.log(` ${c.dim('│')} ${c.cyan("import { Spreadsheet, Worksheet } from '@jspreadsheet-ce/react';")}`);
|
|
190
|
+
} else if (framework === 'vue') {
|
|
191
|
+
console.log(` ${c.dim('│')} ${c.cyan("import { Spreadsheet, Worksheet } from '@jspreadsheet-ce/vue';")}`);
|
|
192
|
+
} else if (framework === 'angular') {
|
|
193
|
+
console.log(` ${c.dim('│')} ${c.cyan(`import jspreadsheet from '${mainPkg}';`)}`);
|
|
194
|
+
console.log(` ${c.dim('│')}`);
|
|
195
|
+
console.log(` ${c.dim('│')} ${c.cyan(`jspreadsheet(divRef, { worksheets: [{ minDimensions: [10, 10] }] });`)}`);
|
|
196
|
+
console.log(` ${c.dim('│')}`);
|
|
197
|
+
console.log(` ${c.dim('│')} ${c.dim('Use CUSTOM_ELEMENTS_SCHEMA or call jspreadsheet in ngAfterViewInit')}`);
|
|
198
|
+
} else {
|
|
199
|
+
console.log(` ${c.dim('│')} ${c.cyan(`import jspreadsheet from '${mainPkg}';`)}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
console.log(` ${c.dim('│')}`);
|
|
204
|
+
console.log(` ${c.dim('│')} ${c.bold('Next steps:')}`);
|
|
205
|
+
console.log(` ${c.dim('│')} → Start building: ${c.blue('npm run dev')}`);
|
|
206
|
+
|
|
207
|
+
if (isPro) {
|
|
208
|
+
console.log(` ${c.dim('│')} → Docs: ${c.blue('https://jspreadsheet.com/docs')}`);
|
|
209
|
+
if (!license) {
|
|
210
|
+
console.log(` ${c.dim('│')} → Get a license: ${c.blue('https://jspreadsheet.com/me')}`);
|
|
211
|
+
}
|
|
212
|
+
console.log(` ${c.dim('│')} → Pricing: ${c.blue('https://jspreadsheet.com/pricing')}`);
|
|
213
|
+
} else {
|
|
214
|
+
console.log(` ${c.dim('│')} → Docs: ${c.blue('https://bossanova.uk/jspreadsheet/docs')}`);
|
|
215
|
+
console.log(` ${c.dim('│')}`);
|
|
216
|
+
console.log(` ${c.dim('│')} Need advanced formulas, import/export, or more?`);
|
|
217
|
+
console.log(` ${c.dim('│')} Try ${c.bold('Jspreadsheet Pro')}: ${c.blue('https://jspreadsheet.com')}`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
console.log(` ${c.dim('│')}`);
|
|
221
|
+
console.log(` ${c.dim('└')} Happy building!`);
|
|
222
|
+
console.log('');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ─── Utilities ───────────────────────────────────────────────────────
|
|
226
|
+
|
|
227
|
+
function detectPackageManager() {
|
|
228
|
+
const cwd = process.cwd();
|
|
229
|
+
if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn';
|
|
230
|
+
if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';
|
|
231
|
+
if (fs.existsSync(path.join(cwd, 'bun.lockb'))) return 'bun';
|
|
232
|
+
return 'npm';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function getInstallCommand(pkg) {
|
|
236
|
+
const pm = detectPackageManager();
|
|
237
|
+
if (pm === 'yarn') return `yarn add ${pkg}`;
|
|
238
|
+
if (pm === 'pnpm') return `pnpm add ${pkg}`;
|
|
239
|
+
if (pm === 'bun') return `bun add ${pkg}`;
|
|
240
|
+
return `npm install ${pkg}`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function registerEmail(email) {
|
|
244
|
+
return new Promise((resolve) => {
|
|
245
|
+
const data = JSON.stringify({ email });
|
|
246
|
+
|
|
247
|
+
const options = {
|
|
248
|
+
hostname: 'jspreadsheet.com',
|
|
249
|
+
port: 443,
|
|
250
|
+
path: '/me/register',
|
|
251
|
+
method: 'POST',
|
|
252
|
+
headers: {
|
|
253
|
+
'Content-Type': 'application/json',
|
|
254
|
+
'Content-Length': Buffer.byteLength(data),
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const req = https.request(options, (res) => {
|
|
259
|
+
let body = '';
|
|
260
|
+
res.on('data', (chunk) => body += chunk);
|
|
261
|
+
res.on('end', () => {
|
|
262
|
+
try {
|
|
263
|
+
const result = JSON.parse(body);
|
|
264
|
+
resolve(result.license || null);
|
|
265
|
+
} catch (e) {
|
|
266
|
+
resolve(null);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
req.on('error', () => resolve(null));
|
|
272
|
+
req.write(data);
|
|
273
|
+
req.end();
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// ─── Main ────────────────────────────────────────────────────────────
|
|
278
|
+
|
|
279
|
+
async function main() {
|
|
280
|
+
const flags = parseArgs();
|
|
281
|
+
|
|
282
|
+
// Version
|
|
283
|
+
if (flags.version) {
|
|
284
|
+
const { version } = require('./package.json');
|
|
285
|
+
console.log(version);
|
|
286
|
+
process.exit(0);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Help
|
|
290
|
+
if (flags.help) {
|
|
291
|
+
printHelp();
|
|
292
|
+
process.exit(0);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Validate flags
|
|
296
|
+
if (flags.edition && !VALID_EDITIONS.includes(flags.edition)) {
|
|
297
|
+
console.error(`\n ${c.red('✗')} Invalid edition: ${flags.edition}`);
|
|
298
|
+
console.error(` ${c.dim('Valid options: pro, ce')}\n`);
|
|
299
|
+
process.exit(1);
|
|
300
|
+
}
|
|
301
|
+
if (flags.framework && !VALID_FRAMEWORKS.includes(flags.framework)) {
|
|
302
|
+
console.error(`\n ${c.red('✗')} Invalid framework: ${flags.framework}`);
|
|
303
|
+
console.error(` ${c.dim('Valid options: react, vue, angular, vanilla')}\n`);
|
|
304
|
+
process.exit(1);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const isInteractive = process.stdin.isTTY && !process.env.CI;
|
|
308
|
+
|
|
309
|
+
// Non-interactive with missing required flags
|
|
310
|
+
if (!isInteractive && !flags.edition) {
|
|
311
|
+
console.error(`\n ${c.red('✗')} --edition is required in non-interactive mode`);
|
|
312
|
+
console.error(` ${c.dim('Run with --help for usage info')}\n`);
|
|
313
|
+
process.exit(1);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ── Banner ──
|
|
317
|
+
printBanner();
|
|
318
|
+
|
|
319
|
+
// ── Step 1: Edition ──
|
|
320
|
+
let edition = flags.edition;
|
|
321
|
+
if (!edition) {
|
|
322
|
+
printFeatureComparison();
|
|
323
|
+
edition = await select({
|
|
324
|
+
message: 'Which edition would you like to install?',
|
|
325
|
+
choices: [
|
|
326
|
+
{
|
|
327
|
+
name: `Pro ${c.dim('— Commercial, full-featured')}`,
|
|
328
|
+
value: 'pro',
|
|
329
|
+
short: 'Pro',
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
name: `CE ${c.dim('— Community Edition, MIT license')}`,
|
|
333
|
+
value: 'ce',
|
|
334
|
+
short: 'CE',
|
|
335
|
+
},
|
|
336
|
+
],
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// ── Step 2: Framework ──
|
|
341
|
+
let framework = flags.framework;
|
|
342
|
+
if (!framework) {
|
|
343
|
+
if (!isInteractive) {
|
|
344
|
+
framework = 'vanilla';
|
|
345
|
+
console.log(` ${c.dim('No --framework specified, defaulting to vanilla')}`);
|
|
346
|
+
} else {
|
|
347
|
+
console.log('');
|
|
348
|
+
framework = await select({
|
|
349
|
+
message: 'Select your framework',
|
|
350
|
+
choices: [
|
|
351
|
+
{ name: 'React', value: 'react' },
|
|
352
|
+
{ name: 'Vue', value: 'vue' },
|
|
353
|
+
{ name: 'Angular', value: 'angular' },
|
|
354
|
+
{ name: 'Vanilla JavaScript', value: 'vanilla' },
|
|
355
|
+
new Separator(),
|
|
356
|
+
{ name: `Other ${c.dim('(vanilla JS package)')}`, value: 'vanilla' },
|
|
357
|
+
],
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const pkg = PACKAGES[edition][framework];
|
|
363
|
+
|
|
364
|
+
// ── Step 3: Registration (Pro only) ──
|
|
365
|
+
let license = null;
|
|
366
|
+
|
|
367
|
+
if (edition === 'pro' && !flags.skipRegistration) {
|
|
368
|
+
if (flags.email) {
|
|
369
|
+
// Non-interactive registration
|
|
370
|
+
console.log(` ${c.dim('Registering')} ${flags.email}${c.dim('...')}`);
|
|
371
|
+
license = await registerEmail(flags.email);
|
|
372
|
+
if (license) {
|
|
373
|
+
console.log(` ${c.green('✓')} License key generated`);
|
|
374
|
+
} else {
|
|
375
|
+
console.log(` ${c.yellow('!')} Could not register. You can register later at:`);
|
|
376
|
+
console.log(` ${c.blue('https://jspreadsheet.com/me')}`);
|
|
377
|
+
}
|
|
378
|
+
} else if (isInteractive) {
|
|
379
|
+
console.log('');
|
|
380
|
+
const support = await select({
|
|
381
|
+
message: 'Get a free 30-day trial license for production deployment and support?',
|
|
382
|
+
choices: [
|
|
383
|
+
{
|
|
384
|
+
name: `Yes, register with my email`,
|
|
385
|
+
value: 'register',
|
|
386
|
+
description: 'Get a license key for deployment + priority support',
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
name: `No thanks, continue in evaluation mode`,
|
|
390
|
+
value: 'skip',
|
|
391
|
+
description: 'Free on localhost — register anytime later for production',
|
|
392
|
+
},
|
|
393
|
+
],
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
if (support === 'register') {
|
|
397
|
+
console.log('');
|
|
398
|
+
const email = await input({
|
|
399
|
+
message: 'Your email',
|
|
400
|
+
required: true,
|
|
401
|
+
validate: (value) => {
|
|
402
|
+
if (!value) return 'Email is required';
|
|
403
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
|
|
404
|
+
return 'Please enter a valid email address';
|
|
405
|
+
}
|
|
406
|
+
return true;
|
|
407
|
+
},
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
console.log(`\n ${c.dim('Registering...')}`);
|
|
411
|
+
license = await registerEmail(email);
|
|
412
|
+
|
|
413
|
+
if (license) {
|
|
414
|
+
console.log(` ${c.green('✓')} Done! Your license key has been generated.`);
|
|
415
|
+
} else {
|
|
416
|
+
console.log(` ${c.yellow('!')} Could not register at this time.`);
|
|
417
|
+
console.log(` ${c.dim('You can register later at:')} ${c.blue('https://jspreadsheet.com/me')}`);
|
|
418
|
+
console.log(` ${c.dim('Continuing with evaluation mode.')}`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// ── Step 4: Install ──
|
|
425
|
+
const cmd = getInstallCommand(pkg);
|
|
426
|
+
|
|
427
|
+
console.log('');
|
|
428
|
+
if (flags.dryRun) {
|
|
429
|
+
console.log(` ${c.yellow('●')} Dry run — would install ${c.bold(pkg)}`);
|
|
430
|
+
console.log(` ${c.dim('$')} ${c.dim(cmd)}`);
|
|
431
|
+
} else {
|
|
432
|
+
console.log(` ${c.cyan('●')} Installing ${c.bold(pkg)}...`);
|
|
433
|
+
console.log(` ${c.dim('$')} ${c.dim(cmd)}`);
|
|
434
|
+
console.log('');
|
|
435
|
+
|
|
436
|
+
try {
|
|
437
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
438
|
+
} catch (e) {
|
|
439
|
+
console.error(`\n ${c.red('✗')} Installation failed. Try running manually:`);
|
|
440
|
+
console.error(` ${c.dim('$')} ${cmd}\n`);
|
|
441
|
+
process.exit(1);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// ── Step 5: Summary ──
|
|
446
|
+
printSummary(edition, framework, license, flags.dryRun);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// ─── Entry Point ─────────────────────────────────────────────────────
|
|
450
|
+
|
|
451
|
+
main().catch((err) => {
|
|
452
|
+
// Graceful exit on Ctrl+C
|
|
453
|
+
if (err.name === 'ExitPromptError') {
|
|
454
|
+
console.log(`\n ${c.dim('Setup cancelled.')}\n`);
|
|
455
|
+
process.exit(0);
|
|
456
|
+
}
|
|
457
|
+
console.error(err);
|
|
458
|
+
process.exit(1);
|
|
459
|
+
});
|
package/package.json
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@jspreadsheet/install",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "Interactive installer for Jspreadsheet",
|
|
5
|
-
"bin": {
|
|
6
|
-
"@jspreadsheet/install": "index.js",
|
|
7
|
-
"jspreadsheet-install": "index.js"
|
|
8
|
-
},
|
|
9
|
-
"main": "index.js",
|
|
10
|
-
"keywords": [
|
|
11
|
-
"jspreadsheet",
|
|
12
|
-
"spreadsheet",
|
|
13
|
-
"installer",
|
|
14
|
-
"cli"
|
|
15
|
-
],
|
|
16
|
-
"author": "Jspreadsheet",
|
|
17
|
-
"license": "MIT",
|
|
18
|
-
"dependencies": {
|
|
19
|
-
"prompts": "^
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@jspreadsheet/install",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Interactive installer for Jspreadsheet",
|
|
5
|
+
"bin": {
|
|
6
|
+
"@jspreadsheet/install": "index.js",
|
|
7
|
+
"jspreadsheet-install": "index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "index.js",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"jspreadsheet",
|
|
12
|
+
"spreadsheet",
|
|
13
|
+
"installer",
|
|
14
|
+
"cli"
|
|
15
|
+
],
|
|
16
|
+
"author": "Jspreadsheet",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@inquirer/prompts": "^7.10.1",
|
|
20
|
+
"@jspreadsheet-ce/react": "^5.0.2",
|
|
21
|
+
"@jspreadsheet/vue": "^12.4.2"
|
|
22
|
+
}
|
|
23
|
+
}
|