@americanexpress/one-app-dev-bundler
Advanced tools
Comparing version 1.5.4 to 1.5.5
@@ -34,4 +34,3 @@ /* | ||
jest.mock('@fal-works/esbuild-plugin-global-externals', () => ({ globalExternals: (...params) => `esbuild_plugin_for(esbuild-plugin-global-externals)(${JSON.stringify(params)})` })); | ||
jest.mock('@esbuild-plugins/node-globals-polyfill', () => ({ NodeGlobalsPolyfillPlugin: (...params) => `esbuild_plugin_for(node-globals-polyfill)(${JSON.stringify(params)})` })); | ||
jest.mock('@esbuild-plugins/node-modules-polyfill', () => ({ NodeModulesPolyfillPlugin: (...params) => `esbuild_plugin_for(node-modules-polyfill)(${JSON.stringify(params)})` })); | ||
jest.mock('esbuild-plugin-polyfill-node', () => ({ polyfillNode: (...params) => `esbuild_plugin_for(polyfill-node)(${JSON.stringify(params)})` })); | ||
jest.mock('esbuild-plugin-svgr', () => (...params) => `esbuild_plugin_for(esbuild-plugin-svgr)(${JSON.stringify(params)})`); | ||
@@ -38,0 +37,0 @@ jest.mock('../../esbuild/plugins/restrict-runtime-symbols.js', () => (...params) => `esbuild_plugin_for(restrict-runtime-symbols)(${JSON.stringify(params)})`); |
@@ -24,4 +24,5 @@ /* | ||
readFile: jest.fn(() => 'mockFileContent'), | ||
writeFile: jest.fn(() => 'mockWriteFileResponse'), | ||
}, | ||
readFileSync: jest.fn(() => 'mockFileContent'), | ||
writeFileSync: jest.fn(() => 'mockWriteFileResponse'), | ||
})); | ||
@@ -51,3 +52,3 @@ | ||
it('should generate a manifest based upon the content of the first file, and write a new file if the loaded manifest cant be parsed', async () => { | ||
expect.assertions(8); | ||
expect.assertions(9); | ||
const plugin = generateIntegrityManifest({ bundleName: 'mockBundleName' }); | ||
@@ -59,3 +60,3 @@ const hooks = runSetupAndGetLifeHooks(plugin); | ||
// second read is loading the existing manifest | ||
fs.promises.readFile.mockImplementationOnce(() => '} Mock Bad JSON File'); | ||
fs.readFileSync.mockImplementationOnce(() => '} Mock Bad JSON File'); | ||
@@ -65,9 +66,10 @@ const mockResult = { metafile: { outputs: { '/path/to/bundle.js': {} } } }; | ||
expect(fs.promises.readFile).toHaveBeenCalledTimes(2); | ||
expect(fs.promises.readFile).toHaveBeenCalledTimes(1); | ||
expect(fs.readFileSync).toHaveBeenCalledTimes(1); | ||
expect(fs.promises.readFile).toHaveBeenCalledWith('/path/to/bundle.js', 'utf8'); | ||
expect(fs.promises.readFile).toHaveBeenCalledWith('./bundle.integrity.manifest.json', 'utf8'); | ||
expect(fs.readFileSync).toHaveBeenCalledWith('./bundle.integrity.manifest.json', 'utf8'); | ||
expect(fs.promises.writeFile).toHaveBeenCalledTimes(1); | ||
expect(fs.writeFileSync).toHaveBeenCalledTimes(1); | ||
// first parameter of first call | ||
expect(fs.promises.writeFile.mock.calls[0][0]).toBe('./bundle.integrity.manifest.json'); | ||
expect(fs.writeFileSync.mock.calls[0][0]).toBe('./bundle.integrity.manifest.json'); | ||
// Snapshot here for the hash. Its hashing the response from the first readFile mock, | ||
@@ -77,3 +79,3 @@ // 'mockModuleFileContent', therefore if the hash below ever changes, its likely to be | ||
// is also changed | ||
expect(fs.promises.writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` | ||
expect(fs.writeFileSync.mock.calls[0][1]).toMatchInlineSnapshot(` | ||
"{ | ||
@@ -89,3 +91,3 @@ \\"mockBundleName\\": \\"sha256-dVDfvIfLZ/EauFs99M0kCfTCNSTcAaeR8tIfSmPWMBU= sha384-bkhDhTm0NmB0SvMS9As2gTFJ86GfZIOyXBPzQPCTmtoDXvQTaTrNqe6skXgbJNT7\\" | ||
it('should generate a manifest based upon the content of the first file, and preserve existing keys in the loaded manifest', async () => { | ||
expect.assertions(8); | ||
expect.assertions(9); | ||
const plugin = generateIntegrityManifest({ bundleName: 'mockBundleName' }); | ||
@@ -95,6 +97,6 @@ const hooks = runSetupAndGetLifeHooks(plugin); | ||
// first read is the bundle generated by the build | ||
// read bundle generated by the build | ||
fs.promises.readFile.mockImplementationOnce(() => 'mockModuleFileContent 2'); // A different content here that the other test, just to get a different set of hashes | ||
// second read is loading the existing manifest | ||
fs.promises.readFile.mockImplementationOnce(() => '{"existingKey": "existing value"}'); | ||
// this read is loading the existing manifest | ||
fs.readFileSync.mockImplementationOnce(() => '{"existingKey": "existing value"}'); | ||
@@ -104,9 +106,10 @@ const mockResult = { metafile: { outputs: { '/path/to/bundle.js': {} } } }; | ||
expect(fs.promises.readFile).toHaveBeenCalledTimes(2); | ||
expect(fs.promises.readFile).toHaveBeenCalledTimes(1); | ||
expect(fs.readFileSync).toHaveBeenCalledTimes(1); | ||
expect(fs.promises.readFile).toHaveBeenCalledWith('/path/to/bundle.js', 'utf8'); | ||
expect(fs.promises.readFile).toHaveBeenCalledWith('./bundle.integrity.manifest.json', 'utf8'); | ||
expect(fs.readFileSync).toHaveBeenCalledWith('./bundle.integrity.manifest.json', 'utf8'); | ||
expect(fs.promises.writeFile).toHaveBeenCalledTimes(1); | ||
expect(fs.writeFileSync).toHaveBeenCalledTimes(1); | ||
// first parameter of first call | ||
expect(fs.promises.writeFile.mock.calls[0][0]).toBe('./bundle.integrity.manifest.json'); | ||
expect(fs.writeFileSync.mock.calls[0][0]).toBe('./bundle.integrity.manifest.json'); | ||
// Snapshot here for the hash. Its hashing the response from the first readFile mock, | ||
@@ -116,3 +119,3 @@ // 'mockModuleFileContent 2', therefore if the hash below ever changes, its likely to be | ||
// is also changed | ||
expect(fs.promises.writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` | ||
expect(fs.writeFileSync.mock.calls[0][1]).toMatchInlineSnapshot(` | ||
"{ | ||
@@ -136,3 +139,3 @@ \\"existingKey\\": \\"existing value\\", | ||
expect(fs.promises.readFile).not.toHaveBeenCalled(); | ||
expect(fs.promises.writeFile).not.toHaveBeenCalled(); | ||
expect(fs.writeFileSync).not.toHaveBeenCalled(); | ||
}); | ||
@@ -139,0 +142,0 @@ }); |
@@ -17,6 +17,5 @@ /* | ||
import fs from 'node:fs'; | ||
import esbuild from 'esbuild'; | ||
import { readPackageUpSync } from 'read-pkg-up'; | ||
import writeToModuleConfig from '../../utils/write-to-module-config'; | ||
import { bundleExternalFallbacks } from '../../utils/bundle-external-fallbacks.js'; | ||
@@ -50,4 +49,14 @@ | ||
jest.mock('node:fs'); | ||
// mock reading integrity manifest | ||
jest.mock('node:fs', () => ({ | ||
readFileSync: jest.fn(() => JSON.stringify({ | ||
'awesome.browser': 'sha-awesome-browser', | ||
'awesome.node': 'sha-awesome-node', | ||
node: 'shaNode', | ||
browser: 'shaBrowser', | ||
})), | ||
})); | ||
jest.mock('../../utils/write-to-module-config'); | ||
jest.spyOn(process, 'cwd').mockImplementation(() => '/path/'); | ||
@@ -120,2 +129,5 @@ | ||
}, | ||
dependencies: { | ||
awesome: '^1.2.3', | ||
}, | ||
}, | ||
@@ -126,3 +138,3 @@ })); | ||
packageJson: { | ||
version: '1.0.0', | ||
version: '1.2.3', | ||
}, | ||
@@ -133,4 +145,2 @@ })); | ||
fs.readFileSync.mockImplementationOnce(() => 'const testing = true;'); | ||
await bundleExternalFallbacks(); | ||
@@ -144,5 +154,5 @@ | ||
], | ||
globalName: '__holocron_external__awesome__1_0_0', | ||
globalName: '__holocron_external__awesome__1_2_3', | ||
footer: { | ||
js: 'Holocron.registerExternal({ name: "awesome", version: "1.0.0", module: __holocron_external__awesome__1_0_0});', | ||
js: 'Holocron.registerExternal({ name: "awesome", version: "1.2.3", module: __holocron_external__awesome__1_2_3});', | ||
}, | ||
@@ -171,2 +181,5 @@ mocked: 'browser', | ||
}, | ||
dependencies: { | ||
awesome: '^2.0.0', | ||
}, | ||
}, | ||
@@ -177,3 +190,3 @@ })); | ||
packageJson: { | ||
version: '1.0.0', | ||
version: '2.1.0', | ||
}, | ||
@@ -184,4 +197,2 @@ })); | ||
fs.readFileSync.mockImplementationOnce(() => 'const testing = true;'); | ||
const error = new Error('Testing'); | ||
@@ -198,5 +209,5 @@ | ||
], | ||
globalName: '__holocron_external__awesome__1_0_0', | ||
globalName: '__holocron_external__awesome__2_1_0', | ||
mocked: 'browser', | ||
footer: { js: 'Holocron.registerExternal({ name: "awesome", version: "1.0.0", module: __holocron_external__awesome__1_0_0});' }, | ||
footer: { js: 'Holocron.registerExternal({ name: "awesome", version: "2.1.0", module: __holocron_external__awesome__2_1_0});' }, | ||
outfile: '/path/build/1.0.0/awesome.browser.js', | ||
@@ -213,3 +224,2 @@ }); | ||
expect(fs.writeFileSync).not.toHaveBeenCalled(); | ||
expect(console.error).toHaveBeenCalledTimes(2); | ||
@@ -228,2 +238,38 @@ expect(console.error).toHaveBeenCalledWith('Failed to build fallback for external awesome for browser', error); | ||
}); | ||
it('writes to module config', async () => { | ||
readPackageUpSync.mockImplementationOnce(() => ({ | ||
packageJson: { | ||
version: '1.0.0', | ||
'one-amex': { | ||
bundler: { | ||
requiredExternals: ['awesome'], | ||
}, | ||
}, | ||
dependencies: { | ||
awesome: '^1.2.3', | ||
}, | ||
}, | ||
})); | ||
readPackageUpSync.mockImplementation(() => ({ | ||
packageJson: { | ||
version: '1.2.3', | ||
}, | ||
})); | ||
await bundleExternalFallbacks(); | ||
expect(writeToModuleConfig).toHaveBeenCalledWith({ | ||
requiredExternals: { | ||
awesome: { | ||
name: 'awesome', | ||
version: '1.2.3', | ||
semanticRange: '^1.2.3', | ||
browserIntegrity: 'sha-awesome-browser', | ||
nodeIntegrity: 'sha-awesome-node', | ||
}, | ||
}, | ||
}); | ||
}); | ||
}); |
@@ -6,2 +6,15 @@ # Change Log | ||
## [1.5.5](https://github.com/americanexpress/one-app-cli/compare/@americanexpress/one-app-dev-bundler@1.5.3...@americanexpress/one-app-dev-bundler@1.5.5) (2023-11-13) | ||
### Bug Fixes | ||
* **fallback-integrity:** ensure node & browser integrity in module config ([#584](https://github.com/americanexpress/one-app-cli/issues/584)) ([e14fc4f](https://github.com/americanexpress/one-app-cli/commit/e14fc4f7d4110cd038379ac759fc54fcb6797ce2)) | ||
* **one-app-dev-bundler:** replace depreacted node polyfill plugin ([#582](https://github.com/americanexpress/one-app-cli/issues/582)) ([2f7fa3c](https://github.com/americanexpress/one-app-cli/commit/2f7fa3c0f337f05c9fea75e49600e5c9e6f3eb80)) | ||
* **one-app-dev-bundler:** sass style loader ([#577](https://github.com/americanexpress/one-app-cli/issues/577)) ([6559915](https://github.com/americanexpress/one-app-cli/commit/655991594a5161afce533e5966c5ad77fc7774f1)) | ||
## [1.5.4](https://github.com/americanexpress/one-app-cli/compare/@americanexpress/one-app-dev-bundler@1.5.3...@americanexpress/one-app-dev-bundler@1.5.4) (2023-10-04) | ||
@@ -8,0 +21,0 @@ |
@@ -18,4 +18,4 @@ /* | ||
import { globalExternals } from '@fal-works/esbuild-plugin-global-externals'; | ||
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill'; | ||
import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill'; | ||
// eslint-disable-next-line import/no-unresolved -- false positive due to package not have main field in package.json | ||
import { polyfillNode } from 'esbuild-plugin-polyfill-node'; | ||
import { readPackageUpSync } from 'read-pkg-up'; | ||
@@ -99,6 +99,3 @@ import path from 'node:path'; | ||
// TODO make these opt in, this would be a breaking change as webpack always includes them | ||
NodeGlobalsPolyfillPlugin({ | ||
buffer: true, | ||
}), | ||
NodeModulesPolyfillPlugin(), | ||
polyfillNode(), | ||
bundleAssetSizeLimiter(commonConfigPluginOptions), | ||
@@ -156,7 +153,5 @@ externalsLoader(browserConfigPluginOptions), | ||
removeWebpackLoaderSyntax, | ||
bundleAssetSizeLimiter(commonConfigPluginOptions), | ||
env === 'browser' && legacyBundler(externalName), | ||
generateIntegrityManifest({ bundleName: externalName }), | ||
generateIntegrityManifest({ bundleName: `${externalName}.${env}` }), | ||
restrictRuntimeSymbols(browserConfigPluginOptions), | ||
timeBuild({ bundleName: externalName, watch }), | ||
timeBuild({ bundleName: `${externalName}.${env}`, watch }), | ||
].filter(Boolean), | ||
@@ -163,0 +158,0 @@ }); |
@@ -21,6 +21,8 @@ /* | ||
async function writeIntegrityFragment(bundleName, integrityString, fileName) { | ||
// NOTE:: This needs to be synchronous to avoid race condition resulting in | ||
// missing integrity manifest entries | ||
function writeIntegrityFragment(bundleName, integrityString, fileName) { | ||
let integrityObject = {}; | ||
try { | ||
integrityObject = JSON.parse(await fs.promises.readFile(fileName, 'utf8')); | ||
integrityObject = JSON.parse(fs.readFileSync(fileName, 'utf8')); | ||
} catch (e) { | ||
@@ -31,4 +33,3 @@ // empty catch in case file does not exist | ||
integrityObject[bundleName] = integrityString; | ||
return fs.promises.writeFile(fileName, JSON.stringify(integrityObject, null, 2)); | ||
return fs.writeFileSync(fileName, JSON.stringify(integrityObject, null, 2)); | ||
} | ||
@@ -53,3 +54,3 @@ | ||
await writeIntegrityFragment(bundleName, integrityString, './bundle.integrity.manifest.json'); | ||
writeIntegrityFragment(bundleName, integrityString, './bundle.integrity.manifest.json'); | ||
@@ -56,0 +57,0 @@ return result; |
{ | ||
"name": "@americanexpress/one-app-dev-bundler", | ||
"version": "1.5.4", | ||
"version": "1.5.5", | ||
"description": "A development bundler focussed on speed and modern features.", | ||
@@ -29,4 +29,2 @@ "main": "index.js", | ||
"@americanexpress/one-app-locale-bundler": "^6.6.0", | ||
"@esbuild-plugins/node-globals-polyfill": "^0.1.1", | ||
"@esbuild-plugins/node-modules-polyfill": "^0.2.2", | ||
"@fal-works/esbuild-plugin-global-externals": "^2.1.2", | ||
@@ -40,2 +38,3 @@ "@fullhuman/postcss-purgecss": "^3.0.0", | ||
"esbuild": "^0.15.9", | ||
"esbuild-plugin-polyfill-node": "^0.3.0", | ||
"esbuild-plugin-svgr": "^1.0.1", | ||
@@ -86,3 +85,3 @@ "filesize": "^9.0.1", | ||
}, | ||
"gitHead": "b902ec72fac135c37870c4c860796955ae3eb23b" | ||
"gitHead": "7995a388f1ee7d9c7ad20b60fa835dcb9dd1d751" | ||
} |
@@ -19,3 +19,5 @@ /* | ||
import snakeCase from 'lodash.snakecase'; | ||
import fs from 'node:fs'; | ||
import generateESBuildOptions from '../esbuild/generateESBuildOptions.js'; | ||
import writeToModuleConfig from './write-to-module-config.js'; | ||
@@ -73,2 +75,22 @@ const EXTERNAL_PREFIX = '__holocron_external'; | ||
})))); | ||
const integrityManifest = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'bundle.integrity.manifest.json'), 'utf-8')); | ||
const requiredExternalsData = requiredExternals.reduce((obj, externalName) => { | ||
const version = readPackageUpSync({ | ||
cwd: path.resolve(process.cwd(), 'node_modules', externalName), | ||
})?.packageJson.version; | ||
const semanticRange = packageJson.dependencies[externalName]; | ||
return { | ||
...obj, | ||
[externalName]: { | ||
name: externalName, | ||
version, | ||
semanticRange, | ||
browserIntegrity: integrityManifest[`${externalName}.browser`], | ||
nodeIntegrity: integrityManifest[`${externalName}.node`], | ||
}, | ||
}; | ||
}, {}); | ||
writeToModuleConfig({ requiredExternals: requiredExternalsData }); | ||
} | ||
@@ -75,0 +97,0 @@ }; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
316580
22
94
6516
+ Added@jspm/core@2.0.1(transitive)
+ Addedesbuild-plugin-polyfill-node@0.3.0(transitive)
+ Addedimport-meta-resolve@3.1.1(transitive)
- Removed@esbuild-plugins/node-globals-polyfill@0.1.1(transitive)
- Removed@esbuild-plugins/node-modules-polyfill@0.2.2(transitive)
- Removedescape-string-regexp@4.0.0(transitive)
- Removedestree-walker@0.6.1(transitive)
- Removedmagic-string@0.25.9(transitive)
- Removedrollup-plugin-inject@3.0.2(transitive)
- Removedrollup-plugin-node-polyfills@0.2.1(transitive)
- Removedrollup-pluginutils@2.8.2(transitive)
- Removedsourcemap-codec@1.4.8(transitive)