@mpis/run 0.0.9 → 0.0.11

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print-screen.js","sourceRoot":"","sources":["../../src/common/print-screen.ts"],"names":[],"mappings":"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"}
package/loader/bin.js CHANGED
@@ -2,4 +2,6 @@
2
2
 
3
3
  import '@idlebox/source-map-support/register';
4
4
 
5
+ process.title = `MpisRun`;
6
+
5
7
  await import('../lib/bin.js');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mpis/run",
3
3
  "type": "module",
4
- "version": "0.0.9",
4
+ "version": "0.0.11",
5
5
  "keywords": [],
6
6
  "bin": {
7
7
  "run": "./loader/bin.js",
@@ -12,22 +12,19 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "split-cmd": "^1.1.0",
15
- "execa": "^9.6.0",
16
- "@build-script/rushstack-config-loader": "^0.0.26",
17
- "@idlebox/common": "^1.4.21",
18
- "@idlebox/args": "^0.0.15",
19
- "@idlebox/logger": "^0.0.8",
20
- "@mpis/client": "^0.0.8",
21
- "@idlebox/node": "^1.4.14",
22
- "@mpis/server": "^0.0.7",
23
- "@mpis/shared": "^0.0.7",
24
- "@idlebox/source-map-support": "^0.0.8"
15
+ "@build-script/rushstack-config-loader": "^0.0.27",
16
+ "@idlebox/args": "^0.0.16",
17
+ "@idlebox/logger": "^0.0.9",
18
+ "@idlebox/node": "^1.4.15",
19
+ "@idlebox/common": "^1.5.0",
20
+ "@mpis/client": "^0.0.9",
21
+ "@mpis/server": "^0.0.8",
22
+ "@idlebox/source-map-support": "^0.0.9"
25
23
  },
26
24
  "devDependencies": {
27
25
  "@types/node": "^24.0.14",
28
- "@build-script/single-dog-asset": "^1.0.39",
29
- "@idlebox/esbuild-executer": "^0.0.7",
30
- "@internal/local-rig": "^1.0.1"
26
+ "@build-script/single-dog-asset": "latest",
27
+ "@idlebox/esbuild-executer": "^0.0.7"
31
28
  },
32
29
  "sideEffects": false,
33
30
  "license": "MIT",
package/src/bin.ts CHANGED
@@ -1,44 +1,28 @@
1
- import { humanDate, prettyFormatError, registerGlobalLifecycle, toDisposable } from '@idlebox/common';
1
+ import { functionToDisposable, humanDate, prettyPrintError, registerGlobalLifecycle } from '@idlebox/common';
2
2
  import { logger } from '@idlebox/logger';
3
3
  import { registerNodejsExitHandler, setExitCodeIfNot, shutdown } from '@idlebox/node';
4
4
  import { channelClient } from '@mpis/client';
5
- import { CompileError, ModeKind, ProcessIPCClient, WorkersManager } from '@mpis/server';
5
+ import { ProcessIPCClient } from '@mpis/server';
6
6
  import { rmSync } from 'node:fs';
7
7
  import { dumpConfig } from './commands/config.js';
8
- import { context, parseCliArgs } from './common/args.js';
9
- import { loadConfigFile } from './common/config-file.js';
8
+ import { context } from './common/args.js';
9
+ import { config } from './common/config-file.js';
10
+ import { addBreakModeDebugCommands } from './common/interactive.js';
11
+ import { initializeWorkers, workersManager } from './common/manager.js';
10
12
  import { projectRoot } from './common/paths.js';
13
+ import { reprintWatchModeError } from './common/print-screen.js';
11
14
  import { initializeStdin, registerCommand } from './common/stdin.js';
12
15
 
13
16
  registerNodejsExitHandler();
14
17
 
15
- parseCliArgs();
16
-
17
- let execute_index = 0;
18
- const start = Date.now();
19
- registerGlobalLifecycle(
20
- toDisposable(() => {
21
- logger.info`Operation completed in ${humanDate.delta(Date.now() - start)} (${process.exitCode ? 'failed' : 'success'}).`;
22
- }),
23
- );
24
-
25
18
  registerCommand({
26
19
  name: ['status', 's'],
27
20
  description: '显示当前状态',
28
21
  callback: () => reprintWatchModeError(),
29
22
  });
30
23
 
31
- process.title = `MpisRun`;
32
-
33
24
  logger.info`Running command "${context.command}" in ${projectRoot}`;
34
25
 
35
- const defaultNoClear = logger.debug.isEnabled || !process.stderr.isTTY;
36
- let workersManager: WorkersManager;
37
-
38
- const config = loadConfigFile(context.watchMode);
39
- logger.verbose`loaded config file: ${config}`;
40
- const errors = new Map<ProcessIPCClient, Error | null>();
41
-
42
26
  switch (context.command) {
43
27
  case 'clean':
44
28
  executeClean();
@@ -57,7 +41,7 @@ switch (context.command) {
57
41
  logger.debug`build completed.`;
58
42
  setExitCodeIfNot(0);
59
43
  } catch (e: any) {
60
- logger.error`failed ${context.command} project: ${e.message}`;
44
+ prettyPrintError(`failed ${context.command} project`, e);
61
45
  shutdown(1);
62
46
  }
63
47
  }
@@ -69,16 +53,14 @@ switch (context.command) {
69
53
  }
70
54
  initializeStdin();
71
55
  await executeBuild().catch((e: Error) => {
72
- logger.error`failed ${context.command} project: ${e.message}`;
56
+ prettyPrintError(`failed ${context.command} project`, e);
73
57
  shutdown(1);
74
58
  });
75
59
  break;
76
60
  }
77
61
 
78
- // channelClient.displayName = `MpisRun`;
79
-
80
62
  async function executeBuild() {
81
- workersManager = new WorkersManager(context.watchMode ? ModeKind.Watch : ModeKind.Build);
63
+ let shuttingDown = false;
82
64
 
83
65
  initializeWorkers();
84
66
  const graph = workersManager.finalize();
@@ -93,7 +75,7 @@ async function executeBuild() {
93
75
 
94
76
  const times = `(+${humanDate.delta(w.time.executeStart!, w.time.executeEnd!)})`;
95
77
 
96
- if (context.watchMode) {
78
+ if (context.watchMode && !shuttingDown) {
97
79
  printFailedRunError(w, `unexpected exit in watch mode ${times}`);
98
80
  } else if (!w.isSuccess) {
99
81
  printFailedRunError(w, `failed to execute ${times}`);
@@ -110,8 +92,7 @@ async function executeBuild() {
110
92
  channelClient.start();
111
93
 
112
94
  if (context.breakMode) {
113
- logger.warn`Break mode enabled, waiting for input command...`;
114
- addDebugCommand();
95
+ addBreakModeDebugCommands();
115
96
  return;
116
97
  }
117
98
  logger.verbose`Workers initialized, starting execution...`;
@@ -119,6 +100,12 @@ async function executeBuild() {
119
100
 
120
101
  logger.verbose`Startup returned.`;
121
102
 
103
+ registerGlobalLifecycle(
104
+ functionToDisposable(() => {
105
+ shuttingDown = true;
106
+ }),
107
+ );
108
+
122
109
  reprintWatchModeError();
123
110
  }
124
111
 
@@ -130,45 +117,6 @@ function executeClean() {
130
117
  logger.success`Cleaned up ${config.clean.length} folders.`;
131
118
  }
132
119
 
133
- function initializeWorkers() {
134
- let last: ProcessIPCClient | undefined;
135
- for (const title of config.buildTitles) {
136
- const cmds = config.build.get(title);
137
- if (!cmds) throw logger.fatal`program state error, no build command "${title}"`;
138
-
139
- if (!cmds.env['DEBUG']) cmds.env['DEBUG'] = '';
140
- if (!cmds.env['DEBUG_LEVEL']) cmds.env['DEBUG_LEVEL'] = '';
141
- const worker = new ProcessIPCClient(title.replace(/\s+/g, ''), cmds.command, cmds.cwd, cmds.env);
142
-
143
- for (const path of config.additionalPaths) {
144
- worker.pathvar.add(path);
145
- }
146
-
147
- worker.displayTitle = `run:${cmds.command[0]}`;
148
-
149
- workersManager.addWorker(worker, last ? [last._id] : []);
150
-
151
- let nodeFirstTime = true;
152
- worker.onFailure((e) => {
153
- errors.set(worker, e);
154
- reprintWatchModeError(nodeFirstTime);
155
- nodeFirstTime = false;
156
- sendStatus();
157
- });
158
- worker.onSuccess(() => {
159
- errors.set(worker, null);
160
- if (nodeFirstTime) {
161
- nodeFirstTime = false;
162
- } else {
163
- reprintWatchModeError();
164
- }
165
- sendStatus();
166
- });
167
-
168
- last = worker;
169
- }
170
- }
171
-
172
120
  const cls = /\x1Bc/g;
173
121
 
174
122
  function printFailedRunError(worker: ProcessIPCClient, message: string) {
@@ -190,116 +138,3 @@ function printFailedRunError(worker: ProcessIPCClient, message: string) {
190
138
  logger.error`"${worker._id}" ${message}`;
191
139
  shutdown(1);
192
140
  }
193
-
194
- let printTo: NodeJS.Timeout | undefined;
195
- function reprintWatchModeError(noClear?: boolean) {
196
- if (printTo) clearTimeout(printTo);
197
- printTo = setTimeout(() => {
198
- printTo = undefined;
199
-
200
- if (context.watchMode) {
201
- if (!noClear && !defaultNoClear) process.stderr.write('\x1Bc');
202
- }
203
- const graph = workersManager.finalize();
204
- console.error('%s\n%s', graph.debugFormatList(), graph.debugFormatSummary());
205
- printAllErrors();
206
- }, 50);
207
- }
208
-
209
- function addDebugCommand() {
210
- registerCommand({
211
- name: ['continue', 'c'],
212
- description: '开始执行',
213
- callback: () => {
214
- workersManager.finalize().startup();
215
- },
216
- });
217
- registerCommand({
218
- name: ['debug'],
219
- description: '切换调试模式(仅在启动前有效)',
220
- callback: (text: string) => {
221
- const [_, index, on_off] = text.split(/\s+/);
222
- const list = workersManager._allWorkers as ProcessIPCClient[];
223
- const worker = list[Number(index)];
224
- if (!worker) {
225
- logger.error`worker index out of range: ${index}`;
226
- return;
227
- }
228
- if (on_off === 'on') {
229
- worker.env['DEBUG'] = '*,-executer:*,-dispose:*';
230
- worker.env['DEBUG_LEVEL'] = 'verbose';
231
- logger.success`debug mode enabled for worker "${worker._id}"`;
232
- } else if (on_off === 'off') {
233
- worker.env['DEBUG'] = '';
234
- worker.env['DEBUG_LEVEL'] = '';
235
- logger.success`debug mode disabled for worker "${worker._id}"`;
236
- } else {
237
- logger.error`invalid argument: ${text}`;
238
- }
239
- },
240
- });
241
- // registerCommand({
242
- // name: ['print', 'p'],
243
- // description: '显示命令执行输出',
244
- // callback: () => {
245
- // },
246
- // });
247
- }
248
-
249
- function sendStatus() {
250
- const noError = errors.values().every((e) => !e);
251
- if (noError) {
252
- channelClient.success(`all ${workersManager.size()} workers completed successfully.`);
253
- } else {
254
- let errorCnt = 0;
255
- const arr: string[] = [];
256
- for (const [client, err] of errors.entries()) {
257
- if (err) {
258
- errorCnt++;
259
- arr.push(client._id);
260
- }
261
- }
262
- channelClient.failed(`mpis-run: ${arr.join(', ')} (${errorCnt} / ${workersManager.size()})`, formatAllErrors());
263
- }
264
- }
265
-
266
- function formatAllErrors() {
267
- const lines: string[] = [];
268
- const colorEnabled = logger.colorEnabled;
269
- let index = 0;
270
- for (const [worker, error] of errors) {
271
- if (error === null) continue;
272
-
273
- index++;
274
-
275
- let tag = '';
276
- if (error.name !== 'Error') {
277
- tag = ` (${error.name})`;
278
- }
279
- const banner = colorEnabled ? `\x1B[48;5;9m ERROR ${index} \x1B[0m` : `ERROR ${index}`;
280
- lines.push(`\n${banner}${tag} ${worker._id}`);
281
- if (error instanceof CompileError) {
282
- lines.push(error.toString());
283
- } else if (error instanceof Error) {
284
- lines.push(prettyFormatError(error));
285
- } else {
286
- lines.push(`can not handle error: ${error}`);
287
- }
288
- lines.push(`\n${banner} ${worker._id}`);
289
- }
290
- return lines.join('\n');
291
- }
292
-
293
- function printAllErrors() {
294
- execute_index++;
295
- const execTip = `exec: ${execute_index} / ${humanDate.delta(Date.now() - start)}`;
296
-
297
- const numFailed = [...errors.values().filter((e) => !!e)].length;
298
- if (numFailed !== 0) {
299
- console.error(formatAllErrors());
300
-
301
- logger.error(`💥 ${numFailed} of ${workersManager.size()} worker failed (${execTip})`);
302
- } else {
303
- logger.success(`✅ no error in ${workersManager.size()} workers (${execTip})`);
304
- }
305
- }
@@ -11,7 +11,7 @@ export function printUsage() {
11
11
  // console.log(' init create config file if not');
12
12
  }
13
13
 
14
- export function parseCliArgs() {
14
+ function parseCliArgs() {
15
15
  const debugLevel = argv.flag(['-d', '--debug']);
16
16
 
17
17
  const debugMode = debugLevel > 0;
@@ -75,8 +75,6 @@ export function parseCliArgs() {
75
75
  dumpConfig,
76
76
  };
77
77
 
78
- context = r;
79
-
80
78
  if (argv.unused().length) {
81
79
  printUsage();
82
80
  console.error('');
@@ -85,4 +83,4 @@ export function parseCliArgs() {
85
83
  return r;
86
84
  }
87
85
 
88
- export let context: Readonly<ReturnType<typeof parseCliArgs>>;
86
+ export const context: Readonly<ReturnType<typeof parseCliArgs>> = parseCliArgs();
@@ -5,6 +5,7 @@ import { readFileSync } from 'node:fs';
5
5
  import { resolve } from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { split as splitCmd } from 'split-cmd';
8
+ import { context } from './args.js';
8
9
  import { projectRoot, selfRoot } from './paths.js';
9
10
 
10
11
  interface IPackageBinary {
@@ -54,7 +55,7 @@ function watchModeCmd(command: string | readonly string[], watch?: string | read
54
55
  return [...cmdArr, ...watch];
55
56
  }
56
57
 
57
- export function loadConfigFile(watchMode: boolean): IConfigFile {
58
+ function loadConfigFile(watchMode: boolean): IConfigFile {
58
59
  const config = new ProjectConfig(projectRoot, undefined, logger);
59
60
  const schemaFile = resolve(selfRoot, 'commands.schema.json');
60
61
 
@@ -236,3 +237,6 @@ function resolveCommandIsFile(config: ProjectConfig, command: string[]) {
236
237
 
237
238
  command.splice(0, 1, process.execPath, r.effective);
238
239
  }
240
+
241
+ export const config = loadConfigFile(context.watchMode);
242
+ logger.verbose`loaded config file: ${config}`;
@@ -0,0 +1,46 @@
1
+ import { logger } from '@idlebox/logger';
2
+ import type { ProcessIPCClient } from '@mpis/server';
3
+ import { workersManager } from './manager.js';
4
+ import { registerCommand } from './stdin.js';
5
+
6
+ export function addBreakModeDebugCommands() {
7
+ logger.warn`Break mode enabled, waiting for input command...`;
8
+
9
+ registerCommand({
10
+ name: ['continue', 'c'],
11
+ description: '开始执行',
12
+ callback: () => {
13
+ workersManager.finalize().startup();
14
+ },
15
+ });
16
+ registerCommand({
17
+ name: ['debug'],
18
+ description: '切换调试模式(仅在启动前有效)',
19
+ callback: (text: string) => {
20
+ const [_, index, on_off] = text.split(/\s+/);
21
+ const list = workersManager._allWorkers as ProcessIPCClient[];
22
+ const worker = list[Number(index)];
23
+ if (!worker) {
24
+ logger.error`worker index out of range: ${index}`;
25
+ return;
26
+ }
27
+ if (on_off === 'on') {
28
+ worker.env['DEBUG'] = '*,-executer:*,-dispose:*';
29
+ worker.env['DEBUG_LEVEL'] = 'verbose';
30
+ logger.success`debug mode enabled for worker "${worker._id}"`;
31
+ } else if (on_off === 'off') {
32
+ worker.env['DEBUG'] = '';
33
+ worker.env['DEBUG_LEVEL'] = '';
34
+ logger.success`debug mode disabled for worker "${worker._id}"`;
35
+ } else {
36
+ logger.error`invalid argument: ${text}`;
37
+ }
38
+ },
39
+ });
40
+ // registerCommand({
41
+ // name: ['print', 'p'],
42
+ // description: '显示命令执行输出',
43
+ // callback: () => {
44
+ // },
45
+ // });
46
+ }
@@ -0,0 +1,64 @@
1
+ import { logger } from '@idlebox/logger';
2
+ import { channelClient } from '@mpis/client';
3
+ import { ModeKind, ProcessIPCClient, WorkersManager } from '@mpis/server';
4
+ import { context } from './args.js';
5
+ import { config } from './config-file.js';
6
+ import { errors, formatAllErrors, reprintWatchModeError } from './print-screen.js';
7
+
8
+ export const workersManager = new WorkersManager(context.watchMode ? ModeKind.Watch : ModeKind.Build);
9
+
10
+ export function initializeWorkers() {
11
+ let last: ProcessIPCClient | undefined;
12
+ for (const title of config.buildTitles) {
13
+ const cmds = config.build.get(title);
14
+ if (!cmds) throw logger.fatal`program state error, no build command "${title}"`;
15
+
16
+ if (!cmds.env['DEBUG']) cmds.env['DEBUG'] = '';
17
+ if (!cmds.env['DEBUG_LEVEL']) cmds.env['DEBUG_LEVEL'] = '';
18
+ const worker = new ProcessIPCClient(title.replace(/\s+/g, ''), cmds.command, cmds.cwd, cmds.env);
19
+
20
+ for (const path of config.additionalPaths) {
21
+ worker.pathvar.add(path);
22
+ }
23
+
24
+ worker.displayTitle = `run:${cmds.command[0]}`;
25
+
26
+ workersManager.addWorker(worker, last ? [last._id] : []);
27
+
28
+ let nodeFirstTime = true;
29
+ worker.onFailure((e) => {
30
+ errors.set(worker, e);
31
+ reprintWatchModeError(nodeFirstTime);
32
+ nodeFirstTime = false;
33
+ sendStatus();
34
+ });
35
+ worker.onSuccess(() => {
36
+ errors.set(worker, null);
37
+ if (nodeFirstTime) {
38
+ nodeFirstTime = false;
39
+ } else {
40
+ reprintWatchModeError();
41
+ }
42
+ sendStatus();
43
+ });
44
+
45
+ last = worker;
46
+ }
47
+ }
48
+
49
+ function sendStatus() {
50
+ const noError = errors.values().every((e) => !e);
51
+ if (noError) {
52
+ channelClient.success(`all ${workersManager.size()} workers completed successfully.`);
53
+ } else {
54
+ let errorCnt = 0;
55
+ const arr: string[] = [];
56
+ for (const [client, err] of errors.entries()) {
57
+ if (err) {
58
+ errorCnt++;
59
+ arr.push(client._id);
60
+ }
61
+ }
62
+ channelClient.failed(`mpis-run: ${arr.join(', ')} (${errorCnt} / ${workersManager.size()})`, formatAllErrors());
63
+ }
64
+ }
@@ -0,0 +1,73 @@
1
+ import { humanDate, prettyFormatError, registerGlobalLifecycle, toDisposable } from '@idlebox/common';
2
+ import { logger } from '@idlebox/logger';
3
+ import { CompileError, type ProcessIPCClient } from '@mpis/server';
4
+ import { context } from './args.js';
5
+ import { workersManager } from './manager.js';
6
+
7
+ let printTo: NodeJS.Timeout | undefined;
8
+ const defaultNoClear = logger.debug.isEnabled || !process.stderr.isTTY;
9
+ export const errors = new Map<ProcessIPCClient, Error | null>();
10
+
11
+ export function reprintWatchModeError(noClear?: boolean) {
12
+ if (printTo) clearTimeout(printTo);
13
+ printTo = setTimeout(() => {
14
+ printTo = undefined;
15
+
16
+ if (context.watchMode) {
17
+ if (!noClear && !defaultNoClear) process.stderr.write('\x1Bc');
18
+ }
19
+ const graph = workersManager.finalize();
20
+ console.error('%s\n%s', graph.debugFormatList(), graph.debugFormatSummary());
21
+ printAllErrors();
22
+ }, 50);
23
+ }
24
+
25
+ let execute_index = 0;
26
+ const start = Date.now();
27
+
28
+ function printAllErrors() {
29
+ execute_index++;
30
+ const execTip = `exec: ${execute_index} / ${humanDate.delta(Date.now() - start)}`;
31
+
32
+ const numFailed = [...errors.values().filter((e) => !!e)].length;
33
+ if (numFailed !== 0) {
34
+ console.error(formatAllErrors());
35
+
36
+ logger.error(`💥 ${numFailed} of ${workersManager.size()} worker failed (${execTip})`);
37
+ } else {
38
+ logger.success(`✅ no error in ${workersManager.size()} workers (${execTip})`);
39
+ }
40
+ }
41
+
42
+ export function formatAllErrors() {
43
+ const lines: string[] = [];
44
+ const colorEnabled = logger.colorEnabled;
45
+ let index = 0;
46
+ for (const [worker, error] of errors) {
47
+ if (error === null) continue;
48
+
49
+ index++;
50
+
51
+ let tag = '';
52
+ if (error.name !== 'Error') {
53
+ tag = ` (${error.name})`;
54
+ }
55
+ const banner = colorEnabled ? `\x1B[48;5;9m ERROR ${index} \x1B[0m` : `ERROR ${index}`;
56
+ lines.push(`\n${banner}${tag} ${worker._id}`);
57
+ if (error instanceof CompileError) {
58
+ lines.push(error.toString());
59
+ } else if (error instanceof Error) {
60
+ lines.push(prettyFormatError(error));
61
+ } else {
62
+ lines.push(`can not handle error: ${error}`);
63
+ }
64
+ lines.push(`\n${banner} ${worker._id}`);
65
+ }
66
+ return lines.join('\n');
67
+ }
68
+
69
+ registerGlobalLifecycle(
70
+ toDisposable(() => {
71
+ logger.info`Operation completed in ${humanDate.delta(Date.now() - start)} (${process.exitCode !== 0 ? 'failed' : 'success'}).`;
72
+ }),
73
+ );
package/src/tsconfig.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "@internal/local-rig/profiles/default/tsconfig.json",
2
+ "extends": "@build-script/single-dog-asset/package/tsconfig.json",
3
3
  "compilerOptions": {
4
4
  "typeRoots": ["../node_modules/@types", "../node_modules"],
5
5
  "outDir": "../lib",
@@ -1,7 +0,0 @@
1
- export { printUsage } from './common/args.js';
2
- export { projectRoot } from './common/paths.js';
3
- export { selfRoot } from './common/paths.js';
4
- export type { ICommand } from './common/config-file.js';
5
- export type { IConfigFile } from './common/config-file.js';
6
- export { loadConfigFile } from './common/config-file.js';
7
- //# sourceMappingURL=autoindex.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"autoindex.d.ts","sourceRoot":"","sources":["../src/autoindex.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG7C,YAAY,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
package/lib/autoindex.js DELETED
@@ -1,14 +0,0 @@
1
- // DO NOT EDIT THIS FILE
2
- // @ts-ignore
3
- /* eslint-disable */
4
- /* common/args.ts */
5
- // Identifiers
6
- export { printUsage } from './common/args.js';
7
- /* common/paths.ts */
8
- // Identifiers
9
- export { projectRoot } from './common/paths.js';
10
- export { selfRoot } from './common/paths.js';
11
- export { loadConfigFile } from './common/config-file.js';
12
- /* bin.ts */
13
- // Identifiers
14
- //# sourceMappingURL=autoindex.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"autoindex.js","sourceRoot":"","sources":["../src/autoindex.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,aAAa;AACb,oBAAoB;AAEpB,oBAAoB;AACpB,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,qBAAqB;AACrB,cAAc;AACd,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAK7C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY;AACZ,cAAc"}