at-builder 1.2.2 → 1.2.4

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,379 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import logger from "./logger";
4
+
5
+ export interface DiagnosticIssue {
6
+ id: string;
7
+ severity: 'error' | 'warning';
8
+ message: string;
9
+ suggestion?: string;
10
+ fixable: boolean;
11
+ file?: string;
12
+ }
13
+
14
+ /**
15
+ * Run comprehensive diagnostics on the project
16
+ */
17
+ export const runDiagnostics = async (projectPath: string, verbose: boolean = false): Promise<DiagnosticIssue[]> => {
18
+ const issues: DiagnosticIssue[] = [];
19
+
20
+ if (verbose) logger.info("runDiagnostics", `Running diagnostics on ${projectPath}`);
21
+
22
+ // Check for required files
23
+ await checkEnvFile(projectPath, issues);
24
+ await checkAdobeConfig(projectPath, issues);
25
+ await checkWatchConfig(projectPath, issues);
26
+ await checkPackageJson(projectPath, issues);
27
+ await checkActivitiesFolder(projectPath, issues);
28
+
29
+ // Check environment variables
30
+ await checkEnvVariables(projectPath, issues);
31
+
32
+ // Check dependencies
33
+ await checkDependencies(projectPath, issues);
34
+
35
+ return issues;
36
+ };
37
+
38
+ /**
39
+ * Attempt to fix the provided issues
40
+ */
41
+ export const fixIssues = async (issues: DiagnosticIssue[], projectPath: string, verbose: boolean = false): Promise<number> => {
42
+ let fixedCount = 0;
43
+
44
+ for (const issue of issues) {
45
+ if (!issue.fixable) continue;
46
+
47
+ try {
48
+ if (verbose) logger.info("fixIssues", `Attempting to fix: ${issue.id}`);
49
+
50
+ const success = await fixIssue(issue, projectPath, verbose);
51
+ if (success) {
52
+ console.log(`✅ Fixed: ${issue.message}`);
53
+ fixedCount++;
54
+ } else {
55
+ console.log(`❌ Could not fix: ${issue.message}`);
56
+ }
57
+ } catch (error) {
58
+ console.log(`❌ Error fixing ${issue.id}: ${error.message}`);
59
+ }
60
+ }
61
+
62
+ return fixedCount;
63
+ };
64
+
65
+ /**
66
+ * Fix a specific issue
67
+ */
68
+ const fixIssue = async (issue: DiagnosticIssue, projectPath: string, verbose: boolean): Promise<boolean> => {
69
+ switch (issue.id) {
70
+ case 'missing-env':
71
+ return await createEnvFile(projectPath);
72
+ case 'missing-adobe-config':
73
+ return await createAdobeConfig(projectPath);
74
+ case 'missing-watch-config':
75
+ return await createWatchConfig(projectPath);
76
+ case 'missing-activities-folder':
77
+ return await createActivitiesFolder(projectPath);
78
+ case 'missing-package-json':
79
+ return await createPackageJson(projectPath);
80
+ default:
81
+ return false;
82
+ }
83
+ };
84
+
85
+ /**
86
+ * Check if .env file exists and has required variables
87
+ */
88
+ const checkEnvFile = async (projectPath: string, issues: DiagnosticIssue[]): Promise<void> => {
89
+ const envPath = path.join(projectPath, '.env');
90
+
91
+ if (!fs.existsSync(envPath)) {
92
+ issues.push({
93
+ id: 'missing-env',
94
+ severity: 'error',
95
+ message: '.env file is missing',
96
+ suggestion: 'Create .env file with required environment variables',
97
+ fixable: true,
98
+ file: '.env'
99
+ });
100
+ return;
101
+ }
102
+
103
+ // Check if .env has required variables
104
+ const envContent = fs.readFileSync(envPath, 'utf8');
105
+ const requiredVars = [
106
+ 'ACTIVITIES_BASE_FOLDER',
107
+ 'ACTIVITY_FOLDER_NAME',
108
+ 'ADOBE_CLIENT_ID',
109
+ 'ADOBE_CLIENT_SECRET'
110
+ ];
111
+
112
+ const missingVars = requiredVars.filter(varName => !envContent.includes(varName));
113
+
114
+ if (missingVars.length > 0) {
115
+ issues.push({
116
+ id: 'incomplete-env',
117
+ severity: 'warning',
118
+ message: `.env file missing variables: ${missingVars.join(', ')}`,
119
+ suggestion: 'Add missing environment variables to .env file',
120
+ fixable: true,
121
+ file: '.env'
122
+ });
123
+ }
124
+ };
125
+
126
+ /**
127
+ * Check if adobe.config.js exists
128
+ */
129
+ const checkAdobeConfig = async (projectPath: string, issues: DiagnosticIssue[]): Promise<void> => {
130
+ const configPath = path.join(projectPath, 'adobe.config.js');
131
+
132
+ if (!fs.existsSync(configPath)) {
133
+ issues.push({
134
+ id: 'missing-adobe-config',
135
+ severity: 'error',
136
+ message: 'adobe.config.js file is missing',
137
+ suggestion: 'Create Adobe Target API configuration file',
138
+ fixable: true,
139
+ file: 'adobe.config.js'
140
+ });
141
+ }
142
+ };
143
+
144
+ /**
145
+ * Check if watch-config.json exists
146
+ */
147
+ const checkWatchConfig = async (projectPath: string, issues: DiagnosticIssue[]): Promise<void> => {
148
+ const configPath = path.join(projectPath, 'watch-config.json');
149
+
150
+ if (!fs.existsSync(configPath)) {
151
+ issues.push({
152
+ id: 'missing-watch-config',
153
+ severity: 'warning',
154
+ message: 'watch-config.json file is missing',
155
+ suggestion: 'Create build configuration file',
156
+ fixable: true,
157
+ file: 'watch-config.json'
158
+ });
159
+ }
160
+ };
161
+
162
+ /**
163
+ * Check if package.json exists
164
+ */
165
+ const checkPackageJson = async (projectPath: string, issues: DiagnosticIssue[]): Promise<void> => {
166
+ const packagePath = path.join(projectPath, 'package.json');
167
+
168
+ if (!fs.existsSync(packagePath)) {
169
+ issues.push({
170
+ id: 'missing-package-json',
171
+ severity: 'error',
172
+ message: 'package.json file is missing',
173
+ suggestion: 'Initialize npm project with package.json',
174
+ fixable: true,
175
+ file: 'package.json'
176
+ });
177
+ }
178
+ };
179
+
180
+ /**
181
+ * Check if Activities folder exists
182
+ */
183
+ const checkActivitiesFolder = async (projectPath: string, issues: DiagnosticIssue[]): Promise<void> => {
184
+ // Try to read ACTIVITIES_BASE_FOLDER from .env, fallback to default
185
+ let activitiesFolder = 'Activities';
186
+ const envPath = path.join(projectPath, '.env');
187
+
188
+ if (fs.existsSync(envPath)) {
189
+ const envContent = fs.readFileSync(envPath, 'utf8');
190
+ const match = envContent.match(/ACTIVITIES_BASE_FOLDER=["']?([^"'\n\r]+)["']?/);
191
+ if (match) {
192
+ activitiesFolder = match[1];
193
+ }
194
+ }
195
+
196
+ const activitiesPath = path.join(projectPath, activitiesFolder);
197
+
198
+ if (!fs.existsSync(activitiesPath)) {
199
+ issues.push({
200
+ id: 'missing-activities-folder',
201
+ severity: 'warning',
202
+ message: `${activitiesFolder} folder is missing`,
203
+ suggestion: `Create ${activitiesFolder} folder for your activities`,
204
+ fixable: true,
205
+ file: activitiesFolder
206
+ });
207
+ }
208
+ };
209
+
210
+ /**
211
+ * Check environment variables content
212
+ */
213
+ const checkEnvVariables = async (projectPath: string, issues: DiagnosticIssue[]): Promise<void> => {
214
+ const envPath = path.join(projectPath, '.env');
215
+ if (!fs.existsSync(envPath)) return;
216
+
217
+ const envContent = fs.readFileSync(envPath, 'utf8');
218
+
219
+ // Check if ACTIVITY_FOLDER_NAME is empty
220
+ if (envContent.includes('ACTIVITY_FOLDER_NAME=""') || envContent.includes('ACTIVITY_FOLDER_NAME=\'\'')) {
221
+ issues.push({
222
+ id: 'empty-activity-folder-name',
223
+ severity: 'warning',
224
+ message: 'ACTIVITY_FOLDER_NAME is empty',
225
+ suggestion: 'Set ACTIVITY_FOLDER_NAME to your activity folder name',
226
+ fixable: false
227
+ });
228
+ }
229
+
230
+ // Check if Adobe credentials are empty
231
+ if (envContent.includes('ADOBE_CLIENT_ID=""') || envContent.includes('ADOBE_CLIENT_ID=\'\'')) {
232
+ issues.push({
233
+ id: 'empty-adobe-client-id',
234
+ severity: 'warning',
235
+ message: 'ADOBE_CLIENT_ID is empty',
236
+ suggestion: 'Set your Adobe Target API client ID',
237
+ fixable: false
238
+ });
239
+ }
240
+
241
+ if (envContent.includes('ADOBE_CLIENT_SECRET=""') || envContent.includes('ADOBE_CLIENT_SECRET=\'\'')) {
242
+ issues.push({
243
+ id: 'empty-adobe-client-secret',
244
+ severity: 'warning',
245
+ message: 'ADOBE_CLIENT_SECRET is empty',
246
+ suggestion: 'Set your Adobe Target API client secret',
247
+ fixable: false
248
+ });
249
+ }
250
+ };
251
+
252
+ /**
253
+ * Check dependencies
254
+ */
255
+ const checkDependencies = async (projectPath: string, issues: DiagnosticIssue[]): Promise<void> => {
256
+ const packagePath = path.join(projectPath, 'package.json');
257
+ if (!fs.existsSync(packagePath)) return;
258
+
259
+ const nodeModulesPath = path.join(projectPath, 'node_modules');
260
+
261
+ if (!fs.existsSync(nodeModulesPath)) {
262
+ issues.push({
263
+ id: 'missing-node-modules',
264
+ severity: 'warning',
265
+ message: 'node_modules folder is missing',
266
+ suggestion: 'Run "npm install" to install dependencies',
267
+ fixable: false
268
+ });
269
+ }
270
+ };
271
+
272
+ // Fix functions
273
+
274
+ const createEnvFile = async (projectPath: string): Promise<boolean> => {
275
+ const envPath = path.join(projectPath, '.env');
276
+ const envContent = `ACTIVITIES_BASE_FOLDER="Activities"
277
+ ACTIVITY_FOLDER_NAME=""
278
+ PUPPETEER_LANDING_PAGE=""
279
+ TARGET_URL=""
280
+ LOGIN_URL=""
281
+ VARIATION="Variation-1"
282
+ NODE_ENV="development"
283
+ VERBOSE=false
284
+
285
+ # Adobe Target Deployment Configuration
286
+ ADOBE_CLIENT_ID=""
287
+ ADOBE_CLIENT_SECRET=""`;
288
+
289
+ try {
290
+ fs.writeFileSync(envPath, envContent, 'utf8');
291
+ return true;
292
+ } catch (error) {
293
+ return false;
294
+ }
295
+ };
296
+
297
+ const createAdobeConfig = async (projectPath: string): Promise<boolean> => {
298
+ const configPath = path.join(projectPath, 'adobe.config.js');
299
+ const configContent = `/**
300
+ * Adobe Target API Configuration
301
+ *
302
+ * Configuration constants for Adobe Target API integration.
303
+ * These values are used by the deployment script to connect to Adobe Target.
304
+ */
305
+
306
+ module.exports = {
307
+ BASE_URL_NEW: 'https://mc.adobe.io/ups/target/',
308
+ BASE_URL: 'https://mc.adobe.io/ups/target/activities/ab/',
309
+ IMS_TOKEN_URL: 'https://ims-na1.adobelogin.com/ims/token/v3',
310
+ IMS_SCOPE: 'openid,AdobeID,target_sdk,additional_info.projectedProductContext'
311
+ };`;
312
+
313
+ try {
314
+ fs.writeFileSync(configPath, configContent, 'utf8');
315
+ return true;
316
+ } catch (error) {
317
+ return false;
318
+ }
319
+ };
320
+
321
+ const createWatchConfig = async (projectPath: string): Promise<boolean> => {
322
+ const configPath = path.join(projectPath, 'watch-config.json');
323
+ const configContent = {
324
+ "VARIATION": "Variation-1"
325
+ };
326
+
327
+ try {
328
+ fs.writeFileSync(configPath, JSON.stringify(configContent, null, 2), 'utf8');
329
+ return true;
330
+ } catch (error) {
331
+ return false;
332
+ }
333
+ };
334
+
335
+ const createActivitiesFolder = async (projectPath: string): Promise<boolean> => {
336
+ // Try to read ACTIVITIES_BASE_FOLDER from .env, fallback to default
337
+ let activitiesFolder = 'Activities';
338
+ const envPath = path.join(projectPath, '.env');
339
+
340
+ if (fs.existsSync(envPath)) {
341
+ const envContent = fs.readFileSync(envPath, 'utf8');
342
+ const match = envContent.match(/ACTIVITIES_BASE_FOLDER=["']?([^"'\n\r]+)["']?/);
343
+ if (match) {
344
+ activitiesFolder = match[1];
345
+ }
346
+ }
347
+
348
+ const activitiesPath = path.join(projectPath, activitiesFolder);
349
+
350
+ try {
351
+ fs.mkdirSync(activitiesPath, { recursive: true });
352
+ return true;
353
+ } catch (error) {
354
+ return false;
355
+ }
356
+ };
357
+
358
+ const createPackageJson = async (projectPath: string): Promise<boolean> => {
359
+ const packagePath = path.join(projectPath, 'package.json');
360
+ const packageContent = {
361
+ "name": path.basename(projectPath),
362
+ "version": "1.0.0",
363
+ "description": "",
364
+ "main": "index.js",
365
+ "scripts": {
366
+ "test": "echo \"Error: no test specified\" && exit 1"
367
+ },
368
+ "keywords": [],
369
+ "author": "",
370
+ "license": "ISC"
371
+ };
372
+
373
+ try {
374
+ fs.writeFileSync(packagePath, JSON.stringify(packageContent, null, 2), 'utf8');
375
+ return true;
376
+ } catch (error) {
377
+ return false;
378
+ }
379
+ };
package/tsconfig.json CHANGED
@@ -22,7 +22,7 @@
22
22
  "experimentalDecorators": true,
23
23
  "skipLibCheck": true,
24
24
  "esModuleInterop": true,
25
- "resolveJsonModule": true,
25
+ "resolveJsonModule": true
26
26
  },
27
27
  "include": [
28
28
  "src/**/*",
package/webpack.config.js CHANGED
@@ -1,3 +1,6 @@
1
+ /* eslint-disable no-undef */
2
+ /* eslint-disable @typescript-eslint/no-require-imports */
3
+
1
4
  const path = require('path');
2
5
  const fs = require('fs');
3
6
  const dotenv = require('dotenv');
@@ -74,7 +77,40 @@ var traversePath = function (dir) {
74
77
 
75
78
  // console.log("\x1b[33m%s\x1b[0m", `${process.env.ACTIVITY_FOLDER_NAME}`);
76
79
 
77
- var files = traversePath(path.join(PWD, 'Activities', process.env.ACTIVITY_FOLDER_NAME).toString());
80
+ // Validate required environment variables
81
+ if (!process.env.ACTIVITY_FOLDER_NAME || process.env.ACTIVITY_FOLDER_NAME.trim() === '') {
82
+ console.error('\x1b[31m%s\x1b[0m', '❌ Error: ACTIVITY_FOLDER_NAME environment variable is required but not set.');
83
+ console.error('\x1b[33m%s\x1b[0m', '💡 Please set ACTIVITY_FOLDER_NAME in your .env file or run "atb doctor --fix" to check your configuration.');
84
+ process.exit(1);
85
+ }
86
+
87
+ // Use configurable activities folder name from environment
88
+ const ACTIVITIES_BASE_FOLDER = process.env.ACTIVITIES_BASE_FOLDER || 'Activities';
89
+ const ACTIVITY_FOLDER = process.env.ACTIVITY_FOLDER_NAME.trim();
90
+
91
+ console.log('\x1b[36m%s\x1b[0m', `📦 Building activity: ${ACTIVITY_FOLDER}`);
92
+ console.log('\x1b[36m%s\x1b[0m', `📁 Activities folder: ${ACTIVITIES_BASE_FOLDER}`);
93
+
94
+ // Check if the activity folder exists
95
+ const activityPath = path.join(PWD, ACTIVITIES_BASE_FOLDER, ACTIVITY_FOLDER);
96
+ if (!fs.existsSync(activityPath)) {
97
+ console.error('\x1b[31m%s\x1b[0m', `❌ Error: Activity folder not found: ${activityPath}`);
98
+ console.error('\x1b[33m%s\x1b[0m', '💡 Please check your ACTIVITY_FOLDER_NAME or create the activity folder first.');
99
+ console.error('\x1b[33m%s\x1b[0m', '💡 Run "atb new" to create a new activity or "atb doctor" to diagnose issues.');
100
+ process.exit(1);
101
+ }
102
+
103
+ var files = traversePath(activityPath.toString());
104
+
105
+ // Check if we found any files to build
106
+ if (!files || files.length === 0) {
107
+ console.error('\x1b[31m%s\x1b[0m', `❌ Error: No buildable files found in ${activityPath}`);
108
+ console.error('\x1b[33m%s\x1b[0m', '💡 Please ensure your activity folder contains variations (folders starting with "V") with .js or .ts files.');
109
+ console.error('\x1b[33m%s\x1b[0m', '💡 Expected structure: Activities/your-activity/Variation-1/index.js');
110
+ process.exit(1);
111
+ }
112
+
113
+ console.log('\x1b[36m%s\x1b[0m', `🔍 Found ${files.length} file(s) to build`);
78
114
 
79
115
  //Create entry object which is needed for webpack config
80
116
  var entries = {};
@@ -1,196 +0,0 @@
1
- {
2
- "version": "1.1.5",
3
- "name": "at-builder",
4
- "dependencies": {
5
- "@babel/core": {
6
- "version": "7.26.8",
7
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.8.tgz",
8
- "overridden": false
9
- },
10
- "@babel/eslint-parser": {
11
- "version": "7.18.9",
12
- "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.18.9.tgz",
13
- "overridden": false
14
- },
15
- "@babel/plugin-proposal-class-properties": {
16
- "version": "7.18.6",
17
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz",
18
- "overridden": false
19
- },
20
- "@babel/plugin-syntax-dynamic-import": {
21
- "version": "7.8.3",
22
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
23
- "overridden": false
24
- },
25
- "@babel/plugin-transform-runtime": {
26
- "version": "7.18.9",
27
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.9.tgz",
28
- "overridden": false
29
- },
30
- "@babel/preset-env": {
31
- "version": "7.18.9",
32
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.9.tgz",
33
- "overridden": false
34
- },
35
- "@babel/preset-react": {
36
- "version": "7.18.6",
37
- "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz",
38
- "overridden": false
39
- },
40
- "@babel/runtime": {
41
- "version": "7.18.9",
42
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
43
- "overridden": false
44
- },
45
- "@types/node": {
46
- "version": "22.13.4",
47
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz",
48
- "overridden": false
49
- },
50
- "async": {
51
- "version": "3.2.3",
52
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
53
- "overridden": false
54
- },
55
- "babel-loader": {
56
- "version": "9.2.1",
57
- "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz",
58
- "overridden": false
59
- },
60
- "babel-plugin-transform-async-to-generator": {
61
- "version": "6.24.1",
62
- "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
63
- "overridden": false
64
- },
65
- "build": {
66
- "version": "0.1.4",
67
- "resolved": "https://registry.npmjs.org/build/-/build-0.1.4.tgz",
68
- "overridden": false
69
- },
70
- "chokidar": {
71
- "version": "4.0.3",
72
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
73
- "overridden": false
74
- },
75
- "cli-color": {
76
- "version": "2.0.3",
77
- "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz",
78
- "overridden": false
79
- },
80
- "commander": {
81
- "version": "13.1.0",
82
- "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz",
83
- "overridden": false
84
- },
85
- "cross-env": {
86
- "version": "7.0.3",
87
- "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
88
- "overridden": false
89
- },
90
- "css-loader": {
91
- "version": "7.1.2",
92
- "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz",
93
- "overridden": false
94
- },
95
- "dotenv": {
96
- "version": "16.0.0",
97
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz",
98
- "overridden": false
99
- },
100
- "eslint-loader": {
101
- "version": "4.0.2",
102
- "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-4.0.2.tgz",
103
- "overridden": false
104
- },
105
- "eslint-webpack-plugin": {
106
- "version": "4.2.0",
107
- "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-4.2.0.tgz",
108
- "overridden": false
109
- },
110
- "eslint": {
111
- "version": "9.20.1",
112
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz",
113
- "overridden": false
114
- },
115
- "inquirer": {
116
- "version": "12.4.1",
117
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.4.1.tgz",
118
- "overridden": false
119
- },
120
- "plop": {
121
- "version": "4.0.1",
122
- "resolved": "https://registry.npmjs.org/plop/-/plop-4.0.1.tgz",
123
- "overridden": false
124
- },
125
- "postcss-loader": {
126
- "version": "8.1.1",
127
- "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz",
128
- "overridden": false
129
- },
130
- "postcss-preset-env": {
131
- "version": "10.1.4",
132
- "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.1.4.tgz",
133
- "overridden": false
134
- },
135
- "postcss": {
136
- "version": "8.4.12",
137
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz",
138
- "overridden": false
139
- },
140
- "puppeteer": {
141
- "version": "24.2.0",
142
- "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.2.0.tgz",
143
- "overridden": false
144
- },
145
- "readline": {
146
- "version": "1.3.0",
147
- "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz",
148
- "overridden": false
149
- },
150
- "sass-loader": {
151
- "version": "16.0.4",
152
- "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.4.tgz",
153
- "overridden": false
154
- },
155
- "sass": {
156
- "version": "1.53.0",
157
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.53.0.tgz",
158
- "overridden": false
159
- },
160
- "style-loader": {
161
- "version": "4.0.0",
162
- "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz",
163
- "overridden": false
164
- },
165
- "terser-webpack-plugin": {
166
- "version": "5.3.3",
167
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz",
168
- "overridden": false
169
- },
170
- "ts-loader": {
171
- "version": "9.3.1",
172
- "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.1.tgz",
173
- "overridden": false
174
- },
175
- "typescript": {
176
- "version": "5.7.3",
177
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
178
- "overridden": false
179
- },
180
- "webpack-cli": {
181
- "version": "6.0.1",
182
- "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz",
183
- "overridden": false
184
- },
185
- "webpack": {
186
- "version": "5.72.0",
187
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.0.tgz",
188
- "overridden": false
189
- },
190
- "wrapper-webpack-plugin": {
191
- "version": "2.1.0",
192
- "resolved": "https://registry.npmjs.org/wrapper-webpack-plugin/-/wrapper-webpack-plugin-2.1.0.tgz",
193
- "overridden": false
194
- }
195
- }
196
- }