@macrulez/devtoolz 0.4.1 → 0.4.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.
Files changed (85) hide show
  1. package/README.md +13 -0
  2. package/dist/cli.js +2 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/image-batch/run.d.ts +4 -1
  5. package/dist/commands/image-batch/run.js +5 -0
  6. package/dist/commands/image-batch/run.js.map +1 -1
  7. package/dist/commands/image-hash/sharp-loader.d.ts +3 -0
  8. package/dist/commands/image-hash/sharp-loader.js.map +1 -1
  9. package/dist/commands/ui/cli.d.ts +2 -0
  10. package/dist/commands/ui/cli.js +78 -0
  11. package/dist/commands/ui/cli.js.map +1 -0
  12. package/dist/commands/ui/fs-routes.d.ts +7 -0
  13. package/dist/commands/ui/fs-routes.js +135 -0
  14. package/dist/commands/ui/fs-routes.js.map +1 -0
  15. package/dist/commands/ui/http.d.ts +41 -0
  16. package/dist/commands/ui/http.js +81 -0
  17. package/dist/commands/ui/http.js.map +1 -0
  18. package/dist/commands/ui/jobs.d.ts +15 -0
  19. package/dist/commands/ui/jobs.js +73 -0
  20. package/dist/commands/ui/jobs.js.map +1 -0
  21. package/dist/commands/ui/modules/checks.d.ts +28 -0
  22. package/dist/commands/ui/modules/checks.js +556 -0
  23. package/dist/commands/ui/modules/checks.js.map +1 -0
  24. package/dist/commands/ui/modules/cleanup.d.ts +2 -0
  25. package/dist/commands/ui/modules/cleanup.js +305 -0
  26. package/dist/commands/ui/modules/cleanup.js.map +1 -0
  27. package/dist/commands/ui/modules/image-batch-backups.d.ts +2 -0
  28. package/dist/commands/ui/modules/image-batch-backups.js +116 -0
  29. package/dist/commands/ui/modules/image-batch-backups.js.map +1 -0
  30. package/dist/commands/ui/modules/image-batch-manage.d.ts +2 -0
  31. package/dist/commands/ui/modules/image-batch-manage.js +245 -0
  32. package/dist/commands/ui/modules/image-batch-manage.js.map +1 -0
  33. package/dist/commands/ui/modules/image-batch.d.ts +2 -0
  34. package/dist/commands/ui/modules/image-batch.js +225 -0
  35. package/dist/commands/ui/modules/image-batch.js.map +1 -0
  36. package/dist/commands/ui/modules/image-hash.d.ts +2 -0
  37. package/dist/commands/ui/modules/image-hash.js +158 -0
  38. package/dist/commands/ui/modules/image-hash.js.map +1 -0
  39. package/dist/commands/ui/modules/index.d.ts +2 -0
  40. package/dist/commands/ui/modules/index.js +11 -0
  41. package/dist/commands/ui/modules/index.js.map +1 -0
  42. package/dist/commands/ui/open-browser.d.ts +1 -0
  43. package/dist/commands/ui/open-browser.js +18 -0
  44. package/dist/commands/ui/open-browser.js.map +1 -0
  45. package/dist/commands/ui/scan.d.ts +20 -0
  46. package/dist/commands/ui/scan.js +57 -0
  47. package/dist/commands/ui/scan.js.map +1 -0
  48. package/dist/commands/ui/server.d.ts +18 -0
  49. package/dist/commands/ui/server.js +196 -0
  50. package/dist/commands/ui/server.js.map +1 -0
  51. package/dist/ui/assets/ChecksPage-MLWSelKP.js +1 -0
  52. package/dist/ui/assets/ChecksPage-pbC0Txsh.css +1 -0
  53. package/dist/ui/assets/CleanupPage-B2ZTFOpP.js +4 -0
  54. package/dist/ui/assets/CleanupPage-k7sTI4iz.css +1 -0
  55. package/dist/ui/assets/FolderBrowser-BX3-y8sM.js +1 -0
  56. package/dist/ui/assets/FolderBrowser-DRh-WZPz.css +1 -0
  57. package/dist/ui/assets/ImageBatchPage-CvsCvu1q.js +4 -0
  58. package/dist/ui/assets/ImageBatchPage-DiK8ODUc.css +1 -0
  59. package/dist/ui/assets/ImageHashPage-Bbhxvjj0.js +1 -0
  60. package/dist/ui/assets/ImageHashPage-CUXnoJEA.css +1 -0
  61. package/dist/ui/assets/SourcePicker-C3qFDUoL.css +1 -0
  62. package/dist/ui/assets/SourcePicker-CVgtCk78.js +1 -0
  63. package/dist/ui/assets/UiSegmented-Q_ter8VK.css +1 -0
  64. package/dist/ui/assets/UiSegmented-YV1YATxM.js +1 -0
  65. package/dist/ui/assets/core-DVezgdzc.js +12 -0
  66. package/dist/ui/assets/css-Z72CF80r.js +1 -0
  67. package/dist/ui/assets/engine-javascript-CNmxVhbB.js +141 -0
  68. package/dist/ui/assets/github-dark-DHJKELXO.js +1 -0
  69. package/dist/ui/assets/github-light-DAi9KRSo.js +1 -0
  70. package/dist/ui/assets/highlight-CsAszz7F.js +2 -0
  71. package/dist/ui/assets/html-BlS82ilI.js +1 -0
  72. package/dist/ui/assets/index-BzfkjuG8.css +1 -0
  73. package/dist/ui/assets/index-pDKL0Y31.js +3 -0
  74. package/dist/ui/assets/javascript-wDzz0qaB.js +1 -0
  75. package/dist/ui/assets/json-Cp-IABpG.js +1 -0
  76. package/dist/ui/assets/jsx-g9-lgVsj.js +1 -0
  77. package/dist/ui/assets/markdown-Cvjx9yec.js +1 -0
  78. package/dist/ui/assets/scss-Cw6XMfVs.js +1 -0
  79. package/dist/ui/assets/tsx-COt5Ahok.js +1 -0
  80. package/dist/ui/assets/typescript-BPQ3VLAy.js +1 -0
  81. package/dist/ui/assets/useCopy-vCfkPGWW.js +1 -0
  82. package/dist/ui/assets/vue-CwSeJimo.js +1 -0
  83. package/dist/ui/assets/yaml-Buea-lGh.js +1 -0
  84. package/dist/ui/index.html +17 -0
  85. package/package.json +17 -4
@@ -0,0 +1,305 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync, } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { extname, join, relative, resolve, sep } from 'node:path';
5
+ import { copyIntoBackup, newJournal, saveJournal, } from '../../image-batch/backup.js';
6
+ import { runRestore } from '../../image-batch/restore.js';
7
+ import { runConsoleStrip } from '../../console-strip/run.js';
8
+ import { runStripComments } from '../../strip-comments/run.js';
9
+ import { resolveUserPath } from '../fs-routes.js';
10
+ import { HttpError, asObject, sendJson, } from '../http.js';
11
+ import { startJob } from '../jobs.js';
12
+ const IGNORE = {
13
+ key: 'ignore',
14
+ label: 'Ignore',
15
+ type: 'list',
16
+ default: '',
17
+ help: 'Extra patterns to skip, one per line (gitignore syntax).',
18
+ };
19
+ function list(options, key) {
20
+ const value = options[key];
21
+ return (typeof value === 'string' ? value : '')
22
+ .split(/\r?\n|,/)
23
+ .map((part) => part.trim())
24
+ .filter(Boolean);
25
+ }
26
+ const TOOLS = [
27
+ {
28
+ id: 'strip-comments',
29
+ title: 'Remove comments',
30
+ description: 'Delete // and /* */ comments from source files, without touching code.',
31
+ verb: 'comment',
32
+ options: [
33
+ {
34
+ key: 'keepJsdoc',
35
+ label: 'Keep JSDoc on exports',
36
+ type: 'boolean',
37
+ default: false,
38
+ help: 'Leave the /** */ comment right above an exported declaration.',
39
+ },
40
+ IGNORE,
41
+ ],
42
+ run: (cwd, paths, options, write) => {
43
+ const report = runStripComments({
44
+ paths,
45
+ cwd,
46
+ keepJsdoc: options.keepJsdoc === true,
47
+ ignoreGlobs: list(options, 'ignore'),
48
+ diff: true,
49
+ ...(write ? { yes: true } : {}),
50
+ });
51
+ return { filesScanned: report.filesScanned, changes: report.changes, skipped: [] };
52
+ },
53
+ },
54
+ {
55
+ id: 'console-strip',
56
+ title: 'Remove console calls',
57
+ description: 'Delete console.log, console.debug and debugger statements.',
58
+ verb: 'call',
59
+ options: [
60
+ {
61
+ key: 'methods',
62
+ label: 'console methods',
63
+ type: 'list',
64
+ default: 'log\ndebug',
65
+ help: 'Which console.<method> calls to remove, one per line.',
66
+ },
67
+ {
68
+ key: 'debugger',
69
+ label: 'Also remove debugger statements',
70
+ type: 'boolean',
71
+ default: true,
72
+ help: 'Delete bare `debugger;` lines too.',
73
+ },
74
+ IGNORE,
75
+ ],
76
+ run: (cwd, paths, options, write) => {
77
+ const methods = list(options, 'methods');
78
+ const report = runConsoleStrip({
79
+ paths,
80
+ cwd,
81
+ ...(methods.length ? { methods } : {}),
82
+ debugger: options.debugger !== false,
83
+ ignoreGlobs: list(options, 'ignore'),
84
+ diff: true,
85
+ ...(write ? { yes: true } : {}),
86
+ });
87
+ return {
88
+ filesScanned: report.filesScanned,
89
+ changes: report.changes,
90
+ skipped: report.skipped.map((entry) => ({
91
+ file: entry.file,
92
+ line: entry.line,
93
+ column: entry.column,
94
+ snippet: entry.snippet,
95
+ reason: entry.reason,
96
+ })),
97
+ };
98
+ },
99
+ },
100
+ ];
101
+ const EDITABLE = new Set(['.ts', '.tsx', '.js', '.jsx', '.cjs', '.mjs', '.vue']);
102
+ const BACKUP_ROOT = join(homedir(), '.devtoolz', 'cleanup-backups');
103
+ function sha1(text) {
104
+ return createHash('sha1').update(text).digest('hex');
105
+ }
106
+ function projectOf(ctx, value) {
107
+ const dir = resolveUserPath(typeof value === 'string' ? value : null, ctx.server.cwd);
108
+ if (!statSync(dir, { throwIfNoEntry: false })?.isDirectory()) {
109
+ throw new HttpError(404, `${dir} is not a folder`);
110
+ }
111
+ return dir;
112
+ }
113
+ function toolOf(id) {
114
+ const found = TOOLS.find((tool) => tool.id === id);
115
+ if (!found)
116
+ throw new HttpError(404, `no tool named "${id}"`);
117
+ return found;
118
+ }
119
+ function backupDirFor(project) {
120
+ return join(BACKUP_ROOT, sha1(realpathSync(project)).slice(0, 12));
121
+ }
122
+ function inside(project, abs) {
123
+ const root = realpathSync(project);
124
+ const real = existsSync(abs) ? realpathSync(abs) : abs;
125
+ return real.startsWith(root + sep);
126
+ }
127
+ async function scan(ctx) {
128
+ const tool = toolOf(ctx.params.id);
129
+ const body = asObject(await ctx.readBody());
130
+ const cwd = projectOf(ctx, body.project);
131
+ const options = body.options === undefined ? {} : asObject(body.options, 'options');
132
+ const id = startJob(async () => {
133
+ const started = Date.now();
134
+ const output = tool.run(cwd, ['.'], options, false);
135
+ const files = output.changes.map((change) => {
136
+ const abs = resolve(cwd, change.file);
137
+ return {
138
+ ...change,
139
+ hash: existsSync(abs) ? sha1(readFileSync(abs)) : '',
140
+ };
141
+ });
142
+ return {
143
+ tool: tool.id,
144
+ project: cwd,
145
+ filesScanned: output.filesScanned,
146
+ files,
147
+ skipped: output.skipped,
148
+ total: files.reduce((sum, file) => sum + file.count, 0),
149
+ tookMs: Date.now() - started,
150
+ };
151
+ });
152
+ sendJson(ctx.res, 202, { jobId: id });
153
+ }
154
+ async function apply(ctx) {
155
+ const tool = toolOf(ctx.params.id);
156
+ const body = asObject(await ctx.readBody());
157
+ const cwd = projectOf(ctx, body.project);
158
+ const options = body.options === undefined ? {} : asObject(body.options, 'options');
159
+ if (!Array.isArray(body.files) || body.files.length === 0) {
160
+ throw new HttpError(400, 'choose at least one file');
161
+ }
162
+ const requested = body.files.map((item) => {
163
+ const entry = asObject(item, 'a file entry');
164
+ if (typeof entry.file !== 'string' || typeof entry.hash !== 'string') {
165
+ throw new HttpError(400, 'each file needs a path and the hash from the scan');
166
+ }
167
+ return { file: entry.file, hash: entry.hash };
168
+ });
169
+ const now = new Date();
170
+ const stamp = now.toISOString().replace(/[:.]/g, '-');
171
+ const backupDir = join(backupDirFor(cwd), `${stamp}-${tool.id}`);
172
+ const journal = newJournal(cwd, now);
173
+ const results = [];
174
+ for (const { file, hash } of requested) {
175
+ const abs = resolve(cwd, file);
176
+ if (!EDITABLE.has(extname(abs).toLowerCase()) || !inside(cwd, abs)) {
177
+ results.push({ file, status: 'refused', message: 'This file cannot be changed from here.' });
178
+ continue;
179
+ }
180
+ if (!existsSync(abs)) {
181
+ results.push({ file, status: 'changed', message: 'The file no longer exists.' });
182
+ continue;
183
+ }
184
+ const before = readFileSync(abs);
185
+ if (sha1(before) !== hash) {
186
+ results.push({
187
+ file,
188
+ status: 'changed',
189
+ message: 'The file changed after the scan. Scan again.',
190
+ });
191
+ continue;
192
+ }
193
+ try {
194
+ const backup = join(backupDir, relative(cwd, abs));
195
+ copyIntoBackup(abs, backup);
196
+ const output = tool.run(cwd, [abs], options, true);
197
+ const change = output.changes[0];
198
+ if (!change) {
199
+ results.push({ file, status: 'unchanged', message: 'Nothing to remove any more.' });
200
+ continue;
201
+ }
202
+ const after = readFileSync(abs);
203
+ const entry = {
204
+ path: abs,
205
+ backup,
206
+ bytesBefore: before.length,
207
+ bytesAfter: after.length,
208
+ hashBefore: sha1(before),
209
+ hashAfter: sha1(after),
210
+ };
211
+ journal.entries.push(entry);
212
+ results.push({ file, status: 'applied', count: change.count });
213
+ }
214
+ catch (error) {
215
+ results.push({
216
+ file,
217
+ status: 'error',
218
+ message: error instanceof Error ? error.message : String(error),
219
+ });
220
+ }
221
+ }
222
+ let savedTo;
223
+ if (journal.entries.length > 0) {
224
+ saveJournal(backupDir, journal);
225
+ mkdirSync(backupDir, { recursive: true });
226
+ writeFileSync(join(backupDir, 'meta.json'), JSON.stringify({ tool: tool.id, project: cwd, files: journal.entries.length }));
227
+ savedTo = backupDir;
228
+ }
229
+ sendJson(ctx.res, 200, { results, backupDir: savedTo });
230
+ }
231
+ async function undo(ctx) {
232
+ const body = asObject(await ctx.readBody());
233
+ const cwd = projectOf(ctx, body.project);
234
+ if (typeof body.dir !== 'string')
235
+ throw new HttpError(400, 'give the backup folder');
236
+ const dir = resolve(body.dir);
237
+ if (!dir.startsWith(backupDirFor(cwd) + sep)) {
238
+ throw new HttpError(403, 'this is not a cleanup backup of this project');
239
+ }
240
+ const report = await runRestore({
241
+ dir,
242
+ cwd,
243
+ force: body.force === true,
244
+ assumeYes: true,
245
+ interactive: false,
246
+ });
247
+ sendJson(ctx.res, 200, report);
248
+ }
249
+ function history(ctx) {
250
+ const cwd = projectOf(ctx, ctx.url.searchParams.get('project'));
251
+ const root = backupDirFor(cwd);
252
+ const rows = [];
253
+ if (statSync(root, { throwIfNoEntry: false })?.isDirectory()) {
254
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
255
+ if (!entry.isDirectory())
256
+ continue;
257
+ const dir = join(root, entry.name);
258
+ try {
259
+ const journal = JSON.parse(readFileSync(join(dir, 'journal.json'), 'utf8'));
260
+ const meta = existsSync(join(dir, 'meta.json'))
261
+ ? JSON.parse(readFileSync(join(dir, 'meta.json'), 'utf8'))
262
+ : {};
263
+ rows.push({
264
+ dir,
265
+ name: entry.name,
266
+ tool: meta.tool ?? 'cleanup',
267
+ files: journal.entries.length,
268
+ createdAt: journal.createdAt,
269
+ });
270
+ }
271
+ catch {
272
+ continue;
273
+ }
274
+ }
275
+ }
276
+ rows.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
277
+ sendJson(ctx.res, 200, { backups: rows.slice(0, 20) });
278
+ }
279
+ const routes = [
280
+ {
281
+ method: 'GET',
282
+ path: '/api/cleanup/tools',
283
+ handler: ({ res }) => {
284
+ sendJson(res, 200, TOOLS.map(({ id, title, description, verb, options }) => ({
285
+ id,
286
+ title,
287
+ description,
288
+ verb,
289
+ options,
290
+ })));
291
+ },
292
+ },
293
+ { method: 'POST', path: '/api/cleanup/:id/scan', handler: scan },
294
+ { method: 'POST', path: '/api/cleanup/:id/apply', handler: apply },
295
+ { method: 'POST', path: '/api/cleanup/undo', handler: undo },
296
+ { method: 'GET', path: '/api/cleanup/history', handler: history },
297
+ ];
298
+ export const cleanupModule = {
299
+ id: 'cleanup',
300
+ title: 'Code cleanup',
301
+ description: 'Remove comments and console calls, with a diff you approve file by file.',
302
+ status: 'available',
303
+ routes,
304
+ };
305
+ //# sourceMappingURL=cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../../../src/commands/ui/modules/cleanup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { type Route } from '../http.js';
2
+ export declare const backupRoutes: Route[];
@@ -0,0 +1,116 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, readFileSync, readdirSync, rmSync, statSync } from 'node:fs';
3
+ import { basename, join } from 'node:path';
4
+ import { DEFAULT_BACKUP_DIR, JOURNAL_FILE, loadJournal, } from '../../image-batch/backup.js';
5
+ import { ImageBatchUsageError } from '../../image-batch/errors.js';
6
+ import { runRestore } from '../../image-batch/restore.js';
7
+ import { resolveUserPath } from '../fs-routes.js';
8
+ import { HttpError, asObject, sendJson } from '../http.js';
9
+ function usage(task) {
10
+ try {
11
+ return task();
12
+ }
13
+ catch (error) {
14
+ if (error instanceof ImageBatchUsageError)
15
+ throw new HttpError(400, error.message);
16
+ throw error;
17
+ }
18
+ }
19
+ function summary(dir, journal) {
20
+ return {
21
+ dir,
22
+ name: basename(dir),
23
+ createdAt: journal.createdAt,
24
+ cwd: journal.cwd,
25
+ files: journal.entries.length,
26
+ bytesBefore: journal.entries.reduce((sum, entry) => sum + entry.bytesBefore, 0),
27
+ bytesAfter: journal.entries.reduce((sum, entry) => sum + entry.bytesAfter, 0),
28
+ };
29
+ }
30
+ function dirFrom(ctx, value) {
31
+ if (typeof value !== 'string' || value.trim() === '')
32
+ throw new HttpError(400, 'give the backup folder');
33
+ const dir = resolveUserPath(value, ctx.server.cwd);
34
+ if (!statSync(dir, { throwIfNoEntry: false })?.isDirectory()) {
35
+ throw new HttpError(404, `${dir} is not a folder`);
36
+ }
37
+ return dir;
38
+ }
39
+ function listBackups(ctx) {
40
+ const root = join(ctx.server.cwd, DEFAULT_BACKUP_DIR);
41
+ const rows = [];
42
+ if (statSync(root, { throwIfNoEntry: false })?.isDirectory()) {
43
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
44
+ if (!entry.isDirectory())
45
+ continue;
46
+ const dir = join(root, entry.name);
47
+ if (!existsSync(join(dir, JOURNAL_FILE)))
48
+ continue;
49
+ try {
50
+ rows.push(summary(dir, loadJournal(dir)));
51
+ }
52
+ catch {
53
+ continue;
54
+ }
55
+ }
56
+ }
57
+ rows.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
58
+ sendJson(ctx.res, 200, { root, backups: rows });
59
+ }
60
+ function sha1(path) {
61
+ try {
62
+ return createHash('sha1').update(readFileSync(path)).digest('hex');
63
+ }
64
+ catch {
65
+ return undefined;
66
+ }
67
+ }
68
+ async function inspect(ctx) {
69
+ const dir = dirFrom(ctx, ctx.url.searchParams.get('dir'));
70
+ const journal = usage(() => loadJournal(dir));
71
+ const report = await usage(() => runRestore({ dir, cwd: ctx.server.cwd, dryRun: true }));
72
+ const counts = { ...report.counts };
73
+ const entries = journal.entries.map((entry, index) => {
74
+ let status = report.results[index]?.status ?? 'error';
75
+ if (status === 'modified' && sha1(entry.path) === entry.hashBefore) {
76
+ counts.modified -= 1;
77
+ counts.restored += 1;
78
+ status = 'restored';
79
+ }
80
+ return {
81
+ path: entry.path,
82
+ backup: entry.backup,
83
+ bytesBefore: entry.bytesBefore,
84
+ bytesAfter: entry.bytesAfter,
85
+ status,
86
+ message: report.results[index]?.message,
87
+ };
88
+ });
89
+ sendJson(ctx.res, 200, { ...summary(dir, journal), counts, entries });
90
+ }
91
+ async function restore(ctx) {
92
+ const body = asObject(await ctx.readBody());
93
+ const dir = dirFrom(ctx, body.dir);
94
+ const report = await usage(() => runRestore({
95
+ dir,
96
+ cwd: ctx.server.cwd,
97
+ force: body.force === true,
98
+ assumeYes: true,
99
+ interactive: false,
100
+ }));
101
+ sendJson(ctx.res, 200, report);
102
+ }
103
+ async function remove(ctx) {
104
+ const body = asObject(await ctx.readBody());
105
+ const dir = dirFrom(ctx, body.dir);
106
+ usage(() => loadJournal(dir));
107
+ rmSync(dir, { recursive: true, force: true });
108
+ sendJson(ctx.res, 200, { deleted: dir });
109
+ }
110
+ export const backupRoutes = [
111
+ { method: 'GET', path: '/api/image-batch/backups', handler: listBackups },
112
+ { method: 'GET', path: '/api/image-batch/backup', handler: inspect },
113
+ { method: 'POST', path: '/api/image-batch/backup/restore', handler: restore },
114
+ { method: 'POST', path: '/api/image-batch/backup/delete', handler: remove },
115
+ ];
116
+ //# sourceMappingURL=image-batch-backups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-batch-backups.js","sourceRoot":"","sources":["../../../../src/commands/ui/modules/image-batch-backups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { type Route } from '../http.js';
2
+ export declare const manageRoutes: Route[];