@softarc/native-federation 4.1.2 → 4.2.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.
- package/LICENSE.md +7 -0
- package/README.md +638 -0
- package/dist/config.js +17 -0
- package/dist/domain.js +2 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +21 -0
- package/{src → dist}/internal.d.ts +6 -7
- package/dist/internal.js +26 -0
- package/dist/lib/config/configuration-context.js +15 -0
- package/dist/lib/config/default-skip-list.js +36 -0
- package/dist/lib/config/get-external-imports.d.ts +2 -0
- package/dist/lib/config/get-external-imports.js +60 -0
- package/dist/lib/config/get-used-dependencies.d.ts +24 -0
- package/dist/lib/config/get-used-dependencies.js +126 -0
- package/{src/lib/utils → dist/lib/config}/mapped-paths.d.ts +2 -2
- package/dist/lib/config/mapped-paths.js +31 -0
- package/dist/lib/config/remove-unused-deps.js +11 -0
- package/dist/lib/config/share-utils.d.ts +20 -0
- package/dist/lib/config/share-utils.js +344 -0
- package/dist/lib/config/with-native-federation.js +80 -0
- package/{src/lib/core → dist/lib/core/build}/build-adapter.d.ts +1 -1
- package/dist/lib/core/build/build-adapter.js +16 -0
- package/dist/lib/core/build/build-for-federation.d.ts +4 -0
- package/dist/lib/core/build/build-for-federation.js +207 -0
- package/{src/lib/utils → dist/lib/core/build}/build-result-map.d.ts +1 -1
- package/dist/lib/core/build/build-result-map.js +39 -0
- package/dist/lib/core/build/bundle-exposed-and-mappings.d.ts +13 -0
- package/dist/lib/core/build/bundle-exposed-and-mappings.js +178 -0
- package/dist/lib/core/build/bundle-shared.d.ts +34 -0
- package/dist/lib/core/build/bundle-shared.js +261 -0
- package/dist/lib/core/build/compute-integrity.d.ts +11 -0
- package/dist/lib/core/build/compute-integrity.js +20 -0
- package/dist/lib/core/build/default-external-list.js +32 -0
- package/dist/lib/core/build/get-externals.d.ts +2 -0
- package/dist/lib/core/build/get-externals.js +9 -0
- package/dist/lib/core/build/rebuild-for-federation.d.ts +4 -0
- package/dist/lib/core/build/rebuild-for-federation.js +52 -0
- package/dist/lib/core/build/rewrite-chunk-imports.d.ts +5 -0
- package/dist/lib/core/build/rewrite-chunk-imports.js +74 -0
- package/dist/lib/core/cache/cache-persistence.d.ts +22 -0
- package/dist/lib/core/cache/cache-persistence.js +63 -0
- package/{src/lib/core → dist/lib/core/cache}/federation-cache.d.ts +2 -2
- package/dist/lib/core/cache/federation-cache.js +22 -0
- package/dist/lib/core/federation-builder.js +53 -0
- package/{src → dist}/lib/core/normalize-options.d.ts +13 -1
- package/dist/lib/core/normalize-options.js +67 -0
- package/dist/lib/core/output/write-federation-info.d.ts +5 -0
- package/dist/lib/core/output/write-federation-info.js +17 -0
- package/dist/lib/core/output/write-import-map.d.ts +11 -0
- package/dist/lib/core/output/write-import-map.js +42 -0
- package/dist/lib/core/rebuild-queue.js +61 -0
- package/{src → dist}/lib/domain/config/external-config.contract.d.ts +2 -2
- package/dist/lib/domain/config/external-config.contract.js +0 -0
- package/{src → dist}/lib/domain/config/federation-config.contract.d.ts +6 -2
- package/dist/lib/domain/config/federation-config.contract.js +0 -0
- package/dist/lib/domain/config/index.js +0 -0
- package/dist/lib/domain/config/skip-list.contract.js +0 -0
- package/dist/lib/domain/core/build-adapter.contract.js +0 -0
- package/dist/lib/domain/core/build-notification-options.contract.js +9 -0
- package/dist/lib/domain/core/chunk.js +12 -0
- package/dist/lib/domain/core/federation-cache.contract.js +0 -0
- package/{src → dist}/lib/domain/core/federation-info.contract.d.ts +1 -0
- package/dist/lib/domain/core/federation-info.contract.js +0 -0
- package/dist/lib/domain/core/federation-options.contract.js +0 -0
- package/{src → dist}/lib/domain/core/index.d.ts +1 -0
- package/dist/lib/domain/core/index.js +9 -0
- package/dist/lib/domain/core/manifest.contract.d.ts +5 -0
- package/dist/lib/domain/core/manifest.contract.js +0 -0
- package/dist/lib/domain/utils/file-watcher.contract.js +0 -0
- package/dist/lib/domain/utils/io-port.contract.d.ts +45 -0
- package/dist/lib/domain/utils/io-port.contract.js +0 -0
- package/dist/lib/domain/utils/keyvaluepair.contract.js +0 -0
- package/dist/lib/domain/utils/mapped-path.contract.js +0 -0
- package/dist/lib/domain/utils/package-json.contract.d.ts +27 -0
- package/dist/lib/domain/utils/package-json.contract.js +0 -0
- package/dist/lib/domain/utils/used-dependencies.contract.js +0 -0
- package/dist/lib/utils/errors.js +10 -0
- package/{src → dist}/lib/utils/file-watcher.d.ts +2 -0
- package/dist/lib/utils/file-watcher.js +51 -0
- package/dist/lib/utils/hash-file.d.ts +7 -0
- package/dist/lib/utils/hash-file.js +15 -0
- package/dist/lib/utils/io/node-io-adapter.d.ts +2 -0
- package/dist/lib/utils/io/node-io-adapter.js +68 -0
- package/dist/lib/utils/io/package-json-repository.d.ts +5 -0
- package/dist/lib/utils/io/package-json-repository.js +79 -0
- package/dist/lib/utils/logger.js +29 -0
- package/dist/lib/utils/normalize.js +22 -0
- package/dist/lib/utils/package/entry-point-resolver.d.ts +2 -0
- package/dist/lib/utils/package/entry-point-resolver.js +78 -0
- package/dist/lib/utils/package/esm-detection.d.ts +5 -0
- package/dist/lib/utils/package/esm-detection.js +10 -0
- package/dist/lib/utils/package/exports-resolver.d.ts +13 -0
- package/dist/lib/utils/package/exports-resolver.js +55 -0
- package/dist/lib/utils/package/package-info.d.ts +7 -0
- package/dist/lib/utils/package/package-info.js +31 -0
- package/dist/lib/utils/package/resolve-wildcard-keys.d.ts +3 -0
- package/dist/lib/utils/package/resolve-wildcard-keys.js +22 -0
- package/dist/lib/utils/package/version-maps.d.ts +3 -0
- package/dist/lib/utils/package/version-maps.js +8 -0
- package/dist/lib/utils/path-patterns.d.ts +14 -0
- package/dist/lib/utils/path-patterns.js +28 -0
- package/package.json +45 -22
- package/src/config.js +0 -4
- package/src/domain.js +0 -2
- package/src/index.d.ts +0 -10
- package/src/index.js +0 -10
- package/src/internal.js +0 -11
- package/src/lib/config/configuration-context.js +0 -10
- package/src/lib/config/default-skip-list.js +0 -31
- package/src/lib/config/remove-unused-deps.js +0 -10
- package/src/lib/config/share-utils.d.ts +0 -10
- package/src/lib/config/share-utils.js +0 -302
- package/src/lib/config/with-native-federation.js +0 -71
- package/src/lib/core/build-adapter.js +0 -12
- package/src/lib/core/build-for-federation.d.ts +0 -4
- package/src/lib/core/build-for-federation.js +0 -173
- package/src/lib/core/bundle-exposed-and-mappings.d.ts +0 -7
- package/src/lib/core/bundle-exposed-and-mappings.js +0 -174
- package/src/lib/core/bundle-shared.d.ts +0 -13
- package/src/lib/core/bundle-shared.js +0 -222
- package/src/lib/core/default-external-list.js +0 -29
- package/src/lib/core/federation-builder.js +0 -45
- package/src/lib/core/federation-cache.js +0 -16
- package/src/lib/core/get-externals.d.ts +0 -2
- package/src/lib/core/get-externals.js +0 -6
- package/src/lib/core/normalize-options.js +0 -58
- package/src/lib/core/rebuild-for-federation.d.ts +0 -4
- package/src/lib/core/rebuild-for-federation.js +0 -43
- package/src/lib/core/write-federation-info.d.ts +0 -3
- package/src/lib/core/write-federation-info.js +0 -6
- package/src/lib/core/write-import-map.d.ts +0 -6
- package/src/lib/core/write-import-map.js +0 -33
- package/src/lib/domain/config/external-config.contract.js +0 -1
- package/src/lib/domain/config/federation-config.contract.js +0 -1
- package/src/lib/domain/config/index.js +0 -1
- package/src/lib/domain/config/skip-list.contract.js +0 -1
- package/src/lib/domain/config/with-native-federation.contract.d.ts +0 -2
- package/src/lib/domain/config/with-native-federation.contract.js +0 -1
- package/src/lib/domain/core/build-adapter.contract.js +0 -1
- package/src/lib/domain/core/build-notification-options.contract.js +0 -6
- package/src/lib/domain/core/chunk.js +0 -8
- package/src/lib/domain/core/federation-cache.contract.js +0 -1
- package/src/lib/domain/core/federation-info.contract.js +0 -1
- package/src/lib/domain/core/federation-options.contract.js +0 -1
- package/src/lib/domain/core/index.js +0 -2
- package/src/lib/domain/utils/file-watcher.contract.js +0 -1
- package/src/lib/domain/utils/index.d.ts +0 -2
- package/src/lib/domain/utils/index.js +0 -1
- package/src/lib/domain/utils/keyvaluepair.contract.js +0 -1
- package/src/lib/domain/utils/mapped-path.contract.js +0 -5
- package/src/lib/domain/utils/used-dependencies.contract.js +0 -1
- package/src/lib/utils/build-result-map.js +0 -29
- package/src/lib/utils/cache-persistence.d.ts +0 -19
- package/src/lib/utils/cache-persistence.js +0 -66
- package/src/lib/utils/errors.js +0 -7
- package/src/lib/utils/file-watcher.js +0 -51
- package/src/lib/utils/get-external-imports.d.ts +0 -1
- package/src/lib/utils/get-external-imports.js +0 -80
- package/src/lib/utils/get-used-dependencies.d.ts +0 -7
- package/src/lib/utils/get-used-dependencies.js +0 -123
- package/src/lib/utils/hash-file.d.ts +0 -3
- package/src/lib/utils/hash-file.js +0 -13
- package/src/lib/utils/logger.js +0 -27
- package/src/lib/utils/mapped-paths.js +0 -33
- package/src/lib/utils/normalize.js +0 -17
- package/src/lib/utils/package-info.d.ts +0 -30
- package/src/lib/utils/package-info.js +0 -268
- package/src/lib/utils/rebuild-queue.js +0 -63
- package/src/lib/utils/resolve-glob.d.ts +0 -1
- package/src/lib/utils/resolve-glob.js +0 -29
- package/src/lib/utils/resolve-wildcard-keys.d.ts +0 -29
- package/src/lib/utils/resolve-wildcard-keys.js +0 -126
- package/src/lib/utils/rewrite-chunk-imports.d.ts +0 -2
- package/src/lib/utils/rewrite-chunk-imports.js +0 -48
- /package/{src → dist}/config.d.ts +0 -0
- /package/{src → dist}/domain.d.ts +0 -0
- /package/{src → dist}/lib/config/configuration-context.d.ts +0 -0
- /package/{src → dist}/lib/config/default-skip-list.d.ts +0 -0
- /package/{src → dist}/lib/config/remove-unused-deps.d.ts +0 -0
- /package/{src → dist}/lib/config/with-native-federation.d.ts +0 -0
- /package/{src/lib/core → dist/lib/core/build}/default-external-list.d.ts +0 -0
- /package/{src → dist}/lib/core/federation-builder.d.ts +0 -0
- /package/{src/lib/utils → dist/lib/core}/rebuild-queue.d.ts +0 -0
- /package/{src → dist}/lib/domain/config/index.d.ts +0 -0
- /package/{src → dist}/lib/domain/config/skip-list.contract.d.ts +0 -0
- /package/{src → dist}/lib/domain/core/build-adapter.contract.d.ts +0 -0
- /package/{src → dist}/lib/domain/core/build-notification-options.contract.d.ts +0 -0
- /package/{src → dist}/lib/domain/core/chunk.d.ts +0 -0
- /package/{src → dist}/lib/domain/core/federation-cache.contract.d.ts +0 -0
- /package/{src → dist}/lib/domain/core/federation-options.contract.d.ts +0 -0
- /package/{src → dist}/lib/domain/utils/file-watcher.contract.d.ts +0 -0
- /package/{src → dist}/lib/domain/utils/keyvaluepair.contract.d.ts +0 -0
- /package/{src → dist}/lib/domain/utils/mapped-path.contract.d.ts +0 -0
- /package/{src → dist}/lib/domain/utils/used-dependencies.contract.d.ts +0 -0
- /package/{src → dist}/lib/utils/errors.d.ts +0 -0
- /package/{src → dist}/lib/utils/logger.d.ts +0 -0
- /package/{src → dist}/lib/utils/normalize.d.ts +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { nodeIo } from "../../utils/io/node-io-adapter.js";
|
|
4
|
+
import { toChunkImport } from "../../domain/core/chunk.js";
|
|
5
|
+
function rewriteChunkImports(filePath) {
|
|
6
|
+
rewriteChunkImportsCore(nodeIo, filePath);
|
|
7
|
+
}
|
|
8
|
+
function rewriteChunkImportsCore(io, filePath) {
|
|
9
|
+
io.writeText(filePath, transformChunkImports(io.readText(filePath), path.basename(filePath)));
|
|
10
|
+
}
|
|
11
|
+
function transformChunkImports(sourceCode, fileName) {
|
|
12
|
+
const sourceFile = ts.createSourceFile(
|
|
13
|
+
fileName,
|
|
14
|
+
sourceCode,
|
|
15
|
+
ts.ScriptTarget.ESNext,
|
|
16
|
+
true,
|
|
17
|
+
ts.ScriptKind.JS
|
|
18
|
+
);
|
|
19
|
+
const printer = ts.createPrinter();
|
|
20
|
+
function visit(node) {
|
|
21
|
+
if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
|
|
22
|
+
const moduleSpecifier = node.moduleSpecifier;
|
|
23
|
+
if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
|
|
24
|
+
const text = moduleSpecifier.text;
|
|
25
|
+
if (text.startsWith("./")) {
|
|
26
|
+
const newModuleSpecifier = ts.factory.createStringLiteral(toChunkImport(text));
|
|
27
|
+
if (ts.isImportDeclaration(node)) {
|
|
28
|
+
return ts.factory.updateImportDeclaration(
|
|
29
|
+
node,
|
|
30
|
+
node.modifiers,
|
|
31
|
+
node.importClause,
|
|
32
|
+
newModuleSpecifier,
|
|
33
|
+
node.assertClause
|
|
34
|
+
);
|
|
35
|
+
} else {
|
|
36
|
+
return ts.factory.updateExportDeclaration(
|
|
37
|
+
node,
|
|
38
|
+
node.modifiers,
|
|
39
|
+
node.isTypeOnly,
|
|
40
|
+
node.exportClause,
|
|
41
|
+
newModuleSpecifier,
|
|
42
|
+
node.assertClause
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
|
|
49
|
+
const [arg] = node.arguments;
|
|
50
|
+
if (arg && ts.isStringLiteral(arg)) {
|
|
51
|
+
const text = arg.text;
|
|
52
|
+
if (text.startsWith("./")) {
|
|
53
|
+
const newArg = ts.factory.createStringLiteral(toChunkImport(text));
|
|
54
|
+
return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [
|
|
55
|
+
newArg
|
|
56
|
+
]);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return ts.visitEachChild(node, visit, void 0);
|
|
61
|
+
}
|
|
62
|
+
const transformed = ts.transform(sourceFile, [(_) => (node) => ts.visitNode(node, visit)]);
|
|
63
|
+
const updatedSourceFile = transformed.transformed[0];
|
|
64
|
+
return printer.printFile(updatedSourceFile);
|
|
65
|
+
}
|
|
66
|
+
function isSourceFile(fileName) {
|
|
67
|
+
return !!fileName.match(/.(m|c)?js$/);
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
isSourceFile,
|
|
71
|
+
rewriteChunkImports,
|
|
72
|
+
rewriteChunkImportsCore,
|
|
73
|
+
transformChunkImports
|
|
74
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { NormalizedExternalConfig } from '../../domain/config/external-config.contract.js';
|
|
2
|
+
import type { ChunkInfo, IntegrityMap, SharedInfo } from '../../domain/core/federation-info.contract.js';
|
|
3
|
+
import type { FileReaderPort, FileWriterPort, HashPort } from '../../domain/utils/io-port.contract.js';
|
|
4
|
+
export declare const getDefaultCachePath: (workspaceRoot: string) => string;
|
|
5
|
+
export declare const getFilename: (title: string, dev?: boolean) => string;
|
|
6
|
+
export declare const getChecksum: (shared: Record<string, NormalizedExternalConfig>, dev: "1" | "0", builderVersion?: string) => string;
|
|
7
|
+
export declare const getChecksumCore: (hash: HashPort, shared: Record<string, NormalizedExternalConfig>, dev: "1" | "0", builderVersion?: string) => string;
|
|
8
|
+
export type CacheMetadata = {
|
|
9
|
+
checksum: string;
|
|
10
|
+
externals: SharedInfo[];
|
|
11
|
+
chunks?: ChunkInfo;
|
|
12
|
+
integrity?: IntegrityMap;
|
|
13
|
+
files: string[];
|
|
14
|
+
};
|
|
15
|
+
type CachePort = FileReaderPort & FileWriterPort;
|
|
16
|
+
export declare const cacheEntryCore: (io: CachePort, pathToCache: string, fileName: string) => {
|
|
17
|
+
getMetadata: (checksum: string) => CacheMetadata | undefined;
|
|
18
|
+
persist: (payload: CacheMetadata) => void;
|
|
19
|
+
copyFiles: (fullOutputPath: string) => void;
|
|
20
|
+
clear: () => void;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { nodeIo } from "../../utils/io/node-io-adapter.js";
|
|
3
|
+
import { logger } from "../../utils/logger.js";
|
|
4
|
+
const getDefaultCachePath = (workspaceRoot) => path.join(workspaceRoot, "node_modules/.cache/native-federation");
|
|
5
|
+
const getFilename = (title, dev) => {
|
|
6
|
+
const devSuffix = dev ? "-dev" : "";
|
|
7
|
+
return `${title}${devSuffix}.meta.json`;
|
|
8
|
+
};
|
|
9
|
+
const getChecksum = (shared, dev, builderVersion = "") => getChecksumCore(nodeIo, shared, dev, builderVersion);
|
|
10
|
+
const getChecksumCore = (hash, shared, dev, builderVersion = "") => {
|
|
11
|
+
const denseExternals = Object.keys(shared).sort().reduce((clean, external) => {
|
|
12
|
+
return clean + ":" + external + (shared[external].version ? `@${shared[external].version}` : "");
|
|
13
|
+
}, "deps");
|
|
14
|
+
return hash.hash("sha256", denseExternals + `:dev=${dev}:builder=${builderVersion}`).hex();
|
|
15
|
+
};
|
|
16
|
+
const cacheEntryCore = (io, pathToCache, fileName) => {
|
|
17
|
+
const metadataFile = path.join(pathToCache, fileName);
|
|
18
|
+
const readMetadata = () => JSON.parse(io.readText(metadataFile));
|
|
19
|
+
return {
|
|
20
|
+
getMetadata: (checksum) => {
|
|
21
|
+
if (!io.exists(pathToCache) || !io.exists(metadataFile)) return void 0;
|
|
22
|
+
const cachedResult = readMetadata();
|
|
23
|
+
if (cachedResult.checksum !== checksum) return void 0;
|
|
24
|
+
return cachedResult;
|
|
25
|
+
},
|
|
26
|
+
persist: (payload) => {
|
|
27
|
+
io.writeText(metadataFile, JSON.stringify(payload));
|
|
28
|
+
},
|
|
29
|
+
copyFiles: (fullOutputPath) => {
|
|
30
|
+
if (!io.exists(metadataFile))
|
|
31
|
+
throw new Error("Error copying artifacts to dist, metadata file could not be found.");
|
|
32
|
+
const cachedResult = readMetadata();
|
|
33
|
+
io.mkdirp(fullOutputPath);
|
|
34
|
+
cachedResult.files.forEach((file) => {
|
|
35
|
+
const cachedFile = path.join(pathToCache, file);
|
|
36
|
+
const distFileName = path.join(fullOutputPath, file);
|
|
37
|
+
if (io.exists(cachedFile)) io.copyFile(cachedFile, distFileName);
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
clear: () => {
|
|
41
|
+
if (!io.exists(pathToCache)) {
|
|
42
|
+
io.mkdirp(pathToCache);
|
|
43
|
+
logger.debug(`Creating cache folder '${pathToCache}' for '${fileName}'.`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!io.exists(metadataFile)) return;
|
|
47
|
+
logger.debug(`Purging cached bundle '${metadataFile}'.`);
|
|
48
|
+
const cachedResult = readMetadata();
|
|
49
|
+
cachedResult.files.forEach((file) => {
|
|
50
|
+
const cachedFile = path.join(pathToCache, file);
|
|
51
|
+
if (io.exists(cachedFile)) io.remove(cachedFile);
|
|
52
|
+
});
|
|
53
|
+
io.remove(metadataFile);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
export {
|
|
58
|
+
cacheEntryCore,
|
|
59
|
+
getChecksum,
|
|
60
|
+
getChecksumCore,
|
|
61
|
+
getDefaultCachePath,
|
|
62
|
+
getFilename
|
|
63
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { FederationCache } from '
|
|
2
|
-
import type { ChunkInfo, IntegrityMap, SharedInfo } from '
|
|
1
|
+
import type { FederationCache } from '../../domain/core/federation-cache.contract.js';
|
|
2
|
+
import type { ChunkInfo, IntegrityMap, SharedInfo } from '../../domain/core/federation-info.contract.js';
|
|
3
3
|
export declare function createFederationCache(cachePath: string): FederationCache<undefined>;
|
|
4
4
|
export declare function createFederationCache<TBundlerCache>(cachePath: string, bundlerCache: TBundlerCache): FederationCache<TBundlerCache>;
|
|
5
5
|
export declare function addExternalsToCache(cache: FederationCache, { externals, chunks, integrity, }: {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
function createFederationCache(cachePath, bundlerCache) {
|
|
2
|
+
return { externals: [], cachePath, bundlerCache };
|
|
3
|
+
}
|
|
4
|
+
function addExternalsToCache(cache, {
|
|
5
|
+
externals,
|
|
6
|
+
chunks,
|
|
7
|
+
integrity
|
|
8
|
+
}) {
|
|
9
|
+
cache.externals.push(...externals);
|
|
10
|
+
if (chunks) {
|
|
11
|
+
if (!cache.chunks) cache.chunks = {};
|
|
12
|
+
cache.chunks = { ...cache.chunks, ...chunks };
|
|
13
|
+
}
|
|
14
|
+
if (integrity) {
|
|
15
|
+
if (!cache.integrity) cache.integrity = {};
|
|
16
|
+
cache.integrity = { ...cache.integrity, ...integrity };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
addExternalsToCache,
|
|
21
|
+
createFederationCache
|
|
22
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { getConfigContext, usePackageJson, useWorkspace } from "../config/configuration-context.js";
|
|
2
|
+
import { getBuildAdapter, setBuildAdapter } from "./build/build-adapter.js";
|
|
3
|
+
import { buildForFederation } from "./build/build-for-federation.js";
|
|
4
|
+
import { getExternals } from "./build/get-externals.js";
|
|
5
|
+
import { normalizeFederationOptions } from "./normalize-options.js";
|
|
6
|
+
import { rebuildForFederation } from "./build/rebuild-for-federation.js";
|
|
7
|
+
let externals = [];
|
|
8
|
+
let config;
|
|
9
|
+
let options;
|
|
10
|
+
let fedInfo;
|
|
11
|
+
async function init(params) {
|
|
12
|
+
setBuildAdapter(params.adapter);
|
|
13
|
+
useWorkspace(params.options.workspaceRoot);
|
|
14
|
+
usePackageJson(params.options.packageJson);
|
|
15
|
+
params.options.workspaceRoot = getConfigContext().workspaceRoot ?? params.options.workspaceRoot;
|
|
16
|
+
const normalized = await normalizeFederationOptions(params.options);
|
|
17
|
+
options = normalized.options;
|
|
18
|
+
config = normalized.config;
|
|
19
|
+
externals = getExternals(config);
|
|
20
|
+
}
|
|
21
|
+
async function build(opts = {}) {
|
|
22
|
+
if (!fedInfo) {
|
|
23
|
+
fedInfo = await buildForFederation(config, options, externals, opts.signal);
|
|
24
|
+
} else {
|
|
25
|
+
fedInfo = await rebuildForFederation(
|
|
26
|
+
config,
|
|
27
|
+
options,
|
|
28
|
+
externals,
|
|
29
|
+
opts.modifiedFiles ?? [],
|
|
30
|
+
opts.signal
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function close() {
|
|
35
|
+
return getBuildAdapter().dispose();
|
|
36
|
+
}
|
|
37
|
+
const federationBuilder = {
|
|
38
|
+
init,
|
|
39
|
+
build,
|
|
40
|
+
close,
|
|
41
|
+
get federationInfo() {
|
|
42
|
+
return fedInfo;
|
|
43
|
+
},
|
|
44
|
+
get externals() {
|
|
45
|
+
return externals;
|
|
46
|
+
},
|
|
47
|
+
get config() {
|
|
48
|
+
return config;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export {
|
|
52
|
+
federationBuilder
|
|
53
|
+
};
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { NormalizedFederationConfig } from '../domain/config/federation-config.contract.js';
|
|
2
2
|
import type { FederationOptions, NormalizedFederationOptions } from '../domain/core/federation-options.contract.js';
|
|
3
|
+
import type { FileReaderPort } from '../domain/utils/io-port.contract.js';
|
|
3
4
|
import { type FederationCache } from '../../domain.js';
|
|
5
|
+
import { getUsedDependenciesFactory } from '../config/get-used-dependencies.js';
|
|
6
|
+
type ConfigLoader = (fullConfigPath: string) => Promise<NormalizedFederationConfig>;
|
|
7
|
+
interface NormalizeFederationDeps {
|
|
8
|
+
io: FileReaderPort;
|
|
9
|
+
loadConfig: ConfigLoader;
|
|
10
|
+
usedDependenciesFactory?: typeof getUsedDependenciesFactory;
|
|
11
|
+
}
|
|
4
12
|
export declare function normalizeFederationOptions(options: FederationOptions): Promise<{
|
|
5
13
|
config: NormalizedFederationConfig;
|
|
6
14
|
options: NormalizedFederationOptions<undefined>;
|
|
@@ -9,4 +17,8 @@ export declare function normalizeFederationOptions<TBundlerCache>(options: Feder
|
|
|
9
17
|
config: NormalizedFederationConfig;
|
|
10
18
|
options: NormalizedFederationOptions<TBundlerCache>;
|
|
11
19
|
}>;
|
|
12
|
-
export declare function
|
|
20
|
+
export declare function normalizeFederationOptionsCore<TBundlerCache = undefined>(deps: NormalizeFederationDeps, options: FederationOptions, cache?: FederationCache<TBundlerCache>): Promise<{
|
|
21
|
+
config: NormalizedFederationConfig;
|
|
22
|
+
options: NormalizedFederationOptions<TBundlerCache>;
|
|
23
|
+
}>;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { pathToFileURL } from "url";
|
|
3
|
+
import { nodeIo } from "../utils/io/node-io-adapter.js";
|
|
4
|
+
import { removeUnusedDeps } from "../config/remove-unused-deps.js";
|
|
5
|
+
import { createFederationCache } from "./cache/federation-cache.js";
|
|
6
|
+
import { getDefaultCachePath } from "./cache/cache-persistence.js";
|
|
7
|
+
import { getUsedDependenciesFactory } from "../config/get-used-dependencies.js";
|
|
8
|
+
import { logger } from "../utils/logger.js";
|
|
9
|
+
import { normalizePackageName } from "../utils/normalize.js";
|
|
10
|
+
const defaultConfigLoader = async (fullConfigPath) => (await import(pathToFileURL(fullConfigPath).href))?.default;
|
|
11
|
+
async function normalizeFederationOptions(options, cache) {
|
|
12
|
+
return normalizeFederationOptionsCore(
|
|
13
|
+
{ io: nodeIo, loadConfig: defaultConfigLoader },
|
|
14
|
+
options,
|
|
15
|
+
cache
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
async function normalizeFederationOptionsCore(deps, options, cache) {
|
|
19
|
+
const fullConfigPath = path.join(options.workspaceRoot, options.federationConfig);
|
|
20
|
+
if (!deps.io.exists(fullConfigPath)) {
|
|
21
|
+
throw new Error("Expected " + fullConfigPath);
|
|
22
|
+
}
|
|
23
|
+
let config = await deps.loadConfig(fullConfigPath);
|
|
24
|
+
const federationCache = cache ?? createFederationCache(
|
|
25
|
+
getDefaultCachePath(options.workspaceRoot)
|
|
26
|
+
);
|
|
27
|
+
const normalizedOptions = {
|
|
28
|
+
...options,
|
|
29
|
+
entryPoints: options.entryPoints ?? Object.values(config.exposes ?? {}).map((e) => e.file),
|
|
30
|
+
projectName: resolveProjectName(options.projectName ?? config.name),
|
|
31
|
+
cacheExternalArtifacts: options.cacheExternalArtifacts ?? true,
|
|
32
|
+
federationCache
|
|
33
|
+
};
|
|
34
|
+
if (config.features.ignoreUnusedDeps) {
|
|
35
|
+
const getUsedDeps = (deps.usedDependenciesFactory ?? getUsedDependenciesFactory)(
|
|
36
|
+
options.workspaceRoot,
|
|
37
|
+
options.entryPoints
|
|
38
|
+
);
|
|
39
|
+
config = removeUnusedDeps(getUsedDeps(config), config);
|
|
40
|
+
logger.info("Removed unused dependencies.");
|
|
41
|
+
logger.debug(
|
|
42
|
+
'This can be disabled per dependency/external using the "includeSecondaries: {keepAll: true}" property. Or in general by disabling the "ignoreUnusedDeps" feature. '
|
|
43
|
+
);
|
|
44
|
+
} else {
|
|
45
|
+
const withWildcard = Object.keys(config.sharedMappings).some((m) => m.includes("*"));
|
|
46
|
+
if (withWildcard) {
|
|
47
|
+
logger.warn(
|
|
48
|
+
"Sharing mapped paths with wildcards (*) is only supported with ignoreUnusedDeps feature."
|
|
49
|
+
);
|
|
50
|
+
config.sharedMappings = Object.entries(config.sharedMappings).filter(([_path]) => !_path.includes("*")).reduce((acc, [_path, _import]) => ({ ...acc, [_path]: _import }), {});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { config, options: normalizedOptions };
|
|
54
|
+
}
|
|
55
|
+
function resolveProjectName(name) {
|
|
56
|
+
if (!name || name.length < 1) {
|
|
57
|
+
logger.warn(
|
|
58
|
+
"Project name in 'federation.config.js' is empty, defaulting to 'shell' cache folder (could collide with other projects in the workspace)."
|
|
59
|
+
);
|
|
60
|
+
return "shell";
|
|
61
|
+
}
|
|
62
|
+
return normalizePackageName(name);
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
normalizeFederationOptions,
|
|
66
|
+
normalizeFederationOptionsCore
|
|
67
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FederationInfo } from '../../domain/core/federation-info.contract.js';
|
|
2
|
+
import type { FileWriterPort } from '../../domain/utils/io-port.contract.js';
|
|
3
|
+
import type { FederationOptions } from '../../domain/core/federation-options.contract.js';
|
|
4
|
+
export declare function writeFederationInfoCore(io: FileWriterPort, federationInfo: FederationInfo, fedOptions: FederationOptions): void;
|
|
5
|
+
export declare function writeFederationInfo(federationInfo: FederationInfo, fedOptions: FederationOptions): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { nodeIo } from "../../utils/io/node-io-adapter.js";
|
|
3
|
+
function writeFederationInfoCore(io, federationInfo, fedOptions) {
|
|
4
|
+
const metaDataPath = path.join(
|
|
5
|
+
fedOptions.workspaceRoot,
|
|
6
|
+
fedOptions.outputPath,
|
|
7
|
+
"remoteEntry.json"
|
|
8
|
+
);
|
|
9
|
+
io.writeText(metaDataPath, JSON.stringify(federationInfo, null, 2));
|
|
10
|
+
}
|
|
11
|
+
function writeFederationInfo(federationInfo, fedOptions) {
|
|
12
|
+
writeFederationInfoCore(nodeIo, federationInfo, fedOptions);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
writeFederationInfo,
|
|
16
|
+
writeFederationInfoCore
|
|
17
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ChunkInfo, IntegrityMap, SharedInfo } from '../../domain/core/federation-info.contract.js';
|
|
2
|
+
import type { FileWriterPort } from '../../domain/utils/io-port.contract.js';
|
|
3
|
+
import type { FederationOptions } from '../../domain/core/federation-options.contract.js';
|
|
4
|
+
export declare function writeImportMapCore(io: FileWriterPort, sharedInfo: {
|
|
5
|
+
externals: SharedInfo[];
|
|
6
|
+
chunks?: ChunkInfo;
|
|
7
|
+
}, fedOption: FederationOptions, fileIntegrity?: IntegrityMap): void;
|
|
8
|
+
export declare function writeImportMap(sharedInfo: {
|
|
9
|
+
externals: SharedInfo[];
|
|
10
|
+
chunks?: ChunkInfo;
|
|
11
|
+
}, fedOption: FederationOptions, fileIntegrity?: IntegrityMap): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { toChunkImport } from "../../domain/core/chunk.js";
|
|
3
|
+
import { nodeIo } from "../../utils/io/node-io-adapter.js";
|
|
4
|
+
function writeImportMapCore(io, sharedInfo, fedOption, fileIntegrity) {
|
|
5
|
+
const imports = sharedInfo.externals.reduce(
|
|
6
|
+
(acc, cur) => {
|
|
7
|
+
return {
|
|
8
|
+
...acc,
|
|
9
|
+
[cur.packageName]: cur.outFileName
|
|
10
|
+
};
|
|
11
|
+
},
|
|
12
|
+
{}
|
|
13
|
+
);
|
|
14
|
+
if (sharedInfo.chunks) {
|
|
15
|
+
Object.values(sharedInfo.chunks).forEach((c) => {
|
|
16
|
+
c.forEach((e) => {
|
|
17
|
+
const key = toChunkImport(e);
|
|
18
|
+
imports[key] = e;
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const importMap = { imports };
|
|
23
|
+
if (fileIntegrity) {
|
|
24
|
+
const integrity = {};
|
|
25
|
+
for (const url of Object.values(imports)) {
|
|
26
|
+
const sri = fileIntegrity[url];
|
|
27
|
+
if (sri) integrity[url] = sri;
|
|
28
|
+
}
|
|
29
|
+
if (Object.keys(integrity).length > 0) {
|
|
30
|
+
importMap.integrity = integrity;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const importMapPath = path.join(fedOption.workspaceRoot, fedOption.outputPath, "importmap.json");
|
|
34
|
+
io.writeText(importMapPath, JSON.stringify(importMap, null, 2));
|
|
35
|
+
}
|
|
36
|
+
function writeImportMap(sharedInfo, fedOption, fileIntegrity) {
|
|
37
|
+
writeImportMapCore(nodeIo, sharedInfo, fedOption, fileIntegrity);
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
writeImportMap,
|
|
41
|
+
writeImportMapCore
|
|
42
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { logger } from "../utils/logger.js";
|
|
2
|
+
class RebuildQueue {
|
|
3
|
+
activeBuilds = /* @__PURE__ */ new Map();
|
|
4
|
+
buildCounter = 0;
|
|
5
|
+
async track(rebuildFn, interruptPromise) {
|
|
6
|
+
const buildId = ++this.buildCounter;
|
|
7
|
+
const pendingCancellations = Array.from(this.activeBuilds.values()).map((buildControl) => {
|
|
8
|
+
buildControl.controller.abort();
|
|
9
|
+
return buildControl.buildFinished.promise;
|
|
10
|
+
});
|
|
11
|
+
if (pendingCancellations.length > 0) {
|
|
12
|
+
logger.info(`Aborting ${pendingCancellations.length} bundling task(s)..`);
|
|
13
|
+
await Promise.all(pendingCancellations);
|
|
14
|
+
}
|
|
15
|
+
let resolveCompletion;
|
|
16
|
+
const completionPromise = new Promise((resolve) => {
|
|
17
|
+
resolveCompletion = resolve;
|
|
18
|
+
});
|
|
19
|
+
const control = {
|
|
20
|
+
controller: new AbortController(),
|
|
21
|
+
buildFinished: {
|
|
22
|
+
resolve: resolveCompletion,
|
|
23
|
+
promise: completionPromise
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
this.activeBuilds.set(buildId, control);
|
|
27
|
+
const buildPromise = rebuildFn(control.controller.signal).then((result) => ({ type: "completed", result })).catch((error) => ({ type: "completed", result: { success: false, error } }));
|
|
28
|
+
let trackResult;
|
|
29
|
+
try {
|
|
30
|
+
if (interruptPromise) {
|
|
31
|
+
const interruptResult = interruptPromise.then((value) => ({
|
|
32
|
+
type: "interrupted",
|
|
33
|
+
value
|
|
34
|
+
}));
|
|
35
|
+
const raceResult = await Promise.race([buildPromise, interruptResult]);
|
|
36
|
+
if (raceResult.type === "interrupted") {
|
|
37
|
+
control.controller.abort();
|
|
38
|
+
await buildPromise;
|
|
39
|
+
trackResult = raceResult;
|
|
40
|
+
} else {
|
|
41
|
+
trackResult = raceResult;
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
trackResult = await buildPromise;
|
|
45
|
+
}
|
|
46
|
+
} finally {
|
|
47
|
+
control.buildFinished.resolve();
|
|
48
|
+
this.activeBuilds.delete(buildId);
|
|
49
|
+
}
|
|
50
|
+
return trackResult;
|
|
51
|
+
}
|
|
52
|
+
dispose() {
|
|
53
|
+
for (const buildControl of this.activeBuilds.values()) {
|
|
54
|
+
buildControl.controller.abort();
|
|
55
|
+
}
|
|
56
|
+
this.activeBuilds.clear();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export {
|
|
60
|
+
RebuildQueue
|
|
61
|
+
};
|
|
@@ -31,13 +31,13 @@ export interface NormalizedExternalConfig {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
export type IncludeSecondariesOptions = {
|
|
34
|
-
skip
|
|
34
|
+
skip?: string | string[];
|
|
35
35
|
resolveGlob?: boolean;
|
|
36
36
|
keepAll?: boolean;
|
|
37
37
|
} | boolean;
|
|
38
38
|
export type SharedExternalsConfig = Record<string, ExternalConfig>;
|
|
39
39
|
export type NormalizedSharedExternalsConfig = Record<string, NormalizedExternalConfig>;
|
|
40
|
-
export type ShareAllExternalsOptions = ExternalConfig & {
|
|
40
|
+
export type ShareAllExternalsOptions = Omit<ExternalConfig, 'includeSecondaries'> & {
|
|
41
41
|
includeSecondaries?: IncludeSecondariesOptions;
|
|
42
42
|
};
|
|
43
43
|
export type ShareExternalsOptions = Record<string, ShareAllExternalsOptions>;
|
|
File without changes
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { PreparedSkipList, SkipList } from './skip-list.contract.js';
|
|
2
2
|
import type { PathToImport } from '../utils/mapped-path.contract.js';
|
|
3
3
|
import type { NormalizedSharedExternalsConfig, SharedExternalsConfig } from './external-config.contract.js';
|
|
4
|
+
export type ExposeEntry = {
|
|
5
|
+
file: string;
|
|
6
|
+
element?: string;
|
|
7
|
+
};
|
|
4
8
|
export interface FederationConfig {
|
|
5
9
|
name?: string;
|
|
6
|
-
exposes?: Record<string, string>;
|
|
10
|
+
exposes?: Record<string, string | ExposeEntry>;
|
|
7
11
|
shared?: SharedExternalsConfig;
|
|
8
12
|
platform?: 'browser' | 'node';
|
|
9
13
|
sharedMappings?: Array<string>;
|
|
@@ -21,7 +25,7 @@ export interface FederationConfig {
|
|
|
21
25
|
export interface NormalizedFederationConfig {
|
|
22
26
|
$type: 'classic';
|
|
23
27
|
name: string;
|
|
24
|
-
exposes: Record<string,
|
|
28
|
+
exposes: Record<string, ExposeEntry>;
|
|
25
29
|
shared: NormalizedSharedExternalsConfig;
|
|
26
30
|
sharedMappings: PathToImport;
|
|
27
31
|
skip: PreparedSkipList;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
var BuildNotificationType = /* @__PURE__ */ ((BuildNotificationType2) => {
|
|
2
|
+
BuildNotificationType2["COMPLETED"] = "federation-rebuild-complete";
|
|
3
|
+
BuildNotificationType2["ERROR"] = "federation-rebuild-error";
|
|
4
|
+
BuildNotificationType2["CANCELLED"] = "federation-rebuild-cancelled";
|
|
5
|
+
return BuildNotificationType2;
|
|
6
|
+
})(BuildNotificationType || {});
|
|
7
|
+
export {
|
|
8
|
+
BuildNotificationType
|
|
9
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const CHUNK_PREFIX = "@nf-internal";
|
|
2
|
+
function toChunkImport(fileName) {
|
|
3
|
+
if (fileName.startsWith("./")) {
|
|
4
|
+
fileName = fileName.slice(2);
|
|
5
|
+
}
|
|
6
|
+
const packageName = fileName.replace(/.(m|c)?js$/, "");
|
|
7
|
+
return CHUNK_PREFIX + "/" + packageName;
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
CHUNK_PREFIX,
|
|
11
|
+
toChunkImport
|
|
12
|
+
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -4,3 +4,4 @@ export type { FederationOptions, NormalizedFederationOptions, } from './federati
|
|
|
4
4
|
export type { EntryPoint, NFBuildAdapterOptions, NFBuildAdapter, NFBuildAdapterResult, NFBuildAdapterContext, } from './build-adapter.contract.js';
|
|
5
5
|
export { CHUNK_PREFIX, toChunkImport } from './chunk.js';
|
|
6
6
|
export type { FederationCache } from './federation-cache.contract.js';
|
|
7
|
+
export type { FederationManifest } from './manifest.contract.js';
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type HashAlgorithm = 'md5' | 'sha256' | 'sha384' | 'sha512';
|
|
2
|
+
export interface Digest {
|
|
3
|
+
hex(): string;
|
|
4
|
+
base64(): string;
|
|
5
|
+
}
|
|
6
|
+
export interface FileReaderPort {
|
|
7
|
+
readText(path: string): string;
|
|
8
|
+
readBytes(path: string): Uint8Array;
|
|
9
|
+
exists(path: string): boolean;
|
|
10
|
+
/** False on ENOENT, never throws. */
|
|
11
|
+
isFile(path: string): boolean;
|
|
12
|
+
/** False on ENOENT, never throws. */
|
|
13
|
+
isDirectory(path: string): boolean;
|
|
14
|
+
/** Immediate child entry names (not full paths). Empty array on ENOENT, never throws. */
|
|
15
|
+
readDir(path: string): string[];
|
|
16
|
+
}
|
|
17
|
+
export interface FileWriterPort {
|
|
18
|
+
writeText(path: string, data: string): void;
|
|
19
|
+
mkdirp(path: string): void;
|
|
20
|
+
copyFile(from: string, to: string): void;
|
|
21
|
+
remove(path: string): void;
|
|
22
|
+
}
|
|
23
|
+
export interface GlobPort {
|
|
24
|
+
globFiles(pattern: string, opts: {
|
|
25
|
+
cwd: string;
|
|
26
|
+
}): string[];
|
|
27
|
+
}
|
|
28
|
+
export interface HashPort {
|
|
29
|
+
hash(algorithm: HashAlgorithm, data: Uint8Array | string): Digest;
|
|
30
|
+
}
|
|
31
|
+
export interface WatchHandle {
|
|
32
|
+
close(): void;
|
|
33
|
+
}
|
|
34
|
+
export interface WatchPort {
|
|
35
|
+
/**
|
|
36
|
+
* For a recursive directory watch `onEvent` receives the changed entry's
|
|
37
|
+
* filename relative to `path`; for a file it receives the path itself (or
|
|
38
|
+
* null when the platform omits it).
|
|
39
|
+
*/
|
|
40
|
+
watch(path: string, opts: {
|
|
41
|
+
recursive: boolean;
|
|
42
|
+
}, onEvent: (filename: string | null) => void): WatchHandle;
|
|
43
|
+
}
|
|
44
|
+
export interface IoPort extends FileReaderPort, FileWriterPort, GlobPort, HashPort, WatchPort {
|
|
45
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|