@@ -3,9 +3,12 @@ import {
33 existsSync ,
44 mkdirSync ,
55 rmSync ,
6- writeFileSync
6+ writeFileSync ,
7+ readFileSync
78} from 'node:fs'
89import path from 'node:path'
10+ import { spawnSync } from 'node:child_process'
11+ import { randomUUID } from 'node:crypto'
912
1013import { globSync as tinyGlobSync } from 'tinyglobby'
1114
@@ -26,6 +29,8 @@ import {
2629 isBuiltin ,
2730 normalizeId
2831} from '../scripts/utils/packages.js'
32+ import { envAsBoolean } from '@socketsecurity/registry/lib/env'
33+ import assert from 'node:assert'
2934
3035const {
3136 BABEL_RUNTIME ,
@@ -44,6 +49,9 @@ const CONSTANTS_JS = `${CONSTANTS}.js`
4449const CONSTANTS_STUB_CODE = createStubCode ( `../${ CONSTANTS_JS } ` )
4550const VENDOR_JS = `${ VENDOR } .js`
4651
52+ const IS_SENTRY_BUILD = envAsBoolean ( process . env [ 'SOCKET_WITH_SENTRY' ] ) ;
53+ const IS_PUBLISH = envAsBoolean ( process . env [ 'SOCKET_IS_PUBLISHED' ] )
54+
4755const distConstantsPath = path . join ( rootDistPath , CONSTANTS_JS )
4856const distModuleSyncPath = path . join ( rootDistPath , MODULE_SYNC )
4957const distRequirePath = path . join ( rootDistPath , REQUIRE )
@@ -52,6 +60,10 @@ const editablePkgJson = readPackageJsonSync(rootPath, { editable: true })
5260
5361const processEnvTapRegExp =
5462 / \b p r o c e s s \. e n v (?: \. T A P | \[ [ ' " ] T A P [ ' " ] \] ) ( \s * \? [ ^ : ] + : \s * ) ? / g
63+ const processEnvSocketIsPublishedRegExp =
64+ / \b p r o c e s s \. e n v (?: \. S O C K E T _ I S _ P U B L I S H E D | \[ [ ' " ] S O C K E T _ I S _ P U B L I S H E D [ ' " ] \] ) / g
65+ const processEnvSocketCliVersionRegExp =
66+ / \b p r o c e s s \. e n v (?: \. S O C K E T _ C L I _ V E R S I O N | \[ [ ' " ] S O C K E T _ C L I _ V E R S I O N [ ' " ] \] ) / g
5567
5668function createStubCode ( relFilepath ) {
5769 return `'use strict'\n\nmodule.exports = require('${ relFilepath } ')\n`
@@ -104,13 +116,28 @@ function updateDepStatsSync(depStats) {
104116 delete depStats . dependencies [ key ]
105117 }
106118 }
119+
120+ assert ( Object . keys ( editablePkgJson ?. content ?. bin ) . join ( ',' ) === 'socket,socket-npm,socket-npx' , 'If this fails, make sure to update the rollup sentry override for .bin to match the regular build!' ) ;
121+ if ( IS_SENTRY_BUILD ) {
122+ editablePkgJson . content [ 'name' ] = '@socketsecurity/socket-with-sentry'
123+ editablePkgJson . content [ 'description' ] = "CLI tool for Socket.dev, includes Sentry error handling, otherwise identical to the regular `socket` package"
124+ editablePkgJson . content [ 'bin' ] = {
125+ "socket-with-sentry" : "bin/cli.js" ,
126+ "socket-npm-with-sentry" : "bin/npm-cli.js" ,
127+ "socket-npx-with-sentry" : "bin/npx-cli.js"
128+ }
129+ // Add Sentry as a regular dep for this build
130+ depStats . dependencies [ '@sentry/node' ] = '9.1.0' ;
131+ }
132+
107133 depStats . dependencies = toSortedObject ( depStats . dependencies )
108134 depStats . devDependencies = toSortedObject ( depStats . devDependencies )
109135 depStats . esm = toSortedObject ( depStats . esm )
110136 depStats . external = toSortedObject ( depStats . external )
111137 depStats . transitives = toSortedObject ( depStats . transitives )
112138 // Write dep stats.
113139 writeFileSync ( depStatsPath , `${ formatObject ( depStats ) } \n` , 'utf8' )
140+
114141 // Update dependencies with additional inlined modules.
115142 editablePkgJson
116143 . update ( {
@@ -120,6 +147,40 @@ function updateDepStatsSync(depStats) {
120147 }
121148 } )
122149 . saveSync ( )
150+
151+ if ( IS_SENTRY_BUILD ) {
152+ // Replace the name in the package lock too, just in case.
153+ const lock = readFileSync ( 'package-lock.json' , 'utf8' ) ;
154+ // Note: this should just replace the first occurrence, even if there are more
155+ const lock2 = lock . replace ( '"name": "socket",' , '"name": "@socketsecurity/socket-with-sentry",' )
156+ writeFileSync ( 'package-lock.json' , lock2 )
157+ }
158+ }
159+
160+ function versionBanner ( _chunk ) {
161+ let pkgJsonVersion = 'unknown' ;
162+ try { pkgJsonVersion = JSON . parse ( readFileSync ( 'package.json' , 'utf8' ) ) ?. version ?? 'unknown' } catch { }
163+
164+ let gitHash = ''
165+ try {
166+ const obj = spawnSync ( 'git' , [ 'rev-parse' , '--short' , 'HEAD' ] ) ;
167+ if ( obj . stdout ) {
168+ gitHash = obj . stdout . toString ( 'utf8' ) . trim ( )
169+ }
170+ } catch { }
171+
172+ // Make each build generate a unique version id, regardless
173+ // Mostly for development: confirms the build refreshed. For prod
174+ // builds the git hash should suffice to identify the build.
175+ const rng = randomUUID ( ) . split ( '-' ) [ 0 ] ;
176+
177+ return `
178+ var SOCKET_CLI_PKG_JSON_VERSION = "${ pkgJsonVersion } "
179+ var SOCKET_CLI_GIT_HASH = "${ gitHash } "
180+ var SOCKET_CLI_BUILD_RNG = "${ rng } "
181+ var SOCKET_PUB = ${ IS_PUBLISH }
182+ var SOCKET_CLI_VERSION = "${ pkgJsonVersion } :${ gitHash } :${ rng } ${ IS_PUBLISH ? ':pub' :'' } "
183+ ` . trim ( ) . split ( '\n' ) . map ( s => s . trim ( ) ) . join ( '\n' )
123184}
124185
125186export default ( ) => {
@@ -132,12 +193,15 @@ export default () => {
132193 } ,
133194 output : [
134195 {
196+ intro : versionBanner , // Note: "banner" would defeat "use strict"
135197 dir : path . relative ( rootPath , distModuleSyncPath ) ,
136198 entryFileNames : '[name].js' ,
137199 exports : 'auto' ,
138200 externalLiveBindings : false ,
139201 format : 'cjs' ,
140- freeze : false
202+ freeze : false ,
203+ sourcemap : true ,
204+ sourcemapDebugIds : true ,
141205 }
142206 ] ,
143207 external ( id_ ) {
@@ -182,12 +246,15 @@ export default () => {
182246 } ,
183247 output : [
184248 {
249+ intro : versionBanner , // Note: "banner" would defeat "use strict"
185250 dir : path . relative ( rootPath , distRequirePath ) ,
186251 entryFileNames : '[name].js' ,
187252 exports : 'auto' ,
188253 externalLiveBindings : false ,
189254 format : 'cjs' ,
190- freeze : false
255+ freeze : false ,
256+ sourcemap : true ,
257+ sourcemapDebugIds : true ,
191258 }
192259 ] ,
193260 plugins : [
@@ -197,6 +264,19 @@ export default () => {
197264 find : processEnvTapRegExp ,
198265 replace : ( _match , ternary ) => ( ternary ? '' : 'false' )
199266 } ) ,
267+ // Replace `process.env.SOCKET_IS_PUBLISHED` with a boolean
268+ socketModifyPlugin ( {
269+ find : processEnvSocketIsPublishedRegExp ,
270+ // Note: these are going to be bools in JS, not strings
271+ replace : ( ) => ( IS_PUBLISH ? 'true' : 'false' )
272+ } ) ,
273+ // Replace `process.env.SOCKET_CLI_VERSION` with var ref that rollup
274+ // adds to the top of each file.
275+ socketModifyPlugin ( {
276+ find : processEnvSocketCliVersionRegExp ,
277+ replace : 'SOCKET_CLI_VERSION'
278+ } ) ,
279+
200280 {
201281 generateBundle ( _options , bundle ) {
202282 for ( const basename of Object . keys ( bundle ) ) {
0 commit comments