From be24d25dce2a321bc71dff798888b695ba6e6ae3 Mon Sep 17 00:00:00 2001 From: atanasster Date: Wed, 11 Mar 2020 15:24:06 -0400 Subject: [PATCH] feat: caching of props-info parsing --- core/instrument/package.json | 4 +- .../instrument/src/babel/extract-component.ts | 48 ++----------- core/instrument/src/index.ts | 2 +- .../src/{project => misc}/packageInfo.ts | 4 +- core/instrument/src/misc/propsInfo.ts | 68 +++++++++++++++++++ yarn.lock | 14 ++++ 6 files changed, 92 insertions(+), 48 deletions(-) rename core/instrument/src/{project => misc}/packageInfo.ts (98%) create mode 100644 core/instrument/src/misc/propsInfo.ts diff --git a/core/instrument/package.json b/core/instrument/package.json index a0c3b5a54..507fb94d2 100644 --- a/core/instrument/package.json +++ b/core/instrument/package.json @@ -40,6 +40,7 @@ "@storybook/csf": "^0.0.1", "crypto": "^1.0.1", "deepmerge": "^4.2.2", + "find-cache-dir": "^3.3.1", "hosted-git-info": "^3.0.4", "resolve": "^1.15.1", "prettier": "^1.19.1", @@ -48,8 +49,9 @@ "devDependencies": { "@babel/types": "^7.8.3", "@rollup/plugin-node-resolve": "^7.1.1", - "@types/jest": "^25.1.2", + "@types/find-cache-dir": "^3.2.0", "@types/hosted-git-info": "^3.0.0", + "@types/jest": "^25.1.2", "cross-env": "^5.2.1", "docz-rollup": "^2.1.0", "eslint": "^6.5.1", diff --git a/core/instrument/src/babel/extract-component.ts b/core/instrument/src/babel/extract-component.ts index 900670a68..ae3b6d19a 100644 --- a/core/instrument/src/babel/extract-component.ts +++ b/core/instrument/src/babel/extract-component.ts @@ -4,52 +4,12 @@ import { StoryAttributes, StoryComponent, StoriesKind, - ComponentInfo, } from '@component-controls/specification'; import { followImports } from './follow-imports'; -import { packageInfo } from '../project/packageInfo'; -import { - InstrumentOptions, - PropsLoaderConfig, - PropsInfoExtractorFunction, -} from '../types'; - -const extractComponentProps = async ( - options: PropsLoaderConfig[], - filePath: string, - componentName?: string, - source?: string, -): Promise => { - const loaders = options.filter(loader => { - const include = Array.isArray(loader.use) - ? loader.use - : loader.use - ? [loader.use] - : undefined; - const exclude = Array.isArray(loader.exclude) - ? loader.exclude - : loader.exclude - ? [loader.exclude] - : undefined; - return ( - include && - include.some(mask => filePath.match(mask)) && - (!exclude || !exclude.some(mask => filePath.match(mask))) - ); - }); +import { packageInfo } from '../misc/packageInfo'; +import { propsInfo } from '../misc/propsInfo'; +import { InstrumentOptions } from '../types'; - if (loaders.length > 1) { - console.error(`Multiple propsloaders found for file ${filePath}`); - } - const propsLoaderName = loaders.length === 1 ? loaders[0] : undefined; - if (propsLoaderName) { - const propsLoader: PropsInfoExtractorFunction = require(propsLoaderName.name)( - propsLoaderName.options, - ); - return await propsLoader(filePath, componentName, source); - } - return undefined; -}; const componentFromParams = ( attributes?: StoryAttributes, ): string | undefined => { @@ -116,7 +76,7 @@ export const extractComponent = async ( }; const { propsLoaders } = options || {}; if (follow && follow.filePath && Array.isArray(propsLoaders)) { - const info = await extractComponentProps( + const info = await propsInfo( propsLoaders, follow.filePath, follow.importedName, diff --git a/core/instrument/src/index.ts b/core/instrument/src/index.ts index 9de390e3e..96fb300bf 100644 --- a/core/instrument/src/index.ts +++ b/core/instrument/src/index.ts @@ -18,7 +18,7 @@ import { extractCSFStories } from './babel/csf-stories'; import { extractMDXStories } from './babel/mdx-stories'; import { removeMDXAttributes } from './babel/remove-mdx-attributes'; import { extractStoreComponent } from './babel/extract-component'; -import { packageInfo } from './project/packageInfo'; +import { packageInfo } from './misc/packageInfo'; import { InstrumentOptions, InstrumentOptionsMDX, diff --git a/core/instrument/src/project/packageInfo.ts b/core/instrument/src/misc/packageInfo.ts similarity index 98% rename from core/instrument/src/project/packageInfo.ts rename to core/instrument/src/misc/packageInfo.ts index 36f5e856e..0602c893c 100644 --- a/core/instrument/src/project/packageInfo.ts +++ b/core/instrument/src/misc/packageInfo.ts @@ -1,5 +1,5 @@ -import fs from 'fs'; -import path from 'path'; +import * as fs from 'fs'; +import * as path from 'path'; //@ts-ignore import readJson from 'read-package-json'; import hostedGitInfo from 'hosted-git-info'; diff --git a/core/instrument/src/misc/propsInfo.ts b/core/instrument/src/misc/propsInfo.ts new file mode 100644 index 000000000..34a5df7de --- /dev/null +++ b/core/instrument/src/misc/propsInfo.ts @@ -0,0 +1,68 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +import { createHash } from 'crypto'; +import findCacheDir from 'find-cache-dir'; +import { ComponentInfo } from '@component-controls/specification'; +import { PropsLoaderConfig, PropsInfoExtractorFunction } from '../types'; + +export const propsInfo = async ( + options: PropsLoaderConfig[], + filePath: string, + componentName?: string, + source?: string, +): Promise => { + const cacheFolder = + findCacheDir({ name: 'component-controls-props-info' }) || os.tmpdir(); + + //create cache folder if it doesnt exist + if (!fs.existsSync(cacheFolder)) { + fs.mkdirSync(cacheFolder, { recursive: true }); + } + const cachedFileName = path.join( + cacheFolder, + createHash('md5') + .update(filePath) + .digest('hex'), + ); + + if (fs.existsSync(cachedFileName)) { + const cacheStats = fs.statSync(cachedFileName); + const fileStats = fs.statSync(filePath); + if (cacheStats.mtime.getTime() >= fileStats.mtime.getTime()) { + const fileData = fs.readFileSync(cachedFileName, 'utf8'); + return JSON.parse(fileData); + } + } + let result: ComponentInfo | undefined = undefined; + const loaders = options.filter(loader => { + const include = Array.isArray(loader.use) + ? loader.use + : loader.use + ? [loader.use] + : undefined; + const exclude = Array.isArray(loader.exclude) + ? loader.exclude + : loader.exclude + ? [loader.exclude] + : undefined; + return ( + include && + include.some(mask => filePath.match(mask)) && + (!exclude || !exclude.some(mask => filePath.match(mask))) + ); + }); + + if (loaders.length > 1) { + console.error(`Multiple propsloaders found for file ${filePath}`); + } + const propsLoaderName = loaders.length === 1 ? loaders[0] : undefined; + if (propsLoaderName) { + const propsLoader: PropsInfoExtractorFunction = require(propsLoaderName.name)( + propsLoaderName.options, + ); + result = await propsLoader(filePath, componentName, source); + } + fs.writeFileSync(cachedFileName, JSON.stringify(result || {})); + return result; +}; diff --git a/yarn.lock b/yarn.lock index dc7158cdb..b6cb2662e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3302,6 +3302,11 @@ resolved "https://registry.yarnpkg.com/@types/faker/-/faker-4.1.10.tgz#ec31466931086122b05be719d084989ffe3d6eb6" integrity sha512-Z1UXXNyxUcuu7CSeRmVizMgH7zVYiwfiTgXMnSTvsYDUnVt3dbMSpPdfG/H41IBiclgFGQJgLVdDFeinhhmWTg== +"@types/find-cache-dir@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@types/find-cache-dir/-/find-cache-dir-3.2.0.tgz#eaaf331699dccf52c47926e4d4f8f3ed8db33f3c" + integrity sha512-+JeT9qb2Jwzw72WdjU+TSvD5O1QRPWCeRpDJV+guiIq+2hwR0DFGw+nZNbTFjMIVe6Bf4GgAKeB/6Ytx6+MbeQ== + "@types/fs-extra@^8.0.0": version "8.1.0" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.0.tgz#1114834b53c3914806cd03b3304b37b3bd221a4d" @@ -7766,6 +7771,15 @@ find-cache-dir@^3.0.0, find-cache-dir@^3.2.0: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-cache-dir@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + find-node-modules@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/find-node-modules/-/find-node-modules-2.0.0.tgz#5db1fb9e668a3d451db3d618cd167cdd59e41b69"