@entrinsik/vite-plugin-informer 1.0.1 → 1.0.2
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/bin/deploy.js +37 -12
- package/bin/init.js +11 -23
- package/package.json +1 -1
- package/src/deploy.js +37 -21
package/bin/deploy.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import dotenv from 'dotenv';
|
|
4
|
-
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
5
5
|
import { resolve } from 'node:path';
|
|
6
6
|
import { deploy } from '../src/deploy.js';
|
|
7
7
|
|
|
@@ -24,33 +24,58 @@ if (!baseUrl || (!apiKey && (!user || !pass))) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// Read project metadata from package.json
|
|
27
|
-
|
|
27
|
+
const pkgPath = resolve('package.json');
|
|
28
|
+
let pkg;
|
|
28
29
|
let displayName;
|
|
29
30
|
let description;
|
|
31
|
+
let savedId;
|
|
32
|
+
|
|
30
33
|
try {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
if (slug && slug.startsWith('@') && slug.includes('/')) {
|
|
35
|
-
slug = slug.split('/')[1];
|
|
36
|
-
}
|
|
37
|
-
// Read display name and description from informer config section
|
|
34
|
+
pkg = JSON.parse(await readFile(pkgPath, 'utf8'));
|
|
35
|
+
|
|
36
|
+
// Read display name, description, and saved ID from informer config section
|
|
38
37
|
displayName = pkg.informer?.name;
|
|
39
38
|
description = pkg.informer?.description;
|
|
39
|
+
savedId = pkg.informer?.id;
|
|
40
40
|
} catch {
|
|
41
41
|
console.error('Could not read package.json in current directory.');
|
|
42
42
|
process.exit(1);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
if (!
|
|
46
|
-
|
|
45
|
+
if (!displayName) {
|
|
46
|
+
// Fall back to package name for display
|
|
47
|
+
displayName = pkg.name;
|
|
48
|
+
if (displayName && displayName.startsWith('@') && displayName.includes('/')) {
|
|
49
|
+
displayName = displayName.split('/')[1];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!displayName) {
|
|
54
|
+
console.error('package.json must have an "informer.name" or "name" field.');
|
|
47
55
|
process.exit(1);
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
const distDir = resolve('dist');
|
|
51
59
|
|
|
52
60
|
try {
|
|
53
|
-
await deploy({
|
|
61
|
+
const result = await deploy({
|
|
62
|
+
baseUrl,
|
|
63
|
+
apiKey,
|
|
64
|
+
user,
|
|
65
|
+
pass,
|
|
66
|
+
distDir,
|
|
67
|
+
name: displayName,
|
|
68
|
+
description,
|
|
69
|
+
id: savedId
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Save the report ID back to package.json for future deploys
|
|
73
|
+
if (result.id && result.id !== savedId) {
|
|
74
|
+
if (!pkg.informer) pkg.informer = {};
|
|
75
|
+
pkg.informer.id = result.id;
|
|
76
|
+
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
77
|
+
console.log(`Saved report ID "${result.id}" to package.json`);
|
|
78
|
+
}
|
|
54
79
|
} catch (err) {
|
|
55
80
|
console.error('Deploy failed:', err.message);
|
|
56
81
|
process.exit(1);
|
package/bin/init.js
CHANGED
|
@@ -4,6 +4,7 @@ import { readFile, writeFile, mkdir, cp, access, readdir } from 'node:fs/promise
|
|
|
4
4
|
import { resolve, dirname, join, basename } from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { createInterface } from 'node:readline';
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
7
8
|
|
|
8
9
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
10
|
const cwd = process.cwd();
|
|
@@ -176,27 +177,17 @@ function prompt(question, defaultValue) {
|
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
/**
|
|
179
|
-
* Convert
|
|
180
|
+
* Convert package name to friendly display name.
|
|
180
181
|
* "magic-quickbooks-report" -> "Magic Quickbooks Report"
|
|
182
|
+
* "@org/my-report" -> "My Report"
|
|
181
183
|
*/
|
|
182
|
-
function
|
|
183
|
-
return
|
|
184
|
+
function packageNameToDisplayName(name) {
|
|
185
|
+
return name
|
|
184
186
|
.replace(/^@[^/]+\//, '') // Remove scope
|
|
185
187
|
.replace(/[-_]/g, ' ')
|
|
186
188
|
.replace(/\b\w/g, c => c.toUpperCase());
|
|
187
189
|
}
|
|
188
190
|
|
|
189
|
-
/**
|
|
190
|
-
* Convert name to slug.
|
|
191
|
-
* "Magic Quickbooks Report" -> "magic-quickbooks-report"
|
|
192
|
-
*/
|
|
193
|
-
function nameToSlug(name) {
|
|
194
|
-
return name
|
|
195
|
-
.toLowerCase()
|
|
196
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
197
|
-
.replace(/^-|-$/g, '');
|
|
198
|
-
}
|
|
199
|
-
|
|
200
191
|
async function init() {
|
|
201
192
|
console.log('Initializing Informer Magic Report project...\n');
|
|
202
193
|
|
|
@@ -219,24 +210,21 @@ async function init() {
|
|
|
219
210
|
}
|
|
220
211
|
|
|
221
212
|
// 3. Get report info from user
|
|
222
|
-
const
|
|
223
|
-
const existingName = pkg.informer?.name;
|
|
224
|
-
const defaultName = existingName || slugToName(defaultSlug);
|
|
213
|
+
const defaultName = pkg.informer?.name || packageNameToDisplayName(pkg.name || basename(cwd));
|
|
225
214
|
|
|
226
215
|
console.log('Configure your Magic Report:\n');
|
|
227
216
|
|
|
228
217
|
const reportName = await prompt('Report name', defaultName);
|
|
229
|
-
const reportSlug = await prompt('Report slug', nameToSlug(reportName) || defaultSlug);
|
|
230
218
|
|
|
231
219
|
console.log('');
|
|
232
220
|
|
|
233
221
|
// 4. Update package.json
|
|
234
222
|
if (!pkg.informer) pkg.informer = {};
|
|
235
223
|
pkg.informer.name = reportName;
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
224
|
+
// Generate a stable UUID for this report
|
|
225
|
+
if (!pkg.informer.id) {
|
|
226
|
+
pkg.informer.id = randomUUID();
|
|
227
|
+
console.log(`Generated report ID: ${pkg.informer.id}`);
|
|
240
228
|
}
|
|
241
229
|
|
|
242
230
|
// 5. Add plugin to dependencies if not present
|
|
@@ -254,7 +242,7 @@ async function init() {
|
|
|
254
242
|
}
|
|
255
243
|
|
|
256
244
|
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
257
|
-
console.log(`
|
|
245
|
+
console.log(`Updated package.json with informer.name="${reportName}"`);
|
|
258
246
|
|
|
259
247
|
// 7. Update vite.config
|
|
260
248
|
await updateViteConfig();
|
package/package.json
CHANGED
package/src/deploy.js
CHANGED
|
@@ -16,38 +16,51 @@ const ROOT_CONFIG_FILES = ['data-access.yaml'];
|
|
|
16
16
|
/**
|
|
17
17
|
* Deploy a built Vite project to Informer as a Magic Report.
|
|
18
18
|
*
|
|
19
|
-
* @param {{ baseUrl: string, apiKey?: string, user?: string, pass?: string,
|
|
19
|
+
* @param {{ baseUrl: string, apiKey?: string, user?: string, pass?: string, distDir: string, name: string, description?: string, id?: string }} opts
|
|
20
|
+
* @returns {Promise<{ id: string, url: string }>} The report's natural ID and URL
|
|
20
21
|
*/
|
|
21
|
-
export async function deploy({ baseUrl, apiKey, user, pass,
|
|
22
|
+
export async function deploy({ baseUrl, apiKey, user, pass, distDir, name, description, id }) {
|
|
22
23
|
const api = createClient({ baseUrl, apiKey, user, pass });
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const naturalId = `${me.username}:${slug}`;
|
|
25
|
+
let report = null;
|
|
26
|
+
let naturalId = null;
|
|
27
27
|
|
|
28
|
-
//
|
|
29
|
-
|
|
28
|
+
// 1. If we have a saved ID, try to look it up
|
|
29
|
+
if (id) {
|
|
30
|
+
console.log(`Looking up report "${id}"...`);
|
|
31
|
+
report = await api.get(`reports/${id}`);
|
|
32
|
+
if (report) {
|
|
33
|
+
naturalId = report.naturalId || id;
|
|
34
|
+
console.log(`Found existing report: ${naturalId}`);
|
|
35
|
+
} else {
|
|
36
|
+
console.log(`Report "${id}" not found, will create new...`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
30
39
|
|
|
31
|
-
//
|
|
40
|
+
// 2. Create if not found (or no ID was provided)
|
|
32
41
|
if (!report) {
|
|
33
|
-
console.log(`
|
|
34
|
-
|
|
42
|
+
console.log(`Creating new report "${name}"...`);
|
|
43
|
+
const payload = {
|
|
35
44
|
type: 'magicReport',
|
|
36
|
-
name: name
|
|
45
|
+
name: name,
|
|
37
46
|
description: description || ''
|
|
38
|
-
}
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
throw new Error(`Failed to create report "${naturalId}"`);
|
|
47
|
+
};
|
|
48
|
+
// If we have a saved ID (UUID), use it for the new report
|
|
49
|
+
if (id) {
|
|
50
|
+
payload.id = id;
|
|
43
51
|
}
|
|
44
|
-
|
|
52
|
+
report = await api.post('reports', payload);
|
|
53
|
+
if (!report || !report.id) {
|
|
54
|
+
throw new Error(`Failed to create report "${name}"`);
|
|
55
|
+
}
|
|
56
|
+
naturalId = report.naturalId || `${report.ownerId}:${report.slug}`;
|
|
57
|
+
console.log(`Created report: ${naturalId}`);
|
|
45
58
|
}
|
|
46
59
|
|
|
47
|
-
//
|
|
60
|
+
// 3. Update name/description if provided (for existing reports)
|
|
48
61
|
const updates = {};
|
|
49
|
-
if (name) updates.name = name;
|
|
50
|
-
if (description !== undefined) updates.description = description;
|
|
62
|
+
if (name && report.name !== name) updates.name = name;
|
|
63
|
+
if (description !== undefined && report.description !== description) updates.description = description;
|
|
51
64
|
if (Object.keys(updates).length > 0) {
|
|
52
65
|
await api.put(`reports/${naturalId}`, updates);
|
|
53
66
|
}
|
|
@@ -125,10 +138,13 @@ export async function deploy({ baseUrl, apiKey, user, pass, slug, distDir, name,
|
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
140
|
|
|
128
|
-
// 9. Print report URL
|
|
141
|
+
// 9. Print report URL and return UUID for saving
|
|
129
142
|
const totalFiles = entries.length + configCount;
|
|
130
143
|
const reportUrl = `${baseUrl.replace(/\/+$/, '')}/reports/r/${naturalId}`;
|
|
131
144
|
console.log(`\nPublished ${totalFiles} files to: ${reportUrl}`);
|
|
145
|
+
|
|
146
|
+
// Return the stable UUID (not natural ID) for package.json storage
|
|
147
|
+
return { id: report.id, url: reportUrl };
|
|
132
148
|
}
|
|
133
149
|
|
|
134
150
|
/**
|