mirror of
https://github.com/alibaba/ice.git
synced 2024-10-23 07:04:52 +08:00
chore: first commit
This commit is contained in:
parent
ac910ed2dc
commit
26ffa95e90
3
.commitlintrc.js
Normal file
3
.commitlintrc.js
Normal file
@ -0,0 +1,3 @@
|
||||
const { getCommitlintConfig } = require('@iceworks/spec');
|
||||
|
||||
module.exports = getCommitlintConfig('common');
|
23
.eslintignore
Normal file
23
.eslintignore
Normal file
@ -0,0 +1,23 @@
|
||||
# 忽略目录
|
||||
build/
|
||||
test/
|
||||
tests/
|
||||
node_modules/
|
||||
dist/
|
||||
out/
|
||||
|
||||
# node 覆盖率文件
|
||||
coverage/
|
||||
|
||||
# 忽略测试文件
|
||||
/packages/*/__tests__
|
||||
/packages/*/lib/
|
||||
|
||||
# 忽略第三方包
|
||||
/vendor/loader.js
|
||||
|
||||
# 忽略文件
|
||||
**/*-min.js
|
||||
**/*.min.js
|
||||
|
||||
workspace/
|
54
.eslintrc.js
Normal file
54
.eslintrc.js
Normal file
@ -0,0 +1,54 @@
|
||||
const { getESLintConfig } = require('@iceworks/spec');
|
||||
|
||||
const commonRules = {
|
||||
'react/jsx-filename-extension': 0,
|
||||
'no-underscore-dangle': 0,
|
||||
'class-methods-use-this': 0,
|
||||
'no-param-reassign': 0,
|
||||
'no-console': 0,
|
||||
'comma-dangle': 0,
|
||||
'prefer-object-spread': 0,
|
||||
'import/named': 0,
|
||||
indent: 0,
|
||||
semi: 2,
|
||||
'react/react-in-jsx-scope': 0,
|
||||
'jsx-a11y/html-has-lang': 0,
|
||||
'react/static-property-placement': 0,
|
||||
'no-multiple-empty-lines': 1,
|
||||
'react/jsx-no-bind': 0
|
||||
};
|
||||
|
||||
const jsRules = getESLintConfig('react', {
|
||||
rules: commonRules
|
||||
});
|
||||
const tsRules = getESLintConfig('react-ts', {
|
||||
rules: {
|
||||
...commonRules,
|
||||
'@typescript-eslint/ban-types': 0,
|
||||
'@typescript-eslint/ban-ts-comment': 0,
|
||||
'@typescript-eslint/no-explicit-any': 0,
|
||||
'@typescript-eslint/interface-name-prefix': 0,
|
||||
'@typescript-eslint/explicit-function-return-type': 0,
|
||||
'@typescript-eslint/no-var-requires': 0,
|
||||
'@typescript-eslint/explicit-module-boundary-types': 0,
|
||||
'no-use-before-define': 0,
|
||||
'no-unused-vars': 0,
|
||||
'@typescript-eslint/no-unused-vars': 1,
|
||||
'@typescript-eslint/ban-ts-ignore': 0,
|
||||
}
|
||||
});
|
||||
|
||||
delete tsRules.root;
|
||||
|
||||
module.exports = {
|
||||
...jsRules,
|
||||
overrides: [
|
||||
{
|
||||
...tsRules,
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
},
|
||||
],
|
||||
env: {
|
||||
jest: true,
|
||||
},
|
||||
};
|
93
.github/CONTRIBUTING.md
vendored
Normal file
93
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
# Contributing Guide
|
||||
|
||||
Hi! I’m really excited that you are interested in contributing to ICE. Before submitting your contribution though, please make sure to take a moment and read through the following guidelines.
|
||||
|
||||
- [Setup Environment](#setup-environment)
|
||||
- [Run Examples](#run-examples)
|
||||
- [Publish Packages](publish-packages)
|
||||
- [Pull Request Guidelines](#pull-request-guidelines)
|
||||
- [Issue Reporting Guidelines](#issue-reporting-guidelines)
|
||||
- [Git Commit Specific](#git-commit-specific)
|
||||
|
||||
## Setup Environment
|
||||
|
||||
clone repo and initialize the setup environment:
|
||||
|
||||
```bash
|
||||
# 1. clone and setup
|
||||
$ git clone git@github.com:ice-lab/icejs.git
|
||||
$ cd icejs && npm run setup
|
||||
|
||||
# 2. watch packages
|
||||
$ npm run watch
|
||||
```
|
||||
|
||||
## Run Examples
|
||||
|
||||
We provide a lot of examples, you can run the examples:
|
||||
|
||||
```bash
|
||||
$ cd examples/basic-spa
|
||||
$ npm link ../../packages/icejs
|
||||
$ npm start
|
||||
```
|
||||
|
||||
## Publish Packages
|
||||
|
||||
When you need to release, you can execute the command:
|
||||
|
||||
```bash
|
||||
$ npm run publish
|
||||
# 1. ✔️ ✔️ ✔️ Checking the working tree status...
|
||||
# 2. 📦 📦 📦 Building packages...
|
||||
# 3. ⚡ ⚡ ⚡ Update package version automatically...
|
||||
# 4. 🚀 🚀 🚀 Start publishing...
|
||||
# 5. 🔖 🔖 🔖 Commit & Create tag'...
|
||||
# 6. 💡 💡 💡 Start syncing...
|
||||
```
|
||||
|
||||
* When you need to release a latest version, the tag will be created automatically, running `npm publish` will tag your package with the `latest` dist-tag.
|
||||
* To publish a package with the `beta` dist-tag, you can choose to release rc、beta、alpha versions, the tag will not be created.
|
||||
|
||||
## Rollback Packages
|
||||
|
||||
When a serious bug occurs in the production environment, you can backtrack the package version:
|
||||
|
||||
```bash
|
||||
# rollback packages
|
||||
$ npm run rollback <version>
|
||||
|
||||
# sync packages
|
||||
$ npm run sync
|
||||
```
|
||||
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
- Only code that's ready for release should be committed to the master branch. All development should be done in dedicated branches.
|
||||
- Checkout a **new** topic branch from master branch, and merge back against master branch.
|
||||
- Make sure `npm test` passes.
|
||||
- If adding new feature:
|
||||
- Add accompanying test case.
|
||||
- Provide convincing reason to add this feature. Ideally you should open a suggestion issue first and have it greenlighted before working on it.
|
||||
- If fixing a bug:
|
||||
- If you are resolving a special issue, add `(fix #xxxx[,#xxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `update entities encoding/decoding (fix #3899)`.
|
||||
- Provide detailed description of the bug in the PR. Live demo preferred.
|
||||
- Add appropriate test coverage if applicable.
|
||||
|
||||
## Issue Reporting Guidelines
|
||||
|
||||
- The issue list of this repo is **exclusively** for bug reports and feature requests. Non-conforming issues will be closed immediately.
|
||||
- For simple beginner questions, you can get quick answers from
|
||||
- For more complicated questions, you can use Google or StackOverflow. Make sure to provide enough information when asking your questions - this makes it easier for others to help you!
|
||||
- Try to search for your issue, it may have already been answered or even fixed in the development branch.
|
||||
- It is **required** that you clearly describe the steps necessary to reproduce the issue you are running into. Issues with no clear repro steps will not be triaged. If an issue labeled "need repro" receives no further input from the issue author for more than 5 days, it will be closed.
|
||||
- For bugs that involves build setups, you can create a reproduction repository with steps in the README.
|
||||
- If your issue is resolved but still open, don’t hesitate to close it. In case you found a solution by yourself, it could be helpful to explain how you fixed it.
|
||||
|
||||
## Git Commit Specific
|
||||
|
||||
- Your commits message must follow our [git commit specific](./GIT_COMMIT_SPECIFIC.md).
|
||||
- We will check your commit message, if it does not conform to the specification, the commit will be automatically refused, make sure you have read the specification above.
|
||||
- You could use `git cz` with a CLI interface to replace `git commit` command, it will help you to build a proper commit-message, see [commitizen](https://github.com/commitizen/cz-cli).
|
||||
- It's OK to have multiple small commits as you work on your branch - we will let GitHub automatically squash it before merging.
|
39
.github/GIT_COMMIT_SPECIFIC.md
vendored
Normal file
39
.github/GIT_COMMIT_SPECIFIC.md
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# GIT COMMIT MESSAGE CHEAT SHEET
|
||||
|
||||
**Proposed format of the commit message**
|
||||
|
||||
```
|
||||
<type>: <subject>
|
||||
|
||||
<body>
|
||||
```
|
||||
|
||||
All lines are wrapped at 100 characters !
|
||||
|
||||
**Allowed `<type>`**
|
||||
|
||||
- feat (A new feature)
|
||||
- fix (A bug fix)
|
||||
- docs (Documentation only changes)
|
||||
- style (Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc))
|
||||
- perf (A code change that improves performance)
|
||||
- refactor (A code change that neither fixes a bug nor adds a feature)
|
||||
- test (Adding missing tests or correcting existing tests)
|
||||
- build (Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm))
|
||||
- ci (Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs))
|
||||
- chore (Other changes that don't modify src or test files)
|
||||
- revert (Reverts a previous commit)
|
||||
- release (Relase version)
|
||||
|
||||
|
||||
**Breaking changes**
|
||||
|
||||
All breaking changes have to be mentioned in message body, on separated line:
|
||||
|
||||
_Breaks removed $browser.setUrl() method (use $browser.url(newUrl))_
|
||||
_Breaks ng: repeat option is no longer supported on selects (use ng:options)_
|
||||
|
||||
**Message body**
|
||||
|
||||
- uses the imperative, present tense: “change” not “changed” nor “changes”
|
||||
- includes motivation for the change and contrasts with previous behavior
|
27
.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
name: 'Bug report'
|
||||
about: 'Report ice.js, components, documents and other issues'
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!--
|
||||
Fusion 组件相关问题反馈请移步:https://fusion.design/feedback
|
||||
-->
|
||||
|
||||
## What is the current behavior? 发生了什么?
|
||||
|
||||
<!--
|
||||
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.
|
||||
-->
|
||||
<!-- 清晰的描述下遇到的问题,建议附上错误截图 -->
|
||||
|
||||
## What is the expected behavior? 期望的结果是什么?
|
||||
|
||||
## Any additional comments? 相关环境信息?
|
||||
|
||||
- **ice.js Version**:
|
||||
- **build.json Configuration**:
|
||||
- **Node Version**:
|
||||
- **Platform**:
|
23
.github/workflows/1.x-publisher.yml
vendored
Normal file
23
.github/workflows/1.x-publisher.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
name: 1.x Publisher
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- stable/1.x
|
||||
|
||||
jobs:
|
||||
build-and-publish-stable:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm run setup
|
||||
- run: npm run publish:stable
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||
ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}
|
||||
ACCESS_KEY_SECRET: ${{ secrets.ACCESS_KEY_SECRET }}
|
||||
REGISTRY: https://registry.npmjs.org
|
23
.github/workflows/auto-publisher.yml
vendored
Normal file
23
.github/workflows/auto-publisher.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
name: Auto Publisher
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build-and-publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm run setup
|
||||
- run: npm run publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||
ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}
|
||||
ACCESS_KEY_SECRET: ${{ secrets.ACCESS_KEY_SECRET }}
|
||||
REGISTRY: https://registry.npmjs.org
|
24
.github/workflows/beta-publisher.yml
vendored
Normal file
24
.github/workflows/beta-publisher.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: Beta Publisher
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- beta
|
||||
|
||||
jobs:
|
||||
build-and-publish-beta:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: nelonoel/branch-name@v1
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm run setup
|
||||
- run: npm run publish:beta
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||
ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}
|
||||
ACCESS_KEY_SECRET: ${{ secrets.ACCESS_KEY_SECRET }}
|
||||
REGISTRY: https://registry.npmjs.org
|
34
.github/workflows/ci.yml
vendored
Normal file
34
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
name: CI
|
||||
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=6144
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set branch name
|
||||
run: echo >>$GITHUB_ENV BRANCH_NAME=${GITHUB_REF#refs/heads/}
|
||||
- name: Echo branch name
|
||||
run: echo ${BRANCH_NAME}
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm run setup
|
||||
- run: npm run dependency:check
|
||||
- run: npm run lint
|
||||
- run: npm run test
|
||||
- run: npm run version:check
|
||||
- run: npm run coverage
|
||||
env:
|
||||
ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}
|
||||
ACCESS_KEY_SECRET: ${{ secrets.ACCESS_KEY_SECRET }}
|
||||
CI: true
|
24
.github/workflows/contributors.yml
vendored
Normal file
24
.github/workflows/contributors.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: Add contributors
|
||||
on:
|
||||
# schedule:
|
||||
# - cron: '5 * * * *'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
add-contributors:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: BobAnkh/add-contributors@master
|
||||
with:
|
||||
REPO_NAME: "alibaba/ice"
|
||||
CONTRIBUTOR: "## Contributors"
|
||||
COLUMN_PER_ROW: "10"
|
||||
ACCESS_TOKEN: ${{secrets.PERSONAL_GITHUB_TOKEN}}
|
||||
IMG_WIDTH: "60"
|
||||
FONT_SIZE: "14"
|
||||
PATH: "/README.md"
|
||||
COMMIT_MESSAGE: "docs(README): update contributors"
|
||||
AVATAR_SHAPE: "round"
|
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
# https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Dependencies
|
||||
node_modules
|
||||
jspm_packages
|
||||
|
||||
# Only keep yarn.lock in the root
|
||||
package-lock.json
|
||||
*/**/yarn.lock
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# Others
|
||||
.npm
|
||||
.eslintcache
|
||||
.idea
|
||||
.DS_Store
|
||||
.happypack
|
||||
.vscode
|
||||
.tmp
|
||||
*.swp
|
||||
*.dia~
|
||||
*.temp.json
|
||||
|
||||
# Packages
|
||||
packages/*/lib/
|
||||
|
||||
# temp folder .ice
|
||||
examples/*/.ice
|
||||
|
||||
build
|
||||
dist
|
||||
.history
|
4
.husky/commit-msg
Executable file
4
.husky/commit-msg
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no -- commitlint -E HUSKY_GIT_PARAMS
|
4
.husky/pre-commit
Executable file
4
.husky/pre-commit
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npm run lint
|
9
.prettierignore
Normal file
9
.prettierignore
Normal file
@ -0,0 +1,9 @@
|
||||
node_modules
|
||||
.ice
|
||||
dist
|
||||
*.d.ts
|
||||
*.js
|
||||
fixtures
|
||||
*.md
|
||||
*.yaml
|
||||
*.less
|
8
.prettierrc
Normal file
8
.prettierrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"proseWrap": "never",
|
||||
"overrides": [{ "files": ".prettierrc", "options": { "parser": "json" } }],
|
||||
"plugins": ["prettier-plugin-organize-imports", "prettier-plugin-packagejson"]
|
||||
}
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
MIT LICENSE
|
||||
|
||||
Copyright (c) 2018-present Alibaba Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
7
README.md
Normal file
7
README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# icejs
|
||||
|
||||
> v3 develop version
|
||||
|
||||
## LICENSE
|
||||
|
||||
[MIT](https://github.com/ice-lab/ice-next/blob/master/LICENSE)
|
1
examples/basic-vite/.eslintignore
Normal file
1
examples/basic-vite/.eslintignore
Normal file
@ -0,0 +1 @@
|
||||
/src
|
1
examples/basic-vite/README.md
Normal file
1
examples/basic-vite/README.md
Normal file
@ -0,0 +1 @@
|
||||
# basic vite example
|
21
examples/basic-vite/build.json
Normal file
21
examples/basic-vite/build.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"hash": false,
|
||||
"minify": "esbuild",
|
||||
"polyfill": false,
|
||||
"vite": true,
|
||||
"vendor": false,
|
||||
"plugins": [
|
||||
"build-plugin-jsx-plus"
|
||||
],
|
||||
"sassLoaderOptions": {
|
||||
"prependData": ".test{color:red}"
|
||||
},
|
||||
"tsChecker": true,
|
||||
"proxy": {
|
||||
"/api": {
|
||||
"target": "http://jsonplaceholder.typicode.com",
|
||||
"changeOrigin": true,
|
||||
"pathRewrite": { "^/api": "/todos" }
|
||||
}
|
||||
}
|
||||
}
|
11
examples/basic-vite/mock/index.ts
Normal file
11
examples/basic-vite/mock/index.ts
Normal file
@ -0,0 +1,11 @@
|
||||
const status = 'SUCCESS';
|
||||
// mock/index.js
|
||||
export default {
|
||||
'GET /api/repo': {
|
||||
status,
|
||||
data: {
|
||||
group: 'ice.js',
|
||||
url: 'https://github.com/ice-lab/ice.js'
|
||||
}
|
||||
},
|
||||
};
|
17
examples/basic-vite/package.json
Normal file
17
examples/basic-vite/package.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "basic-vite",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"start": "../../packages/icejs/bin/ice-cli.js start",
|
||||
"build": "../../packages/icejs/bin/ice-cli.js build"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^17.0.0",
|
||||
"react-dom": "^17.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
11
examples/basic-vite/public/index.html
Normal file
11
examples/basic-vite/public/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="ice-container"></div>
|
||||
</body>
|
||||
</html>
|
8
examples/basic-vite/src/Layout/index.tsx
Normal file
8
examples/basic-vite/src/Layout/index.tsx
Normal file
@ -0,0 +1,8 @@
|
||||
export default ({ children }) => {
|
||||
return (
|
||||
<div>
|
||||
Layout
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
10
examples/basic-vite/src/app.tsx
Normal file
10
examples/basic-vite/src/app.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { runApp, IAppConfig } from 'ice';
|
||||
|
||||
const appConfig: IAppConfig = {
|
||||
app: {
|
||||
rootId: 'ice-container',
|
||||
errorBoundary: true,
|
||||
},
|
||||
};
|
||||
|
||||
runApp(appConfig);
|
11
examples/basic-vite/src/global.scss
Normal file
11
examples/basic-vite/src/global.scss
Normal file
@ -0,0 +1,11 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
|
||||
'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
}
|
5
examples/basic-vite/src/pages/Dashboard/Page1/index.tsx
Normal file
5
examples/basic-vite/src/pages/Dashboard/Page1/index.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
export default () => {
|
||||
return (
|
||||
<div>Page1</div>
|
||||
);
|
||||
};
|
5
examples/basic-vite/src/pages/Dashboard/Page2/index.tsx
Normal file
5
examples/basic-vite/src/pages/Dashboard/Page2/index.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
export default () => {
|
||||
return (
|
||||
<div>Page2</div>
|
||||
);
|
||||
};
|
8
examples/basic-vite/src/pages/Dashboard/index.tsx
Normal file
8
examples/basic-vite/src/pages/Dashboard/index.tsx
Normal file
@ -0,0 +1,8 @@
|
||||
export default ({ children }) => {
|
||||
return (
|
||||
<div>
|
||||
这是 Dashboard
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
75
examples/basic-vite/src/pages/Home/index.css
Normal file
75
examples/basic-vite/src/pages/Home/index.css
Normal file
@ -0,0 +1,75 @@
|
||||
:root {
|
||||
--primay: black;
|
||||
--bg-primay: white;
|
||||
|
||||
--link: #2a0b0b;
|
||||
}
|
||||
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 20px 0px;
|
||||
}
|
||||
|
||||
.header {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.body {
|
||||
margin: 20px 0 10px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
button {
|
||||
outline: none;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 10px 35px;
|
||||
|
||||
background: #845ec2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
|
||||
background: var(--bg-primay);
|
||||
color: var(--primay);
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
color: var(--link);
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: calc(10px + 2vmin);
|
||||
}
|
52
examples/basic-vite/src/pages/Home/index.tsx
Normal file
52
examples/basic-vite/src/pages/Home/index.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import { Head } from 'ice';
|
||||
import { useState } from 'react';
|
||||
import store from './store';
|
||||
import './index.css';
|
||||
|
||||
function App() {
|
||||
const [count, setCount] = useState<number>(0);
|
||||
const [titleState] = store.useModel('title');
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<Head>
|
||||
<meta charSet="utf-8" />
|
||||
<title>Home title</title>
|
||||
<meta name="keywords" content="About Keywords" />
|
||||
<meta name="description" content="About Description" />
|
||||
</Head>
|
||||
<header className="App-header">
|
||||
<p x-if={titleState.title} className="header">{titleState.title}</p>
|
||||
|
||||
<div className="body">
|
||||
<button type="button" onClick={() => setCount((e: number) => e + 1)}>
|
||||
🪂 Click me : {count}
|
||||
</button>
|
||||
|
||||
<p> Don't forget to install <a href="https://appworks.site/">AppWorks</a> in Your Vscode.</p>
|
||||
<p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
{' | '}
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://vitejs.dev/guide/features.html"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Vite Docs
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
10
examples/basic-vite/src/pages/Home/models/title.ts
Normal file
10
examples/basic-vite/src/pages/Home/models/title.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export default {
|
||||
state: {
|
||||
title: '🚀 Vite + Icejs'
|
||||
},
|
||||
reducers: {
|
||||
update(prevState, payload) {
|
||||
return { title: payload };
|
||||
},
|
||||
}
|
||||
};
|
6
examples/basic-vite/src/pages/Home/store.ts
Normal file
6
examples/basic-vite/src/pages/Home/store.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { createStore } from 'ice';
|
||||
import title from './models/title';
|
||||
|
||||
const store = createStore({ title });
|
||||
|
||||
export default store;
|
40
examples/basic-vite/src/routes.ts
Normal file
40
examples/basic-vite/src/routes.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { IRouterConfig, lazy } from 'ice';
|
||||
import DashboardLayout from '@/pages/Dashboard';
|
||||
import Dashboard1 from '@/pages/Dashboard/Page1';
|
||||
import Dashboard2 from '@/pages/Dashboard/Page2';
|
||||
import Layout from '@/Layout';
|
||||
|
||||
const Home = lazy(() => import('@/pages/Home'));
|
||||
|
||||
const routes: IRouterConfig[] = [
|
||||
{
|
||||
path: '/',
|
||||
component: Home,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
component: Layout,
|
||||
children: [
|
||||
{
|
||||
path: '/dashboard',
|
||||
component: DashboardLayout,
|
||||
children: [
|
||||
{
|
||||
path: '/a',
|
||||
component: Dashboard1,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/b',
|
||||
component: Dashboard2,
|
||||
exact: true
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
export default routes;
|
3
examples/basic-vite/src/store.ts
Normal file
3
examples/basic-vite/src/store.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { createStore } from 'ice';
|
||||
|
||||
export default createStore({});
|
4
examples/basic-vite/src/typings.d.ts
vendored
Normal file
4
examples/basic-vite/src/typings.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module '*.module.scss' {
|
||||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
38
examples/basic-vite/tsconfig.json
Normal file
38
examples/basic-vite/tsconfig.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"buildOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"outDir": "build",
|
||||
"module": "esnext",
|
||||
"target": "es6",
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"rootDir": "./",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noImplicitAny": false,
|
||||
"importHelpers": true,
|
||||
"strictNullChecks": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"noUnusedLocals": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["node", "jest", "vite/client"],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
],
|
||||
"ice": [
|
||||
".ice/index.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
40
jest.config.js
Normal file
40
jest.config.js
Normal file
@ -0,0 +1,40 @@
|
||||
/* const { getHookFiles } = require('./packages/icejs/lib/require-hook');
|
||||
|
||||
const moduleNameMapper = getHookFiles().reduce((mapper, [id, value]) => {
|
||||
mapper[`^${id}$`] = value;
|
||||
return mapper;
|
||||
}, {}); */
|
||||
|
||||
module.exports = {
|
||||
coverageDirectory: './coverage/',
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: ['packages/*/lib/*.{js,jsx}'],
|
||||
coveragePathIgnorePatterns: [
|
||||
'<rootDir>/node_modules/'
|
||||
],
|
||||
// copy from jest config
|
||||
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.jsx?$': 'babel-jest',
|
||||
'^.+\\.tsx?$': 'ts-jest'
|
||||
},
|
||||
roots: [
|
||||
'<rootDir>/packages',
|
||||
'<rootDir>/test',
|
||||
],
|
||||
testPathIgnorePatterns: [
|
||||
'/node_modules/',
|
||||
'/lib/',
|
||||
'create-cli-utils/'
|
||||
],
|
||||
testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
// For ts-jest use rootDir's tsconfig.json, while unable to resolve references.
|
||||
// The following strategy maybe not the best, but it works.
|
||||
// https://github.com/kulshekhar/ts-jest/issues/1648
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: 'tsconfig.base.json',
|
||||
},
|
||||
},
|
||||
};
|
51
package.json
Normal file
51
package.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"description": "A universal framework based on React",
|
||||
"scripts": {
|
||||
"setup": "rm -rf node_modules && pnpm install && pnpm run build",
|
||||
"watch": "esmo ./scripts/watch.ts",
|
||||
"build": "esmo ./scripts/build.ts",
|
||||
"clean": "rimraf packages/*/lib",
|
||||
"lint": "eslint --cache --ext .js,.jsx,.ts,.tsx ./",
|
||||
"lint:fix": "npm run lint -- --fix",
|
||||
"test": "jest --forceExit --ci",
|
||||
"test:watch": "jest --watch"
|
||||
},
|
||||
"author": "ice-admin@alibaba-inc.com",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^16.1.0",
|
||||
"@iceworks/spec": "^1.5.0",
|
||||
"@types/cross-spawn": "^6.0.2",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/glob": "^7.2.0",
|
||||
"@types/jest": "^27.4.0",
|
||||
"@types/node": "^17.0.12",
|
||||
"@types/pify": "^5.0.1",
|
||||
"@types/semver": "^7.3.9",
|
||||
"chokidar": "^3.5.3",
|
||||
"dependency-check": "^4.1.0",
|
||||
"eslint": "^8.7.0",
|
||||
"esno": "^0.14.0",
|
||||
"execa": "^6.0.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"glob": "^7.2.0",
|
||||
"husky": "^7.0.4",
|
||||
"ice-npm-utils": "^3.0.1",
|
||||
"jest": "^27.4.7",
|
||||
"pify": "^5.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"prettier-plugin-organize-imports": "^2.3.4",
|
||||
"prettier-plugin-packagejson": "^2.2.15",
|
||||
"puppeteer": "^13.1.2",
|
||||
"react": "^17.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"stylelint": "^14.3.0",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"packageManager": "pnpm"
|
||||
}
|
11
packages/icejs/package.json
Normal file
11
packages/icejs/package.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "icejs",
|
||||
"version": "3.0.0",
|
||||
"description": "ice",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "ice-admin",
|
||||
"license": "MIT"
|
||||
}
|
1
packages/icejs/src/index.ts
Normal file
1
packages/icejs/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export default () => 'ice';
|
7
packages/icejs/test/index.test.ts
Normal file
7
packages/icejs/test/index.test.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import ice from '../src/index';
|
||||
|
||||
describe('basic test', () => {
|
||||
it('test return value', () => {
|
||||
expect(ice()).toBe('ice');
|
||||
});
|
||||
});
|
9
packages/icejs/tsconfig.json
Normal file
9
packages/icejs/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "lib",
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
15
packages/plugin-app/package.json
Normal file
15
packages/plugin-app/package.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "plugin-app",
|
||||
"version": "1.0.0",
|
||||
"description": "plugin app",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "ice-admin",
|
||||
"files": [
|
||||
"runtime",
|
||||
"lib"
|
||||
],
|
||||
"license": "MIT"
|
||||
}
|
3
packages/plugin-app/runtime/index.ts
Normal file
3
packages/plugin-app/runtime/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export default () => {
|
||||
return 'plugin runtime';
|
||||
};
|
1
packages/plugin-app/src/index.ts
Normal file
1
packages/plugin-app/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export default () => 'plugin';
|
7
packages/plugin-app/test/index.test.ts
Normal file
7
packages/plugin-app/test/index.test.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import ice from '../src/index';
|
||||
|
||||
describe('basic test', () => {
|
||||
it('test return value', () => {
|
||||
expect(ice()).toBe('plugin');
|
||||
});
|
||||
});
|
9
packages/plugin-app/tsconfig.json
Normal file
9
packages/plugin-app/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"rootDir": "src",
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
5966
pnpm-lock.yaml
Normal file
5966
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load Diff
3
pnpm-workspace.yaml
Normal file
3
pnpm-workspace.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
packages:
|
||||
- 'packages/*'
|
||||
- 'examples/*'
|
27
scripts/build.ts
Normal file
27
scripts/build.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import glob from 'glob';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import { run } from './shell';
|
||||
|
||||
(async () => {
|
||||
await run('npm run clean');
|
||||
|
||||
const fileParten = '*/src/**/!(*.ts|*.tsx|*.rs)';
|
||||
console.log(`[COPY]: ${fileParten}`);
|
||||
|
||||
const cwd = path.join(process.cwd(), 'packages');
|
||||
const files = glob.sync(fileParten, { cwd, nodir: true });
|
||||
// eslint-disable-next-line
|
||||
for (const file of files) {
|
||||
const from = path.join(cwd, file);
|
||||
const to = path.join(cwd, file.replace(/\/src\//, '/lib/'));
|
||||
// eslint-disable-next-line
|
||||
await fs.mkdirp(path.dirname(to));
|
||||
// eslint-disable-next-line
|
||||
await fs.copyFile(from, to);
|
||||
}
|
||||
await run('npx tsc --build ./tsconfig.json');
|
||||
})().catch((e) => {
|
||||
console.trace(e);
|
||||
process.exit(128);
|
||||
});
|
18
scripts/dependencyCheck.ts
Normal file
18
scripts/dependencyCheck.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { execaCommand } from 'execa';
|
||||
import getPackages from './getPackages';
|
||||
|
||||
// eslint-disable-next-line
|
||||
const chalk = require('chalk');
|
||||
|
||||
(async () => {
|
||||
const { packageDirs } = await getPackages();
|
||||
packageDirs.forEach((pkgDir) => {
|
||||
execaCommand(`dependency-check ${pkgDir} --missing`, {
|
||||
cwd: pkgDir,
|
||||
stdio: 'inherit'
|
||||
});
|
||||
});
|
||||
})().catch((e) => {
|
||||
console.log(chalk.red('\n ⚠️ ⚠️ ⚠️ 依赖检查失败\n\n'), e);
|
||||
process.exit(128);
|
||||
});
|
84
scripts/getPackageInfos.ts
Normal file
84
scripts/getPackageInfos.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import { existsSync, readdirSync, readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { getNpmInfo } from 'ice-npm-utils';
|
||||
import * as semver from 'semver';
|
||||
|
||||
const TARGET_DIRECTORY = join(__dirname, '../packages');
|
||||
|
||||
export interface IPackageInfo {
|
||||
name: string;
|
||||
directory: string;
|
||||
localVersion: string;
|
||||
publishVersion: string;
|
||||
mainFile: string; // package.json main file
|
||||
shouldPublish: boolean;
|
||||
packageInfo: {
|
||||
[key: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
function checkBuildSuccess(directory: string, mainFile: string): boolean {
|
||||
const isExist = existsSync(join(directory, mainFile));
|
||||
if (!isExist) {
|
||||
throw new Error(`build failed directory ${directory} do not exist main file`);
|
||||
}
|
||||
return isExist;
|
||||
}
|
||||
|
||||
function checkVersionExists(pkg: string, version: string, distTag: string): Promise<boolean> {
|
||||
const tag = distTag || 'latest';
|
||||
return getNpmInfo(pkg).then((data) => {
|
||||
if (!data['dist-tags'] || (!data['dist-tags'][tag] && !data['dist-tags'].latest)) {
|
||||
console.error(`${pkg} 没有 ${tag} 和 latest 版本号`, data);
|
||||
return Promise.reject(new Error('Error: 没有版本号信息'));
|
||||
}
|
||||
// 如果该 tag 未发布,用 latest
|
||||
return data['dist-tags'][tag] || data['dist-tags'].latest;
|
||||
}).then((tagVersion) => version === tagVersion).catch(() => false);
|
||||
}
|
||||
|
||||
export function getVersionPrefix(version): string {
|
||||
return isNaN(version[0]) ? version[0] : '';
|
||||
}
|
||||
|
||||
export async function getPackageInfos(distTag = ''): Promise<IPackageInfo[]> {
|
||||
const packageInfos: IPackageInfo[] = [];
|
||||
if (!existsSync(TARGET_DIRECTORY)) {
|
||||
console.log(`[ERROR] Directory ${TARGET_DIRECTORY} not exist!`);
|
||||
} else {
|
||||
const packageFolders: string[] = readdirSync(TARGET_DIRECTORY)
|
||||
.filter((filename) => filename[0] !== '.')
|
||||
.map((packageFolder) => join(TARGET_DIRECTORY, packageFolder));
|
||||
console.log('[PUBLISH] Start check with following packages:');
|
||||
await Promise.all(packageFolders.map(async (packageFolder) => {
|
||||
const packageInfoPath = join(packageFolder, 'package.json');
|
||||
// Process package info.
|
||||
if (existsSync(packageInfoPath)) {
|
||||
const packageInfo = JSON.parse(readFileSync(packageInfoPath, 'utf8'));
|
||||
const packageName = packageInfo.name;
|
||||
const publishVersion = semver.valid(semver.coerce(packageInfo.version));
|
||||
console.log(`- ${packageName}`);
|
||||
|
||||
try {
|
||||
packageInfos.push({
|
||||
name: packageName,
|
||||
directory: packageFolder,
|
||||
localVersion: packageInfo.version,
|
||||
publishVersion,
|
||||
mainFile: packageInfo.main,
|
||||
packageInfo,
|
||||
// If localVersion not exist, publish it
|
||||
shouldPublish:
|
||||
checkBuildSuccess(packageFolder, packageInfo.main) &&
|
||||
!await checkVersionExists(packageName, publishVersion, distTag)
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] get ${packageName} information failed: `, e);
|
||||
}
|
||||
} else {
|
||||
console.log(`[ERROR] ${packageFolder}'s package.json not found.`);
|
||||
}
|
||||
}));
|
||||
}
|
||||
return packageInfos;
|
||||
}
|
29
scripts/getPackages.ts
Normal file
29
scripts/getPackages.ts
Normal file
@ -0,0 +1,29 @@
|
||||
/* eslint no-restricted-syntax:0, no-await-in-loop:0, no-restricted-syntax:0 */
|
||||
import * as path from 'path';
|
||||
import * as fse from 'fs-extra';
|
||||
import * as _glob from 'glob';
|
||||
import * as pify from 'pify';
|
||||
|
||||
const glob = pify(_glob);
|
||||
|
||||
export default async function getPackages() {
|
||||
const packageNames = [];
|
||||
const packageDirs = [];
|
||||
const rootPkgPath = path.join(process.cwd(), 'package.json');
|
||||
const rootPkgContent = fse.readJSONSync(rootPkgPath);
|
||||
|
||||
for (const workspace of rootPkgContent.workspaces || []) {
|
||||
const dirs = await glob(workspace);
|
||||
for (const dir of dirs) {
|
||||
if (fse.existsSync(path.resolve(dir, 'package.json'))) {
|
||||
const pkgContent = fse.readJSONSync(path.resolve(dir, 'package.json'));
|
||||
packageNames.push(pkgContent.name);
|
||||
packageDirs.push(path.resolve(dir));
|
||||
} else {
|
||||
console.warn('Invalid workspace package:', dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { packageNames, packageDirs };
|
||||
}
|
40
scripts/publishPackage.ts
Normal file
40
scripts/publishPackage.ts
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Scripts to check unpublished version and run publish
|
||||
*/
|
||||
import { spawnSync } from 'child_process';
|
||||
import { setPublishedPackages } from './published-info';
|
||||
import { IPackageInfo, getPackageInfos } from './getPackageInfos';
|
||||
|
||||
const publishTag = process.env.PUBLISH_TAG || '';
|
||||
|
||||
function publish(pkg: string, version: string, directory: string): void {
|
||||
console.log('[PUBLISH]', `${pkg}@${version}`);
|
||||
const npmCommand = ['publish'];
|
||||
if (publishTag) {
|
||||
npmCommand.push(`--tag=${publishTag}`);
|
||||
}
|
||||
spawnSync('npm', npmCommand, {
|
||||
stdio: 'inherit',
|
||||
cwd: directory,
|
||||
});
|
||||
}
|
||||
|
||||
// Entry
|
||||
console.log('[PUBLISH] Start:');
|
||||
getPackageInfos(publishTag).then((packageInfos: IPackageInfo[]) => {
|
||||
// Publish
|
||||
let publishedCount = 0;
|
||||
const publishedPackages = [];
|
||||
for (let i = 0; i < packageInfos.length; i++) {
|
||||
const { name, directory, localVersion, shouldPublish } = packageInfos[i];
|
||||
if (shouldPublish) {
|
||||
publishedCount++;
|
||||
console.log(`--- ${name}@${localVersion} ---`);
|
||||
publish(name, localVersion, directory);
|
||||
publishedPackages.push(`${name}:${localVersion}`);
|
||||
}
|
||||
}
|
||||
console.log(`[PUBLISH PACKAGE PRODUCTION] Complete (count=${publishedCount}):`);
|
||||
console.log(`${publishedPackages.join('\n')}`);
|
||||
setPublishedPackages(publishedPackages);
|
||||
});
|
108
scripts/publishPackageWithDistTag.ts
Normal file
108
scripts/publishPackageWithDistTag.ts
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Scripts to check unpublished version and run publish
|
||||
*/
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import { spawnSync } from 'child_process';
|
||||
import { setPublishedPackages } from './published-info';
|
||||
import { IPackageInfo, getPackageInfos, getVersionPrefix } from './getPackageInfos';
|
||||
|
||||
const PUBLISH_TYPE = process.env.PUBLISH_TYPE || 'beta';
|
||||
const VERSION_PREFIX = process.env.VERSION_PREFIX || PUBLISH_TYPE;
|
||||
const DIST_TAG_REG = new RegExp(`([^-]+)-${VERSION_PREFIX}\\.(\\d+)`);
|
||||
|
||||
interface ITagPackageInfo extends IPackageInfo {
|
||||
distTagVersion: string;
|
||||
}
|
||||
|
||||
const publishTag = process.env.PUBLISH_TAG || '';
|
||||
function getVersionInfo(packageInfo: IPackageInfo, tag: string): ITagPackageInfo {
|
||||
const { name, localVersion } = packageInfo;
|
||||
|
||||
let version = localVersion;
|
||||
|
||||
if (!DIST_TAG_REG.test(localVersion)) {
|
||||
let distTagVersion = 1;
|
||||
const childProcess = spawnSync('npm', [
|
||||
'show', name, 'dist-tags',
|
||||
'--json',
|
||||
], {
|
||||
encoding: 'utf-8'
|
||||
});
|
||||
|
||||
let distTags = {};
|
||||
try {
|
||||
distTags = JSON.parse(childProcess.stdout) || {};
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (err) {}
|
||||
const matched = (distTags[tag] || '').match(DIST_TAG_REG);
|
||||
|
||||
// 1.0.0-beta.1 -> ["1.0.0-beta.1", "1.0.0", "1"] -> 1.0.0-beta.2
|
||||
if (matched && matched[1] === localVersion && matched[2]) {
|
||||
distTagVersion = Number(matched[2]) + 1;
|
||||
}
|
||||
version += `-${VERSION_PREFIX}.${distTagVersion}`;
|
||||
}
|
||||
|
||||
return Object.assign({}, packageInfo, { distTagVersion: version });
|
||||
}
|
||||
|
||||
function updatePackageJson(packageInfos: ITagPackageInfo[]): void {
|
||||
packageInfos.forEach((packageInfo: ITagPackageInfo) => {
|
||||
const { directory, distTagVersion } = packageInfo;
|
||||
|
||||
const packageFile = path.join(directory, 'package.json');
|
||||
const packageData = fs.readJsonSync(packageFile);
|
||||
|
||||
packageData.version = distTagVersion;
|
||||
|
||||
for (let i = 0; i < packageInfos.length; i++) {
|
||||
const dependenceName = packageInfos[i].name;
|
||||
const dependenceVersion = packageInfos[i].distTagVersion;
|
||||
|
||||
if (packageData.dependencies && packageData.dependencies[dependenceName]) {
|
||||
packageData.dependencies[dependenceName] = `${getVersionPrefix(packageData.dependencies[dependenceName])}${dependenceVersion}`;
|
||||
} else if (packageData.devDependencies && packageData.devDependencies[dependenceName]) {
|
||||
packageData.devDependencies[dependenceName] = `${getVersionPrefix(packageData.devDependencies[dependenceName])}${dependenceVersion}`;
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync(packageFile, JSON.stringify(packageData, null, 2));
|
||||
});
|
||||
}
|
||||
|
||||
function publish(pkg: string, distTagVersion: string, directory: string, tag: string): void {
|
||||
console.log(`[PUBLISH ${tag.toUpperCase()}]`, `${pkg}@${distTagVersion}`);
|
||||
spawnSync('npm', [
|
||||
'publish',
|
||||
`--tag=${tag}`,
|
||||
], {
|
||||
stdio: 'inherit',
|
||||
cwd: directory,
|
||||
});
|
||||
}
|
||||
|
||||
// Entry
|
||||
console.log(`[PUBLISH ${PUBLISH_TYPE.toUpperCase()}] Start:`);
|
||||
getPackageInfos(publishTag).then((packageInfos: IPackageInfo[]) => {
|
||||
const shouldPublishPackages = packageInfos
|
||||
.filter((packageInfo) => packageInfo.shouldPublish)
|
||||
.map((packageInfo) => getVersionInfo(packageInfo, PUBLISH_TYPE));
|
||||
|
||||
updatePackageJson(shouldPublishPackages);
|
||||
|
||||
// Publish
|
||||
let publishedCount = 0;
|
||||
const publishedPackages = [];
|
||||
shouldPublishPackages.forEach((packageInfo) => {
|
||||
const { name, directory, distTagVersion } = packageInfo;
|
||||
publishedCount++;
|
||||
console.log(`--- ${name}@${distTagVersion} ---`);
|
||||
publish(name, distTagVersion, directory, PUBLISH_TYPE);
|
||||
publishedPackages.push(`${name}:${distTagVersion}`);
|
||||
});
|
||||
|
||||
console.log(`[PUBLISH PACKAGE ${PUBLISH_TYPE.toUpperCase()}] Complete (count=${publishedCount}):`);
|
||||
console.log(`${publishedPackages.join('\n')}`);
|
||||
setPublishedPackages(publishedPackages);
|
||||
});
|
11
scripts/publishedInfo.ts
Normal file
11
scripts/publishedInfo.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
// Set and get published packages info
|
||||
const PACKAGE_TEMP_FILE = 'publishedPackages.temp.json';
|
||||
export function setPublishedPackages(publishedPackages: string[]): void {
|
||||
fs.writeFileSync(path.join(process.cwd(), PACKAGE_TEMP_FILE), JSON.stringify(publishedPackages));
|
||||
}
|
||||
export function getPublishedPackages(): string[] {
|
||||
return JSON.parse(fs.readFileSync(path.join(process.cwd(), PACKAGE_TEMP_FILE), 'utf-8'));
|
||||
}
|
6
scripts/shell.ts
Normal file
6
scripts/shell.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { execaCommand } from 'execa';
|
||||
|
||||
export async function run(command: string) {
|
||||
console.log(`[RUN]: ${command}`);
|
||||
return execaCommand(command, { stdio: 'inherit' });
|
||||
}
|
35
scripts/tagVersion.ts
Normal file
35
scripts/tagVersion.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as semver from 'semver';
|
||||
import { getPackageInfos, IPackageInfo, getVersionPrefix } from './getPackageInfos';
|
||||
|
||||
console.log('[VERSION] tag versions');
|
||||
|
||||
function updatePackageVersion(publishPackages: IPackageInfo[]) {
|
||||
publishPackages.forEach((publishPackage: IPackageInfo) => {
|
||||
const { directory, packageInfo, publishVersion, name } = publishPackage;
|
||||
packageInfo.version = publishVersion;
|
||||
// update package version depend on publish package
|
||||
for (let i = 0; i < publishPackages.length; i++) {
|
||||
const dependenceName = publishPackages[i].name;
|
||||
const dependenceVersion = publishPackages[i].publishVersion;
|
||||
|
||||
if (packageInfo.dependencies && packageInfo.dependencies[dependenceName]) {
|
||||
packageInfo.dependencies[dependenceName] = `${getVersionPrefix(packageInfo.dependencies[dependenceName])}${dependenceVersion}`;
|
||||
} else if (packageInfo.devDependencies && packageInfo.devDependencies[dependenceName]) {
|
||||
if (!semver.satisfies(dependenceVersion, packageInfo.devDependencies[dependenceName])) {
|
||||
packageInfo.devDependencies[dependenceName] = `${getVersionPrefix(packageInfo.devDependencies[dependenceName])}${dependenceVersion}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`[VERSION] update package ${name} with version ${publishVersion}`);
|
||||
fs.writeFileSync(path.join(directory, 'package.json'), JSON.stringify(packageInfo, null, 2));
|
||||
});
|
||||
}
|
||||
|
||||
getPackageInfos().then((packageInfos: IPackageInfo[]) => {
|
||||
const shouldPublishPackages = packageInfos
|
||||
.filter((packageInfo) => packageInfo.shouldPublish);
|
||||
console.log('shouldPublishPackages', shouldPublishPackages);
|
||||
updatePackageVersion(shouldPublishPackages);
|
||||
});
|
38
scripts/versionCheck.ts
Normal file
38
scripts/versionCheck.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import * as semver from 'semver';
|
||||
import { getPackageInfos, IPackageInfo } from './getPackageInfos';
|
||||
|
||||
function checkPackageVersion(publishPackages: IPackageInfo[]) {
|
||||
publishPackages.forEach((publishPackage: IPackageInfo) => {
|
||||
const { publishVersion, localVersion, name, packageInfo } = publishPackage;
|
||||
if (publishVersion !== localVersion) {
|
||||
throw new Error(`[ERROR] version of package ${name} is not valid local verison: ${localVersion}`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < publishPackages.length; i++) {
|
||||
const dependenceName = publishPackages[i].name;
|
||||
const dependenceVersion = publishPackages[i].publishVersion;
|
||||
const dependencyInfo = `${dependenceName}${packageInfo.dependencies[dependenceName]}`;
|
||||
if (packageInfo.dependencies && packageInfo.dependencies[dependenceName]) {
|
||||
if (!semver.satisfies(dependenceVersion, packageInfo.dependencies[dependenceName])) {
|
||||
throw new Error(`[ERROR] dependency ${dependencyInfo} of package ${name}
|
||||
is not satisfied with verison ${dependenceVersion}`);
|
||||
}
|
||||
} else if (packageInfo.devDependencies && packageInfo.devDependencies[dependenceName]) {
|
||||
if (!semver.satisfies(dependenceVersion, packageInfo.devDependencies[dependenceName])) {
|
||||
throw new Error(`[ERROR] devDependency ${dependencyInfo} of package ${name}
|
||||
is not satisfied with verison ${dependenceVersion}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getPackageInfos().then((packageInfos: IPackageInfo[]) => {
|
||||
const shouldPublishPackages = packageInfos
|
||||
.filter((packageInfo) => packageInfo.shouldPublish);
|
||||
checkPackageVersion(shouldPublishPackages);
|
||||
console.log('[VERSION] check successfully');
|
||||
}).catch((e) => {
|
||||
console.trace(e.message);
|
||||
process.exit(128);
|
||||
});
|
42
scripts/watch.ts
Normal file
42
scripts/watch.ts
Normal file
@ -0,0 +1,42 @@
|
||||
/* eslint @typescript-eslint/explicit-function-return-type:0, no-shadow: 0 */
|
||||
import glob from 'glob';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as chokidar from 'chokidar';
|
||||
import { run } from './shell';
|
||||
|
||||
(async () => {
|
||||
await run('npm run clean');
|
||||
|
||||
const filePatten = '*/src/**/!(*.ts|*.tsx|*.rs)';
|
||||
console.log(`[COPY]: ${filePatten}`);
|
||||
const cwd = path.join(process.cwd(), 'packages');
|
||||
console.log('glob', glob);
|
||||
const files = glob.sync(filePatten, { cwd, nodir: true });
|
||||
/* eslint no-restricted-syntax:0 */
|
||||
for (const file of files) {
|
||||
/* eslint no-await-in-loop:0 */
|
||||
await copyOneFile(file, cwd);
|
||||
}
|
||||
|
||||
const watcher = chokidar.watch(cwd, { ignoreInitial: true });
|
||||
watcher
|
||||
.on('all', (event, filePath) => {
|
||||
const availableEvents = ['add', 'change'];
|
||||
if (availableEvents.includes(event)
|
||||
&& filePath.match(/.+[\\/]src[\\/].+\.(?!ts$|tsx$|rs$)/)) {
|
||||
console.log('non-ts change detected:', filePath);
|
||||
copyOneFile(path.relative(cwd, filePath), cwd);
|
||||
}
|
||||
});
|
||||
await run('npx tsc --build ./tsconfig.json -w');
|
||||
})().catch((e) => {
|
||||
console.trace(e);
|
||||
process.exit(128);
|
||||
});
|
||||
|
||||
async function copyOneFile(file, cwd) {
|
||||
const from = path.join(cwd, file);
|
||||
const to = path.join(cwd, file.replace(/\/src\//, '/lib/'));
|
||||
await fs.copy(from, to);
|
||||
}
|
123
test/utils/browser.ts
Normal file
123
test/utils/browser.ts
Normal file
@ -0,0 +1,123 @@
|
||||
import * as http from 'http';
|
||||
import * as url from 'url';
|
||||
import * as fse from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import * as puppeteer from 'puppeteer';
|
||||
|
||||
export interface IPage extends puppeteer.Page {
|
||||
html?: () => Promise<string>;
|
||||
$text?: (selector: string, trim?: boolean) => Promise<string|null>;
|
||||
$$text?: (selector: string, trim?: boolean) => Promise<(string|null)[]>;
|
||||
$attr?: (selector: string, attr: string) => Promise<string|null>;
|
||||
$$attr?: (selector: string, attr: string) => Promise<(string|null)[]>;
|
||||
push?: (url: string, options?: puppeteer.WaitForOptions & { referer?: string }) => Promise<puppeteer.HTTPResponse>;
|
||||
}
|
||||
|
||||
interface IBrowserOptions {
|
||||
cwd?: string;
|
||||
port?: number;
|
||||
server?: http.Server;
|
||||
}
|
||||
|
||||
export default class Browser {
|
||||
private server: http.Server;
|
||||
private browser: puppeteer.Browser;
|
||||
private baseUrl: string;
|
||||
|
||||
constructor (options: IBrowserOptions) {
|
||||
const { server } = options;
|
||||
if (server) {
|
||||
this.server = server;
|
||||
} else {
|
||||
const { cwd, port } = options;
|
||||
this.server = this.createServer(cwd, port);
|
||||
}
|
||||
}
|
||||
|
||||
createServer(cwd: string, port: number) {
|
||||
return http.createServer((req, res) => {
|
||||
const requrl: string = req.url || '';
|
||||
const pathname = `${cwd}${url.parse(requrl).pathname}`;
|
||||
if (fse.existsSync(pathname)) {
|
||||
switch (path.extname(pathname)) { // set HTTP HEAD
|
||||
case '.html':
|
||||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
break;
|
||||
case '.js':
|
||||
res.writeHead(200, { 'Content-Type': 'text/javascript' });
|
||||
break;
|
||||
case '.css':
|
||||
res.writeHead(200, { 'Content-Type': 'text/css' });
|
||||
break;
|
||||
case '.gif':
|
||||
res.writeHead(200, { 'Content-Type': 'image/gif' });
|
||||
break;
|
||||
case '.jpg':
|
||||
res.writeHead(200, { 'Content-Type': 'image/jpeg' });
|
||||
break;
|
||||
case '.png':
|
||||
res.writeHead(200, { 'Content-Type': 'image/png' });
|
||||
break;
|
||||
default:
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
});
|
||||
}
|
||||
fse.readFile(pathname, (_err, data) => {
|
||||
res.end(data);
|
||||
});
|
||||
} else {
|
||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||
res.end('<h1>404 Not Found</h1>');
|
||||
console.log(`${pathname} Not Found.`);
|
||||
}
|
||||
}).listen(port, '127.0.0.1');
|
||||
}
|
||||
|
||||
async start () {
|
||||
this.browser = await puppeteer.launch();
|
||||
}
|
||||
|
||||
async close () {
|
||||
if (!this.browser) { return }
|
||||
await this.browser.close();
|
||||
this.server.close();
|
||||
}
|
||||
|
||||
async page (url: string) {
|
||||
this.baseUrl = url;
|
||||
if (!this.browser) { throw new Error('Please call start() before page(url)'); }
|
||||
const page: IPage = await this.browser.newPage();
|
||||
await page.goto(url);
|
||||
page.push = (url, options) => page.goto(`${this.baseUrl}${url}`, options);
|
||||
page.html = () =>
|
||||
page.evaluate(() => window.document.documentElement.outerHTML);
|
||||
page.$text = (selector, trim) => page.$eval(selector, (el, trim) => {
|
||||
return trim ? (el.textContent || '').replace(/^\s+|\s+$/g, '') : el.textContent
|
||||
}, trim);
|
||||
page.$$text = (selector, trim) =>
|
||||
page.$$eval(selector, (els, trim) => els.map((el) => {
|
||||
return trim ? (el.textContent || '').replace(/^\s+|\s+$/g, '') : el.textContent
|
||||
}), trim);
|
||||
page.$attr = (selector, attr) => {
|
||||
return page.$eval(
|
||||
selector,
|
||||
(el: Element, ...args: unknown[]) => {
|
||||
const [] = args;
|
||||
return el.getAttribute(attr)
|
||||
},
|
||||
attr
|
||||
)
|
||||
};
|
||||
page.$$attr = (selector, attr) =>{
|
||||
return page.$$eval(
|
||||
selector,
|
||||
(els, ...args: unknown[]) => {
|
||||
return els.map(el => el.getAttribute(attr))
|
||||
},
|
||||
attr
|
||||
);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
}
|
52
test/utils/build.ts
Normal file
52
test/utils/build.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import * as path from 'path';
|
||||
import * as process from 'process';
|
||||
import { build } from 'build-scripts';
|
||||
import * as getPort from 'get-port';
|
||||
import Browser, { IPage } from './browser';
|
||||
import getBuiltInPlugins = require('../../packages/icejs/src/getBuiltInPlugins');
|
||||
|
||||
interface ISetupBrowser {
|
||||
(options: {
|
||||
example: string;
|
||||
outputDir?: string;
|
||||
defaultHtml?: string;
|
||||
}): Promise<IReturn>;
|
||||
}
|
||||
|
||||
interface IReturn {
|
||||
page: IPage;
|
||||
browser: Browser;
|
||||
}
|
||||
|
||||
// get builtIn plugins
|
||||
export const buildFixture = function(example: string) {
|
||||
test(`setup ${example}`, async () => {
|
||||
const rootDir = path.join(__dirname, `../../examples/${example}`);
|
||||
const processCwdSpy = jest.spyOn(process, 'cwd');
|
||||
processCwdSpy.mockReturnValue(rootDir);
|
||||
process.env.DISABLE_FS_CACHE = 'true';
|
||||
|
||||
await build({
|
||||
args: {
|
||||
config: path.join(rootDir, 'build.json'),
|
||||
},
|
||||
rootDir,
|
||||
getBuiltInPlugins: (userConfig) => {
|
||||
return getBuiltInPlugins(userConfig).concat(require.resolve('./test-plugin'));
|
||||
},
|
||||
});
|
||||
}, 120000);
|
||||
}
|
||||
|
||||
export const setupBrowser: ISetupBrowser = async (options) => {
|
||||
const { example, outputDir = 'build', defaultHtml = 'index.html' } = options;
|
||||
const rootDir = path.join(__dirname, `../../examples/${example}`);
|
||||
const port = await getPort();
|
||||
const browser = new Browser({ cwd: path.join(rootDir, outputDir), port });
|
||||
await browser.start();
|
||||
const page = await browser.page(`http://127.0.0.1:${port}/${defaultHtml}`);
|
||||
return {
|
||||
browser,
|
||||
page,
|
||||
}
|
||||
}
|
9
test/utils/executeCommand.ts
Normal file
9
test/utils/executeCommand.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { spawnSync } from 'child_process';
|
||||
|
||||
export default (order: string, cwd: string) => {
|
||||
const [command, ...args] = order.split(' ');
|
||||
spawnSync(command, args, {
|
||||
stdio: 'inherit',
|
||||
cwd,
|
||||
});
|
||||
}
|
51
test/utils/start.ts
Normal file
51
test/utils/start.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import * as path from 'path';
|
||||
import { start } from 'build-scripts';
|
||||
import * as getPort from 'get-port';
|
||||
import Browser, { IPage } from './browser';
|
||||
import { Server } from 'http';
|
||||
import getBuiltInPlugins = require('../../packages/icejs/src/getBuiltInPlugins');
|
||||
|
||||
interface ISetupBrowser {
|
||||
(options: { port: number; defaultPath?: string; server: Server; }): Promise<IReturn>;
|
||||
}
|
||||
|
||||
interface IReturn {
|
||||
page: IPage;
|
||||
browser: Browser;
|
||||
}
|
||||
|
||||
// get builtIn plugins
|
||||
export const startFixture = async function (example: string) {
|
||||
const port = await getPort();
|
||||
const rootDir = path.join(__dirname, `../../examples/${example}`);
|
||||
const processCwdSpy = jest.spyOn(process, 'cwd');
|
||||
processCwdSpy.mockReturnValue(rootDir);
|
||||
process.env.DISABLE_FS_CACHE = 'true';
|
||||
|
||||
const devServer = await start({
|
||||
args: {
|
||||
config: path.join(rootDir, 'build.json'),
|
||||
port,
|
||||
disableOpen: true
|
||||
},
|
||||
rootDir,
|
||||
getBuiltInPlugins: (userConfig) => {
|
||||
return getBuiltInPlugins(userConfig).concat(require.resolve('./test-plugin'));
|
||||
},
|
||||
}) as any as Server;
|
||||
return {
|
||||
port,
|
||||
devServer
|
||||
};
|
||||
};
|
||||
|
||||
export const setupStartBrowser: ISetupBrowser = async (options) => {
|
||||
const { port, server, defaultPath = '' } = options;
|
||||
const browser = new Browser({ server });
|
||||
await browser.start();
|
||||
const page = await browser.page(`http://127.0.0.1:${port}/${defaultPath}`);
|
||||
return {
|
||||
browser,
|
||||
page,
|
||||
};
|
||||
};
|
6
test/utils/test-plugin.ts
Normal file
6
test/utils/test-plugin.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export default ({ modifyUserConfig }) => {
|
||||
// disable minify to speed-up fixture builds
|
||||
modifyUserConfig('minify', false);
|
||||
// disable sourceMap to speed-up fixture start
|
||||
modifyUserConfig('sourceMap', false);
|
||||
}
|
12
tsconfig.base.json
Normal file
12
tsconfig.base.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES5",
|
||||
"jsx": "react",
|
||||
"experimentalDecorators": true,
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"allowJs": true
|
||||
}
|
||||
}
|
7
tsconfig.json
Normal file
7
tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "packages/plugin-app"},
|
||||
{ "path": "packages/icejs" }
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user