├── .prettierignore ├── lerna.json ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── stale.yml ├── PULL_REQUEST_TEMPLATE.md ├── workflows │ ├── twitter-release.yml │ └── codeql-analysis.yml └── CONTRIBUTING.md ├── packages ├── vite-plugin-pilet │ ├── tsconfig.json │ ├── src │ │ ├── types.ts │ │ ├── index.ts │ │ └── banner.ts │ ├── LICENSE │ └── package.json └── piral-cli-vite │ ├── src │ ├── index.ts │ ├── actions.ts │ └── vite │ │ ├── common.ts │ │ ├── bundler-run.ts │ │ ├── pilet.ts │ │ └── piral.ts │ ├── tsconfig.json │ ├── LICENSE │ ├── package.json │ └── README.md ├── .editorconfig ├── prettier.config.js ├── tsconfig.json ├── LICENSE ├── tslint.json ├── package.json ├── CHANGELOG.md ├── README.md ├── .gitignore ├── tools └── changelog-version.js ├── CODE_OF_CONDUCT.md └── azure-pipelines.yml /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | package-lock.json 3 | src/**/node_modules 4 | src/**/lib 5 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "useWorkspaces": true, 4 | "version": "1.3.0" 5 | } 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [smapiot, FlorianRappl] 4 | -------------------------------------------------------------------------------- /packages/vite-plugin-pilet/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "include": [ 7 | "./src" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | end_of_line = lf 10 | max_line_length = null 11 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 120, 3 | singleQuote: true, 4 | trailingComma: 'all', 5 | bracketSpacing: true, 6 | parser: 'typescript', 7 | semi: true, 8 | jsxBracketSameLine: true, 9 | }; 10 | -------------------------------------------------------------------------------- /packages/piral-cli-vite/src/index.ts: -------------------------------------------------------------------------------- 1 | import * as actions from './actions'; 2 | import type { CliPlugin } from 'piral-cli'; 3 | 4 | const plugin: CliPlugin = (cli) => { 5 | cli.withBundler('vite', actions); 6 | }; 7 | 8 | module.exports = plugin; 9 | -------------------------------------------------------------------------------- /packages/piral-cli-vite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "allowSyntheticDefaultImports": true, 6 | "esModuleInterop": true 7 | }, 8 | "include": [ 9 | "./src" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /packages/vite-plugin-pilet/src/types.ts: -------------------------------------------------------------------------------- 1 | import type { SharedDependency } from 'piral-cli'; 2 | 3 | export interface PiletPluginOptions { 4 | id: string; 5 | debug: boolean; 6 | importmap: Array; 7 | requireRef: string; 8 | piletName: string; 9 | schema: 'v2' | 'v3'; 10 | } 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Issue Templates 2 | 3 | Please use one of the following templates to create your issue: 4 | 5 | - [Bug report](https://github.com/smapiot/piral-cli-vite/issues/new?template=bug_report.md) 6 | - [Feature proposal](https://github.com/smapiot/piral-cli-vite/issues/new?template=feature_request.md) 7 | 8 | In case of questions please either use [our Gitter chat room](https://gitter.im/piral-io/community) or (preferably) [the Piral tag on StackOverflow](https://stackoverflow.com/questions/tagged/piral). 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "noImplicitAny": false, 6 | "removeComments": false, 7 | "jsx": "react", 8 | "noLib": false, 9 | "moduleResolution": "node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "skipLibCheck": true, 13 | "target": "ES2020", 14 | "sourceMap": true, 15 | "lib": ["es6", "dom", "esnext"] 16 | }, 17 | "exclude": [ 18 | "dist", 19 | "node_modules", 20 | "**/*.test.ts", 21 | "**/*.test.tsx", 22 | "packages/**/node_modules", 23 | "packages/**/lib" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'enhancement' 6 | assignees: '' 7 | --- 8 | 9 | # New Feature Proposal 10 | 11 | For more information, see the `CONTRIBUTING` guide. 12 | 13 | ## Description 14 | 15 | [Description of the proposed feature] 16 | 17 | ## Background 18 | 19 | [Provide any additional background for the feature, e.g., why is the current solution insufficient, what problem will it solve, etc.] 20 | 21 | ## Discussion 22 | 23 | [Optionally, outline any pros and cons you can currently think of to provide the basis for a solid discussion] 24 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 21 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - in-review 8 | - in-testing 9 | - in-implementation 10 | - information 11 | - spike 12 | - help wanted 13 | # Label to use when marking an issue as stale 14 | staleLabel: wontfix 15 | # Comment to post when marking an issue as stale. Set to `false` to disable 16 | markComment: > 17 | This issue has been automatically marked as stale because it has not had 18 | recent activity. It will be closed if no further activity occurs. Thank you 19 | for your contributions. 20 | # Comment to post when closing a stale issue. Set to `false` to disable 21 | closeComment: false -------------------------------------------------------------------------------- /packages/piral-cli-vite/src/actions.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | import type { 3 | DebugPiletBundlerDefinition, 4 | DebugPiralBundlerDefinition, 5 | BuildPiletBundlerDefinition, 6 | BuildPiralBundlerDefinition, 7 | WatchPiralBundlerDefinition, 8 | } from 'piral-cli'; 9 | 10 | export const debugPiral: DebugPiralBundlerDefinition = { 11 | path: resolve(__dirname, 'vite', 'piral.js'), 12 | }; 13 | 14 | export const watchPiral: WatchPiralBundlerDefinition = { 15 | path: resolve(__dirname, 'vite', 'piral.js'), 16 | }; 17 | 18 | export const buildPiral: BuildPiralBundlerDefinition = { 19 | path: resolve(__dirname, 'vite', 'piral.js'), 20 | }; 21 | 22 | export const debugPilet: DebugPiletBundlerDefinition = { 23 | path: resolve(__dirname, 'vite', 'pilet.js'), 24 | }; 25 | 26 | export const buildPilet: BuildPiletBundlerDefinition = { 27 | path: resolve(__dirname, 'vite', 'pilet.js'), 28 | }; 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | --- 8 | 9 | # Bug Report 10 | 11 | For more information, see the `CONTRIBUTING` guide. 12 | 13 | ## Prerequisites 14 | 15 | - [ ] Can you reproduce the problem in a [MWE](https://en.wikipedia.org/wiki/Minimal_working_example)? 16 | - [ ] Are you running the latest version? 17 | - [ ] Did you perform a search in the issues? 18 | 19 | ## Environment Details and Version 20 | 21 | [Package Version, OS, Browser, ...] 22 | 23 | ## Description 24 | 25 | [Description of the bug] 26 | 27 | ## Steps to Reproduce 28 | 29 | 1. [First Step] 30 | 2. [next step...] 31 | 32 | ## Expected behavior 33 | 34 | [What you expected to happen] 35 | 36 | ## Actual behavior 37 | 38 | [What actually happened] 39 | 40 | ## Possible Origin / Solution 41 | 42 | [Optionally, share your idea to fix the issue] 43 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # New Pull Request 2 | 3 | For more information, see the `CONTRIBUTING` guide. 4 | 5 | ## Prerequisites 6 | 7 | Please make sure you can check the following boxes: 8 | 9 | - [ ] I have read the **CONTRIBUTING** document 10 | - [ ] My code follows the code style of this project 11 | - [ ] All new and existing tests passed 12 | 13 | ## Type(s) of Changes 14 | 15 | ### Contribution Type 16 | 17 | What types of changes does your code introduce? Put an `x` in all the boxes that apply: 18 | 19 | - [ ] Bug fix (non-breaking change which fixes an issue, please reference the issue id) 20 | - [ ] New feature (non-breaking change which adds functionality, make sure to open an associated issue first) 21 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 22 | - [ ] I have updated the documentation accordingly 23 | - [ ] I have added tests to cover my changes 24 | 25 | ### Description 26 | 27 | [Place a meaningful description here] 28 | 29 | ### Remarks 30 | 31 | [Optionally place any follow-up comments, remarks, observations, or notes here for future reference] 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 - 2025 smapiot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/piral-cli-vite/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 - 2025 smapiot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/vite-plugin-pilet/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 - 2025 smapiot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-prettier" 4 | ], 5 | "rulesDirectory": [ 6 | "tslint-plugin-prettier" 7 | ], 8 | "rules": { 9 | "prettier": true, 10 | "prefer-for-of": true, 11 | "curly": [ 12 | true, 13 | "ignore-same-line" 14 | ], 15 | "no-duplicate-variable": true, 16 | "no-null-keyword": true, 17 | "no-string-literal": true, 18 | "no-var-keyword": true, 19 | "radix": true, 20 | "triple-equals": [ 21 | true, 22 | "allow-undefined-check" 23 | ], 24 | "array-type": [ 25 | true, 26 | "generic" 27 | ], 28 | "arrow-return-shorthand": true, 29 | "no-consecutive-blank-lines": true, 30 | "one-variable-per-declaration": [ 31 | true, 32 | "ignore-for-loop" 33 | ], 34 | "indent": [ 35 | true, 36 | "spaces", 37 | 2 38 | ], 39 | "variable-name": [ 40 | true, 41 | "ban-keywords", 42 | "check-format", 43 | "allow-pascal-case", 44 | "allow-leading-underscore" 45 | ], 46 | "no-eval": true, 47 | "prefer-const": true, 48 | "import-blacklist": [true, "styled-components"] 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /.github/workflows/twitter-release.yml: -------------------------------------------------------------------------------- 1 | name: tweet-release 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | 8 | jobs: 9 | tweet: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: smapiot/send-tweet-v2-action@v1 13 | name: Tweet new release 14 | with: 15 | status: "New ${{ github.event.repository.name }} release ${{ github.event.release.tag_name }}! ${{ github.event.release.html_url }} #microfrontends #piral #cli #vite #release" 16 | consumer-key: ${{ secrets.TWITTER_CONSUMER_API_KEY }} 17 | consumer-secret: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} 18 | access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }} 19 | access-token-secret: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} 20 | - uses: smapiot/send-bluesky-post-action@v2 21 | name: Bluesky post new release 22 | with: 23 | status: "New ${{ github.event.repository.name }} release ${{ github.event.release.tag_name }}! ${{ github.event.release.html_url }} #microfrontends #piral #cli #vite #release" 24 | bluesky-email: ${{ secrets.BLUESKY_EMAIL }} 25 | bluesky-password: ${{ secrets.BLUESKY_PASSWORD }} 26 | -------------------------------------------------------------------------------- /packages/piral-cli-vite/src/vite/common.ts: -------------------------------------------------------------------------------- 1 | import type { InlineConfig } from 'vite'; 2 | import codegen from 'vite-plugin-codegen'; 3 | import environment from 'vite-plugin-environment'; 4 | 5 | export function createCommonConfig( 6 | root: string, 7 | outDir: string, 8 | develop = true, 9 | sourcemap = true, 10 | minify = true, 11 | variables: Record = {}, 12 | ): InlineConfig { 13 | const varKeys = Object.keys({ 14 | BUILD_PCKG_NAME: process.env.BUILD_PCKG_NAME, 15 | BUILD_PCKG_VERSION: process.env.BUILD_PCKG_VERSION, 16 | BUILD_TIME_FULL: process.env.BUILD_TIME_FULL, 17 | PIRAL_CLI_VERSION: process.env.PIRAL_CLI_VERSION, 18 | NODE_ENV: process.env.NODE_ENV, 19 | ...variables, 20 | }); 21 | return { 22 | root, 23 | build: { 24 | outDir, 25 | sourcemap, 26 | emptyOutDir: false, 27 | minify, 28 | rollupOptions: { 29 | output: { 30 | assetFileNames: '[name].[hash][extname]', 31 | chunkFileNames: '[name].[hash].js', 32 | entryFileNames: '[name].[hash].js', 33 | }, 34 | }, 35 | }, 36 | plugins: [environment(varKeys), codegen({ outDir, rootDir: root })], 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /packages/piral-cli-vite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "piral-cli-vite", 3 | "version": "1.3.0", 4 | "description": "Provides debug and build capabilities for pilets and Piral instances using Vite.", 5 | "keywords": [ 6 | "piral-cli", 7 | "piral", 8 | "plugin", 9 | "vite", 10 | "build", 11 | "debug", 12 | "bundle" 13 | ], 14 | "author": "smapiot", 15 | "homepage": "https://piral.io", 16 | "license": "MIT", 17 | "main": "lib/index.js", 18 | "typings": "lib/index.d.ts", 19 | "engines": { 20 | "node": ">=16.0" 21 | }, 22 | "files": [ 23 | "lib", 24 | "src" 25 | ], 26 | "funding": { 27 | "type": "github", 28 | "url": "https://github.com/sponsors/smapiot" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "git+https://github.com/smapiot/piral-cli-vite.git" 33 | }, 34 | "bugs": { 35 | "url": "https://github.com/smapiot/piral-cli-vite/issues" 36 | }, 37 | "scripts": { 38 | "build": "tsc" 39 | }, 40 | "devDependencies": { 41 | "@types/node": "^16", 42 | "@types/yargs": "^17", 43 | "piral-cli": "1.7.3" 44 | }, 45 | "dependencies": { 46 | "cheerio": "^1", 47 | "sass": "^1.54.0", 48 | "vite": "^4", 49 | "vite-plugin-codegen": "^2", 50 | "vite-plugin-environment": "^1.1.2", 51 | "vite-plugin-pilet": "^1.3.0" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "piral-cli-vite-packages", 3 | "private": true, 4 | "workspaces": [ 5 | "packages/*" 6 | ], 7 | "scripts": { 8 | "bootstrap": "lerna clean --yes && lerna bootstrap", 9 | "setup": "yarn bootstrap", 10 | "build": "lerna run build", 11 | "lint": "tslint -c tslint.json 'src/**/*.{ts,tsx}' --project tsconfig.json", 12 | "prettify": "prettier --config prettier.config.js --write \"src/**/*.{ts,tsx}\"", 13 | "prepublish": "yarn build", 14 | "release": "lerna publish", 15 | "ci:version": "node tools/changelog-version.js", 16 | "ci:version-update": "yarn ci:version --update && git add CHANGELOG.md && git commit -m UpdateReleaseDate", 17 | "ci:canary": "lerna publish $(yarn --silent ci:version)-alpha.$BUILD_BUILDID --exact --yes --force-publish --no-git-tag-version --no-push --dist-tag canary && git checkout -- .", 18 | "ci:prerelease": "lerna publish $(yarn --silent ci:version)-beta.$BUILD_BUILDID --exact --yes --force-publish --no-git-tag-version --no-push --dist-tag next && git checkout -- .", 19 | "ci:release": "lerna publish $(yarn --silent ci:version) --yes --force-publish --message '[skip ci] publish %s'" 20 | }, 21 | "devDependencies": { 22 | "lerna": "^6", 23 | "prettier": "^2.1.1", 24 | "tslint": "^5.12.1", 25 | "tslint-config-prettier": "^1.18.0", 26 | "tslint-plugin-prettier": "^2.0.1", 27 | "typescript": "^5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/piral-cli-vite/src/vite/bundler-run.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events'; 2 | import { InlineConfig, build } from 'vite'; 3 | 4 | interface ViteConfig extends InlineConfig { 5 | debug: boolean; 6 | outFile: string; 7 | requireRef?: string; 8 | } 9 | 10 | export function runVite(options: ViteConfig) { 11 | const { debug, outFile, requireRef, ...config } = options; 12 | const eventEmitter = new EventEmitter(); 13 | const bundle = { 14 | outFile: `/${outFile}`, 15 | outDir: config.build.outDir, 16 | name: outFile, 17 | requireRef, 18 | }; 19 | 20 | return Promise.resolve({ 21 | async bundle() { 22 | if (debug) { 23 | config.build.watch = {}; 24 | } 25 | 26 | const watcher = await build(config); 27 | 28 | if (debug && 'on' in watcher) { 29 | watcher.on('event', (event) => { 30 | if (event.code === 'ERROR') { 31 | console.error(event); 32 | } else if (event.code === 'BUNDLE_START') { 33 | console.info('Bundling ...'); 34 | } else if (event.code === 'BUNDLE_END') { 35 | event.result.close(); 36 | console.info('Bundled!'); 37 | } else if (event.code === 'END') { 38 | eventEmitter.emit('end', bundle); 39 | } 40 | }); 41 | 42 | eventEmitter.emit('start', bundle); 43 | } 44 | 45 | return bundle; 46 | }, 47 | onStart(cb) { 48 | eventEmitter.on('start', cb); 49 | }, 50 | onEnd(cb) { 51 | eventEmitter.on('end', cb); 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.3.1 (tbd) 4 | 5 | - Improved transformation of *index.html* 6 | 7 | ## 1.3.0 (December 26, 2024) 8 | 9 | - Use new codegen plugin 10 | 11 | ## 1.2.1 (December 4, 2024) 12 | 13 | - Improved types of `vite-plugin-codegen` and `vite-plugin-pilet` 14 | 15 | ## 1.2.0 (August 31, 2024) 16 | 17 | - Updated the Vite plugins to work with ESM and CJS 18 | 19 | ## 1.1.1 (February 29, 2024) 20 | 21 | - Fixed support for `vite.config.js` in execution root of `piral build` (#7) 22 | 23 | ## 1.1.0 (February 8, 2024) 24 | 25 | - Improved the documentation 26 | - Added support for standard `vite.config.js` (or alternatives, e.g., `vite.config.ts`) within Vite (#7) 27 | - Added support for pilet schema `v3` 28 | 29 | ## 1.0.3 (November 18, 2023) 30 | 31 | - Fixed invalid reference to CSS stylesheet in pilet (#5) 32 | 33 | ## 1.0.2 (November 16, 2023) 34 | 35 | - Fixed double usage of `vite.config.js` (#4) 36 | - Added `process.env.NODE_ENV` to automatically exposed variables 37 | 38 | ## 1.0.1 (November 8, 2023) 39 | 40 | - Fixed support for source maps in pilets (#3) 41 | 42 | ## 1.0.0 (July 6, 2023) 43 | 44 | - Fixed support in `piral-cli` 1.0.0 (#2) 45 | - Fixed issue to support Angular 16 (#1) 46 | - Updated to use Vite v4 47 | 48 | ## 0.15.2 (July 6, 2023) 49 | 50 | - Changed standard configuration to place assets directly in output folder 51 | 52 | ## 0.15.1 (January 17, 2023) 53 | 54 | - Fixed issue with `vite-plugin-codegen` to have static options 55 | - Fixed empty outdir - will be cleaned up by `piral-cli` 56 | 57 | ## 0.15.0 (November 17, 2022) 58 | 59 | - Initial release 60 | -------------------------------------------------------------------------------- /packages/vite-plugin-pilet/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-plugin-pilet", 3 | "version": "1.3.0", 4 | "description": "Adds support for pilet output in Vite", 5 | "keywords": [ 6 | "vite", 7 | "pilet", 8 | "piral", 9 | "microfrontends", 10 | "plugin" 11 | ], 12 | "author": "smapiot", 13 | "homepage": "https://piral.io", 14 | "license": "MIT", 15 | "type": "module", 16 | "main": "lib/cjs/index.cjs", 17 | "module": "lib/esm/index.mjs", 18 | "typings": "src/index.ts", 19 | "engines": { 20 | "node": ">=16.0" 21 | }, 22 | "exports": { 23 | ".": { 24 | "import": "./lib/esm/index.mjs", 25 | "require": "./lib/cjs/index.cjs", 26 | "types": "./src/index.ts" 27 | }, 28 | "./package.json": "./package.json" 29 | }, 30 | "funding": { 31 | "type": "github", 32 | "url": "https://github.com/sponsors/smapiot" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/smapiot/piral-cli-vite.git" 37 | }, 38 | "bugs": { 39 | "url": "https://github.com/smapiot/piral-cli-vite/issues" 40 | }, 41 | "files": [ 42 | "lib", 43 | "src" 44 | ], 45 | "scripts": { 46 | "test": "tsc --noEmit", 47 | "build": "npm run build:cjs && npm run build:esm", 48 | "build:cjs": "esbuild 'src/index.ts' --sourcemap --bundle --packages=external --platform=node --format=cjs --out-extension:.js=.cjs --outdir=lib/cjs", 49 | "build:esm": "esbuild 'src/index.ts' --sourcemap --bundle --packages=external --platform=node --format=esm --out-extension:.js=.mjs --outdir=lib/esm" 50 | }, 51 | "dependencies": { 52 | "@jridgewell/sourcemap-codec": "^1.4.15", 53 | "magic-string": "^0.30.5" 54 | }, 55 | "devDependencies": { 56 | "piral-cli": "1.7.3", 57 | "vite": "^4" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/vite-plugin-pilet/src/index.ts: -------------------------------------------------------------------------------- 1 | import MagicString from 'magic-string'; 2 | import { decode, encode } from '@jridgewell/sourcemap-codec'; 3 | import type { Plugin } from 'vite'; 4 | import { insertStylesheet, modifyImports, prependBanner } from './banner'; 5 | import type { PiletPluginOptions } from './types'; 6 | 7 | export { PiletPluginOptions }; 8 | 9 | export default function pilet({ id, debug, piletName, importmap, requireRef, schema }: PiletPluginOptions): Plugin { 10 | const cssFiles: Array = []; 11 | 12 | return { 13 | name: 'pilet', 14 | transform(_, id) { 15 | if (id.endsWith('.css') || id.endsWith('.scss') || id.endsWith('.sass')) { 16 | cssFiles.push(id); 17 | } 18 | }, 19 | generateBundle(_, bundle) { 20 | Object.keys(bundle).forEach((file) => { 21 | const asset = bundle[file]; 22 | 23 | if (asset.type === 'chunk' && asset.isEntry && asset.name === id) { 24 | const sm = bundle[`${file}.map`]; 25 | const ms = new MagicString(asset.code); 26 | prependBanner(ms, requireRef, importmap, schema); 27 | asset.code = ms.toString(); 28 | 29 | if (sm && 'source' in sm && typeof sm.source === 'string') { 30 | // shift source map by a single (unmapped) line 31 | const map = JSON.parse(sm.source); 32 | const arr = decode(map.mappings); 33 | arr.unshift([]); 34 | map.mappings = encode(arr); 35 | sm.source = JSON.stringify(map); 36 | } 37 | } 38 | }); 39 | }, 40 | renderChunk(content, asset) { 41 | const ms = new MagicString(content); 42 | modifyImports(ms, importmap); 43 | 44 | if (asset.isEntry && asset.name === id && cssFiles.length) { 45 | insertStylesheet(ms, piletName, debug, schema); 46 | } 47 | 48 | return { 49 | code: ms.toString(), 50 | map: ms.generateMap({ hires: true }), 51 | }; 52 | }, 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Piral Logo](https://github.com/smapiot/piral/raw/main/docs/assets/logo.png)](https://piral.io) 2 | 3 | # piral-cli-vite · [![Build Status](https://smapiot.visualstudio.com/piral-pipelines/_apis/build/status/smapiot.piral-cli-vite?branchName=develop)](https://smapiot.visualstudio.com/piral-pipelines/_build/latest?definitionId=109&branchName=develop) ![GitHub License](https://img.shields.io/badge/license-MIT-blue.svg) 4 | 5 | The `piral-cli` plugin for using `vite` as bundler. 6 | 7 | ## Important Links 8 | 9 | * 📢 **[We are hiring!](https://smapiot.com/jobs)** - work with us on Piral, its ecosystem and our users 10 | * 🌍 [Website](https://piral.io/) - learn more about Piral 11 | * 📖 [Documentation](https://docs.piral.io/) - everything to get started and master micro frontends 12 | * 🉐 **Help translating Piral!** - making PRs in the [documentation branch](https://github.com/smapiot/piral/tree/documentation) 13 | * 🐞 [Issue Tracker](https://github.com/smapiot/piral/issues) - report bugs or suggest new features 14 | * 🗨 [Forums](https://stackoverflow.com/questions/tagged/piral) - use the community support on StackOverflow 15 | * 👪 [Community Chat](https://gitter.im/piral-io/community) - ask questions and provide answers in our Gitter room 16 | 17 | ## Status 18 | 19 | * [x] Pilets (tested / working) 20 | * [x] Codegen 21 | * [x] Bundle Splitting 22 | * [x] ESM output 23 | * [x] CSS / SASS 24 | * [x] Importmap references 25 | * [x] Importmap bundles 26 | * [ ] v0 format (not implemented) 27 | * [ ] v1 format (not implemented) 28 | * [x] v2 format 29 | * [x] v3 format 30 | * [x] tsconfig changes 31 | * [x] Building 32 | * [x] Debugging 33 | * [x] Reloading 34 | * [x] Piral instances (tested / working) 35 | * [x] Codegen 36 | * [x] HTML entry point 37 | * [x] Emulator build 38 | * [x] Release build 39 | * [x] tsconfig changes 40 | * [x] Debugging 41 | * [x] Reloading 42 | 43 | ## License 44 | 45 | This code is released using the MIT license. For more information see the [LICENSE file](LICENSE). 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | packages/*/lib 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # TypeScript v1 declaration files 46 | typings/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Microbundle cache 58 | .rpt2_cache/ 59 | .rts2_cache_cjs/ 60 | .rts2_cache_es/ 61 | .rts2_cache_umd/ 62 | 63 | # Optional REPL history 64 | .node_repl_history 65 | 66 | # Output of 'npm pack' 67 | *.tgz 68 | 69 | # Yarn Integrity file 70 | .yarn-integrity 71 | 72 | # dotenv environment variables file 73 | .env 74 | .env.test 75 | 76 | # parcel-bundler cache (https://parceljs.org/) 77 | .cache 78 | 79 | # Next.js build output 80 | .next 81 | 82 | # Nuxt.js build / generate output 83 | .nuxt 84 | dist 85 | 86 | # Gatsby files 87 | .cache/ 88 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 89 | # https://nextjs.org/blog/next-9-1#public-directory-support 90 | # public 91 | 92 | # vuepress build output 93 | .vuepress/dist 94 | 95 | # Serverless directories 96 | .serverless/ 97 | 98 | # FuseBox cache 99 | .fusebox/ 100 | 101 | # DynamoDB Local files 102 | .dynamodb/ 103 | 104 | # TernJS port file 105 | .tern-port 106 | -------------------------------------------------------------------------------- /tools/changelog-version.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | const { execSync } = require('child_process'); 3 | const { readFileSync, writeFileSync } = require('fs'); 4 | 5 | const defaultPath = join(__dirname, '..', 'CHANGELOG.md'); 6 | 7 | function getChangelogVersion(changelogPath = defaultPath) { 8 | const CHANGELOG = readFileSync(changelogPath, 'utf8'); 9 | const matches = /^\#\# (\d+\.\d+\.\d+) .*/gm.exec(CHANGELOG); 10 | 11 | if (!matches) { 12 | throw new Error('Invalid CHANGELOG format found. Need to fine line starting with "## x.y.z" to get the latest version.'); 13 | } 14 | 15 | const version = matches[1]; 16 | return version; 17 | } 18 | 19 | function updateChangelogDate(changelogPath = defaultPath) { 20 | const CHANGELOG = readFileSync(changelogPath, 'utf8'); 21 | const matches = /^\#\# (\d+\.\d+\.\d+) .*/gm.exec(CHANGELOG); 22 | const date = new Date().toLocaleDateString('en-us', { 23 | month: 'long', 24 | year: 'numeric', 25 | day: 'numeric', 26 | }); 27 | const newContent = CHANGELOG.replace(matches[0], `## ${matches[1]} (${date})`); 28 | writeFileSync(changelogPath, newContent, 'utf8'); 29 | } 30 | 31 | function getVersion(full, flags) { 32 | const id = process.env.BUILD_BUILDID || '0'; 33 | 34 | if (flags.includes('--beta')) { 35 | return `${full}-beta.${id}`; 36 | } else if (flags.includes('--alpha')) { 37 | return `${full}-alpha.${id}`; 38 | } 39 | 40 | return full; 41 | } 42 | 43 | if (require.main === module) { 44 | const args = process.argv; 45 | const changelogVersion = getChangelogVersion(); 46 | const version = getVersion(changelogVersion, args); 47 | const cwd = process.cwd(); 48 | console.log(version); 49 | 50 | if (args.includes('--update')) { 51 | updateChangelogDate(); 52 | } else if (args.includes('--apply')) { 53 | execSync(`lerna version ${version} --no-git-tag-version --yes`, { 54 | cwd, 55 | stdio: 'inherit', 56 | shell: true, 57 | env: { 58 | ...process.env, 59 | PATH: `${process.env.PATH}:${cwd}/node_modules/.bin`, 60 | }, 61 | }); 62 | } 63 | } else { 64 | module.exports = { 65 | getChangelogVersion, 66 | updateChangelogDate, 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /packages/vite-plugin-pilet/src/banner.ts: -------------------------------------------------------------------------------- 1 | import MagicString from 'magic-string'; 2 | import type { SharedDependency } from 'piral-cli'; 3 | import { PiletPluginOptions } from './types'; 4 | 5 | export function modifyImports(ms: MagicString, dependencies: Array) { 6 | ms.replace(/\[.*?\]/, (s) => { 7 | dependencies.forEach((dep) => { 8 | const depRef = (dep as any).requireId || dep.id; 9 | s = s.replace(`'${dep.name}'`, `'${depRef}'`); 10 | }); 11 | 12 | return s; 13 | }); 14 | } 15 | 16 | export function prependBanner( 17 | ms: MagicString, 18 | requireRef: string, 19 | dependencies: Array, 20 | schema: PiletPluginOptions['schema'], 21 | ) { 22 | const deps = dependencies.reduce((deps, dep) => { 23 | deps[dep.id] = dep.ref; 24 | return deps; 25 | }, {}); 26 | 27 | if (schema === 'v2') { 28 | ms.prepend(`//@pilet v:2(${requireRef},${JSON.stringify(deps)})\n`); 29 | } else if (schema === 'v3') { 30 | ms.prepend(`//@pilet v:3(${requireRef},${JSON.stringify(deps)})\n`); 31 | } 32 | } 33 | 34 | export function insertStylesheet(ms: MagicString, name: string, debug: boolean, schema: PiletPluginOptions['schema']) { 35 | if (schema === 'v2') { 36 | const bundleUrl = `function(){try{throw new Error}catch(t){const e=(""+t.stack).match(/(https?|file|ftp|chrome-extension|moz-extension):\\/\\/[^)\\n]+/g);if(e)return e[0].replace(/^((?:https?|file|ftp|chrome-extension|moz-extension):\\/\\/.+)\\/[^\\/]+$/,"$1")+"/"}return"/"}`; 37 | const cssFiles = ['style.css']; 38 | const stylesheet = [ 39 | `var d=document`, 40 | `var __bundleUrl__=(${bundleUrl})()`, 41 | `${JSON.stringify(cssFiles)}.forEach(cf=>{`, 42 | ` var u=__bundleUrl__+cf`, 43 | ` var e=d.createElement("link")`, 44 | ` e.setAttribute('data-origin', ${JSON.stringify(name)})`, 45 | ` e.type="text/css"`, 46 | ` e.rel="stylesheet"`, 47 | ` e.href=${debug ? 'u+"?_="+Math.random()' : 'u'}`, 48 | ` d.head.appendChild(e)`, 49 | `})`, 50 | ].join(';\n '); 51 | const insertLink = `(function(){\n ${stylesheet};\n})()`; 52 | const execute = 'execute: (function () {'; 53 | ms.replace(execute, `${execute}\n${insertLink}`); 54 | } else if (schema === 'v3') { 55 | const cssFiles = ['style.css']; 56 | const execute = 'execute: (function () {'; 57 | const insertLink = `exports("styles", ${JSON.stringify(cssFiles)})`; 58 | ms.replace(execute, `${execute}\n${insertLink}`); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ develop, main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ develop ] 20 | schedule: 21 | - cron: '19 3 * * 1' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'javascript' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /packages/piral-cli-vite/src/vite/pilet.ts: -------------------------------------------------------------------------------- 1 | import pilet from 'vite-plugin-pilet'; 2 | import type { PiletBuildHandler } from 'piral-cli'; 3 | import { createCommonConfig } from './common'; 4 | import { runVite } from './bundler-run'; 5 | 6 | function nameOf(path: string) { 7 | return path.replace(/\.js$/, ''); 8 | } 9 | 10 | function getPackageName() { 11 | return process.env.BUILD_PCKG_NAME; 12 | } 13 | 14 | function getRequireRef() { 15 | const name = getPackageName(); 16 | return `rolluppr_${name.replace(/\W/gi, '')}`; 17 | } 18 | 19 | const supportedSchemas = ['v2', 'v3']; 20 | 21 | function checkSupported(schema: string): asserts schema is 'v2' | 'v3' { 22 | if (!supportedSchemas.includes(schema)) { 23 | throw new Error( 24 | `The provided schema version is not supported. This version supports: ${supportedSchemas.join(', ')}.`, 25 | ); 26 | } 27 | } 28 | 29 | const handler: PiletBuildHandler = { 30 | create(options) { 31 | const schema = options.version; 32 | const piletName = getPackageName(); 33 | const requireRef = getRequireRef(); 34 | const external: Array = []; 35 | const id = nameOf(options.outFile); 36 | const input = { 37 | [id]: options.entryModule, 38 | }; 39 | 40 | // first populate with global externals 41 | options.externals.forEach((name) => { 42 | external.push(name); 43 | }); 44 | 45 | // then populate with distributed externals 46 | options.importmap.forEach((dep) => { 47 | external.push(dep.name); 48 | }); 49 | 50 | // finally add the local importmap entries to the bundler entry points 51 | options.importmap.forEach((dep) => { 52 | if (dep.type === 'local') { 53 | input[nameOf(dep.ref)] = dep.entry; 54 | } 55 | }); 56 | 57 | checkSupported(schema); 58 | 59 | const config = createCommonConfig(options.root, options.outDir, options.develop, options.sourceMaps, options.minify, {}); 60 | 61 | return runVite({ 62 | ...config, 63 | build: { 64 | ...config.build, 65 | lib: { 66 | entry: options.entryModule, 67 | fileName: () => options.outFile, 68 | formats: ['system' as any], 69 | }, 70 | rollupOptions: { 71 | ...config.build.rollupOptions, 72 | input, 73 | output: { 74 | ...config.build.rollupOptions.output, 75 | assetFileNames(assetInfo) { 76 | // keep name of combined stylesheet 77 | if (assetInfo.name === 'style.css') { 78 | return assetInfo.name; 79 | } 80 | 81 | return '[name].[hash][extname]'; 82 | }, 83 | entryFileNames: '[name].js', 84 | }, 85 | external, 86 | }, 87 | }, 88 | plugins: [ 89 | ...config.plugins, 90 | pilet({ 91 | id, 92 | schema, 93 | piletName, 94 | requireRef, 95 | importmap: options.importmap, 96 | debug: options.develop, 97 | }), 98 | ], 99 | debug: options.watch, 100 | outFile: options.outFile, 101 | requireRef, 102 | }); 103 | }, 104 | }; 105 | 106 | export const create = handler.create; 107 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at **contact@piral.io**. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html. 44 | 45 | [homepage]: https://www.contributor-covenant.org 46 | 47 | For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq. 48 | -------------------------------------------------------------------------------- /packages/piral-cli-vite/src/vite/piral.ts: -------------------------------------------------------------------------------- 1 | import type { PiralBuildHandler } from 'piral-cli'; 2 | import type { Plugin } from 'vite'; 3 | import { load } from 'cheerio'; 4 | import { dirname, resolve } from 'path'; 5 | import { readFileSync, readdirSync, writeFileSync } from 'fs'; 6 | 7 | import { createCommonConfig } from './common'; 8 | import { runVite } from './bundler-run'; 9 | 10 | function isLocal(path: string) { 11 | if (path) { 12 | if (path.startsWith(':')) { 13 | return false; 14 | } else if (path.startsWith('http:')) { 15 | return false; 16 | } else if (path.startsWith('https:')) { 17 | return false; 18 | } else if (path.startsWith('data:')) { 19 | return false; 20 | } 21 | 22 | return true; 23 | } 24 | 25 | return false; 26 | } 27 | 28 | function transformIndexHtml(html: string) { 29 | const rx = //gm; 30 | const replacements: Array<[string, string]> = []; 31 | 32 | while (true) { 33 | const match = rx.exec(html); 34 | 35 | if (!match) { 36 | break; 37 | } 38 | 39 | const text = match[0]; 40 | const templateContent = load(text, null, false); 41 | 42 | templateContent('script[src]') 43 | .filter((_, e) => isLocal(e.attribs.src)) 44 | .each((_, e) => { 45 | if (!e.attribs.type) { 46 | e.attribs.type = 'module'; 47 | replacements.push([text, templateContent.html()]); 48 | } 49 | }); 50 | } 51 | 52 | for (const [original, replacement] of replacements) { 53 | html = html.replace(original, replacement); 54 | } 55 | 56 | return html; 57 | } 58 | 59 | function getConfigFile(root: string) { 60 | const fileNames = ['vite.config.ts', 'vite.config.js', 'vite.config.mts', 'vite.config.mjs']; 61 | const files = readdirSync(root); 62 | 63 | for (const name of fileNames) { 64 | if (files.includes(name)) { 65 | return resolve(root, name); 66 | } 67 | } 68 | 69 | return undefined; 70 | } 71 | 72 | const handler: PiralBuildHandler = { 73 | create(options) { 74 | const rootDir = dirname(options.entryFiles); 75 | const newPlugins: Array = []; 76 | const config = createCommonConfig(rootDir, options.outDir, options.emulator, options.sourceMaps, options.minify, { 77 | DEBUG_PIRAL: process.env.DEBUG_PIRAL || (process.env.DEBUG_PIRAL = ''), 78 | DEBUG_PILET: process.env.DEBUG_PILET || (process.env.DEBUG_PILET = ''), 79 | SHARED_DEPENDENCIES: JSON.stringify(options.externals.join(',')), 80 | }); 81 | 82 | if (options.hmr) { 83 | newPlugins.push({ 84 | name: 'hmr-plugin', 85 | generateBundle(_, bundle) { 86 | if (bundle) { 87 | Object.keys(bundle).forEach((file) => { 88 | const asset = bundle[file]; 89 | 90 | if (asset.type === 'chunk' && asset.isEntry) { 91 | asset.code = `(() => new WebSocket(location.origin.replace('http', 'ws')+"/$events").onmessage = () => location.reload())();${asset.code}`; 92 | } 93 | }); 94 | } 95 | }, 96 | }); 97 | } 98 | 99 | const configFile = getConfigFile(options.root); 100 | const indexHtml = resolve(rootDir, 'index.html'); 101 | const content = readFileSync(indexHtml, 'utf8'); 102 | writeFileSync(indexHtml, transformIndexHtml(content), 'utf8'); 103 | 104 | return runVite({ 105 | ...config, 106 | configFile, 107 | plugins: [...config.plugins, ...newPlugins], 108 | debug: options.watch, 109 | outFile: options.outFile, 110 | }); 111 | }, 112 | }; 113 | 114 | export const create = handler.create; 115 | -------------------------------------------------------------------------------- /packages/piral-cli-vite/README.md: -------------------------------------------------------------------------------- 1 | [![Piral Logo](https://github.com/smapiot/piral/raw/main/docs/assets/logo.png)](https://piral.io) 2 | 3 | # [Piral CLI Vite](https://piral.io) · [![GitHub License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/smapiot/piral-cli-vite/blob/main/LICENSE) [![npm version](https://img.shields.io/npm/v/piral-cli-vite.svg?style=flat)](https://www.npmjs.com/package/piral-cli-vite) [![tested with jest](https://img.shields.io/badge/tested_with-jest-99424f.svg)](https://jestjs.io) [![Gitter Chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/piral-io/community) 4 | 5 | This plugin enables using [Vite](https://vitejs.dev/) as the bundler for Piral instances and pilets. 6 | 7 | ## Installation 8 | 9 | Use your favorite npm client for the installation: 10 | 11 | ```sh 12 | npm i piral-cli-vite --save-dev 13 | ``` 14 | 15 | **Note**: If you don't install any bundler for use in `piral-cli` then `piral-cli-vite` will be automatically installed for you. 16 | 17 | ## Using 18 | 19 | There is nothing to do. Standard commands such as `piral build` or `pilet debug` will now work with Vite as the bundler. 20 | 21 | This plugin comes with batteries included. You don't need to install or specify your Vite version. 22 | 23 | ### What's Inside 24 | 25 | Right now it includes: 26 | 27 | - `vite-plugin-codegen` 28 | - `vite-plugin-environment` 29 | 30 | Additionally, most known referenced assets are handled as files. 31 | 32 | As such it should be prepared to include assets (images, videos, ...), stylesheets (CSS and SASS), and work with TypeScript. 33 | 34 | ### Public Folder 35 | 36 | By default the source folder (e.g., `/src`) is set as root. Therefore, the `src/public` folder (if available) will be used for the public assets. If you want to change this you can use a custom Vite config as explained below, e.g.: 37 | 38 | ```js 39 | import { resolve } from 'path'; 40 | 41 | export default { 42 | publicDir: resolve(__dirname, 'public'), 43 | } 44 | ``` 45 | 46 | ### Referencing Scripts 47 | 48 | Vite uses all scripts with `type=module` to be entry points in the *index.html* file. However, as you might just have scaffolded a solution or are more used to simply have ` 54 | ``` 55 | 56 | to 57 | 58 | ```html 59 | 60 | 61 | 62 | 63 | 64 | 65 | ``` 66 | 67 | ### Customizing 68 | 69 | If you want to customize the given config (e.g., to add more plugins) then create a file *vite.config.js* (or anything else accepted by Vite, e.g., *vite.config.ts*) in your root directory. 70 | 71 | In the most trivial version the file looks as follows: 72 | 73 | ```js 74 | import { defineConfig } from 'vite'; 75 | 76 | export default defineConfig({ 77 | // Your config additions here 78 | }); 79 | ``` 80 | 81 | If you want to add some plugin you could do: 82 | 83 | ```js 84 | import { defineConfig } from "vite"; 85 | import legacy from "@vitejs/plugin-legacy"; 86 | 87 | export default defineConfig({ 88 | plugins: [ 89 | legacy({ 90 | targets: ['defaults', 'not IE 11'], 91 | }), 92 | ], 93 | }); 94 | ``` 95 | 96 | The configuration works with all formats that Vite supports. 97 | 98 | ## License 99 | 100 | Piral is released using the MIT license. For more information see the [license file](./LICENSE). 101 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | branches: 3 | include: 4 | - main 5 | - develop 6 | - experimental 7 | 8 | variables: 9 | - group: piral-deployment-variables 10 | - name: previewId 11 | value: $(Build.BuildId) 12 | - name: agentName 13 | value: 'ubuntu-latest' 14 | - name: releaseBranch 15 | value: 'main' 16 | - name: previewBranch 17 | value: 'develop' 18 | - name: canaryBranch 19 | value: 'experimental' 20 | - name: nodeVersion 21 | value: '22.5.1' 22 | 23 | stages: 24 | - stage: Build 25 | displayName: Process Code 26 | 27 | jobs: 28 | - job: BuildCode 29 | displayName: Verify and Build Code 30 | pool: 31 | vmImage: $(agentName) 32 | steps: 33 | - task: NodeTool@0 34 | displayName: Use Node $(nodeVersion) 35 | inputs: 36 | versionSpec: $(nodeVersion) 37 | - task: YarnInstaller@2 38 | displayName: Install Yarn 39 | inputs: 40 | checkLatest: true 41 | - task: Yarn@2 42 | displayName: Install Dependencies 43 | inputs: 44 | Arguments: install 45 | - task: Yarn@2 46 | displayName: Assemble Packages 47 | inputs: 48 | Arguments: setup 49 | - task: Yarn@2 50 | displayName: Test Build 51 | inputs: 52 | Arguments: build 53 | 54 | - stage: CanaryRelease 55 | 56 | displayName: Release Packages (Alpha) 57 | dependsOn: Build 58 | condition: and(succeeded(), eq(variables['Build.SourceBranchName'], variables['canaryBranch'])) 59 | 60 | jobs: 61 | - deployment: CanaryReleasePackages 62 | displayName: CanaryRelease Piral Packages 63 | condition: eq(variables['Build.SourceBranchName'], variables['canaryBranch']) 64 | pool: 65 | vmImage: $(agentName) 66 | environment: 'registry-npmjs-org' 67 | strategy: 68 | runOnce: 69 | deploy: 70 | steps: 71 | - checkout: self 72 | - task: NodeTool@0 73 | displayName: Use Node $(nodeVersion) 74 | inputs: 75 | versionSpec: $(nodeVersion) 76 | - task: YarnInstaller@2 77 | displayName: Install Yarn 78 | inputs: 79 | checkLatest: true 80 | - task: Yarn@2 81 | displayName: Install Dependencies 82 | inputs: 83 | Arguments: install 84 | - task: Yarn@2 85 | displayName: Assemble Packages 86 | inputs: 87 | Arguments: setup 88 | - task: npmAuthenticate@0 89 | inputs: 90 | workingFile: .npmrc 91 | customEndpoint: DefaultNpmConnection 92 | - task: Bash@3 93 | displayName: Configure Git 94 | inputs: 95 | targetType: inline 96 | script: >- 97 | git config --global user.email "releases@piral.io" 98 | 99 | git config --global user.name "Piral Release Bot" 100 | 101 | git checkout $(canaryBranch) 102 | 103 | git checkout -- . 104 | - task: Yarn@2 105 | displayName: Canary Packages 106 | inputs: 107 | Arguments: ci:canary 108 | customEndpoint: DefaultNpmConnection 109 | 110 | - stage: PreviewRelease 111 | 112 | displayName: Release Packages (Beta) 113 | dependsOn: Build 114 | condition: and(succeeded(), eq(variables['Build.SourceBranchName'], variables['previewBranch'])) 115 | 116 | jobs: 117 | - deployment: PreReleasePackages 118 | displayName: PreRelease Piral Packages 119 | condition: eq(variables['Build.SourceBranchName'], variables['previewBranch']) 120 | pool: 121 | vmImage: $(agentName) 122 | environment: 'registry-npmjs-org' 123 | strategy: 124 | runOnce: 125 | deploy: 126 | steps: 127 | - checkout: self 128 | - task: NodeTool@0 129 | displayName: Use Node $(nodeVersion) 130 | inputs: 131 | versionSpec: $(nodeVersion) 132 | - task: YarnInstaller@2 133 | displayName: Install Yarn 134 | inputs: 135 | checkLatest: true 136 | - task: Yarn@2 137 | displayName: Install Dependencies 138 | inputs: 139 | Arguments: install 140 | - task: Yarn@2 141 | displayName: Assemble Packages 142 | inputs: 143 | Arguments: setup 144 | - task: npmAuthenticate@0 145 | inputs: 146 | workingFile: .npmrc 147 | customEndpoint: DefaultNpmConnection 148 | - task: Bash@3 149 | displayName: Configure Git 150 | inputs: 151 | targetType: inline 152 | script: >- 153 | git config --global user.email "releases@piral.io" 154 | 155 | git config --global user.name "Piral Release Bot" 156 | 157 | git checkout $(previewBranch) 158 | 159 | git checkout -- . 160 | - task: Yarn@2 161 | displayName: Prerelease Packages 162 | inputs: 163 | Arguments: ci:prerelease 164 | customEndpoint: DefaultNpmConnection 165 | 166 | - stage: Release 167 | 168 | displayName: Release Packages 169 | dependsOn: Build 170 | condition: and(succeeded(), eq(variables['Build.SourceBranchName'], variables['releaseBranch'])) 171 | 172 | jobs: 173 | - deployment: ReleasePackages 174 | displayName: Release Piral Packages 175 | condition: eq(variables['Build.SourceBranchName'], variables['releaseBranch']) 176 | pool: 177 | vmImage: $(agentName) 178 | environment: 'registry-npmjs-org' 179 | strategy: 180 | runOnce: 181 | deploy: 182 | steps: 183 | - checkout: self 184 | - task: NodeTool@0 185 | displayName: Use Node $(nodeVersion) 186 | inputs: 187 | versionSpec: $(nodeVersion) 188 | - task: YarnInstaller@2 189 | displayName: Install Yarn 190 | inputs: 191 | checkLatest: true 192 | - task: Yarn@2 193 | displayName: Install Dependencies 194 | inputs: 195 | Arguments: install 196 | - task: Yarn@2 197 | displayName: Assemble Packages 198 | inputs: 199 | Arguments: setup 200 | - task: npmAuthenticate@0 201 | inputs: 202 | workingFile: .npmrc 203 | customEndpoint: DefaultNpmConnection 204 | - task: Bash@3 205 | displayName: Configure Git 206 | inputs: 207 | targetType: inline 208 | script: >- 209 | git config --global user.email "releases@piral.io" 210 | 211 | git config --global user.name "Piral Release Bot" 212 | 213 | git remote rm origin 214 | 215 | git remote add origin https://$(githubPersonalAccessToken)@github.com/smapiot/piral-cli-vite.git 216 | 217 | git fetch origin 218 | 219 | git checkout $(releaseBranch) 220 | 221 | git checkout -- . 222 | - task: Yarn@2 223 | displayName: Update Release Date 224 | inputs: 225 | Arguments: ci:version-update 226 | customEndpoint: DefaultNpmConnection 227 | - task: Yarn@2 228 | displayName: Release Packages 229 | inputs: 230 | Arguments: ci:release 231 | customEndpoint: DefaultNpmConnection 232 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | :tada: First off, thanks for taking the time to contribute! 4 | 5 | The following is a set of guidelines for contributing to the `piral-cli-vite` packages, which is hosted in the smapiot organization on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. 6 | 7 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. 8 | 9 | ## Code of Conduct 10 | 11 | This project and everyone participating in it is governed by the [Code of Conduct](../CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to the email specified there. 12 | 13 | ## How Can I Contribute 14 | 15 | ### Development Instructions 16 | 17 | Please find more information about how to setup your machine for developing the `piral-cli-vite` packages in [the source documentation](../README.md). 18 | 19 | ### Reporting Bugs 20 | 21 | Before creating bug report, please make sure that you first check the [existing issues](https://github.com/smapiot/piral-cli-vite/issues?q=is%3Aopen+is%3Aissue+label%3Abug), as you might find that the issue is already reported. Fill out [the required template](https://github.com/smapiot/piral-cli-vite/issues/new?template=bug_report.md), the information it asks for helps us resolve issues faster. 22 | 23 | Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer:, and find related reports :mag_right:. 24 | 25 | ### Suggesting Enhancements 26 | 27 | This section guides you through submitting an enhancement suggestion for the `piral-cli-vite` packages, including completely new features and minor improvements to existing functionality. 28 | 29 | Before creating enhancement suggestions, please make sure that you first check the [existing suggestions](https://github.com/smapiot/piral-cli-vite/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), as you might find that the enhancement has already been requested. Fill out [the template](https://github.com/smapiot/piral-cli-vite/issues/new?template=feature_request.md), including the steps that you imagine you would take if the feature you're requesting existed. 30 | 31 | #### How Do I Submit a Suggestion 32 | 33 | Enhancements or general suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined that the enhancement is not already requested, go ahead and create an issue providing the following information: 34 | 35 | - **Use a clear and descriptive title** for the issue to identify the suggestion. 36 | - **Provide a step-by-step description of the suggested enhancement** in as many details as possible. 37 | - **Describe the current behavior** and **explain which behavior you expected to see instead** and why. 38 | - **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of the `piral-cli-vite` packages which the suggestion is related to. *Note*: We usually live in code. Any code you can already show would be the best illustration. 39 | 40 | ## Branching Model 41 | 42 | ### Main Branches 43 | 44 | The central repository holds four main branches with an infinite lifetime: 45 | 46 | - **main** 47 | - **develop** 48 | - **experimental** 49 | - **documentation** 50 | 51 | We consider `main` to be the main branch where the source code always reflects a production-ready state, and `develop` to be the main branch where the source code always reflects a state with the latest delivered changes for the next release. When the source code in the `develop` branch reaches a stable point and is ready to be released, all of the changes should be merged back into main. Therefore, each time when changes are merged back into main, this is a new production release. 52 | 53 | The **experimental** branch is a special branch for an upcoming release that is unclear in scope and functionality. Releases from this branch should be considered unstable and might never reach production. No hotfixes or minor updates will be first-pushed to this branch. Instead, only (experimental) new features are (potentially exclusively) added to this branch. 54 | 55 | The **documentation** branch is used for updates and fixes to the currently live (i.e., `main`-build) documentation. 56 | 57 | The following table gives an overview: 58 | 59 | | Branch Name | NPM Release / Tag | Version Suffix | 60 | | ------------- | ----------------- | -------------- | 61 | | main | latest | (none) | 62 | | develop | next | beta | 63 | 64 | If you don't know what to do - use `develop` as target for pull requests. 65 | 66 | ### Supporting Branches 67 | 68 | Next to the main branches `main` and `develop`, our development model uses a few of supporting branches to aid parallel development between team members, ease tracking of features and to assist in quickly fixing live production problems. Unlike the main branches, these branches always have a limited life time, since they will be removed eventually. 69 | 70 | The two main different types of branches we may use are: 71 | 72 | - **Feature branches**, i.e., `feature/*` 73 | - **Hotfix branches**, i.e., `hotfix/*` 74 | 75 | #### Creating a Feature Branch 76 | 77 | Create a branch **from** `develop` which must merge back **into** `develop`. 78 | 79 | Naming convention: 80 | 81 | - anything except `main`, `develop`, `release/*`, or `hotfix/*` 82 | - preferred `feature/{issue-id}-{issue-description}`, e.g., `feature/#123-add-foo` 83 | 84 | #### Creating a Hotfix Branch 85 | 86 | Create a branch **from** `main` which must merge back **into** either `main` and / or `develop`. While a *real* hotfix will apply to both immediately, a simple fix will just be applied to `develop`. 87 | 88 | Naming convention: 89 | 90 | - `hotfix/{new-patch-version}`, e.g., `hotfix/1.2.1` 91 | - `hotfix/{issue-id}-{issue-description}`, e.g., `hotfix/#123-fixed-foo-undefined` 92 | 93 | Hotfix branches are normally created from the `main` branch (especially if they are applied to both `main` and `develop`, otherwise creating the branch from `develop` may be okay as well). For example, say version 1.2 is the current production release running live and causing troubles due to a severe bug. But changes on develop are yet unstable. 94 | 95 | ## Pull Request Process 96 | 97 | Following is a short guide on how to make a valid Pull Request. 98 | 99 | 1. Firstly you need a local fork of the the project, so go ahead and press the `fork` button in 100 | GitHub. This will create a copy of the repository in your own GitHub account and you'll see a 101 | note that it's been forked underneath the project name: `Forked from smapiot/piral-cli-vite`. 102 | Clone the newly forked repository locally and set up a new remote that points to the original 103 | project so that you can grab any changes and bring them into your local copy. 104 | 105 | ```sh 106 | git remote add upstream git@github.com:smapiot/piral-cli-vite.git 107 | ``` 108 | 109 | You now have two remotes for this project on disk: 110 | 111 | 1. `origin` which points to your GitHub fork of the project. 112 | You can read and write to this remote. 113 | 2. `upstream` which points to the main project's GitHub repository. 114 | You can only read from this remote. 115 | 116 | 2. Create the branch, following or [Branching Model](#branching-model). 117 | 118 | 3. Do some work :) This is the fun part where you get to contribute to the `piral-cli-vite` packages :rocket:. 119 | 120 | 4. Before pushing your code, few more task that need to be preformed: 121 | 122 | - Make sure that the test and build scripts run successfully 123 | 124 | ```sh 125 | npm test 126 | lerna run build 127 | ``` 128 | 129 | - Update the *CHANGELOG.md* following our convention 130 | 131 | 5. Commit and push the code to the origin. 132 | 133 | ```sh 134 | git commit -m "Description of my awesome new feature" 135 | git push origin HEAD 136 | ``` 137 | 138 | 6. After the code is successfully pushed to the origin repository, navigate to 139 | [`piral-cli-vite` repository](https://github.com/smapiot/piral-cli-vite/pulls) 140 | and issue a new pull request. 141 | 142 | You may merge the Pull Request in once you have the sign-off of at least one other (core) developer, or if you do not have permission to do that, you may request the reviewer to merge it for you. 143 | --------------------------------------------------------------------------------