@plaudit/webpack-extensions 2.54.0 → 2.55.0

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 (42) hide show
  1. package/build/{wordpress-scripts-wrapper → plugins}/AdditionalDependencyInjectorPlugin.js +3 -3
  2. package/build/{wordpress-scripts-wrapper → plugins}/BlockJSONManagingPlugin.d.ts +4 -2
  3. package/build/{wordpress-scripts-wrapper → plugins}/BlockJSONManagingPlugin.js +14 -9
  4. package/build/{wordpress-scripts-wrapper → plugins}/ExtensionsConfigFileGeneratorPlugin.d.ts +6 -3
  5. package/build/plugins/ExtensionsConfigFileGeneratorPlugin.js +173 -0
  6. package/build/plugins/PlainEntrypointsConfigFileGeneratorPlugin.d.ts +24 -0
  7. package/build/plugins/PlainEntrypointsConfigFileGeneratorPlugin.js +244 -0
  8. package/build/plugins/SpecialAssetHandlingPlugin.d.ts +12 -0
  9. package/build/plugins/SpecialAssetHandlingPlugin.js +135 -0
  10. package/build/{wordpress-scripts-wrapper → plugins}/VariablesJSMonitorPlugin.js +1 -1
  11. package/build/{wordpress-scripts-wrapper → plugins}/WPMLConfigBuilder.d.ts +3 -2
  12. package/build/{wordpress-scripts-wrapper → plugins}/WPMLConfigBuilder.js +7 -3
  13. package/build/{wordpress-scripts-wrapper → plugins}/dependency-extraction-webpack-plugin-config-builder.d.ts +1 -7
  14. package/build/shared.d.ts +45 -18
  15. package/build/shared.js +18 -5
  16. package/build/utils/common-config-helpers.d.ts +26 -0
  17. package/build/utils/common-config-helpers.js +336 -0
  18. package/build/{wordpress-scripts-wrapper → utils}/php-serializer.d.ts +1 -1
  19. package/build/{wordpress-scripts-wrapper → utils}/php-serializer.js +1 -1
  20. package/build/utils/php-writer.d.ts +54 -0
  21. package/build/utils/php-writer.js +191 -0
  22. package/build/utils/pseduo-semaphore.d.ts +13 -0
  23. package/build/utils/pseduo-semaphore.js +63 -0
  24. package/build/wordpress-scripts-wrapper.d.ts +1 -20
  25. package/build/wordpress-scripts-wrapper.js +232 -443
  26. package/package.json +4 -4
  27. package/build/wordpress-scripts-wrapper/ExtensionsConfigFileGeneratorPlugin.js +0 -125
  28. package/build/wordpress-scripts-wrapper/SpecialAssetHandlingPlugin.d.ts +0 -7
  29. package/build/wordpress-scripts-wrapper/SpecialAssetHandlingPlugin.js +0 -107
  30. /package/build/{wordpress-scripts-wrapper → plugins}/AdditionalDependencyInjectorPlugin.d.ts +0 -0
  31. /package/build/{wordpress-scripts-wrapper → plugins}/BrowserSyncPlugin.d.ts +0 -0
  32. /package/build/{wordpress-scripts-wrapper → plugins}/BrowserSyncPlugin.js +0 -0
  33. /package/build/{wordpress-scripts-wrapper → plugins}/MiniCSSExtractPluginErrorCleaner.d.ts +0 -0
  34. /package/build/{wordpress-scripts-wrapper → plugins}/MiniCSSExtractPluginErrorCleaner.js +0 -0
  35. /package/build/{wordpress-scripts-wrapper → plugins}/PackageConfigSanityChecker.d.ts +0 -0
  36. /package/build/{wordpress-scripts-wrapper → plugins}/PackageConfigSanityChecker.js +0 -0
  37. /package/build/{wordpress-scripts-wrapper → plugins}/VariablesJSMonitorPlugin.d.ts +0 -0
  38. /package/build/{wordpress-scripts-wrapper → plugins}/dependency-extraction-webpack-plugin-config-builder.js +0 -0
  39. /package/build/{wordpress-scripts-wrapper → plugins}/static-configs.d.ts +0 -0
  40. /package/build/{wordpress-scripts-wrapper → plugins}/static-configs.js +0 -0
  41. /package/build/{wordpress-scripts-wrapper → utils}/json-to-php-but-with-__-injection.d.ts +0 -0
  42. /package/build/{wordpress-scripts-wrapper → utils}/json-to-php-but-with-__-injection.js +0 -0
@@ -0,0 +1,336 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.styleExtension = exports.scriptWithModuleExtension = exports.scriptWithoutModuleExtension = void 0;
7
+ exports.scriptOrStyleTest = scriptOrStyleTest;
8
+ exports.joinPossiblyAbsolutePaths = joinPossiblyAbsolutePaths;
9
+ exports.groupEntrypointsByAssetFile = groupEntrypointsByAssetFile;
10
+ exports.resolveEntryFromDirectory = resolveEntryFromDirectory;
11
+ exports.commonMakeWebpackConfig = commonMakeWebpackConfig;
12
+ const node_fs_1 = __importDefault(require("node:fs"));
13
+ const node_path_1 = __importDefault(require("node:path"));
14
+ const copy_webpack_plugin_1 = __importDefault(require("copy-webpack-plugin"));
15
+ const promises_1 = __importDefault(require("node:fs/promises"));
16
+ const BlockJSONManagingPlugin_1 = require("../plugins/BlockJSONManagingPlugin");
17
+ exports.scriptWithoutModuleExtension = /\.[jt]sx?$/;
18
+ exports.scriptWithModuleExtension = /\.m[jt]sx?$/;
19
+ exports.styleExtension = /\.(p?c|sa)ss$/;
20
+ function scriptOrStyleTest(entryPath, scriptExtension) {
21
+ return scriptExtension.test(entryPath) ? "script" : (exports.styleExtension.test(entryPath) ? "style" : "");
22
+ }
23
+ let isInThemeCache = undefined;
24
+ function isInTheme() {
25
+ return isInThemeCache ?? (isInThemeCache = node_fs_1.default.existsSync(node_path_1.default.join(process.cwd(), "theme.json")));
26
+ }
27
+ function joinPossiblyAbsolutePaths(...paths) {
28
+ return paths.filter((p) => !!p)
29
+ .reduce((res, p) => !res || node_path_1.default.isAbsolute(p) ? p : node_path_1.default.join(res, p), '') || '.';
30
+ }
31
+ function groupEntrypointsByAssetFile(entrypoints, entrypointNameExtractor) {
32
+ const seenPaths = new Map();
33
+ for (const entrypoint of entrypoints) {
34
+ const entrypointName = entrypointNameExtractor(entrypoint);
35
+ const key = entrypointName.substring(0, entrypointName.length - node_path_1.default.extname(entrypointName).length);
36
+ let seen = seenPaths.get(key);
37
+ if (seen === undefined) {
38
+ seenPaths.set(key, seen = []);
39
+ }
40
+ seen.push(entrypoint);
41
+ }
42
+ return seenPaths;
43
+ }
44
+ function mapToRealEntrypoints(entrypoint, dir, args = {}) {
45
+ const { mapper = ep => ep, lazyDependent, associatedQuery, destDir } = args;
46
+ return (Array.isArray(entrypoint) ? entrypoint : [entrypoint])
47
+ .map(ep => joinPossiblyAbsolutePaths(dir, mapper(ep)))
48
+ .filter(ep => node_fs_1.default.statSync(ep, { throwIfNoEntry: false })?.isFile())
49
+ .map(ep => {
50
+ const parsedEntrypoint = node_path_1.default.parse(ep);
51
+ return [joinPossiblyAbsolutePaths(destDir, node_path_1.default.basename(parsedEntrypoint.dir), parsedEntrypoint.name), { import: ep, lazyDependent, associatedQuery }];
52
+ });
53
+ }
54
+ function parseEntrypointsJSON(dir, dest) {
55
+ const entrypointsJSON = JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(dir, 'entrypoints.json'), 'utf8'));
56
+ if (Array.isArray(entrypointsJSON)) {
57
+ return mapToRealEntrypoints(entrypointsJSON, dir, { destDir: dest.destination });
58
+ }
59
+ else {
60
+ return Object.entries(entrypointsJSON).map(([name, config]) => {
61
+ if (typeof config === 'string') {
62
+ return [name, joinPossiblyAbsolutePaths(dir, config)];
63
+ }
64
+ else if (Array.isArray(config)) {
65
+ return [name, config.map(c => joinPossiblyAbsolutePaths(dir, c))];
66
+ }
67
+ else {
68
+ if (typeof config.import === 'string') {
69
+ config.import = joinPossiblyAbsolutePaths(dir, config.import);
70
+ }
71
+ else {
72
+ config.import = config.import.map(c => joinPossiblyAbsolutePaths(dir, c));
73
+ }
74
+ return [name, config];
75
+ }
76
+ });
77
+ }
78
+ }
79
+ function determineEntrypointType(entrypoint, scriptExtension) {
80
+ let res = scriptOrStyleTest(entrypoint[0], scriptExtension);
81
+ if (res) {
82
+ return res;
83
+ }
84
+ if (typeof entrypoint[1] === 'string') {
85
+ return scriptOrStyleTest(entrypoint[1], scriptExtension);
86
+ }
87
+ else if (Array.isArray(entrypoint[1])) {
88
+ return entrypoint[1].reduce((prior, ep) => prior || scriptOrStyleTest(ep, scriptExtension), "");
89
+ }
90
+ else if (typeof entrypoint[1].import === 'string') {
91
+ return scriptOrStyleTest(entrypoint[1].import, scriptExtension);
92
+ }
93
+ else {
94
+ return entrypoint[1].import.reduce((prior, ep) => prior || scriptOrStyleTest(ep, scriptExtension), "");
95
+ }
96
+ }
97
+ function injectTypeAndCountToEntrypointName(entrypointName, type, typeCounts) {
98
+ const entrypointBasename = entrypointName.substring(0, entrypointName.length - node_path_1.default.extname(entrypointName).length);
99
+ const parts = [];
100
+ if (type) {
101
+ parts.push(type);
102
+ }
103
+ if (typeCounts[type] ?? (typeCounts[type] = 0)) {
104
+ parts.push(typeCounts[type].toString());
105
+ }
106
+ typeCounts[type] += 1;
107
+ return `${entrypointBasename}_${parts.join('-')}${node_path_1.default.extname(entrypointName)}`;
108
+ }
109
+ function addPotentiallyDuplicatedEntrypointName(entry, entrypoint, typeCounts, scriptExtension) {
110
+ const type = determineEntrypointType(entrypoint, scriptExtension);
111
+ let potentialKey = injectTypeAndCountToEntrypointName(entrypoint[0], type, typeCounts);
112
+ while (entry[potentialKey]) {
113
+ potentialKey = injectTypeAndCountToEntrypointName(entrypoint[0], type, typeCounts);
114
+ }
115
+ entry[potentialKey] = entrypoint[1];
116
+ }
117
+ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
118
+ const { entrypointFields, processingModules, scriptExtension } = commonConfig;
119
+ return async () => {
120
+ const loadingEntrypoints = [];
121
+ for await (const dirent of await promises_1.default.opendir(srcRoot)) {
122
+ if (!dirent.isDirectory()) {
123
+ continue;
124
+ }
125
+ const dir = joinPossiblyAbsolutePaths(srcRoot, dirent.name);
126
+ loadingEntrypoints.push(new Promise(async (resolve) => {
127
+ const rawEntrypoints = [];
128
+ const wpmlFiles = [];
129
+ try {
130
+ const blockJSON = JSON.parse(await promises_1.default.readFile(node_path_1.default.join(dir, 'block.json'), 'utf8'));
131
+ const blockJSONChunkName = node_path_1.default.join(dest.destination, node_path_1.default.relative(srcRoot, dir), "block.json");
132
+ for (const key of entrypointFields) {
133
+ if (key in blockJSON) {
134
+ rawEntrypoints.push(...mapToRealEntrypoints(blockJSON[key], dir, { mapper: ep => ep.startsWith("file:") ? ep.substring(5) : ep, lazyDependent: blockJSONChunkName, destDir: dest.destination }));
135
+ }
136
+ }
137
+ wpmlFiles.push(node_path_1.default.join(dir, 'block.json'));
138
+ BlockJSONManagingPlugin_1.BlockJSONManagingPlugin.recordBlockJSONAssetSourceDir(blockJSONChunkName, dir);
139
+ }
140
+ catch (e) {
141
+ try {
142
+ const packageJSON = JSON.parse(await promises_1.default.readFile(node_path_1.default.join(dir, 'package.json'), 'utf8'));
143
+ rawEntrypoints.push(...mapToRealEntrypoints(packageJSON['main'], dir, { destDir: dest.destination }));
144
+ rawEntrypoints.push(...mapToRealEntrypoints(packageJSON['style'], dir, { destDir: dest.destination }));
145
+ }
146
+ catch (e) {
147
+ try {
148
+ rawEntrypoints.push(...parseEntrypointsJSON(dir, dest));
149
+ }
150
+ catch (e) {
151
+ // This just means that the directory doesn't contain any declared entrypoints.
152
+ }
153
+ }
154
+ }
155
+ if (!processingModules) {
156
+ try {
157
+ const wpmlFilePath = node_path_1.default.join(dir, "wpml-config.xml");
158
+ await promises_1.default.access(wpmlFilePath);
159
+ wpmlFiles.push(wpmlFilePath);
160
+ }
161
+ catch (e) {
162
+ // This just means that the file doesn't exist
163
+ }
164
+ }
165
+ resolve([rawEntrypoints, wpmlFiles]);
166
+ }));
167
+ }
168
+ const allEntrypoints = await Promise.all(loadingEntrypoints);
169
+ const perAssetPathGroupedEntrypoints = groupEntrypointsByAssetFile(allEntrypoints.flatMap(e => e[0]), e => e[0]);
170
+ const currentEntry = {};
171
+ for (const groupedEntrypoints of perAssetPathGroupedEntrypoints.values()) {
172
+ if (groupedEntrypoints.length === 1 && groupedEntrypoints[0] !== undefined) {
173
+ currentEntry[groupedEntrypoints[0][0]] = groupedEntrypoints[0][1];
174
+ }
175
+ else {
176
+ const typeCounts = {};
177
+ for (const entrypoint of groupedEntrypoints) {
178
+ addPotentiallyDuplicatedEntrypointName(currentEntry, entrypoint, typeCounts, scriptExtension);
179
+ }
180
+ }
181
+ }
182
+ // This is used to allow for block.json dependencies to correctly account for name-deduplication
183
+ for (const [key, entry] of Object.entries(currentEntry)) {
184
+ if (typeof entry === 'object' && !Array.isArray(entry) && 'lazyDependent' in entry && typeof entry.lazyDependent === 'string') {
185
+ BlockJSONManagingPlugin_1.BlockJSONManagingPlugin.recordRawDependency(entry.lazyDependent, key);
186
+ }
187
+ }
188
+ if (!processingModules) {
189
+ const wpmlEntrypointFiles = allEntrypoints.flatMap(e => e[1]);
190
+ try {
191
+ await promises_1.default.access(node_path_1.default.join(srcRoot, "wpml-config.xml"));
192
+ currentEntry["wpml-config.xml"] = { import: [node_path_1.default.join(srcRoot, "wpml-config.xml"), ...wpmlEntrypointFiles] };
193
+ }
194
+ catch (e) {
195
+ // If the wpml-config.xml file does not exist, just "import" the other files that will be used to build the emitted version
196
+ if (wpmlEntrypointFiles.length) {
197
+ currentEntry["wpml-config.xml"] = { import: wpmlEntrypointFiles };
198
+ }
199
+ }
200
+ }
201
+ return currentEntry;
202
+ };
203
+ }
204
+ function commonMakeWebpackConfig(config, commonConfig, webpackConfig, srcIsDirectory, dest, src, srcRoot, entry, plugins) {
205
+ const { standaloneBlocks, variablesFilePath } = config;
206
+ const { fixedRules, processingModules, updateCurrentVariables } = commonConfig;
207
+ const outPath = joinPossiblyAbsolutePaths(process.cwd(), config.outputDir);
208
+ let publicPath = webpackConfig.output?.publicPath;
209
+ if (isInTheme()) {
210
+ let prefix = process.cwd();
211
+ while (prefix.length > 5 && node_path_1.default.basename(prefix) !== "wp-content") {
212
+ prefix = node_path_1.default.dirname(prefix);
213
+ }
214
+ if (prefix.length > 5) {
215
+ prefix = node_path_1.default.dirname(prefix);
216
+ publicPath = `/${node_path_1.default.relative(prefix, outPath)}/`;
217
+ }
218
+ }
219
+ let viableRoots = [...(Array.isArray(webpackConfig.context) ? webpackConfig.context : [webpackConfig.context ?? process.cwd()])];
220
+ if (Array.isArray(srcRoot)) {
221
+ viableRoots.push(...(srcIsDirectory ? srcRoot : srcRoot.map(s => node_path_1.default.dirname(s))));
222
+ }
223
+ else {
224
+ viableRoots.push(srcIsDirectory ? srcRoot : node_path_1.default.dirname(srcRoot));
225
+ }
226
+ let wpContentHolderDirectory = process.cwd();
227
+ while (wpContentHolderDirectory.length > 5) {
228
+ if (node_path_1.default.basename(wpContentHolderDirectory) === 'wp-content') {
229
+ wpContentHolderDirectory = node_path_1.default.dirname(wpContentHolderDirectory);
230
+ if (wpContentHolderDirectory.length > 5) {
231
+ viableRoots.push(wpContentHolderDirectory);
232
+ }
233
+ break;
234
+ }
235
+ wpContentHolderDirectory = node_path_1.default.dirname(wpContentHolderDirectory);
236
+ }
237
+ const distinctViableRoots = new Set();
238
+ viableRoots = viableRoots.filter(value => distinctViableRoots.has(value) ? false : distinctViableRoots.add(value) && true);
239
+ let outputLibrary;
240
+ if (typeof dest === 'object' && dest.externalize) {
241
+ if (Array.isArray(dest.externalize) || typeof dest.externalize === 'string') {
242
+ outputLibrary = {
243
+ name: dest.externalize,
244
+ type: "assign"
245
+ };
246
+ }
247
+ else {
248
+ const originalLibrary = webpackConfig.output?.library;
249
+ if (originalLibrary && typeof originalLibrary === 'object' && !Array.isArray(originalLibrary)) {
250
+ outputLibrary = {
251
+ ...originalLibrary,
252
+ ...dest.externalize
253
+ };
254
+ }
255
+ else {
256
+ outputLibrary = dest.externalize;
257
+ }
258
+ }
259
+ }
260
+ else {
261
+ outputLibrary = webpackConfig.output?.library;
262
+ }
263
+ const canCopyFiles = srcIsDirectory && src !== dest;
264
+ const possiblePlugins = canCopyFiles
265
+ ? plugins.map(plugin => !processingModules && plugin.constructor.name === 'CopyPlugin'
266
+ ? new copy_webpack_plugin_1.default({
267
+ patterns: [{
268
+ from: standaloneBlocks ? '**/(block.json|*.(php|twig|svg))' : '**/(block.json|*.(asset\.php|svg))',
269
+ to: typeof dest === 'string' ? dest : dest.destination,
270
+ context: srcRoot /* canCopyFiles can only be true if srcRoot is a string, so this is safe */, noErrorOnMissing: true
271
+ }]
272
+ })
273
+ : plugin)
274
+ : (srcIsDirectory
275
+ ? plugins.filter(plugin => plugin.constructor.name !== 'CopyPlugin' && plugin.constructor.name !== 'CleanWebpackPlugin')
276
+ : plugins.filter(plugin => plugin.constructor.name !== 'CopyPlugin'));
277
+ return {
278
+ ...webpackConfig,
279
+ devtool: 'source-map',
280
+ mode: "production",
281
+ output: {
282
+ ...webpackConfig.output,
283
+ path: outPath,
284
+ chunkFilename: 'webpack-chunks/[id].js',
285
+ publicPath: publicPath,
286
+ library: outputLibrary
287
+ },
288
+ optimization: {
289
+ ...webpackConfig.optimization,
290
+ splitChunks: {
291
+ ...(webpackConfig.optimization?.splitChunks || {}),
292
+ cacheGroups: {
293
+ style: {
294
+ // This is a flagrant abuse of cache groups, but it fixes a persistent problem wherein the dependencies and versions of scripts and styles were bleeding into each-other
295
+ type: 'css/mini-extract',
296
+ chunks: 'all',
297
+ enforce: true,
298
+ name(_, chunks, cacheGroupKey) {
299
+ const chunkName = chunks.find(chunk => chunk.name)?.name;
300
+ // We use "__${cacheGroupKey}__" instead of "${cacheGroupKey}-" to make it easier to remove when generating the filename
301
+ const filename = `__${cacheGroupKey}__${node_path_1.default.basename(chunkName)}`;
302
+ const dirname = node_path_1.default.dirname(chunkName);
303
+ return dirname === '.' ? filename : `${dirname}/${filename}`;
304
+ }
305
+ },
306
+ default: false
307
+ }
308
+ }
309
+ },
310
+ module: {
311
+ ...webpackConfig.module,
312
+ rules: fixedRules
313
+ },
314
+ resolve: {
315
+ ...webpackConfig.resolve,
316
+ roots: viableRoots,
317
+ extensions: ['.mjsx', '.mjs', '.mtsx', '.mts', '.jsx', '.tsx', '.ts', '...']
318
+ },
319
+ stats: config.stats,
320
+ plugins: config.outputDir ? possiblePlugins : possiblePlugins.filter(plugin => plugin.constructor.name !== 'CleanWebpackPlugin'),
321
+ entry() {
322
+ if (variablesFilePath) {
323
+ delete require.cache[require.resolve(variablesFilePath)];
324
+ updateCurrentVariables(require(variablesFilePath));
325
+ }
326
+ return entry();
327
+ },
328
+ performance: {
329
+ ...webpackConfig.performance,
330
+ assetFilter(assetFilename) {
331
+ // We don't want to warn about the sizes of incompressible assets
332
+ return !/\.(map|svg|png|jpe?g|gif)$/i.test(assetFilename);
333
+ }
334
+ }
335
+ };
336
+ }
@@ -2,5 +2,5 @@ type Config = {
2
2
  objectsAsArrays?: boolean;
3
3
  excludedKeys?: string[];
4
4
  };
5
- export default function phpSerialize(value: any, config?: Config): string;
5
+ export declare function phpSerialize(value: any, config?: Config): string;
6
6
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = phpSerialize;
3
+ exports.phpSerialize = phpSerialize;
4
4
  function phpSerialize(value, config) {
5
5
  switch (typeof value) {
6
6
  case "undefined":
@@ -0,0 +1,54 @@
1
+ import { AssetInfo, Compilation } from "webpack";
2
+ export declare class Expr {
3
+ private readonly value;
4
+ private readonly raw;
5
+ static readonly jsonToPHPConverter: (obj: unknown, parentIndent?: string) => string;
6
+ static readonly convertJsonToPHP: (obj: unknown) => string;
7
+ constructor(value: string, raw?: boolean);
8
+ toString(): string;
9
+ }
10
+ export type ActionOrFilterArgs = {
11
+ priority?: number | Expr;
12
+ functionArgParameters?: string[];
13
+ useVars?: string[];
14
+ };
15
+ export type FunctionCreationArgs = {
16
+ includeExistenceCheck?: boolean;
17
+ useVars?: string[];
18
+ returnType?: string;
19
+ };
20
+ export declare class PHPWriter {
21
+ private readonly inlineFirstLine;
22
+ private buffer;
23
+ private indentation;
24
+ private printingInPHP;
25
+ private fileNamespace;
26
+ private useList;
27
+ constructor(inlineFirstLine?: boolean);
28
+ indent(): this;
29
+ outdent(): this;
30
+ append(...lines: (string | Expr)[]): this;
31
+ static(variable: string, opts?: {
32
+ initializer?: string | Expr;
33
+ withTest?: boolean | 'chainable';
34
+ }): this;
35
+ linebreak(): this;
36
+ call(func: string, args: unknown[], opts?: {
37
+ chain?: boolean;
38
+ assignTo?: string;
39
+ }): this;
40
+ action(name: string | Expr, contents: (writer: this) => void, args?: ActionOrFilterArgs): this;
41
+ filter(name: string | Expr, contents: (writer: this) => void, args?: ActionOrFilterArgs): this;
42
+ actionOrFilter(type: 'action' | 'filter', name: string | Expr, contents: (writer: this) => void, args: ActionOrFilterArgs): this;
43
+ if(condition: string): this;
44
+ elseIf(condition: string): this;
45
+ else(): this;
46
+ endIf(): this;
47
+ function(name: string, parameters: string[], body: (writer: this) => void, args?: FunctionCreationArgs): this;
48
+ closePHP(): this;
49
+ openPHP(): this;
50
+ namespace(namespace: string): this;
51
+ use(...uses: string[]): this;
52
+ toString(): string;
53
+ emitAsset(compilation: Compilation, file: string, assetInfo?: AssetInfo): void;
54
+ }
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PHPWriter = exports.Expr = void 0;
7
+ const json_to_php_but_with____injection_1 = __importDefault(require("./json-to-php-but-with-__-injection"));
8
+ const webpack_1 = require("webpack");
9
+ class Expr {
10
+ value;
11
+ raw;
12
+ static jsonToPHPConverter = json_to_php_but_with____injection_1.default.make({ shortArraySyntax: true });
13
+ static convertJsonToPHP = (obj) => obj instanceof Expr ? obj.toString() : Expr.jsonToPHPConverter(obj);
14
+ constructor(value, raw = true) {
15
+ this.value = value;
16
+ this.raw = raw;
17
+ }
18
+ toString() {
19
+ return this.raw ? this.value : Expr.jsonToPHPConverter(this.value);
20
+ }
21
+ }
22
+ exports.Expr = Expr;
23
+ class PHPWriter {
24
+ inlineFirstLine;
25
+ buffer = "";
26
+ indentation = "";
27
+ printingInPHP = true;
28
+ fileNamespace = "";
29
+ useList = [];
30
+ constructor(inlineFirstLine = false) {
31
+ this.inlineFirstLine = inlineFirstLine;
32
+ }
33
+ indent() {
34
+ this.indentation += "\t";
35
+ return this;
36
+ }
37
+ outdent() {
38
+ this.indentation = this.indentation.slice(0, -1);
39
+ return this;
40
+ }
41
+ append(...lines) {
42
+ for (const line of lines) {
43
+ this.buffer += `\n${this.indentation}${line}`;
44
+ }
45
+ return this;
46
+ }
47
+ static(variable, opts = {}) {
48
+ const initializer = opts.initializer ? Expr.convertJsonToPHP(opts.initializer) : "null";
49
+ this.append(`static ${variable} = ${initializer};`);
50
+ if (opts.withTest) {
51
+ this.if(`${variable} !== ${initializer}`)
52
+ .append(`return ${variable};`);
53
+ if (opts.withTest !== 'chainable') {
54
+ this.endIf();
55
+ }
56
+ }
57
+ return this;
58
+ }
59
+ linebreak() {
60
+ this.buffer += '\n';
61
+ return this;
62
+ }
63
+ call(func, args, opts = {}) {
64
+ const line = `${func}(${args.map(Expr.convertJsonToPHP).join(", ")})${opts.chain === true ? "" : ";"}`;
65
+ return this.append(opts.assignTo ? `${opts.assignTo} = ${line}` : line);
66
+ }
67
+ action(name, contents, args = {}) {
68
+ return this.actionOrFilter('action', name, contents, args);
69
+ }
70
+ filter(name, contents, args = {}) {
71
+ return this.actionOrFilter('filter', name, contents, args);
72
+ }
73
+ actionOrFilter(type, name, contents, args) {
74
+ const { priority = 10, functionArgParameters = [], useVars = [] } = args;
75
+ // The trailing comma inside the first item is necessary
76
+ const declarationComponents = [`${Expr.convertJsonToPHP(name)},`, `function(${functionArgParameters.join(", ")})`];
77
+ if (useVars.length > 0) {
78
+ declarationComponents.push(`use (${useVars.join(", ")})`);
79
+ }
80
+ declarationComponents.push("{");
81
+ this.openPHP().append(`add_${type}(${declarationComponents.join(" ")}`);
82
+ this.indent();
83
+ contents(this);
84
+ this.openPHP().outdent();
85
+ const actionOrFilterArgs = ["}"];
86
+ const accepted_args = Math.max(functionArgParameters.length, 1); // This avoids us unnecessarily setting the accepted_args value to 0 for actions
87
+ if (priority !== 10) {
88
+ actionOrFilterArgs.push(priority.toString());
89
+ if (accepted_args !== 1) {
90
+ actionOrFilterArgs.push(accepted_args.toString());
91
+ }
92
+ }
93
+ else if (accepted_args !== 1) {
94
+ actionOrFilterArgs.push(`accepted_args: ${accepted_args}`);
95
+ }
96
+ return this.append(actionOrFilterArgs.join(", ") + ");");
97
+ }
98
+ if(condition) {
99
+ return this.openPHP().append(`if (${condition}) {`).indent();
100
+ }
101
+ elseIf(condition) {
102
+ return this.openPHP().outdent().append(`} else if (${condition}) {`).indent();
103
+ }
104
+ else() {
105
+ return this.openPHP().outdent().append(`} else {`).indent();
106
+ }
107
+ endIf() {
108
+ return this.openPHP().outdent().append("}");
109
+ }
110
+ function(name, parameters, body, args = {}) {
111
+ if (args.includeExistenceCheck) {
112
+ this.if(`!function_exists('${name}')`);
113
+ }
114
+ else {
115
+ this.openPHP();
116
+ }
117
+ let nameAndParameters = `${name}(${parameters.join(", ")})`;
118
+ const declarationComponents = ["function",];
119
+ if (args.useVars?.length) {
120
+ let useVars = `use (${args.useVars.join(", ")})`;
121
+ if (args.returnType) {
122
+ useVars += `: ${args.returnType}`;
123
+ }
124
+ declarationComponents.push(nameAndParameters, useVars);
125
+ }
126
+ else {
127
+ if (args.returnType) {
128
+ nameAndParameters += `: ${args.returnType}`;
129
+ }
130
+ declarationComponents.push(nameAndParameters);
131
+ }
132
+ declarationComponents.push("{");
133
+ this.append(declarationComponents.join(' '));
134
+ this.indent();
135
+ body(this);
136
+ this.openPHP().outdent().append("}");
137
+ if (args.includeExistenceCheck) {
138
+ return this.endIf();
139
+ }
140
+ return this;
141
+ }
142
+ closePHP() {
143
+ if (!this.printingInPHP) {
144
+ return this;
145
+ }
146
+ this.printingInPHP = false;
147
+ return this.append("?>");
148
+ }
149
+ openPHP() {
150
+ if (this.printingInPHP) {
151
+ return this;
152
+ }
153
+ this.printingInPHP = true;
154
+ return this.append("<?php");
155
+ }
156
+ namespace(namespace) {
157
+ this.fileNamespace = namespace;
158
+ return this;
159
+ }
160
+ use(...uses) {
161
+ for (const use of uses) {
162
+ if (!this.useList.find(u => u.toLowerCase() === use.toLowerCase())) {
163
+ this.useList.push(use);
164
+ }
165
+ }
166
+ return this;
167
+ }
168
+ toString() {
169
+ let fileContents = "";
170
+ if (this.fileNamespace) {
171
+ fileContents += `\nnamespace ${this.fileNamespace};\n`;
172
+ }
173
+ if (this.useList) {
174
+ for (const use of this.useList.toSorted()) {
175
+ fileContents += `\nuse ${use};`;
176
+ }
177
+ fileContents += "\n";
178
+ }
179
+ if (this.inlineFirstLine && !fileContents) {
180
+ return `<?php ${this.buffer.trimStart()}`;
181
+ }
182
+ else {
183
+ return "<?php" + fileContents + this.buffer;
184
+ }
185
+ }
186
+ emitAsset(compilation, file, assetInfo) {
187
+ const contents = this.toString() + "\n";
188
+ compilation[file in compilation.assets ? 'updateAsset' : 'emitAsset'](file, new webpack_1.sources.RawSource(contents), { size: Buffer.byteLength(contents), ...assetInfo });
189
+ }
190
+ }
191
+ exports.PHPWriter = PHPWriter;
@@ -0,0 +1,13 @@
1
+ export declare class PseudoSemaphore<T> {
2
+ private readonly defaultValue;
3
+ private flagSet;
4
+ private readonly flags;
5
+ constructor(defaultValue: T);
6
+ register(id: string): void;
7
+ resolve(id: string, value: T): void;
8
+ reject(id: string): void;
9
+ reset(id: string): void;
10
+ private getFlag;
11
+ private initializeFlag;
12
+ wait(): Promise<T[]>;
13
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PseudoSemaphore = void 0;
4
+ class PseudoSemaphore {
5
+ defaultValue;
6
+ flagSet = 0;
7
+ flags = new Map();
8
+ constructor(defaultValue) {
9
+ this.defaultValue = defaultValue;
10
+ }
11
+ register(id) {
12
+ if (this.flags.has(id)) {
13
+ throw new Error();
14
+ }
15
+ this.initializeFlag(id);
16
+ this.resolve(id, this.defaultValue);
17
+ }
18
+ resolve(id, value) {
19
+ const flag = this.getFlag(id);
20
+ flag[1].resolve(value); // This is deliberately unsafe - I would rather see a cascading failure than a silent one
21
+ flag[2] = true;
22
+ }
23
+ reject(id) {
24
+ const flag = this.getFlag(id);
25
+ flag[1].reject(); // This is deliberately unsafe - I would rather see a cascading failure than a silent one
26
+ flag[2] = true;
27
+ }
28
+ reset(id) {
29
+ const flag = this.getFlag(id);
30
+ // We reject if we reset early to avoid any permanently-hanging promises
31
+ if (!flag[2]) {
32
+ flag[1].reject(); // This is deliberately unsafe - I would rather see a cascading failure than a silent one
33
+ }
34
+ this.initializeFlag(id);
35
+ }
36
+ getFlag(id) {
37
+ const flag = this.flags.get(id);
38
+ if (flag) {
39
+ return flag;
40
+ }
41
+ throw new Error();
42
+ }
43
+ initializeFlag(id) {
44
+ const controller = {};
45
+ const promise = new Promise((resolve, reject) => {
46
+ controller.resolve = resolve;
47
+ controller.reject = reject;
48
+ });
49
+ this.flags.set(id, [promise, controller, false, Date.now()]);
50
+ this.flagSet++;
51
+ promise.catch(() => { });
52
+ }
53
+ async wait() {
54
+ let currentFlagSet;
55
+ let res;
56
+ do {
57
+ currentFlagSet = this.flagSet;
58
+ res = await Promise.all(this.flags.values().toArray().sort((a, b) => a[3] - b[3]).map(flag => flag[0]));
59
+ } while (currentFlagSet !== this.flagSet);
60
+ return res;
61
+ }
62
+ }
63
+ exports.PseudoSemaphore = PseudoSemaphore;