I revived an archived project and released it as FortuneExcel - a plugin for FortuneSheet to import/export Excel (.xlsx) files.
Sections:
Initialization
Reviving the project meant fixing the deprecated code and existing bugs. Along with this, I added export feature, toolbar plugin support for fortune-sheet and set up Github workflow.
Modularization
While implementing a package, it should have maximum abstraction. User should have to add minimal code to their environment for your package to work, all while having no side-effects on their existing code. A proper code strucrure also makes it easier for others to contribute to your code.
Github Workflow
Lets breakdown the pubhlish.yml file.
Run the workflow whenever a release is published or manually triggered from Actions tab:
publish.yml
-----------
on:
release:
types: [published]
workflow_dispatch:
Define premissions required by the workflow:
permissions:
contents: read
pages: write
id-token: write
Checkout the code, setup node environment, install dependencies (see npm i vs npm ci) and publish the package on npm:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "20.x"
registry-url: "https://registry.npmjs.org"
- run: npm ci
- run: npm publish --tag latest --provenance --access public
env:
NODE_AUTH_TOKEN: $
Build the Storybook, upload it as an artifact and deploy it on GitHub Pages:
Note: Update Build and Deployement source to ‘Github Actions’ in repo > Settings > Pages
- run: npm run build-storybook
- uses: actions/upload-pages-artifact@v2
with:
path: storybook-static
- id: deploy
uses: actions/deploy-pages@v3
with:
token: $
Secrets and Tokens
In the above section inside publish.yml, notice github.token
and secrets.NPM_TOKEN
.
While github.token
is automatically provided by GitHub Actions, secrets.NPM_TOKEN
is an automation access token that has to be generated at npmjs.com and set as repository secret on Github.
Emitted Javascript version
Fortune-excel and fortune-sheet were having incompatibility issues due to different transmitted JS when compiled from TS. This is defined by the target
value in compilerOptions
of tsconfig.json. Since fortune-sheet compiles the JS In es5, changing the target from es6 to es5 in fortune-excel fixed the issue:
tsconfig.json
-----------
{
"compilerOptions": {
"target": "es5",
...
}
}
Commonjs entrypoint
After publishing the package, Yarn showed this warning - ‘the package doesn’t seem to have a commonjs entry point’. Compiling the TS in commonjs is necessary for old projects still using CJS instead of ESM. Compiling is ESM is optional since EMS supports CJS, but not visa-versa. To fix the warning:
- Make sure package.json does not have
"type": "module"
definedWhen set to “module”, the type field allows a package to specify all .js files within are ES modules. If the “type” field is omitted or set to “commonjs”, all .js files are treated as CommonJS.
- Define
"module": "commonjs"
in tsconfig.json - refer to this.
Compiling TS for Storybook
To make our plugin work with Storybook in the same repository, we can take two approaches:
- Use the commonjs code inside
/dist/
compiled by Typescript Compiler (tsc): the drawback of this is that it would be difficult to add breakpoints in the browser when testing the repo on storybook, as we are using the compiled code instead of the actual TS code. - Use the actual typescript code: fixes the problem mentioned above
To use the actual TS code:
- Import the plugin in storybook example, and use an alias inside
tsconfig.json
:// tsconfig.json { "paths": { "@corbe30/fortune-excel": ["./src/main.ts"], }, ... }
// stories/Page.tsx import { exportToolBarItem, importToolBarItem } from "@corbe30/fortune-excel";
- Now, although the storybook is referring to
/src/main.ts
to import the plugin, building the storybook will throw a TS compilation error. This is because Storybook uses its own compiler separate from our project’s compliler, Babel. To ensure Babel is configured to handle TypeScript, Babel configuration (babel.config.js
or.babelrc
) should include the TypeScript preset:{ "presets": [ "@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript" ], ... }
Then install the necessary Babel presets:
npm install --save-dev @babel/preset-env @babel/preset-react @babel/preset-typescript