@teambit/pnpm 1.0.106 → 1.0.108

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.
@@ -0,0 +1,22 @@
1
+ import { PnpmError } from '@pnpm/error';
2
+ import { pnpmErrorToBitError } from './pnpm-error-to-bit-error';
3
+
4
+ test('the hint from the fetch error is used', () => {
5
+ const bitError = pnpmErrorToBitError(
6
+ new PnpmError('FETCH_404', 'GET https://node-registry.bit.cloud/dsffsdf: Not Found - 404', {
7
+ hint: `dsffsdf is not in the npm registry, or you have no permission to fetch it.
8
+
9
+ An authorization header was used: Bearer df96[hidden]`,
10
+ })
11
+ );
12
+ expect(bitError.report()).toEqual(`GET https://node-registry.bit.cloud/dsffsdf: Not Found - 404
13
+
14
+ dsffsdf is not in the npm registry, or you have no permission to fetch it.
15
+
16
+ An authorization header was used: Bearer df96[hidden]`);
17
+ });
18
+
19
+ test('a regular error object is reported', () => {
20
+ const bitError = pnpmErrorToBitError(new Error('some error') as any);
21
+ expect(bitError.report()).toEqual('some error');
22
+ });
@@ -0,0 +1,44 @@
1
+ import { PnpmError } from '@pnpm/error';
2
+ import { BitError } from '@teambit/bit-error';
3
+
4
+ export class BitErrorWithRichMessage extends BitError {
5
+ private richMessage: string;
6
+ constructor(message: string, richMessage: string) {
7
+ super(message);
8
+ this.richMessage = richMessage;
9
+ }
10
+ public report() {
11
+ return this.richMessage;
12
+ }
13
+ }
14
+
15
+ export function pnpmErrorToBitError(err: PnpmError): BitError {
16
+ const msg = renderErrorMessage(err);
17
+ const newErr = new BitErrorWithRichMessage(msg, msg);
18
+ newErr.cause = err;
19
+ return newErr;
20
+ }
21
+
22
+ function renderErrorMessage(err: PnpmError): string {
23
+ let output = err.message;
24
+ if (err.hint) {
25
+ output += `\n\n${err.hint}`;
26
+ }
27
+ if (err.pkgsStack != null) {
28
+ if (err.pkgsStack.length > 0) {
29
+ output += `\n\n${formatPkgsStack(err.pkgsStack)}`;
30
+ } else if (err.prefix) {
31
+ output += `\n\nThis error happened while installing a direct dependency of ${err.prefix as string}`;
32
+ }
33
+ }
34
+ return output;
35
+ }
36
+
37
+ function formatPkgsStack(pkgsStack: Array<{ id: string; name: string; version: string }>) {
38
+ return `This error happened while installing the dependencies of \
39
+ ${pkgsStack[0].name}@${pkgsStack[0].version}\
40
+ ${pkgsStack
41
+ .slice(1)
42
+ .map(({ name, version }) => `\n at ${name}@${version}`)
43
+ .join('')}`;
44
+ }
@@ -0,0 +1,23 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { difference } from 'lodash';
4
+ import { readCurrentLockfile } from '@pnpm/lockfile-file';
5
+ import { depPathToFilename } from '@pnpm/dependency-path';
6
+
7
+ /**
8
+ * Reads the private lockfile at node_modules/.pnpm/lock.yaml
9
+ * and removes any directories from node_modules/.pnpm that are not listed in the lockfile.
10
+ */
11
+ export async function pnpmPruneModules(rootDir: string): Promise<void> {
12
+ const virtualStoreDir = path.join(rootDir, 'node_modules/.pnpm');
13
+ const pkgDirs = await readPackageDirsFromVirtualStore(virtualStoreDir);
14
+ if (pkgDirs.length === 0) return;
15
+ const lockfile = await readCurrentLockfile(virtualStoreDir, { ignoreIncompatible: false });
16
+ const dirsShouldBePresent = Object.keys(lockfile?.packages ?? {}).map(depPathToFilename);
17
+ await Promise.all(difference(pkgDirs, dirsShouldBePresent).map((dir) => fs.remove(path.join(virtualStoreDir, dir))));
18
+ }
19
+
20
+ async function readPackageDirsFromVirtualStore(virtualStoreDir: string): Promise<string[]> {
21
+ const allDirs = await fs.readdir(virtualStoreDir);
22
+ return allDirs.filter((dir) => dir !== 'lock.yaml' && dir !== 'node_modules');
23
+ }
package/pnpm.aspect.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { Aspect } from '@teambit/harmony';
2
+
3
+ export const PnpmAspect = Aspect.create({
4
+ id: 'teambit.dependencies/pnpm',
5
+ dependencies: [],
6
+ defaultConfig: {},
7
+ });
8
+
9
+ export default PnpmAspect;
@@ -0,0 +1,26 @@
1
+ import { MainRuntime } from '@teambit/cli';
2
+ import { DependencyResolverAspect, DependencyResolverMain } from '@teambit/dependency-resolver';
3
+ import { LoggerAspect, LoggerMain } from '@teambit/logger';
4
+
5
+ import { PnpmAspect } from './pnpm.aspect';
6
+ import { PnpmPackageManager } from './pnpm.package-manager';
7
+
8
+ export class PnpmMain {
9
+ static runtime = MainRuntime;
10
+ static dependencies = [DependencyResolverAspect, LoggerAspect];
11
+
12
+ static async provider([depResolver, loggerExt]: [DependencyResolverMain, LoggerMain]) {
13
+ const logger = loggerExt.createLogger(PnpmAspect.id);
14
+ const packageManager = new PnpmPackageManager(depResolver, logger);
15
+ depResolver.registerPackageManager(packageManager);
16
+ return new PnpmMain(packageManager);
17
+ }
18
+
19
+ constructor(private packageManager: PnpmPackageManager) {}
20
+
21
+ getPackageManager(): PnpmPackageManager {
22
+ return this.packageManager;
23
+ }
24
+ }
25
+
26
+ PnpmAspect.addRuntime(PnpmMain);
@@ -0,0 +1,326 @@
1
+ import {
2
+ DependencyResolverMain,
3
+ extendWithComponentsFromDir,
4
+ InstallationContext,
5
+ PackageManager,
6
+ PackageManagerInstallOptions,
7
+ PackageManagerResolveRemoteVersionOptions,
8
+ ResolvedPackageVersion,
9
+ Registries,
10
+ Registry,
11
+ BIT_CLOUD_REGISTRY,
12
+ PackageManagerProxyConfig,
13
+ PackageManagerNetworkConfig,
14
+ } from '@teambit/dependency-resolver';
15
+ import { Logger } from '@teambit/logger';
16
+ import fs from 'fs';
17
+ import { memoize, omit } from 'lodash';
18
+ import { PeerDependencyIssuesByProjects } from '@pnpm/core';
19
+ import { readModulesManifest } from '@pnpm/modules-yaml';
20
+ import {
21
+ buildDependenciesHierarchy,
22
+ DependenciesHierarchy,
23
+ createPackagesSearcher,
24
+ PackageNode,
25
+ } from '@pnpm/reviewing.dependencies-hierarchy';
26
+ import { renderTree } from '@pnpm/list';
27
+ import { readWantedLockfile } from '@pnpm/lockfile-file';
28
+ import { ProjectManifest } from '@pnpm/types';
29
+ import { join } from 'path';
30
+ import { readConfig } from './read-config';
31
+ import { pnpmPruneModules } from './pnpm-prune-modules';
32
+ import type { RebuildFn } from './lynx';
33
+
34
+ export class PnpmPackageManager implements PackageManager {
35
+ readonly name = 'pnpm';
36
+
37
+ private _readConfig = async (dir?: string) => {
38
+ const { config, warnings } = await readConfig(dir);
39
+ if (config?.fetchRetries && config?.fetchRetries < 5) {
40
+ config.fetchRetries = 5;
41
+ return { config, warnings };
42
+ }
43
+
44
+ return { config, warnings };
45
+ };
46
+
47
+ public readConfig = memoize(this._readConfig);
48
+
49
+ constructor(private depResolver: DependencyResolverMain, private logger: Logger) {}
50
+
51
+ async install(
52
+ { rootDir, manifests }: InstallationContext,
53
+ installOptions: PackageManagerInstallOptions = {}
54
+ ): Promise<{ dependenciesChanged: boolean; rebuild: RebuildFn; storeDir: string }> {
55
+ // require it dynamically for performance purpose. the pnpm package require many files - do not move to static import
56
+ // eslint-disable-next-line global-require, import/no-dynamic-require
57
+ const { install } = require('./lynx');
58
+
59
+ this.logger.debug(`running installation in root dir ${rootDir}`);
60
+ this.logger.debug('components manifests for installation', manifests);
61
+ if (!installOptions.hidePackageManagerOutput) {
62
+ // this.logger.setStatusLine('installing dependencies using pnpm');
63
+ // turn off the logger because it interrupts the pnpm output
64
+ // this.logger.console('-------------------------PNPM OUTPUT-------------------------');
65
+ this.logger.off();
66
+ }
67
+ const registries = await this.depResolver.getRegistries();
68
+ const proxyConfig = await this.depResolver.getProxyConfig();
69
+ const networkConfig = await this.depResolver.getNetworkConfig();
70
+ const { config } = await this.readConfig(installOptions.packageManagerConfigRootDir);
71
+ if (!installOptions.useNesting) {
72
+ manifests = await extendWithComponentsFromDir(rootDir, manifests);
73
+ }
74
+ if (installOptions.nmSelfReferences) {
75
+ Object.values(manifests).forEach((manifest) => {
76
+ if (manifest.name) {
77
+ manifest.devDependencies = {
78
+ [manifest.name]: 'link:.',
79
+ ...manifest.devDependencies,
80
+ };
81
+ }
82
+ });
83
+ }
84
+ const { dependenciesChanged, rebuild, storeDir } = await install(
85
+ rootDir,
86
+ manifests,
87
+ config.storeDir,
88
+ config.cacheDir,
89
+ registries,
90
+ proxyConfig,
91
+ networkConfig,
92
+ {
93
+ engineStrict: installOptions.engineStrict ?? config.engineStrict,
94
+ excludeLinksFromLockfile: installOptions.excludeLinksFromLockfile,
95
+ lockfileOnly: installOptions.lockfileOnly,
96
+ neverBuiltDependencies: installOptions.neverBuiltDependencies,
97
+ nodeLinker: installOptions.nodeLinker,
98
+ nodeVersion: installOptions.nodeVersion ?? config.nodeVersion,
99
+ includeOptionalDeps: installOptions.includeOptionalDeps,
100
+ ignorePackageManifest: installOptions.ignorePackageManifest,
101
+ dedupeInjectedDeps: installOptions.dedupeInjectedDeps,
102
+ dryRun: installOptions.dryRun,
103
+ overrides: installOptions.overrides,
104
+ hoistPattern: config.hoistPattern,
105
+ publicHoistPattern: config.shamefullyHoist
106
+ ? ['*']
107
+ : ['@eslint/plugin-*', '*eslint-plugin*', '@prettier/plugin-*', '*prettier-plugin-*'],
108
+ packageImportMethod: installOptions.packageImportMethod ?? config.packageImportMethod,
109
+ preferOffline: installOptions.preferOffline,
110
+ rootComponents: installOptions.rootComponents,
111
+ rootComponentsForCapsules: installOptions.rootComponentsForCapsules,
112
+ peerDependencyRules: installOptions.peerDependencyRules,
113
+ sideEffectsCacheRead: installOptions.sideEffectsCache ?? true,
114
+ sideEffectsCacheWrite: installOptions.sideEffectsCache ?? true,
115
+ pnpmHomeDir: config.pnpmHomeDir,
116
+ updateAll: installOptions.updateAll,
117
+ hidePackageManagerOutput: installOptions.hidePackageManagerOutput,
118
+ reportOptions: {
119
+ appendOnly: installOptions.optimizeReportForNonTerminal,
120
+ throttleProgress: installOptions.throttleProgress,
121
+ hideProgressPrefix: installOptions.hideProgressPrefix,
122
+ hideLifecycleOutput: installOptions.hideLifecycleOutput,
123
+ },
124
+ },
125
+ this.logger
126
+ );
127
+ if (!installOptions.hidePackageManagerOutput) {
128
+ this.logger.on();
129
+ // Make a divider row to improve output
130
+ // this.logger.console('-------------------------END PNPM OUTPUT-------------------------');
131
+ // this.logger.consoleSuccess('installing dependencies using pnpm');
132
+ }
133
+ return { dependenciesChanged, rebuild, storeDir };
134
+ }
135
+
136
+ async getPeerDependencyIssues(
137
+ rootDir: string,
138
+ manifests: Record<string, ProjectManifest>,
139
+ installOptions: PackageManagerInstallOptions = {}
140
+ ): Promise<PeerDependencyIssuesByProjects> {
141
+ const proxyConfig = await this.depResolver.getProxyConfig();
142
+ const networkConfig = await this.depResolver.getNetworkConfig();
143
+ const registries = await this.depResolver.getRegistries();
144
+ // require it dynamically for performance purpose. the pnpm package require many files - do not move to static import
145
+ // eslint-disable-next-line global-require, import/no-dynamic-require
146
+ const lynx = require('./lynx');
147
+ const { config } = await this.readConfig(installOptions.packageManagerConfigRootDir);
148
+ return lynx.getPeerDependencyIssues(manifests, {
149
+ storeDir: config.storeDir,
150
+ cacheDir: config.cacheDir,
151
+ proxyConfig,
152
+ registries,
153
+ rootDir,
154
+ networkConfig,
155
+ overrides: installOptions.overrides,
156
+ packageImportMethod: installOptions.packageImportMethod ?? config.packageImportMethod,
157
+ });
158
+ }
159
+
160
+ async resolveRemoteVersion(
161
+ packageName: string,
162
+ options: PackageManagerResolveRemoteVersionOptions
163
+ ): Promise<ResolvedPackageVersion> {
164
+ // require it dynamically for performance purpose. the pnpm package require many files - do not move to static import
165
+ // eslint-disable-next-line global-require, import/no-dynamic-require
166
+ const { resolveRemoteVersion } = require('./lynx');
167
+ const registries = await this.depResolver.getRegistries();
168
+ const proxyConfig = await this.depResolver.getProxyConfig();
169
+ const networkConfig = await this.depResolver.getNetworkConfig();
170
+ const { config } = await this.readConfig(options.packageManagerConfigRootDir);
171
+ return resolveRemoteVersion(packageName, options.rootDir, config.cacheDir, registries, proxyConfig, networkConfig);
172
+ }
173
+
174
+ async getProxyConfig?(): Promise<PackageManagerProxyConfig> {
175
+ // eslint-disable-next-line global-require, import/no-dynamic-require
176
+ const { getProxyConfig } = require('./get-proxy-config');
177
+ const { config } = await this.readConfig();
178
+ return getProxyConfig(config);
179
+ }
180
+
181
+ async getNetworkConfig?(): Promise<PackageManagerNetworkConfig> {
182
+ const { config } = await this.readConfig();
183
+ // We need to use config.rawConfig as it will only contain the settings defined by the user.
184
+ // config contains default values of the settings when they are not defined by the user.
185
+ return {
186
+ maxSockets: config.rawConfig['max-sockets'],
187
+ networkConcurrency: config.rawConfig['network-concurrency'],
188
+ fetchRetries: config.rawConfig['fetch-retries'],
189
+ fetchTimeout: config.rawConfig['fetch-timeout'],
190
+ fetchRetryMaxtimeout: config.rawConfig['fetch-retry-maxtimeout'],
191
+ fetchRetryMintimeout: config.rawConfig['fetch-retry-mintimeout'],
192
+ strictSSL: config.rawConfig['strict-ssl'],
193
+ // These settings don't have default value, so it is safe to read them from config
194
+ // ca is automatically populated from the content of the file specified by cafile.
195
+ ca: config.ca,
196
+ cert: config.cert,
197
+ key: config.key,
198
+ };
199
+ }
200
+
201
+ async getRegistries(): Promise<Registries> {
202
+ // eslint-disable-next-line global-require, import/no-dynamic-require
203
+ const { getRegistries } = require('./get-registries');
204
+ const { config } = await this.readConfig();
205
+ const pnpmRegistry = await getRegistries(config);
206
+ const defaultRegistry = new Registry(
207
+ pnpmRegistry.default.uri,
208
+ pnpmRegistry.default.alwaysAuth,
209
+ pnpmRegistry.default.authHeaderValue,
210
+ pnpmRegistry.default.originalAuthType,
211
+ pnpmRegistry.default.originalAuthValue
212
+ );
213
+
214
+ const pnpmScoped = omit(pnpmRegistry, ['default']);
215
+ const scopesRegistries: Record<string, Registry> = Object.keys(pnpmScoped).reduce((acc, scopedRegName) => {
216
+ const scopedReg = pnpmScoped[scopedRegName];
217
+ const name = scopedRegName.replace('@', '');
218
+ acc[name] = new Registry(
219
+ scopedReg.uri,
220
+ scopedReg.alwaysAuth,
221
+ scopedReg.authHeaderValue,
222
+ scopedReg.originalAuthType,
223
+ scopedReg.originalAuthValue
224
+ );
225
+ return acc;
226
+ }, {});
227
+
228
+ // Add bit registry server if not exist
229
+ if (!scopesRegistries.bit) {
230
+ scopesRegistries.bit = new Registry(BIT_CLOUD_REGISTRY, true);
231
+ }
232
+
233
+ return new Registries(defaultRegistry, scopesRegistries);
234
+ }
235
+
236
+ async getInjectedDirs(rootDir: string, componentDir: string, packageName: string): Promise<string[]> {
237
+ const modulesState = await this._readModulesManifest(rootDir);
238
+ if (modulesState?.injectedDeps == null) return [];
239
+ return modulesState.injectedDeps[`node_modules/${packageName}`] ?? modulesState.injectedDeps[componentDir] ?? [];
240
+ }
241
+
242
+ _readModulesManifest(lockfileDir: string) {
243
+ return readModulesManifest(join(lockfileDir, 'node_modules'));
244
+ }
245
+
246
+ getWorkspaceDepsOfBitRoots(manifests: ProjectManifest[]): Record<string, string> {
247
+ return Object.fromEntries(manifests.map((manifest) => [manifest.name, 'workspace:*']));
248
+ }
249
+
250
+ async pruneModules(rootDir: string): Promise<void> {
251
+ return pnpmPruneModules(rootDir);
252
+ }
253
+
254
+ async findUsages(depName: string, opts: { lockfileDir: string; depth?: number }): Promise<string> {
255
+ const search = createPackagesSearcher([depName]);
256
+ const lockfile = await readWantedLockfile(opts.lockfileDir, { ignoreIncompatible: false });
257
+ const projectPaths = Object.keys(lockfile?.importers ?? {})
258
+ .filter((id) => !id.startsWith('node_modules/.bit_roots'))
259
+ .map((id) => join(opts.lockfileDir, id));
260
+ const cache = new Map();
261
+ const modulesManifest = await this._readModulesManifest(opts.lockfileDir);
262
+ const isHoisted = modulesManifest?.nodeLinker === 'hoisted';
263
+ const getPkgLocation: GetPkgLocation = isHoisted
264
+ ? ({ name }) => join(opts.lockfileDir, 'node_modules', name)
265
+ : ({ path }) => path;
266
+ const results = Object.entries(
267
+ await buildDependenciesHierarchy(projectPaths, {
268
+ depth: opts.depth ?? Infinity,
269
+ include: {
270
+ dependencies: true,
271
+ devDependencies: true,
272
+ optionalDependencies: true,
273
+ },
274
+ lockfileDir: opts.lockfileDir,
275
+ registries: {
276
+ default: 'https://registry.npmjs.org',
277
+ },
278
+ search,
279
+ })
280
+ ).map(([projectPath, builtDependenciesHierarchy]) => {
281
+ pkgNamesToComponentIds(builtDependenciesHierarchy, { cache, getPkgLocation });
282
+ return {
283
+ path: projectPath,
284
+ ...builtDependenciesHierarchy,
285
+ };
286
+ });
287
+ return renderTree(results, {
288
+ alwaysPrintRootPackage: false,
289
+ depth: Infinity,
290
+ search: true,
291
+ long: false,
292
+ showExtraneous: false,
293
+ });
294
+ }
295
+ }
296
+
297
+ type GetPkgLocation = (pkgNode: PackageNode) => string;
298
+
299
+ function pkgNamesToComponentIds(
300
+ deps: DependenciesHierarchy,
301
+ { cache, getPkgLocation }: { cache: Map<string, string>; getPkgLocation: GetPkgLocation }
302
+ ) {
303
+ for (const depType of ['dependencies', 'devDependencies', 'optionalDependencies']) {
304
+ if (deps[depType]) {
305
+ for (const dep of deps[depType]) {
306
+ if (!cache.has(dep.name)) {
307
+ const pkgJson = tryReadPackageJson(getPkgLocation(dep));
308
+ cache.set(
309
+ dep.name,
310
+ pkgJson?.componentId ? `${pkgJson.componentId.scope}/${pkgJson.componentId.name}` : dep.name
311
+ );
312
+ }
313
+ dep.name = cache.get(dep.name);
314
+ pkgNamesToComponentIds(dep, { cache, getPkgLocation });
315
+ }
316
+ }
317
+ }
318
+ }
319
+
320
+ function tryReadPackageJson(pkgDir: string) {
321
+ try {
322
+ return JSON.parse(fs.readFileSync(join(pkgDir, 'package.json'), 'utf8'));
323
+ } catch (err) {
324
+ return undefined;
325
+ }
326
+ }
package/read-config.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { getConfig } from '@pnpm/config';
2
+
3
+ export async function readConfig(dir?: string) {
4
+ const pnpmConfig = await getConfig({
5
+ cliOptions: {
6
+ dir,
7
+ // 'global': true,
8
+ // 'link-workspace-packages': true,
9
+ },
10
+ packageManager: {
11
+ name: 'pnpm',
12
+ version: '1.0.0',
13
+ },
14
+ });
15
+ return pnpmConfig;
16
+ }
package/tsconfig.json CHANGED
@@ -1,38 +1,33 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "lib": [
4
- "es2019",
5
- "DOM",
6
- "ES6",
7
- "DOM.Iterable",
8
- "ScriptHost"
4
+ "esnext",
5
+ "dom",
6
+ "dom.Iterable"
9
7
  ],
10
- "target": "es2015",
11
- "module": "CommonJS",
12
- "jsx": "react",
13
- "allowJs": true,
14
- "composite": true,
8
+ "target": "es2020",
9
+ "module": "es2020",
10
+ "jsx": "react-jsx",
15
11
  "declaration": true,
16
12
  "sourceMap": true,
17
- "skipLibCheck": true,
18
13
  "experimentalDecorators": true,
19
- "outDir": "dist",
14
+ "skipLibCheck": true,
20
15
  "moduleResolution": "node",
21
16
  "esModuleInterop": true,
22
- "rootDir": ".",
23
17
  "resolveJsonModule": true,
24
- "emitDeclarationOnly": true,
25
- "emitDecoratorMetadata": true,
26
- "allowSyntheticDefaultImports": true,
27
- "strictPropertyInitialization": false,
28
- "strict": true,
29
- "noImplicitAny": false,
30
- "preserveConstEnums": true
18
+ "allowJs": true,
19
+ "outDir": "dist",
20
+ "emitDeclarationOnly": true
31
21
  },
32
22
  "exclude": [
23
+ "artifacts",
24
+ "public",
33
25
  "dist",
26
+ "node_modules",
27
+ "package.json",
34
28
  "esm.mjs",
35
- "package.json"
29
+ "**/*.cjs",
30
+ "./dist"
36
31
  ],
37
32
  "include": [
38
33
  "**/*",
package/types/asset.d.ts CHANGED
@@ -5,12 +5,12 @@ declare module '*.png' {
5
5
  declare module '*.svg' {
6
6
  import type { FunctionComponent, SVGProps } from 'react';
7
7
 
8
- export const ReactComponent: FunctionComponent<SVGProps<SVGSVGElement> & { title?: string }>;
8
+ export const ReactComponent: FunctionComponent<
9
+ SVGProps<SVGSVGElement> & { title?: string }
10
+ >;
9
11
  const src: string;
10
12
  export default src;
11
13
  }
12
-
13
- // @TODO Gilad
14
14
  declare module '*.jpg' {
15
15
  const value: any;
16
16
  export = value;
@@ -27,3 +27,15 @@ declare module '*.bmp' {
27
27
  const value: any;
28
28
  export = value;
29
29
  }
30
+ declare module '*.otf' {
31
+ const value: any;
32
+ export = value;
33
+ }
34
+ declare module '*.woff' {
35
+ const value: any;
36
+ export = value;
37
+ }
38
+ declare module '*.woff2' {
39
+ const value: any;
40
+ export = value;
41
+ }