From 564f3a852db8f09fdedb3708af1272c8b4d36063 Mon Sep 17 00:00:00 2001 From: Sergio Carracedo Date: Mon, 24 Feb 2025 12:04:24 +0100 Subject: [PATCH] chore: Exports in package.json and coder sync --- docs/{ => development}/development.md | 0 docs/development/images/coder.png | Bin 0 -> 30758 bytes .../development/using-factorial-one-source.md | 63 ++++++++++++++ docs/getting-started.md | 6 +- docs/index.md | 4 +- .../Navigation/Header/PageHeader/index.tsx | 1 - package.json | 49 ++++++++++- pnpm-lock.yaml | 15 ++++ tsconfig-build-icons.json | 2 +- tsconfig.node.json | 5 +- vite.config.ts | 71 ++++++++++++---- vite/build-sync.plugin.ts | 78 ++++++++++++++++++ vitest.setup.ts => vite/vitest.setup.ts | 0 13 files changed, 270 insertions(+), 24 deletions(-) rename docs/{ => development}/development.md (100%) create mode 100644 docs/development/images/coder.png create mode 100644 docs/development/using-factorial-one-source.md create mode 100644 vite/build-sync.plugin.ts rename vitest.setup.ts => vite/vitest.setup.ts (100%) diff --git a/docs/development.md b/docs/development/development.md similarity index 100% rename from docs/development.md rename to docs/development/development.md diff --git a/docs/development/images/coder.png b/docs/development/images/coder.png new file mode 100644 index 0000000000000000000000000000000000000000..d80c96f9957d3ff313924ad8cd42664a108f94c2 GIT binary patch literal 30758 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 IMPORTANT: Remember to remove use an stable version before to merge into `main` or release + +### How to use local version of `factorial-one` in your local repo (ex. `factorial`'s monorepo) {#local} + +This applies when both `factorial-one` and `factorial`'s monorepo are in the local computer + +1. Go to the `factorial-one` folder: `cd factorial-one` +2. Run `pnpm build:watch` to rebuild the project on any change +3. Run `pnpm link --global` to add the package to the local links +4. Go to the factorial app monorepo: `cd factorial/frontend` +5. Run `pnpm link --global @factorialco/factorial-one` to use the local version of the package + +### How to use local version of `factorial-one` in coder {#cder} + +This applies when `factorial-one` is in your local computer and `factorial`'s monorepo is in coder's dev environment + +**Prerequisites:** + +- [rsync](https://linux.die.net/man/1/rsync) in your local computer: `brew install rsync` +- [coder cli](https://coder.com/docs/getting-started/installation) in your local computer + - ![Coder ssh](images/coder.png) +- Create if not exists `.env.local` and add this line `CODER_REMOTE=[YOUR_CODER_SSH_CONNECTION_STRING]`, for example: + `CODER_REMOTE=coder.sergiocarracedo-dev-env` + > This file is in the `.gitignore` file, so it won't be pushed to the repository + +**Steps:** + +1. Go to the `factorial-one` folder: `cd factorial-one` +2. Run `pnpm dev:coder` to rebuild the project on any change and sync that build to coder workspace + +> Now on each change in the `factorial-one`'s source code, the changes will be reflected in the coder workspace and the +> frontend will be reloaded using always the latest `factorial-one`'s code + diff --git a/docs/getting-started.md b/docs/getting-started.md index b1349da35..3bf098ee3 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -18,7 +18,11 @@ import "@factorialco/factorial-one/styles.css" import "@factorialco/factorial-one/fonts.js" // In any of your components -import { Button } from "@factorialco/factorial-one" +import {Button} from "@factorialco/factorial-one" ``` And that's it! + +Related: + +- [Using factorial one source](development/using-factorial-one-source.md) diff --git a/docs/index.md b/docs/index.md index 3dd73da97..6adeef34e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,6 +2,6 @@ `factorial-one` is a set of component, hooks, utilities used as foundations for the factorial's app - - [Getting started](./getting-started.md) -- [Local Development](./development.md) \ No newline at end of file +- [Local Development](development/development.md) + - [Using factorial-one without build it](development/using-factorial-one-source.md) \ No newline at end of file diff --git a/lib/experimental/Navigation/Header/PageHeader/index.tsx b/lib/experimental/Navigation/Header/PageHeader/index.tsx index e46192c1b..8cbfad11c 100644 --- a/lib/experimental/Navigation/Header/PageHeader/index.tsx +++ b/lib/experimental/Navigation/Header/PageHeader/index.tsx @@ -13,7 +13,6 @@ import { ReactElement } from "react" import { Dropdown } from "../../Dropdown" import Breadcrumbs, { type BreadcrumbItemType } from "../Breadcrumbs" - export type PageAction = { label: string icon: IconType diff --git a/package.json b/package.json index 31044c1d1..a60e8efff 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,50 @@ "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0", "files": [ "assets", - "icons", "dist", "styles.css", "tailwind.config.ts", "postcss.config.js" ], + "exports": { + ".": { + "types": "./dist/lib/factorial-one.d.ts", + "default": "./dist/lib/factorial-one.js" + }, + "./experimental": { + "types": "./lib/experimental/lib/exports.d.ts", + "default": "./dist/lib/experimental.js" + }, + "./icons/animated": { + "types": "./dist/icons/animated/index.d.ts", + "default": "./dist/icons/animated/index.js" + }, + "./icons/animated/*": { + "types": "./dist/icons/animated/*.d.ts", + "default": "./dist/icons/animated/*.js" + }, + "./icons/app": { + "types": "./dist/icons/app/index.d.ts", + "default": "./dist/icons/app/index.js" + }, + "./icons/app/*": { + "types": "./dist/icons/app/*.d.ts", + "default": "./dist/icons/app/*.js" + }, + "./icons/modules": { + "types": "./dist/icons/modules/index.d.ts", + "default": "./dist/icons/modules/index.js" + }, + "./icons/modules/*": { + "types": "./dist/icons/modules/*.d.ts", + "default": "./dist/icons/modules/*.js" + }, + "./icons/*": { + "types": "./dist/icons/*", + "default": "./dist/icons/*" + }, + "./styles.css": "./dist/styles.css" + }, "sideEffects": [ "**/*.css" ], @@ -21,10 +59,12 @@ "dev": "storybook dev -p 6006", "dev:docs": "DOCS_MODE=true pnpm run dev", "start": "pnpm run dev", - "build": "tsc --project ./tsconfig-build.json && BUILD_TYPES=true vite build && pnpm run build:tailwind && run-p build-icons", + "build": "tsc --project ./tsconfig-build.json && pnpm run build:tailwind && run-p build-icons && BUILD_TYPES=true vite build", "build:tsup": "tsup && pnpm run build:tailwind && run-p build-icons", "build-icons": "tsc --project ./tsconfig-build-icons.json", "build:tailwind": "NODE_ENV=production tailwindcss -i ./styles.css -o ./dist/styles.css --postcss --minify", + "build:watch": "pnpm build --watch", + "dev:coder": "pnpm build --watch -- --buildSync", "lint": "eslint -c eslint.config.mjs . --report-unused-disable-directives --max-warnings 0", "lint-fix": "pnpm run lint -- --fix", "preview": "vite preview", @@ -122,8 +162,10 @@ "@typescript-eslint/parser": "^8.24.1", "@vitejs/plugin-react": "^4.3.4", "autoprefixer": "^10.4.20", + "chalk": "^5.4.1", "axe-playwright": "^2.1.0", "chromatic": "^11.25.2", + "consola": "^3.4.0", "emoji-mart": "^5.6.0", "eslint": "^9.21.0", "eslint-plugin-react": "^7.37.4", @@ -150,7 +192,8 @@ "vite": "^6.1.1", "vite-plugin-dts": "4.3.0", "vite-plugin-lib-inject-css": "^2.2.1", - "vitest": "^3.0.5" + "vitest": "^3.0.5", + "dotenv": "^16.4.7" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "^4.34" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 45003f6be..7d8584979 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -268,9 +268,18 @@ importers: axe-playwright: specifier: ^2.1.0 version: 2.1.0(playwright@1.50.0) + chalk: + specifier: ^5.4.1 + version: 5.4.1 chromatic: specifier: ^11.25.2 version: 11.25.2 + consola: + specifier: ^3.4.0 + version: 3.4.0 + dotenv: + specifier: ^16.4.7 + version: 16.4.7 emoji-mart: specifier: ^5.6.0 version: 5.6.0 @@ -3273,6 +3282,10 @@ packages: dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -9185,6 +9198,8 @@ snapshots: no-case: 3.0.4 tslib: 2.8.1 + dotenv@16.4.7: {} + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.1 diff --git a/tsconfig-build-icons.json b/tsconfig-build-icons.json index d926e90ba..074326ea6 100644 --- a/tsconfig-build-icons.json +++ b/tsconfig-build-icons.json @@ -12,9 +12,9 @@ // Types should go into this directory. // Removing this would place the .d.ts files // next to the .js files - "outDir": "icons", "jsx": "react-jsx", "noEmit": false, + "outDir": "dist/icons", "allowImportingTsExtensions": false, // go to js file when using IDE functions like // "Go to Definition" in VSCode diff --git a/tsconfig.node.json b/tsconfig.node.json index 97ede7ee6..f946d96e0 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -7,5 +7,8 @@ "allowSyntheticDefaultImports": true, "strict": true }, - "include": ["vite.config.ts"] + "include": [ + "vite.config.ts", + "vite/**/*" + ] } diff --git a/vite.config.ts b/vite.config.ts index a994d46c3..6567ec6ab 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,25 +1,64 @@ /// import react from "@vitejs/plugin-react" +import { consola } from "consola" +import dotenv from "dotenv" import path, { resolve } from "path" -import { defineConfig } from "vite" +import { defineConfig, Plugin } from "vite" import dts from "vite-plugin-dts" import { libInjectCss } from "vite-plugin-lib-inject-css" +import { buildSyncPlugin } from "./vite/build-sync.plugin" + +dotenv.config({ + path: [".env.local", ".env"], +}) + +const extraPlugins: Plugin[] = [] + +/* Build sync */ +const defaultCoderWorkspaceFolder = + "/home/factorial/workspace/factorial/frontend/node_modules/@factorialco/factorial-one" + +const buildSyncArg = process.argv.find((arg) => arg.startsWith("--buildSync")) +const buildSync = !!buildSyncArg +const buildSyncValue = buildSyncArg + ? buildSyncArg.split("=")[1] || process.env.CODER_REMOTE + : null + +if (buildSync) { + if (!buildSyncValue) { + consola.error( + "The buildSync flag must remote target or you can set it in the env variable CODER_REMOTE in the `.env.local` file" + ) + process.exit(1) + } + + const [remote, remoteFolder] = buildSyncValue.split(":") + + const target = [remote, remoteFolder || defaultCoderWorkspaceFolder] + .filter(Boolean) + .join(":") + + extraPlugins.push( + buildSyncPlugin({ + target, + }) + ) +} +/* ------------ Build sync end ------*/ + +if (process.env.BUILD_TYPES) { + extraPlugins.push( + dts({ + include: ["lib", "src"], + exclude: ["**/*.stories.tsx"], + rollupTypes: true, + }) + ) +} // https://vitejs.dev/config/ export default defineConfig({ - plugins: [ - react(), - libInjectCss(), - ...(process.env.BUILD_TYPES - ? [ - dts({ - include: ["lib", "src"], - exclude: ["**/*.stories.tsx"], - rollupTypes: true - }), - ] - : []), - ], + plugins: [react(), libInjectCss(), ...extraPlugins], resolve: { alias: { "@": path.resolve(__dirname, "./lib"), @@ -37,9 +76,11 @@ export default defineConfig({ }, formats: ["es"], }, + outDir: "dist/lib", copyPublicDir: false, rollupOptions: { external: ["react/jsx-runtime", "react", "react-dom"], + maxParallelFileOps: 100, // Workaround to fix rebuild https://github.com/vitejs/vite/issues/19410#issuecomment-2661835482 output: { globals: { react: "React", @@ -49,6 +90,6 @@ export default defineConfig({ }, test: { environment: "jsdom", - setupFiles: ["./vitest.setup.ts"], + setupFiles: ["./vite/vitest.setup.ts"], }, }) diff --git a/vite/build-sync.plugin.ts b/vite/build-sync.plugin.ts new file mode 100644 index 000000000..82760ab7e --- /dev/null +++ b/vite/build-sync.plugin.ts @@ -0,0 +1,78 @@ +import chalk from "chalk" +import { consola } from "consola" +import { readFileSync } from "fs" +import { spawnSync } from "node:child_process" +import { existsSync } from "node:fs" +import { resolve } from "path" +import { UserConfig } from "vite" + +const consolaPrefix = chalk.cyanBright("[Sync plugin]") + +type CoderSyncPluginConfig = { + sources?: string[] + target: string +} + +/** + * @description Sync plugin + * This plugin will syncronize the build files between the local and the remote server (coder) + * The list of the files and folders to sync is defined in the package.json file in the attribute "files" + * The target is the remote server where the files will be copied + */ +export function buildSyncPlugin(pluginConfig: CoderSyncPluginConfig) { + consola.info("Sync plugin") + + let enabled = true + let sources = pluginConfig.sources + // If no sources are defined, use the package.json files attribute + if (!sources) { + consola.info("Using package.json files attribute as source") + const packageJsonPath = resolve(__dirname, "../package.json") + const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")) + sources = [...packageJson.files, packageJsonPath] + } + + sources = sources.filter((source) => Boolean(source) && existsSync(source)) + + consola.debug(consolaPrefix, sources) + + return { + name: "coder-sync", + description: "Sync files to remote server after build", + config(config: UserConfig, { command }: { command: string }) { + if (command !== "build" && !config.build?.watch) { + console.warn( + 'The buildSync plugin can only be used in "build" mode and "watch". Skipping...' + ) + enabled = false + } + }, + closeBundle: async () => { + if (!enabled) { + return + } + + consola.start( + consolaPrefix, + `Syncing files to ${chalk.whiteBright.bold(pluginConfig.target)}` + ) + try { + const start = Date.now() + spawnSync("rsync", [ + "-avz", + "--delete", + ...sources, + pluginConfig.target, + ]) + consola.success( + consolaPrefix, + "Files synced in ", + Date.now() - start, + "ms" + ) + } catch (error) { + consola.error(consolaPrefix, "Error syncing files", error) + } + }, + } +} diff --git a/vitest.setup.ts b/vite/vitest.setup.ts similarity index 100% rename from vitest.setup.ts rename to vite/vitest.setup.ts