New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@gasket/plugin-webpack

Package Overview
Dependencies
Maintainers
8
Versions
212
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@gasket/plugin-webpack - npm Package Compare versions

Comparing version
7.3.9
to
7.4.0
+61
cjs/actions.cjs
/// <reference types="@gasket/plugin-logger" />
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
default: function() {
return _default;
},
getWebpackConfig: function() {
return getWebpackConfig;
}
});
const _module = require("module");
const _webpackmetricsplugin = /*#__PURE__*/ _interop_require_default(require("./webpack-metrics-plugin.cjs"));
const _gasketenvguardplugin = /*#__PURE__*/ _interop_require_default(require("./gasket-env-guard-plugin.cjs"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const require1 = (0, _module.createRequire)(require("url").pathToFileURL(__filename).toString());
/**
* Sets up a context object with special getters
* @type {import('./internal.d.ts').setupContext}
*/ function setupContext(context) {
return {
...context,
get webpack () {
const webpack = require1('webpack');
return webpack;
}
};
}
function getWebpackConfig(gasket, initConfig, context) {
var _baseConfig, _baseConfig_resolve;
/** @type {import('webpack').Configuration} */ const baseConfig = {
...initConfig,
plugins: [
...initConfig && initConfig.plugins ? initConfig.plugins : [],
new _webpackmetricsplugin.default({
gasket
}),
new _gasketenvguardplugin.default()
].filter(Boolean)
};
(_baseConfig = baseConfig).resolve ?? (_baseConfig.resolve = {});
(_baseConfig_resolve = baseConfig.resolve).alias ?? (_baseConfig_resolve.alias = {});
const alias = /** @type {Record<string, string | false>} */ baseConfig.resolve.alias;
alias.webpack = false;
baseConfig.resolve.alias = alias;
return gasket.execWaterfallSync('webpackConfig', baseConfig, setupContext(context));
}
const _default = {
getWebpackConfig
};
/**
* Webpack plugin that prevents process.env.GASKET_ENV from being bundled
* in browser code to avoid leaking server-side configuration.
*/ Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
class GasketEnvGuardPlugin {
// No constructor needed - this plugin requires no configuration
apply(compiler) {
const pluginName = 'GasketEnvGuardPlugin';
// Hook into the compilation to scan modules
compiler.hooks.compilation.tap(pluginName, (compilation)=>{
// Hook into the module build process
compilation.hooks.buildModule.tap(pluginName, (module)=>{
// Skip node_modules
if (module.resource && module.resource.includes('node_modules')) {
return;
}
// Check for GASKET_ENV usage in the module source
if (module.resource && this.shouldCheckModule(module.resource)) {
this.scheduleSourceCheck(compilation, module);
}
});
});
}
shouldCheckModule(resourcePath) {
// Only check JavaScript/TypeScript files that are not in node_modules
const jsExtensions = [
'.js',
'.jsx',
'.ts',
'.tsx',
'.mjs'
];
return jsExtensions.some((ext)=>resourcePath.endsWith(ext)) && !resourcePath.includes('node_modules');
}
scheduleSourceCheck(compilation, module) {
// Hook into after module build to check the source
compilation.hooks.succeedModule.tap('GasketEnvGuardPlugin', (builtModule)=>{
if (builtModule === module && builtModule._source) {
this.checkModuleSource(compilation, builtModule);
}
});
}
checkModuleSource(compilation, module) {
let source = '';
// Try to get the source code
if (module._source && module._source.source) {
source = module._source.source();
} else if (module.originalSource && module.originalSource.source) {
source = module.originalSource.source();
}
if (source && this.containsGasketEnv(source)) {
this.handleGasketEnvDetection(compilation, module.resource);
}
}
containsGasketEnv(source) {
// Remove comments but preserve string patterns that are actual code
const cleanedSource = source// Remove single-line comments
.replace(/\/\/.*$/gm, '')// Remove multi-line comments
.replace(/\/\*[\s\S]*?\*\//g, '');
// Check for various patterns of GASKET_ENV usage
const patterns = [
/process\.env\.GASKET_ENV/g,
/process\.env\['GASKET_ENV'\]/g,
/process\.env\["GASKET_ENV"\]/g,
/process\.env\[`GASKET_ENV`\]/g
];
// Check if any pattern matches, but avoid matching inside string literals
for (const pattern of patterns){
const matches = [
...cleanedSource.matchAll(pattern)
];
for (const match of matches){
const beforeMatch = cleanedSource.substring(0, match.index);
// Simple check: count unescaped quotes before the match
// If odd number of quotes, we're likely inside a string
const singleQuotes = (beforeMatch.match(RegExp("(?<!\\\\)'", "g")) || []).length;
const doubleQuotes = (beforeMatch.match(RegExp('(?<!\\\\)"', "g")) || []).length;
const backticks = (beforeMatch.match(RegExp("(?<!\\\\)`", "g")) || []).length;
// If we're not inside quotes, this is a real match
if (singleQuotes % 2 === 0 && doubleQuotes % 2 === 0 && backticks % 2 === 0) {
return true;
}
}
}
return false;
}
handleGasketEnvDetection(compilation, resourcePath) {
const message = resourcePath ? `process.env.GASKET_ENV detected in ${resourcePath}` : 'process.env.GASKET_ENV detected in browser bundle';
const error = new Error(`${message}!\n\n` + `GASKET_ENV is intended for server-side environment configuration only.\n` + `Including it in browser bundles can expose sensitive configuration.\n\n` + `Recommended solutions:\n` + `1. Use gasket.config.env for environment-specific config\n` + `2. Use @gasket/data to pass server data to the client\n` + `3. Move environment-specific logic to server-side code\n\n` + `For more guidance, see: https://gasket.dev/docs/guides/webpack#gasket-env-protection`);
compilation.errors.push(error);
}
}
const _default = GasketEnvGuardPlugin;
/// <reference types="create-gasket-app" />
/// <reference types="@gasket/plugin-metadata" />
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _actions = /*#__PURE__*/ _interop_require_default(require("./actions.cjs"));
const _packagejson = /*#__PURE__*/ _interop_require_default(require("../package.json"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const { name, version, description, devDependencies } = _packagejson.default;
/** @type {import('@gasket/core').Plugin} */ const plugin = {
name,
version,
description,
actions: _actions.default,
hooks: {
create (gasket, { pkg, gasketConfig }) {
gasketConfig.addPlugin('pluginWebpack', name);
pkg.add('dependencies', {
[name]: `^${version}`
});
pkg.add('devDependencies', {
webpack: devDependencies.webpack
});
},
metadata (gasket, meta) {
return {
...meta,
actions: [
{
name: 'getWebpackConfig',
description: 'Get the webpack config',
link: 'README.md#getWebpackConfig'
}
],
guides: [
{
name: 'Webpack Configuration Guide',
description: 'Configuring Webpack in Gasket apps',
link: 'docs/webpack.md'
}
],
lifecycles: [
{
name: 'webpackConfig',
method: 'execApplySync',
description: 'Transform the Webpack config',
link: 'README.md#webpackConfig',
parent: 'initWebpack',
after: 'webpack'
},
{
name: 'initWebpack',
description: 'Create a webpack config',
command: 'build',
link: 'README.md#initwebpack'
}
]
};
}
}
};
const _default = plugin;
{}
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _module = require("module");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const require1 = (0, _module.createRequire)(require("url").pathToFileURL(__filename).toString());
/**
* This is a webpack plugin for gathering bundle size data
*/ class WebpackMetricsPlugin {
/**
* Helper function to call the metrics lifecycle
* @type {import('./internal.d.ts').handleMetrics}
*/ async handleMetrics(metrics) {
this.gasket.logger.debug('webpack metrics: ' + JSON.stringify(metrics, null, 2));
}
/**
* This plugin will calculate the sizes of the directories from the webpack
* bundle sent to the browser and call the metrics lifecycle with the data.
*
* Example format of data to emit:
*
* { name: '@gasket/canary-app',
* event: 'webpack',
* data: {
* images: { totalSize: 101231, jpg: 101231 },
* chunks: { totalSize: 128770, js: 128770 },
* runtime: { totalSize: 17671, js: 17671 },
* css: { totalSize: 749, css: 749 },
* pages: { totalSize: 782744, js: 782744 },
* 'bundle.svgs': { totalSize: 10188, svgs: 10188 } },
* time: 1559323660583 }
* @type {import('./internal.d.ts').apply}
*/ apply(compiler) {
const { target, context } = compiler.options;
if (target !== 'web') return;
// eslint-disable-next-line max-statements
compiler.hooks.emit.tap('WebpackMetricsPlugin', ({ assets })=>{
const map = {};
let name;
try {
const packageJSON = require1(`${context}/package.json`);
name = packageJSON.name;
} catch {
name = 'Gasket App';
}
for (const fullpath of Object.keys(assets)){
const asset = assets[fullpath];
const fileSize = asset.size();
const parsed = _path.default.parse(fullpath);
const extension = parsed.ext.slice(1);
let dirname = _path.default.basename(parsed.dir);
const parent = _path.default.basename(_path.default.dirname(parsed.dir));
if (parent === 'pages') {
dirname = parent;
}
map[dirname] = map[dirname] || {
totalSize: 0
};
map[dirname].totalSize += fileSize;
map[dirname][extension] = map[dirname][extension] || 0;
map[dirname][extension] += fileSize;
}
/** @type {import('./index.js').WebpackMetrics} */ const metrics = {
name,
event: 'webpack',
data: map,
time: Date.now()
};
// logging these errors more obvious to future plugin authors.
this.handleMetrics(metrics).catch(()=>{});
});
}
constructor(opts){
/** @type {import('@gasket/core').Gasket} */ this.gasket = opts.gasket;
}
}
const _default = WebpackMetricsPlugin;
+10
-6
/// <reference types="@gasket/plugin-logger" />
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
import WebpackMetricsPlugin from './webpack-metrics-plugin.js';
import GasketEnvGuardPlugin from './gasket-env-guard-plugin.js';
/**
* Sets up a context object with special getters
* @type {import('./internal').setupContext}
* @type {import('./internal.d.ts').setupContext}
*/

@@ -11,3 +16,4 @@ function setupContext(context) {

get webpack() {
return require('webpack');
const webpack = require('webpack');
return webpack;
}

@@ -18,5 +24,3 @@ };

/** @type {import('@gasket/core').ActionHandler<'getWebpackConfig'>} */
function getWebpackConfig(gasket, initConfig, context) {
const WebpackMetricsPlugin = require('./webpack-metrics-plugin');
const GasketEnvGuardPlugin = require('./gasket-env-guard-plugin');
export function getWebpackConfig(gasket, initConfig, context) {

@@ -44,4 +48,4 @@ /** @type {import('webpack').Configuration} */

module.exports = {
export default {
getWebpackConfig
};

@@ -117,2 +117,2 @@ /**

module.exports = GasketEnvGuardPlugin;
export default GasketEnvGuardPlugin;
/// <reference types="create-gasket-app" />
/// <reference types="@gasket/plugin-metadata" />
import actions from './actions.js';
import packageJson from '../package.json' with { type: 'json' };
const {

@@ -9,4 +11,3 @@ name,

devDependencies
} = require('../package.json');
const actions = require('./actions');
} = packageJson;

@@ -67,2 +68,2 @@ /** @type {import('@gasket/core').Plugin} */

module.exports = plugin;
export default plugin;

@@ -18,4 +18,4 @@ import type { Compiler, Configuration } from 'webpack';

export function setupContext(
context: any
): any;
context: object
): object & { webpack: any };

@@ -22,0 +22,0 @@ /** Sets up the initial webpack configuration */

@@ -1,2 +0,4 @@

const path = require('path');
import path from 'path';
import { createRequire } from 'module';
const require = createRequire(import.meta.url);

@@ -14,3 +16,3 @@ /**

* Helper function to call the metrics lifecycle
* @type {import('./internal').handleMetrics}
* @type {import('./internal.d.ts').handleMetrics}
*/

@@ -37,3 +39,3 @@ async handleMetrics(metrics) {

* time: 1559323660583 }
* @type {import('./internal').apply}
* @type {import('./internal.d.ts').apply}
*/

@@ -77,3 +79,3 @@ apply(compiler) {

/** @type {import('.').WebpackMetrics} */
/** @type {import('./index.js').WebpackMetrics} */
const metrics = {

@@ -92,2 +94,2 @@ name,

module.exports = WebpackMetricsPlugin;
export default WebpackMetricsPlugin;
{
"name": "@gasket/plugin-webpack",
"version": "7.3.9",
"version": "7.4.0",
"description": "Adds webpack support to your application",
"type": "module",
"main": "lib/index.js",

@@ -10,4 +11,14 @@ "types": "lib/index.d.ts",

"lib",
"cjs",
"EXAMPLES.md"
],
"exports": {
".": {
"types": "./lib/index.d.ts",
"import": "./lib/index.js",
"require": "./cjs/index.cjs",
"default": "./cjs/index.cjs"
},
"./package.json": "./package.json"
},
"repository": "godaddy/gasket.git",

@@ -27,17 +38,18 @@ "publishConfig": {

"devDependencies": {
"jest": "^29.7.0",
"mock-require": "^3.0.3",
"vitest": "^3.2.0",
"webpack": "^5.98.0",
"@gasket/cjs": "^7.1.0",
"@gasket/core": "^7.6.3",
"@gasket/plugin-logger": "^7.3.8",
"@gasket/plugin-metadata": "^7.5.4",
"create-gasket-app": "^7.4.13"
"@gasket/plugin-logger": "^7.4.0",
"@gasket/plugin-metadata": "^7.5.5",
"create-gasket-app": "^7.4.15"
},
"scripts": {
"build": "gasket-cjs ./lib",
"lint": "eslint .",
"lint:fix": "pnpm run lint --fix",
"posttest": "pnpm run lint && pnpm run typecheck",
"test": "cross-env NODE_OPTIONS='--unhandled-rejections=strict' jest",
"test:coverage": "pnpm run test --coverage",
"test:watch": "pnpm run test --watch",
"test": "vitest run --globals",
"test:coverage": "vitest run --coverage",
"test:watch": "vitest",
"typecheck": "tsc",

@@ -44,0 +56,0 @@ "typecheck:watch": "tsc --watch"