@9apes/cli 0.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/README.md +145 -0
- package/dist/command.d.ts +8 -0
- package/dist/command.d.ts.map +1 -0
- package/dist/command.js +90 -0
- package/dist/command.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +37 -0
- package/dist/config.js.map +1 -0
- package/dist/index-dev.d.ts +3 -0
- package/dist/index-dev.d.ts.map +1 -0
- package/dist/index-dev.js +13 -0
- package/dist/index-dev.js.map +1 -0
- package/dist/index-local.d.ts +3 -0
- package/dist/index-local.d.ts.map +1 -0
- package/dist/index-local.js +13 -0
- package/dist/index-local.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/inject.d.ts +14 -0
- package/dist/inject.d.ts.map +1 -0
- package/dist/inject.js +161 -0
- package/dist/inject.js.map +1 -0
- package/dist/sourcemap.d.ts +48 -0
- package/dist/sourcemap.d.ts.map +1 -0
- package/dist/sourcemap.js +262 -0
- package/dist/sourcemap.js.map +1 -0
- package/dist/status.d.ts +17 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +72 -0
- package/dist/status.js.map +1 -0
- package/dist/upload.d.ts +25 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +119 -0
- package/dist/upload.js.map +1 -0
- package/dist/vite-plugin.d.ts +22 -0
- package/dist/vite-plugin.d.ts.map +1 -0
- package/dist/vite-plugin.js +95 -0
- package/dist/vite-plugin.js.map +1 -0
- package/package.json +61 -0
- package/src/command.ts +100 -0
- package/src/config.ts +44 -0
- package/src/index-dev.ts +16 -0
- package/src/index-local.ts +16 -0
- package/src/index.ts +12 -0
- package/src/inject.ts +195 -0
- package/src/sourcemap.ts +317 -0
- package/src/status.ts +94 -0
- package/src/upload.ts +190 -0
- package/src/vite-plugin.ts +160 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin.js","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@9apes/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A CLI tool built with TypeScript",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./vite": {
|
|
13
|
+
"types": "./dist/vite-plugin.d.ts",
|
|
14
|
+
"import": "./dist/vite-plugin.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"apeslocal-cli": "dist/index-local.js",
|
|
19
|
+
"apesdev-cli": "dist/index-dev.js"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"cli",
|
|
23
|
+
"typescript",
|
|
24
|
+
"node"
|
|
25
|
+
],
|
|
26
|
+
"author": "",
|
|
27
|
+
"license": "ISC",
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/cli-progress": "^3.11.6",
|
|
30
|
+
"@types/node": "24.9.1",
|
|
31
|
+
"@typescript-eslint/eslint-plugin": "8.46.2",
|
|
32
|
+
"@typescript-eslint/parser": "8.46.2",
|
|
33
|
+
"eslint": "8.57.0",
|
|
34
|
+
"eslint-config-prettier": "10.1.8",
|
|
35
|
+
"prettier": "3.6.2",
|
|
36
|
+
"typescript": "5.9.3",
|
|
37
|
+
"vite": "^6.3.1"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"vite": ">=6"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@inquirer/prompts": "7.9.0",
|
|
44
|
+
"axios": "^1.6.0",
|
|
45
|
+
"cli-progress": "^3.12.0",
|
|
46
|
+
"commander": "14.0.1",
|
|
47
|
+
"fast-glob": "^3.3.3",
|
|
48
|
+
"form-data": "^4.0.0",
|
|
49
|
+
"p-limit": "^7.2.0"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc",
|
|
53
|
+
"dev": "tsc --watch",
|
|
54
|
+
"start": "node dist/index.js",
|
|
55
|
+
"clean": "rm -rf dist",
|
|
56
|
+
"lint": "eslint src/**/*.ts",
|
|
57
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
58
|
+
"format": "prettier --write src/**/*.ts",
|
|
59
|
+
"format:check": "prettier --check src/**/*.ts"
|
|
60
|
+
}
|
|
61
|
+
}
|
package/src/command.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import { input } from '@inquirer/prompts';
|
|
3
|
+
import { loadConfig, saveConfig } from './config.js';
|
|
4
|
+
import { injectDebugIdsAndUpload } from './sourcemap.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Setup commands for the CLI program
|
|
8
|
+
* @param configFileName - Name of the config file (e.g., 'config-local.json' or 'config-dev.json')
|
|
9
|
+
* @param baseUrl - Base URL for the API (e.g., 'http://127.0.0.1:8000/api/v1' or 'https://dev.nineapes.com/api/v1')
|
|
10
|
+
* @param cliName - Name of the CLI for error messages (e.g., 'apeslocal-cli' or 'apesdev-cli')
|
|
11
|
+
*/
|
|
12
|
+
export function setupCommands(configFileName: string, baseUrl: string, cliName: string) {
|
|
13
|
+
// Config command with subcommands
|
|
14
|
+
const configCommand = program
|
|
15
|
+
.command('config')
|
|
16
|
+
.description('Manage configuration');
|
|
17
|
+
|
|
18
|
+
// Config set subcommand
|
|
19
|
+
configCommand
|
|
20
|
+
.command('set')
|
|
21
|
+
.description('Set API key')
|
|
22
|
+
.argument('[apikey]', 'API key (optional, will prompt if not provided)')
|
|
23
|
+
.action(async (apikey?: string) => {
|
|
24
|
+
try {
|
|
25
|
+
let finalApiKey = apikey;
|
|
26
|
+
|
|
27
|
+
if (!finalApiKey) {
|
|
28
|
+
finalApiKey = await input({
|
|
29
|
+
message: 'Enter your API key:',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const configPath = saveConfig({ apiKey: finalApiKey }, configFileName);
|
|
34
|
+
console.log('✅ API key saved successfully at : ' + configPath);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('❌ Error setting API key:', error);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Config show subcommand
|
|
42
|
+
configCommand
|
|
43
|
+
.command('show')
|
|
44
|
+
.description('Show current API key')
|
|
45
|
+
.action(() => {
|
|
46
|
+
try {
|
|
47
|
+
const config = loadConfig(configFileName);
|
|
48
|
+
|
|
49
|
+
if (!config) {
|
|
50
|
+
console.log(`❌ No configuration found. Run "${cliName} config set" to set your API key.`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.log('Current API key:', config.apiKey);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error('❌ Error reading config:', error);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Sourcemaps command with subcommands
|
|
62
|
+
const sourcemapsCommand = program
|
|
63
|
+
.command('sourcemaps')
|
|
64
|
+
.description('Manage source maps');
|
|
65
|
+
|
|
66
|
+
// Sourcemaps inject subcommand
|
|
67
|
+
sourcemapsCommand
|
|
68
|
+
.command('inject')
|
|
69
|
+
.description('Inject debug IDs into JavaScript files and source maps')
|
|
70
|
+
.argument('<path>', 'Directory path to process')
|
|
71
|
+
.requiredOption('--projectid <id>', 'Project ID (required)')
|
|
72
|
+
.option('--release-version <version>', 'Release version (optional)')
|
|
73
|
+
.option('--apikey <apikey>', 'Api key (optional, if config not set)')
|
|
74
|
+
.action(async (path: string, options: { projectid: string; releaseVersion?: string; apikey?: string }) => {
|
|
75
|
+
try {
|
|
76
|
+
// Load configuration
|
|
77
|
+
const config = loadConfig(configFileName);
|
|
78
|
+
const apiKey = options.apikey || config?.apiKey;
|
|
79
|
+
|
|
80
|
+
if (!apiKey) {
|
|
81
|
+
console.log(`❌ No API key found. Run "${cliName} config set" to set your API key or use --apikey <apikey> to set the API key.`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Validate path parameter
|
|
86
|
+
if (!path) {
|
|
87
|
+
console.log('❌ Path argument is required.');
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Inject debug IDs into JavaScript files and source maps
|
|
92
|
+
await injectDebugIdsAndUpload(path, { apiKey }, options.projectid, baseUrl, options.releaseVersion);
|
|
93
|
+
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('❌ Error processing sourcemaps:', error);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
|
|
4
|
+
export interface Config {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getConfigPath(configFileName: string): string {
|
|
9
|
+
return path.join(process.cwd(), configFileName);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function loadConfig(configFileName: string): Config | null {
|
|
13
|
+
try {
|
|
14
|
+
const configPath = getConfigPath(configFileName);
|
|
15
|
+
if (!fs.existsSync(configPath)) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const configData = fs.readFileSync(configPath, 'utf8');
|
|
20
|
+
return JSON.parse(configData) as Config;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('Error loading config:', error);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function saveConfig(config: Config, configFileName: string): string {
|
|
28
|
+
try {
|
|
29
|
+
const configPath = getConfigPath(configFileName);
|
|
30
|
+
const configDir = path.dirname(configPath);
|
|
31
|
+
|
|
32
|
+
// Create directory if it doesn't exist
|
|
33
|
+
if (!fs.existsSync(configDir)) {
|
|
34
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Write config file
|
|
38
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
39
|
+
return configPath;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error('Error saving config:', error);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/index-dev.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import { setupCommands } from './command.js';
|
|
4
|
+
|
|
5
|
+
// CLI version and description
|
|
6
|
+
program
|
|
7
|
+
.name('apesdev-cli')
|
|
8
|
+
.description('A CLI tool for dev environment')
|
|
9
|
+
.version('1.0.0');
|
|
10
|
+
|
|
11
|
+
// Setup commands with dev mode
|
|
12
|
+
setupCommands('config-dev.json', 'https://dev.nineapes.com/api/v1', 'apesdev-cli');
|
|
13
|
+
|
|
14
|
+
// Parse command line arguments
|
|
15
|
+
program.parse();
|
|
16
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import { setupCommands } from './command.js';
|
|
4
|
+
|
|
5
|
+
// CLI version and description
|
|
6
|
+
program
|
|
7
|
+
.name('apeslocal-cli')
|
|
8
|
+
.description('A CLI tool for local development environment')
|
|
9
|
+
.version('1.0.0');
|
|
10
|
+
|
|
11
|
+
// Setup commands with local mode
|
|
12
|
+
setupCommands('config-local.json', 'http://127.0.0.1:8000/api/v1', 'apeslocal-cli');
|
|
13
|
+
|
|
14
|
+
// Parse command line arguments
|
|
15
|
+
program.parse();
|
|
16
|
+
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import './command.js';
|
|
4
|
+
|
|
5
|
+
// CLI version and description
|
|
6
|
+
program
|
|
7
|
+
.name('apes-cli')
|
|
8
|
+
.description('A CLI tool built with TypeScript')
|
|
9
|
+
.version('1.0.0');
|
|
10
|
+
|
|
11
|
+
// Parse command line arguments
|
|
12
|
+
program.parse();
|
package/src/inject.ts
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Read file as buffer and decode to UTF-8 with automatic BOM stripping
|
|
6
|
+
* @param jsFile - Path to JavaScript file
|
|
7
|
+
* @returns File content as UTF-8 string
|
|
8
|
+
*/
|
|
9
|
+
async function readFileAsUtf8(jsFile: string): Promise<string> {
|
|
10
|
+
const buffer = await fs.readFile(jsFile);
|
|
11
|
+
const decoder = new TextDecoder('utf-8');
|
|
12
|
+
return decoder.decode(buffer);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Find existing debug ID snippet in file content
|
|
18
|
+
* @param content - File content to search
|
|
19
|
+
* @returns Object with debug ID and its index if found, null otherwise
|
|
20
|
+
*/
|
|
21
|
+
function findExistingDebugId(content: string): { id: string; index: number } | null {
|
|
22
|
+
const debugIdPattern = /_apesDebugIdIdentifier="apes-dbid-([^"]+)"/;
|
|
23
|
+
const match = content.match(debugIdPattern);
|
|
24
|
+
if (!match || match.index === undefined) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
id: match[1],
|
|
29
|
+
index: match.index,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Find the start position of the debug ID snippet
|
|
35
|
+
* @param content - File content to search
|
|
36
|
+
* @param debugIdIndex - Index where the debug ID identifier is found
|
|
37
|
+
* @returns Start index of the snippet, or -1 if not found
|
|
38
|
+
*/
|
|
39
|
+
function findSnippetStart(content: string, debugIdIndex: number): number {
|
|
40
|
+
const snippetStartMarker = ';{try{';
|
|
41
|
+
for (let i = debugIdIndex; i >= 0; i--) {
|
|
42
|
+
if (content.slice(i, i + snippetStartMarker.length) === snippetStartMarker) {
|
|
43
|
+
return i;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return -1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Find the end position of the debug ID snippet
|
|
51
|
+
* @param content - File content to search
|
|
52
|
+
* @param debugIdIndex - Index where the debug ID identifier is found
|
|
53
|
+
* @returns End index (exclusive) of the snippet, or -1 if not found
|
|
54
|
+
*/
|
|
55
|
+
function findSnippetEnd(content: string, debugIdIndex: number): number {
|
|
56
|
+
const snippetEndMarker = '};';
|
|
57
|
+
for (let i = debugIdIndex; i < content.length; i++) {
|
|
58
|
+
if (content.slice(i, i + snippetEndMarker.length) === snippetEndMarker && i > debugIdIndex) {
|
|
59
|
+
return i + snippetEndMarker.length;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return -1;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Remove existing debug ID snippet from file content
|
|
67
|
+
* @param content - File content
|
|
68
|
+
* @param existingDebugId - Object containing the existing debug ID and its index
|
|
69
|
+
* @returns Content with the snippet removed
|
|
70
|
+
*/
|
|
71
|
+
function removeExistingSnippet(
|
|
72
|
+
content: string,
|
|
73
|
+
existingDebugId: { id: string; index: number }
|
|
74
|
+
): string {
|
|
75
|
+
const snippetStart = findSnippetStart(content, existingDebugId.index);
|
|
76
|
+
const snippetEnd = findSnippetEnd(content, existingDebugId.index);
|
|
77
|
+
|
|
78
|
+
if (snippetStart >= 0 && snippetEnd > snippetStart) {
|
|
79
|
+
return content.slice(0, snippetStart) + content.slice(snippetEnd);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return content;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Calculate the insertion position for the debug ID snippet
|
|
87
|
+
* Inserts after shebang (if present) and/or "use strict" directive (if present)
|
|
88
|
+
* @param content - File content
|
|
89
|
+
* @returns Index where the snippet should be inserted
|
|
90
|
+
*/
|
|
91
|
+
function calculateInsertionPosition(content: string): number {
|
|
92
|
+
let position = 0;
|
|
93
|
+
let insertPosition = 0;
|
|
94
|
+
|
|
95
|
+
// Check for shebang (must be at start, ends at first newline)
|
|
96
|
+
const shebangMatch = content.match(/^#!.*(\r?\n)?/);
|
|
97
|
+
if (shebangMatch) {
|
|
98
|
+
position += shebangMatch[0].length;
|
|
99
|
+
insertPosition = position;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check for "use strict" after shebang
|
|
103
|
+
// Pattern: optional whitespace, then "use strict" with quotes, optional semicolon, optional whitespace
|
|
104
|
+
const useStrictPattern = /^\s*["']use strict["'];?\s*/;
|
|
105
|
+
const remainingContent = content.slice(position);
|
|
106
|
+
const useStrictMatch = remainingContent.match(useStrictPattern);
|
|
107
|
+
|
|
108
|
+
if (useStrictMatch) {
|
|
109
|
+
insertPosition = position + useStrictMatch[0].length;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return insertPosition;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Inject debug ID into JavaScript file
|
|
117
|
+
* @param jsFile - Path to JavaScript file
|
|
118
|
+
* @param debugIdSnippet - Debug ID snippet to inject
|
|
119
|
+
* @param debugId - Debug ID
|
|
120
|
+
*/
|
|
121
|
+
export async function injectDebugIdIntoFile(
|
|
122
|
+
jsFile: string,
|
|
123
|
+
debugIdSnippet: string,
|
|
124
|
+
debugId: string
|
|
125
|
+
): Promise<void> {
|
|
126
|
+
try {
|
|
127
|
+
let content = await readFileAsUtf8(jsFile);
|
|
128
|
+
const existingDebugId = findExistingDebugId(content);
|
|
129
|
+
|
|
130
|
+
// If existing debug ID matches the one to inject, skip injection
|
|
131
|
+
if (existingDebugId && existingDebugId.id === debugId) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// If different debug ID exists, remove the old snippet
|
|
136
|
+
if (existingDebugId) {
|
|
137
|
+
content = removeExistingSnippet(content, existingDebugId);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Calculate insertion position and inject the new snippet
|
|
141
|
+
const insertPosition = calculateInsertionPosition(content);
|
|
142
|
+
const before = content.slice(0, insertPosition);
|
|
143
|
+
const after = content.slice(insertPosition);
|
|
144
|
+
const modifiedContent = before + debugIdSnippet + after;
|
|
145
|
+
|
|
146
|
+
// Write back to file
|
|
147
|
+
await fs.writeFile(jsFile, modifiedContent, 'utf-8');
|
|
148
|
+
} catch (error) {
|
|
149
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
150
|
+
throw new Error(`Failed to inject debug ID into ${jsFile}: ${errorMessage}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Inject debug ID into source map file
|
|
158
|
+
* @param mapFile - Path to source map file
|
|
159
|
+
* @param debugId - Debug ID to inject
|
|
160
|
+
*/
|
|
161
|
+
export async function injectDebugIdIntoMapFile(
|
|
162
|
+
mapFile: string | null,
|
|
163
|
+
debugId: string
|
|
164
|
+
): Promise<void> {
|
|
165
|
+
try {
|
|
166
|
+
if (!mapFile) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const content = await fs.readFile(mapFile, 'utf-8');
|
|
171
|
+
|
|
172
|
+
let sourcemap: Record<string, unknown>;
|
|
173
|
+
try {
|
|
174
|
+
sourcemap = JSON.parse(content);
|
|
175
|
+
} catch (parseError) {
|
|
176
|
+
throw new Error(`Invalid JSON in sourcemap file: ${parseError}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Skip if already has the same debug_id
|
|
180
|
+
if (sourcemap.debug_id === debugId) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Add the debug_id field
|
|
185
|
+
sourcemap.debug_id = debugId;
|
|
186
|
+
|
|
187
|
+
// Use compact JSON (no pretty-printing)
|
|
188
|
+
const modifiedContent = JSON.stringify(sourcemap);
|
|
189
|
+
await fs.writeFile(mapFile, modifiedContent, 'utf-8');
|
|
190
|
+
|
|
191
|
+
} catch (error) {
|
|
192
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
193
|
+
throw new Error(`Failed to inject debug ID into ${mapFile}: ${errorMessage}`);
|
|
194
|
+
}
|
|
195
|
+
}
|