@zohodesk/client_build_tool 0.0.14 → 0.0.15-exp.10

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.
Files changed (22) hide show
  1. package/README.md +131 -0
  2. package/README_backup.md +131 -0
  3. package/lib/schemas/defaultConfigValues.js +2 -1
  4. package/lib/shared/bundler/webpack/custom_plugins/ChunkHierarchyPlugin.js +64 -0
  5. package/lib/shared/bundler/webpack/custom_plugins/InjectChunkGraphPlugin.js +45 -0
  6. package/lib/shared/bundler/webpack/custom_plugins/ResourceHintsPlugin.js +39 -36
  7. package/lib/shared/bundler/webpack/pluginConfigs/configChunkHierarchyPlugin.js +21 -0
  8. package/lib/shared/bundler/webpack/pluginConfigs/configInjectChunkGraphPlugin.js +22 -0
  9. package/lib/shared/bundler/webpack/pluginConfigs/configResourceHintsPlugin.js +8 -4
  10. package/lib/shared/bundler/webpack/plugins.js +3 -1
  11. package/npm-shrinkwrap.json +17 -2
  12. package/package.json +2 -1
  13. package/lib/shared/bundler/webpack/common/i18nOptionsValidator.js +0 -121
  14. package/lib/shared/bundler/webpack/custom_plugins/I18nNumericIndexPlugin/I18nGroupRuntimeModule.js +0 -199
  15. package/lib/shared/bundler/webpack/custom_plugins/I18nNumericIndexPlugin/I18nNumericIndexHtmlInjectorPlugin.js +0 -110
  16. package/lib/shared/bundler/webpack/custom_plugins/I18nNumericIndexPlugin/I18nNumericIndexPlugin.js +0 -478
  17. package/lib/shared/bundler/webpack/custom_plugins/I18nNumericIndexPlugin/utils/i18nDataLoader.js +0 -115
  18. package/lib/shared/bundler/webpack/loaderConfigs/i18nIdReplaceLoaderConfig.js +0 -69
  19. package/lib/shared/bundler/webpack/loaders/i18nIdReplaceLoader.js +0 -126
  20. package/lib/shared/bundler/webpack/pluginConfigs/configI18nIndexingPlugin.js +0 -42
  21. package/lib/shared/bundler/webpack/pluginConfigs/configI18nNumericHtmlInjector.js +0 -82
  22. package/lib/shared/bundler/webpack/pluginConfigs/configI18nNumericIndexPlugin.js +0 -95
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zohodesk/client_build_tool",
3
- "version": "0.0.14",
3
+ "version": "0.0.15-exp.10",
4
4
  "description": "A CLI tool to build web applications and client libraries",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -32,6 +32,7 @@
32
32
  "@babel/preset-env": "7.18.2",
33
33
  "@babel/preset-react": "7.17.12",
34
34
  "@babel/preset-typescript": "7.23.2",
35
+ "@zohodesk-private/client_dev_cert": "^1.0.6",
35
36
  "@zohodesk/client_packages_group": "1.0.2",
36
37
  "babel-loader": "9.1.2",
37
38
  "babel-plugin-module-resolver": "5.0.2",
@@ -1,121 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.validateI18nChunkSplitOptions = validateI18nChunkSplitOptions;
7
- exports.validateI18nIndexingOptions = validateI18nIndexingOptions;
8
- exports.validateI18nOptions = validateI18nOptions;
9
- exports.validateRequiredFields = validateRequiredFields;
10
- exports.validateTemplateFormat = validateTemplateFormat;
11
- const LOCALE_PLACEHOLDER = '[locale]';
12
- const REQUIRED_OPTIONS = ['jsResourcePath', 'propertiesFolderPath', 'numericMapPath'];
13
-
14
- function validateRequiredFields(options, requiredFields) {
15
- const missingOptions = requiredFields.filter(opt => {
16
- const value = options[opt];
17
- return value === undefined || value === null || typeof value === 'string' && value.trim() === '';
18
- });
19
-
20
- if (missingOptions.length > 0) {
21
- throw new Error(`[I18nOptionsValidator] Missing required i18n options: ${missingOptions.join(', ')}`);
22
- }
23
- }
24
-
25
- function validateTemplateFormat(template, templateName) {
26
- if (!template || typeof template !== 'string') {
27
- throw new Error(`[I18nOptionsValidator] ${templateName} must be a non-empty string`);
28
- }
29
-
30
- if (!template.includes(LOCALE_PLACEHOLDER)) {
31
- throw new Error(`[I18nOptionsValidator] ${templateName} must include ${LOCALE_PLACEHOLDER} placeholder`);
32
- }
33
- }
34
-
35
- function validateI18nIndexingOptions(i18nOpts) {
36
- if (!i18nOpts || typeof i18nOpts !== 'object') {
37
- throw new Error('[I18nOptionsValidator] i18nIndexing configuration must be a valid object');
38
- }
39
-
40
- if (!i18nOpts.enable) {
41
- return {
42
- skipValidation: true
43
- };
44
- }
45
-
46
- validateRequiredFields(i18nOpts, REQUIRED_OPTIONS);
47
- const numericTemplate = i18nOpts.numericFilenameTemplate || '[locale]/numeric.i18n.js';
48
- const dynamicTemplate = i18nOpts.dynamicFilenameTemplate || '[locale]/dynamic.i18n.js';
49
- validateTemplateFormat(numericTemplate, 'numericFilenameTemplate');
50
- validateTemplateFormat(dynamicTemplate, 'dynamicFilenameTemplate');
51
-
52
- if (i18nOpts.singleFileTemplate) {
53
- validateTemplateFormat(i18nOpts.singleFileTemplate, 'singleFileTemplate');
54
- }
55
-
56
- const includeContentHash = i18nOpts.includeContentHash;
57
- const injectHtml = i18nOpts.injectI18nUrlInIndex !== undefined ? i18nOpts.injectI18nUrlInIndex : true;
58
-
59
- if (includeContentHash && injectHtml) {
60
- throw new Error('[I18nOptionsValidator] includeContentHash and injectI18nUrlInIndex cannot both be true - content hash changes filenames dynamically but HTML injection needs static filenames');
61
- }
62
-
63
- return {
64
- skipValidation: false
65
- };
66
- }
67
-
68
- function validateI18nChunkSplitOptions(chunkSplitOpts) {
69
- if (!chunkSplitOpts || typeof chunkSplitOpts !== 'object') {
70
- throw new Error('[I18nOptionsValidator] i18nChunkSplit configuration must be a valid object');
71
- }
72
-
73
- if (!chunkSplitOpts.chunkSplitEnable || !chunkSplitOpts.useNumericIndexing) {
74
- return {
75
- skipValidation: true
76
- };
77
- }
78
-
79
- if (!chunkSplitOpts.jsResource) {
80
- throw new Error('[I18nOptionsValidator] Missing required jsResource in i18nChunkSplit options');
81
- }
82
-
83
- if (!chunkSplitOpts.numericMapPath) {
84
- throw new Error('[I18nOptionsValidator] Missing required numericMapPath in i18nChunkSplit options');
85
- }
86
-
87
- return {
88
- skipValidation: false
89
- };
90
- }
91
-
92
- function validateI18nOptions(options) {
93
- if (!options || typeof options !== 'object') {
94
- throw new Error('[I18nOptionsValidator] Options must be a valid object');
95
- }
96
-
97
- const hasIndexing = options.i18nIndexing && options.i18nIndexing.enable;
98
- const hasChunkSplit = options.i18nChunkSplit && options.i18nChunkSplit.chunkSplitEnable && options.i18nChunkSplit.useNumericIndexing;
99
-
100
- if (!hasIndexing && !hasChunkSplit) {
101
- throw new Error('[I18nOptionsValidator] i18n validation requires either i18nIndexing to be enabled or i18nChunkSplit with useNumericIndexing');
102
- }
103
-
104
- if (hasIndexing) {
105
- const result = validateI18nIndexingOptions(options.i18nIndexing);
106
-
107
- if (result.skipValidation) {
108
- throw new Error('[I18nOptionsValidator] i18nIndexing is not properly enabled');
109
- }
110
- }
111
-
112
- if (hasChunkSplit) {
113
- const result = validateI18nChunkSplitOptions(options.i18nChunkSplit);
114
-
115
- if (result.skipValidation) {
116
- throw new Error('[I18nOptionsValidator] i18nChunkSplit is not properly configured');
117
- }
118
- }
119
-
120
- return true;
121
- }
@@ -1,199 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.I18nGroupRuntimeModule = void 0;
7
-
8
- var _webpack = require("webpack");
9
-
10
- class I18nGroupRuntimeModule extends _webpack.RuntimeModule {
11
- constructor(options) {
12
- super('i18n-group-loader');
13
- this.options = { ...options
14
- };
15
- }
16
-
17
- generate() {
18
- const {
19
- customGroups,
20
- chunkIdToGroupMapping,
21
- localeVarName,
22
- groupAssetUrls,
23
- publicPathPrefix,
24
- publicPathRuntimeExpression
25
- } = this.options;
26
- const chunkIdToGroup = chunkIdToGroupMapping || {};
27
- return `
28
- // I18n Group Loading Runtime
29
- (function() {
30
- var loadedGroups = {};
31
- var chunkIdToGroup = ${JSON.stringify(chunkIdToGroup)};
32
- var groupAssetUrls = ${JSON.stringify(groupAssetUrls || {})};
33
- var cachedI18nBase;
34
- var scriptCache = null;
35
- var runtimePublicPathPrefixResolver = ${publicPathRuntimeExpression ? `function(){ try { return ${publicPathRuntimeExpression}; } catch (err) { return undefined; } }` : 'function(){ return undefined; }'};
36
- var runtimePublicPathPrefix = runtimePublicPathPrefixResolver();
37
- if (runtimePublicPathPrefix === undefined || runtimePublicPathPrefix === null || runtimePublicPathPrefix === '') {
38
- runtimePublicPathPrefix = ${JSON.stringify(publicPathPrefix || '')};
39
- }
40
- if (typeof runtimePublicPathPrefix !== 'string') {
41
- runtimePublicPathPrefix = runtimePublicPathPrefix != null ? String(runtimePublicPathPrefix) : '';
42
- }
43
-
44
- function ensureTrailingSlash(path) {
45
- if (!path) return '';
46
- return path.charAt(path.length - 1) === '/' ? path : path + '/';
47
- }
48
-
49
- runtimePublicPathPrefix = ensureTrailingSlash(runtimePublicPathPrefix);
50
-
51
- function resolveI18nBase() {
52
- if (cachedI18nBase !== undefined) {
53
- return cachedI18nBase;
54
- }
55
-
56
- var base = __webpack_require__.p || '';
57
- cachedI18nBase = ensureTrailingSlash(base);
58
- return cachedI18nBase;
59
- }
60
-
61
- function buildI18nUrl(relativePath) {
62
- if (!relativePath) {
63
- return runtimePublicPathPrefix || resolveI18nBase();
64
- }
65
-
66
- var normalizedPath = relativePath;
67
- if (normalizedPath.charAt(0) === '/') {
68
- normalizedPath = normalizedPath.slice(1);
69
- }
70
-
71
- if (runtimePublicPathPrefix) {
72
- return runtimePublicPathPrefix + normalizedPath;
73
- }
74
-
75
- var base = resolveI18nBase();
76
- return base + normalizedPath;
77
- }
78
-
79
- function loadI18nGroup(groupName, loadReason) {
80
- if (loadedGroups[groupName]) {
81
- return Promise.resolve();
82
- }
83
-
84
- var locale = ${localeVarName} || 'en_US';
85
- var groupConfig = ${JSON.stringify(customGroups)};
86
- var config = groupConfig[groupName];
87
-
88
- if (!config) {
89
- return Promise.resolve();
90
- }
91
-
92
-
93
- return new Promise(function(resolve, reject) {
94
- var relativePath;
95
-
96
- if (groupAssetUrls[groupName] && groupAssetUrls[groupName][locale]) {
97
- relativePath = groupAssetUrls[groupName][locale];
98
- } else {
99
- relativePath = config.filenameTemplate.replace('[locale]', locale);
100
- }
101
-
102
- var i18nUrl = buildI18nUrl(relativePath);
103
-
104
- var script = document.createElement('script');
105
- script.src = i18nUrl;
106
- script.async = true;
107
-
108
- var cleanup = function() {
109
- if (script.parentNode) {
110
- script.parentNode.removeChild(script);
111
- }
112
- };
113
-
114
- script.onload = function() {
115
- loadedGroups[groupName] = true;
116
- cleanup();
117
- resolve();
118
- };
119
-
120
- script.onerror = function() {
121
- cleanup();
122
- loadedGroups[groupName] = true;
123
- resolve();
124
- };
125
-
126
- document.head.appendChild(script);
127
- });
128
- }
129
-
130
- function findGroupByChunkId(chunkId) {
131
- return chunkIdToGroup[chunkId];
132
- }
133
-
134
- var originalEnsureChunk = __webpack_require__.e;
135
-
136
- if (originalEnsureChunk) {
137
- __webpack_require__.e = function(chunkId) {
138
- var args = arguments;
139
- var self = this;
140
- var groupName = findGroupByChunkId(chunkId);
141
-
142
- if (groupName && !loadedGroups[groupName]) {
143
- var i18nPromise = loadI18nGroup(groupName, 'require');
144
-
145
- return i18nPromise.then(function() {
146
- return originalEnsureChunk.apply(self, args);
147
- }).catch(function(err) {
148
- return originalEnsureChunk.apply(self, args);
149
- });
150
- } else {
151
- return originalEnsureChunk.apply(this, arguments);
152
- }
153
- };
154
- }
155
-
156
- // Simple URL-based detection for setup pages
157
- function detectGroupFromUrl() {
158
- if (typeof window === 'undefined') return null;
159
-
160
- var url = window.location.href;
161
- var groupConfig = ${JSON.stringify(customGroups)};
162
-
163
- for (var groupName in groupConfig) {
164
- var config = groupConfig[groupName];
165
- if (config.urlPatterns && Array.isArray(config.urlPatterns)) {
166
- for (var i = 0; i < config.urlPatterns.length; i++) {
167
- var pattern = config.urlPatterns[i];
168
- if (url.includes(pattern)) {
169
- return groupName;
170
- }
171
- }
172
- }
173
- }
174
-
175
- return null;
176
- }
177
-
178
- function checkAndLoadGroupFromUrl() {
179
- try {
180
- var detectedGroup = detectGroupFromUrl();
181
- if (detectedGroup && !loadedGroups[detectedGroup]) {
182
- loadI18nGroup(detectedGroup, 'url-detection').catch(function(err) {
183
- // Silent error handling
184
- });
185
- }
186
- } catch (err) {
187
- // Silent error handling
188
- }
189
- }
190
-
191
- // Check current URL for immediate loading
192
- checkAndLoadGroupFromUrl();
193
- })();
194
- `;
195
- }
196
-
197
- }
198
-
199
- exports.I18nGroupRuntimeModule = I18nGroupRuntimeModule;
@@ -1,110 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.I18nNumericIndexHtmlInjectorPlugin = void 0;
7
-
8
- var _htmlWebpackPlugin = _interopRequireDefault(require("html-webpack-plugin"));
9
-
10
- var _path = _interopRequireDefault(require("path"));
11
-
12
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
-
14
- const pluginName = 'I18nNumericIndexHtmlInjectorPlugin';
15
- const assetStoreKey = Symbol.for('I18nNumericIndexPluginAssets');
16
-
17
- class I18nNumericIndexHtmlInjectorPlugin {
18
- constructor(options) {
19
- this.options = { ...options,
20
- injectI18nUrlInIndex: options.injectI18nUrlInIndex !== undefined ? options.injectI18nUrlInIndex : true,
21
- includeContentHash: options.includeContentHash || false
22
- };
23
- }
24
-
25
- apply(compiler) {
26
- compiler.hooks.thisCompilation.tap(pluginName, compilation => {
27
- _htmlWebpackPlugin.default.getHooks(compilation).beforeAssetTagGeneration.tapAsync(pluginName, (hookData, cb) => {
28
- if (!this.options.injectI18nUrlInIndex) {
29
- return cb(null, hookData);
30
- }
31
-
32
- const {
33
- assets
34
- } = hookData;
35
- const {
36
- outputFolder = 'i18n-chunk',
37
- numericFilenameTemplate,
38
- dynamicFilenameTemplate,
39
- singleFileTemplate,
40
- htmlTemplateLabel,
41
- singleFile,
42
- i18nAssetsPublicPathPrefix = ''
43
- } = this.options;
44
- const newI18nAssetUrlsToAdd = [];
45
- const emittedAssetNames = compilation.getAssets().map(asset => asset.name);
46
- const recordedAssets = compilation[assetStoreKey] || [];
47
-
48
- const resolveAssetPath = (template, fileType) => {
49
- if (!template) return null;
50
- const recorded = recordedAssets.find(asset => {
51
- if (fileType === 'single') return !asset.fileType;
52
- return asset.fileType === fileType;
53
- });
54
-
55
- if (recorded) {
56
- const assetPath = recorded.outputPath.replace(recorded.locale, htmlTemplateLabel);
57
- return i18nAssetsPublicPathPrefix + assetPath;
58
- }
59
-
60
- const filePath = template.replace(/\[locale\]/g, htmlTemplateLabel);
61
- const fullPath = filePath.includes(outputFolder) || filePath.startsWith('/') ? filePath : _path.default.join(outputFolder, filePath);
62
-
63
- if (emittedAssetNames.includes(fullPath)) {
64
- return i18nAssetsPublicPathPrefix + fullPath;
65
- }
66
-
67
- if (fullPath.includes('[contenthash]')) {
68
- const pattern = fullPath.replace('[contenthash]', '*');
69
- const matchingAsset = emittedAssetNames.find(name => name.startsWith(pattern.split('*')[0]) && name.endsWith(pattern.split('*')[1]));
70
-
71
- if (matchingAsset) {
72
- return i18nAssetsPublicPathPrefix + matchingAsset;
73
- }
74
- }
75
-
76
- return i18nAssetsPublicPathPrefix + fullPath;
77
- };
78
-
79
- if (singleFile) {
80
- const combinedFilename = resolveAssetPath(singleFileTemplate, 'single');
81
-
82
- if (combinedFilename) {
83
- newI18nAssetUrlsToAdd.push(combinedFilename);
84
- }
85
- } else {
86
- const numericFilename = resolveAssetPath(numericFilenameTemplate, 'numeric');
87
-
88
- if (numericFilename) {
89
- newI18nAssetUrlsToAdd.push(numericFilename);
90
- }
91
-
92
- const dynamicFilename = resolveAssetPath(dynamicFilenameTemplate, 'dynamic');
93
-
94
- if (dynamicFilename) {
95
- newI18nAssetUrlsToAdd.push(dynamicFilename);
96
- }
97
- }
98
-
99
- if (newI18nAssetUrlsToAdd.length > 0) {
100
- assets.js = [...newI18nAssetUrlsToAdd, ...assets.js];
101
- }
102
-
103
- return cb(null, hookData);
104
- });
105
- });
106
- }
107
-
108
- }
109
-
110
- exports.I18nNumericIndexHtmlInjectorPlugin = I18nNumericIndexHtmlInjectorPlugin;