@angular-devkit/build-angular 18.2.0-next.0 → 18.2.0-next.2
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.
- package/package.json +18 -18
- package/src/builders/browser-esbuild/index.d.ts +6 -9
- package/src/builders/browser-esbuild/index.js +28 -39
- package/src/builders/extract-i18n/application-extraction.d.ts +2 -2
- package/src/builders/extract-i18n/application-extraction.js +26 -34
- package/src/builders/extract-i18n/builder.js +12 -8
- package/src/builders/extract-i18n/options.js +1 -1
- package/src/builders/web-test-runner/index.js +2 -2
- package/src/tools/babel/webpack-loader.js +1 -2
- package/src/utils/normalize-cache.js +1 -1
package/package.json
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/build-angular",
|
|
3
|
-
"version": "18.2.0-next.
|
|
3
|
+
"version": "18.2.0-next.2",
|
|
4
4
|
"description": "Angular Webpack Build Facade",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"typings": "src/index.d.ts",
|
|
7
7
|
"builders": "builders.json",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@ampproject/remapping": "2.3.0",
|
|
10
|
-
"@angular-devkit/architect": "0.1802.0-next.
|
|
11
|
-
"@angular-devkit/build-webpack": "0.1802.0-next.
|
|
12
|
-
"@angular-devkit/core": "18.2.0-next.
|
|
13
|
-
"@angular/build": "18.2.0-next.
|
|
14
|
-
"@babel/core": "7.24.
|
|
15
|
-
"@babel/generator": "7.24.
|
|
10
|
+
"@angular-devkit/architect": "0.1802.0-next.2",
|
|
11
|
+
"@angular-devkit/build-webpack": "0.1802.0-next.2",
|
|
12
|
+
"@angular-devkit/core": "18.2.0-next.2",
|
|
13
|
+
"@angular/build": "18.2.0-next.2",
|
|
14
|
+
"@babel/core": "7.24.9",
|
|
15
|
+
"@babel/generator": "7.24.10",
|
|
16
16
|
"@babel/helper-annotate-as-pure": "7.24.7",
|
|
17
17
|
"@babel/helper-split-export-declaration": "7.24.7",
|
|
18
18
|
"@babel/plugin-transform-async-generator-functions": "7.24.7",
|
|
19
19
|
"@babel/plugin-transform-async-to-generator": "7.24.7",
|
|
20
20
|
"@babel/plugin-transform-runtime": "7.24.7",
|
|
21
|
-
"@babel/preset-env": "7.24.
|
|
22
|
-
"@babel/runtime": "7.24.
|
|
21
|
+
"@babel/preset-env": "7.24.8",
|
|
22
|
+
"@babel/runtime": "7.24.8",
|
|
23
23
|
"@discoveryjs/json-ext": "0.6.0",
|
|
24
|
-
"@ngtools/webpack": "18.2.0-next.
|
|
24
|
+
"@ngtools/webpack": "18.2.0-next.2",
|
|
25
25
|
"@vitejs/plugin-basic-ssl": "1.1.0",
|
|
26
26
|
"ansi-colors": "4.1.3",
|
|
27
27
|
"autoprefixer": "10.4.19",
|
|
@@ -53,18 +53,18 @@
|
|
|
53
53
|
"postcss-loader": "8.1.1",
|
|
54
54
|
"resolve-url-loader": "5.0.0",
|
|
55
55
|
"rxjs": "7.8.1",
|
|
56
|
-
"sass": "1.77.
|
|
57
|
-
"sass-loader": "
|
|
58
|
-
"semver": "7.6.
|
|
56
|
+
"sass": "1.77.8",
|
|
57
|
+
"sass-loader": "15.0.0",
|
|
58
|
+
"semver": "7.6.3",
|
|
59
59
|
"source-map-loader": "5.0.0",
|
|
60
60
|
"source-map-support": "0.5.21",
|
|
61
|
-
"terser": "5.
|
|
61
|
+
"terser": "5.31.3",
|
|
62
62
|
"tree-kill": "1.2.2",
|
|
63
63
|
"tslib": "2.6.3",
|
|
64
|
-
"vite": "5.3.
|
|
64
|
+
"vite": "5.3.4",
|
|
65
65
|
"watchpack": "2.4.1",
|
|
66
|
-
"webpack": "5.
|
|
67
|
-
"webpack-dev-middleware": "7.
|
|
66
|
+
"webpack": "5.93.0",
|
|
67
|
+
"webpack-dev-middleware": "7.3.0",
|
|
68
68
|
"webpack-dev-server": "5.0.4",
|
|
69
69
|
"webpack-merge": "6.0.1",
|
|
70
70
|
"webpack-subresource-integrity": "5.1.0"
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
"devkit",
|
|
130
130
|
"sdk"
|
|
131
131
|
],
|
|
132
|
-
"packageManager": "yarn@4.3.
|
|
132
|
+
"packageManager": "yarn@4.3.1",
|
|
133
133
|
"repository": {
|
|
134
134
|
"type": "git",
|
|
135
135
|
"url": "https://github.com/angular/angular-cli.git"
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
|
-
import
|
|
9
|
-
import { BuilderContext
|
|
8
|
+
import { Result } from '@angular/build/private';
|
|
9
|
+
import { BuilderContext } from '@angular-devkit/architect';
|
|
10
10
|
import type { Plugin } from 'esbuild';
|
|
11
11
|
import type { Schema as BrowserBuilderOptions } from './schema';
|
|
12
12
|
/**
|
|
@@ -18,12 +18,9 @@ import type { Schema as BrowserBuilderOptions } from './schema';
|
|
|
18
18
|
*/
|
|
19
19
|
export declare function buildEsbuildBrowser(userOptions: BrowserBuilderOptions, context: BuilderContext, infrastructureSettings?: {
|
|
20
20
|
write?: boolean;
|
|
21
|
-
}, plugins?: Plugin[]): AsyncIterable<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
destination: string;
|
|
26
|
-
}[];
|
|
27
|
-
}>;
|
|
21
|
+
}, plugins?: Plugin[]): AsyncIterable<Result>;
|
|
22
|
+
export declare function buildEsbuildBrowserArchitect(options: BrowserBuilderOptions, context: BuilderContext): AsyncGenerator<{
|
|
23
|
+
success: boolean;
|
|
24
|
+
}, void, unknown>;
|
|
28
25
|
declare const _default: import("../../../../architect/src/internal").Builder<BrowserBuilderOptions & import("../../../../core/src").JsonObject>;
|
|
29
26
|
export default _default;
|
|
@@ -11,6 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.buildEsbuildBrowser = buildEsbuildBrowser;
|
|
14
|
+
exports.buildEsbuildBrowserArchitect = buildEsbuildBrowserArchitect;
|
|
14
15
|
const private_1 = require("@angular/build/private");
|
|
15
16
|
const architect_1 = require("@angular-devkit/architect");
|
|
16
17
|
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
@@ -35,19 +36,30 @@ async function* buildEsbuildBrowser(userOptions, context, infrastructureSettings
|
|
|
35
36
|
for await (const result of (0, private_1.buildApplicationInternal)(normalizedOptions, context, {
|
|
36
37
|
write: false,
|
|
37
38
|
}, plugins && { codePlugins: plugins })) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
// Write the file directly from this builder to maintain webpack output compatibility
|
|
40
|
+
// and not output browser files into '/browser'.
|
|
41
|
+
if (infrastructureSettings?.write !== false &&
|
|
42
|
+
(result.kind === private_1.ResultKind.Full || result.kind === private_1.ResultKind.Incremental)) {
|
|
43
|
+
const directoryExists = new Set();
|
|
44
|
+
// Writes the output file to disk and ensures the containing directories are present
|
|
45
|
+
await (0, private_1.emitFilesToDisk)(Object.entries(result.files), async ([filePath, file]) => {
|
|
46
|
+
// Ensure output subdirectories exist
|
|
47
|
+
const basePath = node_path_1.default.dirname(filePath);
|
|
48
|
+
if (basePath && !directoryExists.has(basePath)) {
|
|
49
|
+
await promises_1.default.mkdir(node_path_1.default.join(fullOutputPath, basePath), { recursive: true });
|
|
50
|
+
directoryExists.add(basePath);
|
|
51
|
+
}
|
|
52
|
+
if (file.origin === 'memory') {
|
|
53
|
+
// Write file contents
|
|
54
|
+
await promises_1.default.writeFile(node_path_1.default.join(fullOutputPath, filePath), file.contents);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Copy file contents
|
|
58
|
+
await promises_1.default.copyFile(file.inputPath, node_path_1.default.join(fullOutputPath, filePath), promises_1.default.constants.COPYFILE_FICLONE);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
41
61
|
}
|
|
42
|
-
|
|
43
|
-
// attempts to validate the object with a JSON schema validator. This can lead to slow
|
|
44
|
-
// build completion (even after the actual build is fully complete) or crashes if the
|
|
45
|
-
// size and/or quantity of output files is large. Architect only requires a `success`
|
|
46
|
-
// property so that is all that will be passed here if the infrastructure settings have
|
|
47
|
-
// not been explicitly set to avoid writes. Writing is only disabled when used directly
|
|
48
|
-
// by the dev server which bypasses the architect behavior.
|
|
49
|
-
const builderResult = infrastructureSettings?.write === false ? result : { success: result.success };
|
|
50
|
-
yield builderResult;
|
|
62
|
+
yield result;
|
|
51
63
|
}
|
|
52
64
|
}
|
|
53
65
|
function normalizeOptions(options) {
|
|
@@ -63,32 +75,9 @@ function normalizeOptions(options) {
|
|
|
63
75
|
...otherOptions,
|
|
64
76
|
};
|
|
65
77
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const directoryExists = new Set();
|
|
70
|
-
const ensureDirectoryExists = async (basePath) => {
|
|
71
|
-
if (basePath && !directoryExists.has(basePath)) {
|
|
72
|
-
await promises_1.default.mkdir(node_path_1.default.join(outputPath, basePath), { recursive: true });
|
|
73
|
-
directoryExists.add(basePath);
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
// Writes the output file to disk and ensures the containing directories are present
|
|
77
|
-
await (0, private_1.emitFilesToDisk)(outputFiles, async (file) => {
|
|
78
|
-
// Ensure output subdirectories exist
|
|
79
|
-
const basePath = node_path_1.default.dirname(file.path);
|
|
80
|
-
await ensureDirectoryExists(basePath);
|
|
81
|
-
// Write file contents
|
|
82
|
-
await promises_1.default.writeFile(node_path_1.default.join(outputPath, file.path), file.contents);
|
|
83
|
-
});
|
|
84
|
-
if (assetFiles?.length) {
|
|
85
|
-
await (0, private_1.emitFilesToDisk)(assetFiles, async ({ source, destination }) => {
|
|
86
|
-
const basePath = node_path_1.default.dirname(destination);
|
|
87
|
-
// Ensure output subdirectories exist
|
|
88
|
-
await ensureDirectoryExists(basePath);
|
|
89
|
-
// Copy file contents
|
|
90
|
-
await promises_1.default.copyFile(source, node_path_1.default.join(outputPath, destination), promises_1.default.constants.COPYFILE_FICLONE);
|
|
91
|
-
});
|
|
78
|
+
async function* buildEsbuildBrowserArchitect(options, context) {
|
|
79
|
+
for await (const result of buildEsbuildBrowser(options, context)) {
|
|
80
|
+
yield { success: result.kind !== private_1.ResultKind.Failure };
|
|
92
81
|
}
|
|
93
82
|
}
|
|
94
|
-
exports.default = (0, architect_1.createBuilder)(
|
|
83
|
+
exports.default = (0, architect_1.createBuilder)(buildEsbuildBrowserArchitect);
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { ɵParsedMessage as LocalizeMessage } from '@angular/localize';
|
|
9
9
|
import type { MessageExtractor } from '@angular/localize/tools';
|
|
10
|
-
import type { BuilderContext
|
|
10
|
+
import type { BuilderContext } from '@angular-devkit/architect';
|
|
11
11
|
import type { NormalizedExtractI18nOptions } from './options';
|
|
12
12
|
export declare function extractMessages(options: NormalizedExtractI18nOptions, builderName: string, context: BuilderContext, extractorConstructor: typeof MessageExtractor): Promise<{
|
|
13
|
-
|
|
13
|
+
success: boolean;
|
|
14
14
|
basePath: string;
|
|
15
15
|
messages: LocalizeMessage[];
|
|
16
16
|
useLegacyIds: boolean;
|
|
@@ -12,7 +12,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.extractMessages = extractMessages;
|
|
14
14
|
const private_1 = require("@angular/build/private");
|
|
15
|
-
const node_assert_1 = __importDefault(require("node:assert"));
|
|
16
15
|
const node_path_1 = __importDefault(require("node:path"));
|
|
17
16
|
const browser_esbuild_1 = require("../browser-esbuild");
|
|
18
17
|
async function extractMessages(options, builderName, context, extractorConstructor) {
|
|
@@ -35,48 +34,31 @@ async function extractMessages(options, builderName, context, extractorConstruct
|
|
|
35
34
|
else {
|
|
36
35
|
build = browser_esbuild_1.buildEsbuildBrowser;
|
|
37
36
|
}
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
builderResult = result;
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
(0, node_assert_1.default)(builderResult !== undefined, 'Application builder did not provide a result.');
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
const builderResult = await first(build(buildOptions, context, { write: false }));
|
|
39
|
+
let success = false;
|
|
40
|
+
if (!builderResult || builderResult.kind === private_1.ResultKind.Failure) {
|
|
41
|
+
context.logger.error('Application build failed.');
|
|
47
42
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
success: false,
|
|
51
|
-
error: err.message,
|
|
52
|
-
};
|
|
43
|
+
else if (builderResult.kind !== private_1.ResultKind.Full) {
|
|
44
|
+
context.logger.error('Application build did not provide a full output.');
|
|
53
45
|
}
|
|
54
|
-
|
|
55
|
-
// Output files are only present on a successful build.
|
|
56
|
-
if (builderResult.outputFiles) {
|
|
57
|
-
// Store the JS and JS map files for lookup during extraction
|
|
58
|
-
const files = new Map();
|
|
59
|
-
for (const outputFile of builderResult.outputFiles) {
|
|
60
|
-
if (outputFile.path.endsWith('.js')) {
|
|
61
|
-
files.set(outputFile.path, outputFile.text);
|
|
62
|
-
}
|
|
63
|
-
else if (outputFile.path.endsWith('.js.map')) {
|
|
64
|
-
files.set(outputFile.path, outputFile.text);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
46
|
+
else {
|
|
67
47
|
// Setup the localize message extractor based on the in-memory files
|
|
68
|
-
const extractor = setupLocalizeExtractor(extractorConstructor, files, context);
|
|
69
|
-
//
|
|
70
|
-
|
|
48
|
+
const extractor = setupLocalizeExtractor(extractorConstructor, builderResult.files, context);
|
|
49
|
+
// Extract messages from each output JavaScript file.
|
|
50
|
+
// Output files are only present on a successful build.
|
|
51
|
+
for (const filePath of Object.keys(builderResult.files)) {
|
|
71
52
|
if (!filePath.endsWith('.js')) {
|
|
72
53
|
continue;
|
|
73
54
|
}
|
|
74
55
|
const fileMessages = extractor.extractMessages(filePath);
|
|
75
56
|
messages.push(...fileMessages);
|
|
76
57
|
}
|
|
58
|
+
success = true;
|
|
77
59
|
}
|
|
78
60
|
return {
|
|
79
|
-
|
|
61
|
+
success,
|
|
80
62
|
basePath: context.workspaceRoot,
|
|
81
63
|
messages,
|
|
82
64
|
// Legacy i18n identifiers are not supported with the new application builder
|
|
@@ -84,6 +66,7 @@ async function extractMessages(options, builderName, context, extractorConstruct
|
|
|
84
66
|
};
|
|
85
67
|
}
|
|
86
68
|
function setupLocalizeExtractor(extractorConstructor, files, context) {
|
|
69
|
+
const textDecoder = new TextDecoder();
|
|
87
70
|
// Setup a virtual file system instance for the extractor
|
|
88
71
|
// * MessageExtractor itself uses readFile, relative and resolve
|
|
89
72
|
// * Internal SourceFileLoader (sourcemap support) uses dirname, exists, readFile, and resolve
|
|
@@ -91,7 +74,11 @@ function setupLocalizeExtractor(extractorConstructor, files, context) {
|
|
|
91
74
|
readFile(path) {
|
|
92
75
|
// Output files are stored as relative to the workspace root
|
|
93
76
|
const requestedPath = node_path_1.default.relative(context.workspaceRoot, path);
|
|
94
|
-
const
|
|
77
|
+
const file = files[requestedPath];
|
|
78
|
+
let content;
|
|
79
|
+
if (file?.origin === 'memory') {
|
|
80
|
+
content = textDecoder.decode(file.contents);
|
|
81
|
+
}
|
|
95
82
|
if (content === undefined) {
|
|
96
83
|
throw new Error('Unknown file requested: ' + requestedPath);
|
|
97
84
|
}
|
|
@@ -106,7 +93,7 @@ function setupLocalizeExtractor(extractorConstructor, files, context) {
|
|
|
106
93
|
exists(path) {
|
|
107
94
|
// Output files are stored as relative to the workspace root
|
|
108
95
|
const requestedPath = node_path_1.default.relative(context.workspaceRoot, path);
|
|
109
|
-
return files
|
|
96
|
+
return files[requestedPath] !== undefined;
|
|
110
97
|
},
|
|
111
98
|
dirname(path) {
|
|
112
99
|
return node_path_1.default.dirname(path);
|
|
@@ -137,3 +124,8 @@ function setupLocalizeExtractor(extractorConstructor, files, context) {
|
|
|
137
124
|
});
|
|
138
125
|
return extractor;
|
|
139
126
|
}
|
|
127
|
+
async function first(iterable) {
|
|
128
|
+
for await (const value of iterable) {
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -75,6 +75,9 @@ async function execute(options, context, transforms) {
|
|
|
75
75
|
builderName === '@angular-devkit/build-angular:browser-esbuild') {
|
|
76
76
|
const { extractMessages } = await Promise.resolve().then(() => __importStar(require('./application-extraction')));
|
|
77
77
|
extractionResult = await extractMessages(normalizedOptions, builderName, context, localizeToolsModule.MessageExtractor);
|
|
78
|
+
if (!extractionResult.success) {
|
|
79
|
+
return { success: false };
|
|
80
|
+
}
|
|
78
81
|
}
|
|
79
82
|
else {
|
|
80
83
|
// Purge old build disk cache.
|
|
@@ -82,10 +85,10 @@ async function execute(options, context, transforms) {
|
|
|
82
85
|
await (0, private_1.purgeStaleBuildCache)(context);
|
|
83
86
|
const { extractMessages } = await Promise.resolve().then(() => __importStar(require('./webpack-extraction')));
|
|
84
87
|
extractionResult = await extractMessages(normalizedOptions, builderName, context, transforms);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
// Return the builder result if it failed
|
|
89
|
+
if (!extractionResult.builderResult.success) {
|
|
90
|
+
return extractionResult.builderResult;
|
|
91
|
+
}
|
|
89
92
|
}
|
|
90
93
|
// Perform duplicate message checks
|
|
91
94
|
const { checkDuplicateMessages } = localizeToolsModule;
|
|
@@ -139,12 +142,13 @@ async function createSerializer(localizeToolsModule, format, sourceLocale, baseP
|
|
|
139
142
|
case schema_1.Format.LegacyMigrate:
|
|
140
143
|
return new LegacyMessageIdMigrationSerializer(diagnostics);
|
|
141
144
|
case schema_1.Format.Arb:
|
|
142
|
-
|
|
145
|
+
return new ArbTranslationSerializer(sourceLocale,
|
|
146
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
147
|
+
basePath, {
|
|
143
148
|
relative(from, to) {
|
|
144
149
|
return node_path_1.default.relative(from, to);
|
|
145
150
|
},
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
return new ArbTranslationSerializer(sourceLocale, basePath, fileSystem);
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
152
|
+
});
|
|
149
153
|
}
|
|
150
154
|
}
|
|
@@ -37,8 +37,8 @@ async function normalizeOptions(context, projectName, options) {
|
|
|
37
37
|
// Normalize xliff format extensions
|
|
38
38
|
let format = options.format;
|
|
39
39
|
switch (format) {
|
|
40
|
-
case undefined:
|
|
41
40
|
// Default format is xliff1
|
|
41
|
+
case undefined:
|
|
42
42
|
case schema_1.Format.Xlf:
|
|
43
43
|
case schema_1.Format.Xlif:
|
|
44
44
|
case schema_1.Format.Xliff:
|
|
@@ -47,8 +47,8 @@ exports.default = (0, architect_1.createBuilder)(async (schema, ctx) => {
|
|
|
47
47
|
]);
|
|
48
48
|
// Build the tests and abort on any build failure.
|
|
49
49
|
const buildOutput = await buildTests(testFiles, testDir, options, ctx);
|
|
50
|
-
if (
|
|
51
|
-
return
|
|
50
|
+
if (buildOutput.kind === private_1.ResultKind.Failure) {
|
|
51
|
+
return { success: false };
|
|
52
52
|
}
|
|
53
53
|
// Run the built tests.
|
|
54
54
|
return await runTests(wtr, `${testDir}/browser`, options);
|
|
@@ -153,8 +153,7 @@ exports.default = (0, babel_loader_1.custom)(() => {
|
|
|
153
153
|
case 'error':
|
|
154
154
|
this.emitError(message);
|
|
155
155
|
break;
|
|
156
|
-
case 'info':
|
|
157
|
-
// Webpack does not currently have an informational diagnostic
|
|
156
|
+
case 'info': // Webpack does not currently have an informational diagnostic
|
|
158
157
|
case 'warning':
|
|
159
158
|
this.emitWarning(message);
|
|
160
159
|
break;
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.normalizeCacheOptions = normalizeCacheOptions;
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
12
|
/** Version placeholder is replaced during the build process with actual package version */
|
|
13
|
-
const VERSION = '18.2.0-next.
|
|
13
|
+
const VERSION = '18.2.0-next.2';
|
|
14
14
|
function hasCacheMetadata(value) {
|
|
15
15
|
return (!!value &&
|
|
16
16
|
typeof value === 'object' &&
|