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.4.0
to
8.0.0-next.1
+1
-11
lib/index.js

@@ -9,4 +9,3 @@ /// <reference types="create-gasket-app" />

version,
description,
devDependencies
description
} = packageJson;

@@ -21,11 +20,2 @@

hooks: {
create(gasket, { pkg, gasketConfig }) {
gasketConfig.addPlugin('pluginWebpack', name);
pkg.add('dependencies', {
[name]: `^${version}`
});
pkg.add('devDependencies', {
webpack: devDependencies.webpack
});
},
metadata(gasket, meta) {

@@ -32,0 +22,0 @@ return {

+6
-12
{
"name": "@gasket/plugin-webpack",
"version": "7.4.0",
"version": "8.0.0-next.1",
"description": "Adds webpack support to your application",
"type": "module",
"main": "lib/index.js",
"types": "lib/index.d.ts",

@@ -11,3 +10,2 @@ "files": [

"lib",
"cjs",
"EXAMPLES.md"

@@ -18,5 +16,3 @@ ],

"types": "./lib/index.d.ts",
"import": "./lib/index.js",
"require": "./cjs/index.cjs",
"default": "./cjs/index.cjs"
"import": "./lib/index.js"
},

@@ -41,10 +37,8 @@ "./package.json": "./package.json"

"webpack": "^5.98.0",
"@gasket/cjs": "^7.1.0",
"@gasket/core": "^7.6.3",
"@gasket/plugin-logger": "^7.4.0",
"@gasket/plugin-metadata": "^7.5.5",
"create-gasket-app": "^7.4.15"
"@gasket/core": "^8.0.0-next.1",
"@gasket/plugin-logger": "^8.0.0-next.1",
"@gasket/plugin-metadata": "^8.0.0-next.1",
"create-gasket-app": "^8.0.0-next.1"
},
"scripts": {
"build": "gasket-cjs ./lib",
"lint": "eslint .",

@@ -51,0 +45,0 @@ "lint:fix": "pnpm run lint --fix",

/// <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;