create-qs 0.0.0 → 0.8.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -2
- package/README.zh-CN.md +36 -0
- package/README.zh-TW.md +36 -0
- package/index.js +1883 -0
- package/package.json +33 -5
- package/template/default/.quicksilver/.gitattributes +4 -0
- package/template/default/.quicksilver/manual/en-US/00-setup.md +197 -0
- package/template/default/.quicksilver/manual/zh-CN/00-setup.md +197 -0
- package/template/default/.quicksilver/manual/zh-TW/00-setup.md +197 -0
- package/template/default/AGENTS.md +322 -0
- package/template/default/README.md +5 -0
- package/template/default/_gitignore +70 -0
- package/template/default/build.gradle.kts +5 -0
- package/template/default/eslint.config.js +137 -0
- package/template/default/gradle/repo.settings.gradle.kts +90 -0
- package/template/default/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/template/default/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/template/default/gradle.properties +15 -0
- package/template/default/gradlew +248 -0
- package/template/default/gradlew.bat +93 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/api/build.gradle.kts +8 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/api/src/main/kotlin/{{API_PACKAGE}}/AutoConfiguration.kt +25 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/api/src/main/resources/QUICKSILVER-INF/data/init.jsons +2 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/api/src/test/kotlin/{{API_PACKAGE}}/SmokeTests.kt +58 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/api/src/test/kotlin/{{API_PACKAGE}}/TestConfiguration.kt +6 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/module.yaml +8 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/web/package.json +25 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/web/src/module.ts +16 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/web/src/vite-env.d.ts +10 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/web/tsconfig.app.json +7 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/web/tsconfig.json +7 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/web/tsconfig.node.json +7 -0
- package/template/default/modules/{{MODULE_DIRECTORY}}/web/vite.config.ts +11 -0
- package/template/default/package.json +76 -0
- package/template/default/pnpm-workspace.yaml +35 -0
- package/template/default/publishing.yaml +49 -0
- package/template/default/quicksilver.yaml +13 -0
- package/template/default/run/api/build.gradle.kts +8 -0
- package/template/default/run/api/config/README.md +67 -0
- package/template/default/run/api/config/application-dev.yaml +25 -0
- package/template/default/run/api/config/application-h2.yaml +22 -0
- package/template/default/run/api/config/application-mariadb.yaml +22 -0
- package/template/default/run/api/config/application-mssql.yaml +22 -0
- package/template/default/run/api/config/application-oracle.yaml +22 -0
- package/template/default/run/api/config/application-postgresql.yaml +22 -0
- package/template/default/run/api/config/application-test.yaml +28 -0
- package/template/default/run/api/config/application.yaml +84 -0
- package/template/default/run/api/config/logback-test.xml +141 -0
- package/template/default/run/api/config/logback.xml +142 -0
- package/template/default/run/web/index.html +14 -0
- package/template/default/run/web/index.ts +6 -0
- package/template/default/run/web/package.json +18 -0
- package/template/default/run/web/static/config.js +15 -0
- package/template/default/run/web/tsconfig.app.json +4 -0
- package/template/default/run/web/tsconfig.json +7 -0
- package/template/default/run/web/tsconfig.node.json +4 -0
- package/template/default/run/web/vite.config.ts +21 -0
- package/template/default/settings.gradle.kts +19 -0
package/package.json
CHANGED
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-qs",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.8.21",
|
|
4
|
+
"description": "Create a full-stack Quicksilver project with a single command",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-qs": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"template/**/*",
|
|
12
|
+
"README.md",
|
|
13
|
+
"README.zh-CN.md",
|
|
14
|
+
"README.zh-TW.md"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"quicksilver",
|
|
18
|
+
"create-qs",
|
|
19
|
+
"scaffold",
|
|
20
|
+
"template",
|
|
21
|
+
"preact",
|
|
22
|
+
"typescript",
|
|
23
|
+
"vite"
|
|
24
|
+
],
|
|
25
|
+
"author": "Quicksilver Team",
|
|
5
26
|
"license": "MIT",
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"chalk": "^6.0.0",
|
|
29
|
+
"commander": "^15.0.0",
|
|
30
|
+
"enquirer": "^2.4.1",
|
|
31
|
+
"fs-extra": "^11.4.0"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=22.13.0"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Each language's manual/<language>/00-setup.md is committed, and every `pnpm install` rewrites it
|
|
2
|
+
# with LF line endings. Keep it LF in every checkout: with core.autocrlf (the Git for Windows
|
|
3
|
+
# default) it would be checked out as CRLF, and git status would report it modified after each install.
|
|
4
|
+
manual/*/00-setup.md text eol=lf
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# 00 Setup
|
|
2
|
+
|
|
3
|
+
This chapter covers: **requirements, basic setup, version control, starting the project, directory structure**
|
|
4
|
+
|
|
5
|
+
This chapter is committed with the project. The other chapters of the manual appear after `pnpm install`. This file is maintained by the platform and is overwritten when dependencies are installed again, so put the project's own notes in its README. The project name `power-crm` and the module directory `sales` in the examples only illustrate the directory structure.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
| Name | Version | Notes |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| JDK | **25** | The backend's `sourceCompatibility` / `jvmTarget` (set by the platform's Gradle plugin). A lower version fails to compile |
|
|
12
|
+
| Node.js | **`>=22.13.0`** | The minimum version pnpm 11 requires |
|
|
13
|
+
| pnpm | **11** | pnpm is required, npm and yarn are not supported. Workspaces, catalogs and `allowBuilds` all depend on pnpm.
|
|
14
|
+
| Gradle | No installation needed | The project ships the Gradle Wrapper (`./gradlew`), which downloads Gradle on first run |
|
|
15
|
+
| Database | No installation needed | A file-based H2 database is used by default. To use another database, see [01 Getting Started](01-getting-started.md#switching-databases) |
|
|
16
|
+
|
|
17
|
+
## Basic setup
|
|
18
|
+
|
|
19
|
+
Only the scaffolder `create-qs` is published on the public npm registry, **so creating a project needs no configuration**. The rest of the platform, namely the three groups of npm packages, the Quicksilver Gradle plugin and every Maven artifact (the platform's jars, base packages and runtimes), is published on the internal Nexus server. Both `pnpm install` and the first run of `./gradlew` need to reach it.
|
|
20
|
+
|
|
21
|
+
The address of the internal Nexus server is not made public, so a new project ships no repository address. The npm and Gradle repository addresses are both configured in the home directory, once per machine, and apply to every project on that machine. Before you start, get the following from whoever provides you with Quicksilver. The rest of this chapter refers to them by these names.
|
|
22
|
+
|
|
23
|
+
| Name | Description |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `NEXUS_MAVEN_URL` | The Maven repository address on the internal Nexus server, such as `https://nexus-server/repository/maven-public/` |
|
|
26
|
+
| `NEXUS_NPM_URL` | The npm repository address on the internal Nexus server, such as `https://nexus-server/repository/npm-public/` |
|
|
27
|
+
| `NEXUS_USER`, `NEXUS_PASSWORD` | The Nexus account and password, used only when the repository requires authentication |
|
|
28
|
+
|
|
29
|
+
Each configuration file is described below. Both files are in the home directory and apply to every project on the machine, and the account and password can only be configured there. To have the project itself specify the repository address, see [Using a different repository per project](#using-a-different-repository-per-project) at the end of this chapter.
|
|
30
|
+
|
|
31
|
+
### `~/.npmrc` (home directory)
|
|
32
|
+
|
|
33
|
+
The address and credentials of the npm repository. The `@qs-platform`, `@qs-elements` and `@qs-charts` scopes take one line each, and every other dependency is still fetched from the default registry.
|
|
34
|
+
|
|
35
|
+
```ini
|
|
36
|
+
@qs-platform:registry=NEXUS_NPM_URL
|
|
37
|
+
@qs-elements:registry=NEXUS_NPM_URL
|
|
38
|
+
@qs-charts:registry=NEXUS_NPM_URL
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
These three lines apply to every Quicksilver project on the machine, so new projects need no further configuration. When a single project needs another repository, see [Using a different repository per project](#using-a-different-repository-per-project) at the end of this chapter.
|
|
42
|
+
|
|
43
|
+
When the repository requires authentication, the token is kept in the same file, and it does not need to be edited by hand. Run the following command and enter `NEXUS_USER` and `NEXUS_PASSWORD` when prompted, and npm writes the token it obtains into the file. The password is not echoed and does not stay in the shell history.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm login --registry=NEXUS_NPM_URL --auth-type=legacy
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The line it writes looks like `//nexus-server/repository/npm-public/:_authToken=…`.
|
|
50
|
+
|
|
51
|
+
### `~/.gradle/gradle.properties` (home directory)
|
|
52
|
+
|
|
53
|
+
The address and credentials of the repository for the Gradle plugin and the Maven artifacts are all configured in this file. It applies to every project on the machine and takes precedence over keys of the same name in the project's root `gradle.properties`. In a new project's `gradle.properties`, `quicksilver.repo.url` is empty. When it is not set here either, the build stops at startup with an error that points to this chapter. The repository declarations for the plugin and the artifacts are in the project's `gradle/repo.settings.gradle.kts`, which only reads these keys. Do not edit that file.
|
|
54
|
+
|
|
55
|
+
```properties
|
|
56
|
+
quicksilver.repo.url=NEXUS_MAVEN_URL
|
|
57
|
+
# Add the following two lines only when the repository requires authentication
|
|
58
|
+
quicksilver.repo.user=NEXUS_USER
|
|
59
|
+
quicksilver.repo.password=NEXUS_PASSWORD
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The account and the password must be set together. When only one of them is set, the build stops at startup with an error. When neither is set, the repository is accessed anonymously. The account and password can only be written in this file. When they appear in the project's root `gradle.properties`, the build stops with an error as well, because that file is committed. A repository that requires authentication should use an `https://` address. Over an `http://` address the account and password travel in clear text.
|
|
63
|
+
|
|
64
|
+
The same account can also be used for publishing. In a new project's `publishing.yaml`, the `maven-credentials-prefix` of the publishing target is `quicksilver.repo`, so publishing reads the two lines above. See [08 Packaging and Deployment](08-packaging-deploy.md) for details.
|
|
65
|
+
|
|
66
|
+
When different projects need different repositories, see [Optional configuration](#using-a-different-repository-per-project) at the end of this chapter.
|
|
67
|
+
|
|
68
|
+
## Version control
|
|
69
|
+
|
|
70
|
+
A project created with `create-qs` should be put under version control early. A cloned project is already in a repository, so skip this section. Run the following commands in the project root.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
git init
|
|
74
|
+
git add -A
|
|
75
|
+
git commit -m "Initial commit"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The project template already includes a `.gitignore`. This manual and the skills are written by `pnpm install`. Apart from each language's `00-setup.md`, none of them is committed, and they do not show up in `git status` after dependencies are installed. The first install creates `pnpm-lock.yaml`, which records the exact versions of the dependencies and should be committed.
|
|
79
|
+
|
|
80
|
+
## Starting the project
|
|
81
|
+
|
|
82
|
+
Run the following commands in the project root.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pnpm i
|
|
86
|
+
pnpm dev
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Open <http://localhost:6286> in a browser and sign in as `admin` / `123456`.
|
|
90
|
+
|
|
91
|
+
> This account is **development seed data** in the core module's `init.jsons`, and its password is restored every time the development database is rebuilt. **Change it before deployment.**
|
|
92
|
+
|
|
93
|
+
The backend provides two health check addresses:
|
|
94
|
+
- <http://localhost:6288/api/metrics/status> returns UP as soon as the service starts accepting requests
|
|
95
|
+
- <http://localhost:6288/api/metrics/ready> returns 503 until the database has been initialized. **Use this one to tell whether the service is ready.**
|
|
96
|
+
|
|
97
|
+
## Directory structure
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
power-crm/
|
|
101
|
+
├── AGENTS.md Project instructions for AI coding assistants. Claude Code reads it from version 2.1.277
|
|
102
|
+
├── README.md Project description
|
|
103
|
+
├── quicksilver.yaml Product identity: title, Kotlin package, Maven coordinates, reserved namespaces, packaging
|
|
104
|
+
├── publishing.yaml Publishing targets and the packages to publish
|
|
105
|
+
├── package.json Project scripts (pnpm dev and others) and development tool dependencies
|
|
106
|
+
├── pnpm-workspace.yaml pnpm workspace and dependency version catalogs
|
|
107
|
+
├── settings.gradle.kts Gradle settings: sets the platform version and applies the repository declarations
|
|
108
|
+
├── build.gradle.kts Root Gradle build script: applies the Quicksilver plugin
|
|
109
|
+
├── gradle.properties Platform version, and the repository address for platform artifacts (empty in a new project)
|
|
110
|
+
├── gradlew, gradlew.bat Gradle Wrapper launch scripts. The configuration is in gradle/wrapper/
|
|
111
|
+
├── gradle/repo.settings.gradle.kts
|
|
112
|
+
│ Repository declarations for the platform plugin and artifacts, written when the project is created. Do not edit. For upgrades, see chapter 10 Upgrading
|
|
113
|
+
├── eslint.config.js ESLint configuration
|
|
114
|
+
├── .gitignore Version control ignore rules, which decide what is not committed
|
|
115
|
+
├── modules/sales/ Business module, where most day-to-day development happens
|
|
116
|
+
│ ├── module.yaml Module identity: id, code, namespaces, dependencies, web package name
|
|
117
|
+
│ ├── api/ Backend (Kotlin + Spring Boot)
|
|
118
|
+
│ │ └── src/main/resources/QUICKSILVER-INF/data/init.jsons ← initial data
|
|
119
|
+
│ └── web/ Frontend (Preact + TypeScript)
|
|
120
|
+
│ └── src/module.ts Registry of pages, plugins, components, styles and icons
|
|
121
|
+
├── run/
|
|
122
|
+
│ ├── api/ Spring Boot launcher project
|
|
123
|
+
│ │ └── config/ Runtime configuration, one application-<database>.yaml per database
|
|
124
|
+
│ └── web/ Vite development server entry
|
|
125
|
+
├── test/e2e/scenarios/ End-to-end test specs, created with the first spec. See chapter 07 Testing
|
|
126
|
+
├── local/ Local build output and configuration overrides (such as local/publishing.yaml), not committed
|
|
127
|
+
├── .quicksilver/
|
|
128
|
+
│ ├── .gitattributes Fixes the line endings of each language's 00-setup.md, committed
|
|
129
|
+
│ ├── manual/ This manual, one directory per language. Only each language's `00-setup.md`
|
|
130
|
+
│ │ is committed, the rest is written by `pnpm install`
|
|
131
|
+
│ └── generated/ Reference material fetched by `pnpm qs sources`, not committed
|
|
132
|
+
├── .agents/skills/ The product handbook and three development skills, written by `pnpm install`, not committed
|
|
133
|
+
└── .claude/skills/ Symbolic links to the skills above, so that Claude Code finds them.
|
|
134
|
+
Skills used only by Claude Code can be placed in this directory directly
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The manual and the skills are written by `pnpm install` from `@qs-platform/cli`, follow the CLI version, and are replaced as a whole each time, including the committed `00-setup.md`. Names starting with `qs-` belong to the platform, so give your own skills another prefix. When these directories are missing, run `pnpm qs docs`. Installing dependencies with `--ignore-scripts` does not write them, and running `pnpm install` again while the dependencies are unchanged does not restore them.
|
|
138
|
+
|
|
139
|
+
Keep the following two points in mind:
|
|
140
|
+
|
|
141
|
+
- **`run/` only assembles the modules and starts them. Do not write business code in it.** It usually needs no changes.
|
|
142
|
+
- **The working directory of the application process is `run/api`.** Relative paths such as `./local/...` in the configuration are relative to `run/api/`, not to the project root. A typical sign of a wrong path is an empty database, because the application has created a new database somewhere else.
|
|
143
|
+
|
|
144
|
+
## Next steps
|
|
145
|
+
|
|
146
|
+
After dependencies are installed, the other chapters of the manual appear in this directory. Start with the [table of contents](README.md), then read [01 Getting Started](01-getting-started.md), which explains the options chosen when creating a project, the common commands, and how to switch databases.
|
|
147
|
+
|
|
148
|
+
On first use, run `pnpm qs sources` once. It downloads the platform's API documentation, `init.jsons` and the frontend `.d.ts` files into `.quicksilver/generated/`, which later chapters of the manual refer to in many places.
|
|
149
|
+
|
|
150
|
+
## Optional configuration
|
|
151
|
+
|
|
152
|
+
### Using a different repository per project
|
|
153
|
+
|
|
154
|
+
Both files in the basic setup are in the home directory and apply to every project on the machine. When a single project needs another repository, or the repository address has to travel with the project and apply to everyone who clones it, configure it in the project instead. **npm and Gradle resolve precedence in opposite directions**, so they are configured differently.
|
|
155
|
+
|
|
156
|
+
For npm, `registries` in the project's root `pnpm-workspace.yaml` takes precedence over `~/.npmrc`. Adding that section to the project is enough, and the three lines in `~/.npmrc` can stay. A new project does not include this section.
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
registries:
|
|
160
|
+
'@qs-platform': NEXUS_NPM_URL
|
|
161
|
+
'@qs-elements': NEXUS_NPM_URL
|
|
162
|
+
'@qs-charts': NEXUS_NPM_URL
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
For Gradle the precedence is the other way around: keys in `~/.gradle/gradle.properties` override keys of the same name in every project. Remove `quicksilver.repo.url` from that file first, and fill in the key, empty in a new project, in each project's root `gradle.properties` instead.
|
|
166
|
+
|
|
167
|
+
When the repositories use different accounts, also give each project a credentials prefix. `quicksilver.repo.credentials` sets the prefix, and the account and password keys are the prefix plus `.user` and `.password`. When it is not set, the prefix is `quicksilver.repo`. The prefix name is up to you, and the example below uses `acme.repo`.
|
|
168
|
+
|
|
169
|
+
```properties
|
|
170
|
+
# gradle.properties in the project root
|
|
171
|
+
quicksilver.repo.url=NEXUS_MAVEN_URL
|
|
172
|
+
quicksilver.repo.credentials=acme.repo
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Write the account and password for that prefix in `~/.gradle/gradle.properties`.
|
|
176
|
+
|
|
177
|
+
```properties
|
|
178
|
+
acme.repo.user=NEXUS_USER
|
|
179
|
+
acme.repo.password=NEXUS_PASSWORD
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
When a project is pinned to another repository without a prefix, the build sends that repository the `quicksilver.repo.user` and `quicksilver.repo.password` account from the home directory. So when you pin a project to another repository, set a prefix as well. When you pin it to a repository that allows anonymous reads, add an empty `quicksilver.repo.credentials=` line to the project's root `gradle.properties`, and the build sends no account. When a prefix is set but its account or password is missing, the build stops at startup with an error.
|
|
183
|
+
|
|
184
|
+
For both npm and Gradle, the account and password can only be configured in files in the home directory. `registries` does not accept credentials, and the project's root `gradle.properties` is committed, so it should hold only the repository address and the prefix. The prefix itself is not a secret.
|
|
185
|
+
|
|
186
|
+
## Troubleshooting
|
|
187
|
+
|
|
188
|
+
| Symptom | Likely cause |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `pnpm install` retries for about a minute, then reports `ERR_PNPM_META_FETCH_FAIL ... fetch failed` | This machine cannot reach the configured npm repository address. The error message contains the address actually requested |
|
|
191
|
+
| `pnpm install` reports `ERR_PNPM_FETCH_404` on `@qs-platform/*` (or `@qs-elements/*`, `@qs-charts/*`) | The requested repository does not have the package. The address for that scope may be missing or wrong, so the request went to the public npm registry (these three groups of packages are only published on the internal Nexus server), or the address points to the wrong repository. The address can come from two places, and `registries` in `pnpm-workspace.yaml` takes precedence over `@scope:registry` in `~/.npmrc`. When both are set, check which one is in effect. Some repositories answer 404 instead of 401 when credentials are missing |
|
|
192
|
+
| `pnpm install` reports `ERR_PNPM_FETCH_401` | The repository requires authentication, but `~/.npmrc` has no credentials for that address, or the credentials are for a different address than the repository in effect |
|
|
193
|
+
| Gradle reports `quicksilver.repo.url is not set` at startup | The Maven repository address is set neither in the home directory nor in the project. Configure it as described in [Basic setup](#basic-setup) |
|
|
194
|
+
| Gradle reports `Half a login is set` at startup | Only one of the account and the password is set. Add the key named in the error message |
|
|
195
|
+
| Gradle reports `must not be in this project's gradle.properties` at startup | The account or the password is in the project's root `gradle.properties`. Move it to the home directory file named in the error message |
|
|
196
|
+
| Gradle cannot fetch `com.qsrun.quicksilver.*` artifacts or the plugin | Platform artifacts are only published on the internal Nexus server, not on Maven Central. Check `quicksilver.repo.url` in `~/.gradle/gradle.properties` (both the plugin and the artifacts read it). When that file does not set it, the key of the same name in the project's root `gradle.properties` is used |
|
|
197
|
+
| Gradle reports `Plugin [id: 'com.qsrun.quicksilver.gradle.root', ...] was not found` | The repository cannot be reached, or it requires authentication. This error never mentions 401. Rerun with `--info` to see `HTTP 401`. When authentication is required, configure `quicksilver.repo.user` and `quicksilver.repo.password` as described above |
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# 00 环境准备
|
|
2
|
+
|
|
3
|
+
本章内容:**环境要求、基础设置、纳入版本控制、项目启动、目录结构**
|
|
4
|
+
|
|
5
|
+
本章随项目提交,手册的其余章节在 `pnpm install` 之后才出现。本文件由平台维护,再次安装依赖时会被覆盖,项目自身的说明请写入 README。示例中的项目名 `power-crm` 与模块目录 `sales` 仅用于说明目录结构。
|
|
6
|
+
|
|
7
|
+
## 环境要求
|
|
8
|
+
|
|
9
|
+
| 名称 | 版本 | 说明 |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| JDK | **25** | 后端 `sourceCompatibility` / `jvmTarget` 的版本(由平台的 Gradle 插件设置),低于该值会编译失败 |
|
|
12
|
+
| Node.js | **`>=22.13.0`** | pnpm 11 要求的最低版本 |
|
|
13
|
+
| pnpm | **11** | 必须使用 pnpm,不支持 npm 与 yarn。workspace、catalog、`allowBuilds` 均依赖 pnpm。
|
|
14
|
+
| Gradle | 无需安装 | 项目自带 Gradle Wrapper(`./gradlew`),首次运行时自动下载 |
|
|
15
|
+
| 数据库 | 无需安装 | 默认使用文件型 H2 数据库。使用其他数据库见 [01 快速入门](01-getting-started.md#切换数据库) |
|
|
16
|
+
|
|
17
|
+
## 基础设置
|
|
18
|
+
|
|
19
|
+
公网 npmjs 上只发布了脚手架 `create-qs`,**因此无需任何配置即可创建项目**。平台的其余部分,包括三组 npm 包、Quicksilver 的 Gradle 插件以及全部 Maven 构件(平台的 jar、基础包与运行时),均发布在内部 Nexus 上,执行 `pnpm install` 与首次运行 `./gradlew` 时都需要能够访问它。
|
|
20
|
+
|
|
21
|
+
内部 Nexus 的地址不对外公开,因此新建的项目不预置任何仓库地址。npm 与 Gradle 的仓库地址都配置在用户目录,每台机器配置一次,对本机的所有项目生效。配置之前请先向提供 Quicksilver 的一方获取以下信息,本章后文直接使用这些名称。
|
|
22
|
+
|
|
23
|
+
| 名称 | 说明 |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `NEXUS_MAVEN_URL` | 内部 Nexus 的 Maven 仓库地址,形如 `https://nexus-server/repository/maven-public/` |
|
|
26
|
+
| `NEXUS_NPM_URL` | 内部 Nexus 的 npm 仓库地址,形如 `https://nexus-server/repository/npm-public/` |
|
|
27
|
+
| `NEXUS_USER`、`NEXUS_PASSWORD` | Nexus 的账户与密码,仅在仓库需要身份验证时使用 |
|
|
28
|
+
|
|
29
|
+
以下按配置文件逐一说明。两个文件均位于用户目录,对本机的所有项目生效,账户与密码只能配置在此处。需要由项目本身指定仓库地址时,见文末的[不同项目使用不同仓库](#不同项目使用不同仓库)。
|
|
30
|
+
|
|
31
|
+
### `~/.npmrc`(用户目录)
|
|
32
|
+
|
|
33
|
+
npm 包的仓库地址与凭据。`@qs-platform`、`@qs-elements`、`@qs-charts` 三个 scope 各占一行,其他依赖仍从默认源获取。
|
|
34
|
+
|
|
35
|
+
```ini
|
|
36
|
+
@qs-platform:registry=NEXUS_NPM_URL
|
|
37
|
+
@qs-elements:registry=NEXUS_NPM_URL
|
|
38
|
+
@qs-charts:registry=NEXUS_NPM_URL
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
以上三行对本机的所有 Quicksilver 项目生效,新建项目时无需重复配置。单个项目需要使用其他仓库时,见文末的[不同项目使用不同仓库](#不同项目使用不同仓库)。
|
|
42
|
+
|
|
43
|
+
仓库需要身份验证时,令牌同样保存在此文件中,无需手工编辑。执行以下命令并按提示输入 `NEXUS_USER` 与 `NEXUS_PASSWORD`,npm 会将获得的令牌写入该文件。密码输入不回显,也不会留在命令行历史中。
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm login --registry=NEXUS_NPM_URL --auth-type=legacy
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
写入的内容形如 `//nexus-server/repository/npm-public/:_authToken=…`。
|
|
50
|
+
|
|
51
|
+
### `~/.gradle/gradle.properties`(用户目录)
|
|
52
|
+
|
|
53
|
+
Gradle 插件与 Maven 构件的仓库地址及凭据统一配置在此文件中。此文件对本机所有项目生效,优先于项目根目录 `gradle.properties` 中的同名配置项。新建项目的 `gradle.properties` 中 `quicksilver.repo.url` 为空,此处也未设置时,构建在启动时报错并指向本章。插件与构件的仓库声明集中在项目的 `gradle/repo.settings.gradle.kts` 中,它只读取这些配置项,请勿修改该文件。
|
|
54
|
+
|
|
55
|
+
```properties
|
|
56
|
+
quicksilver.repo.url=NEXUS_MAVEN_URL
|
|
57
|
+
# 以下两行仅在仓库需要身份验证时添加
|
|
58
|
+
quicksilver.repo.user=NEXUS_USER
|
|
59
|
+
quicksilver.repo.password=NEXUS_PASSWORD
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
账户与密码须同时设置,只设置其中一项时构建在启动时报错。两项都不设置时以匿名方式访问。账户与密码只能写在此文件中,写入项目根目录的 `gradle.properties` 时构建同样会报错,因为该文件纳入版本库。需要身份验证的仓库应使用 `https://` 地址,使用 `http://` 地址时,账户与密码以明文传输。
|
|
63
|
+
|
|
64
|
+
同一组账户也可用于发布。新建项目的 `publishing.yaml` 中,发布目标的 `maven-credentials-prefix` 为 `quicksilver.repo`,发布时读取的正是上面两行,详见 [08 打包与部署](08-packaging-deploy.md)。
|
|
65
|
+
|
|
66
|
+
不同项目需要使用不同仓库时,见文末的[可选配置](#不同项目使用不同仓库)。
|
|
67
|
+
|
|
68
|
+
## 纳入版本控制
|
|
69
|
+
|
|
70
|
+
通过 `create-qs` 新建的项目,建议尽早纳入版本控制。克隆得到的项目已在版本库中,可跳过本节。在项目根目录执行以下命令。
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
git init
|
|
74
|
+
git add -A
|
|
75
|
+
git commit -m "Initial commit"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
项目模板已带有 `.gitignore`。本手册与 skill 由 `pnpm install` 写入,除各语言的 `00-setup.md` 外均不纳入版本库,安装依赖后也不会出现在 `git status` 中。首次安装依赖会生成 `pnpm-lock.yaml`,它记录依赖的确切版本,应当纳入版本库。
|
|
79
|
+
|
|
80
|
+
## 启动项目
|
|
81
|
+
|
|
82
|
+
在项目根目录执行以下命令。
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pnpm i
|
|
86
|
+
pnpm dev
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
在浏览器中访问 <http://localhost:6286>,使用 `admin` / `123456` 登录。
|
|
90
|
+
|
|
91
|
+
> 该账户是 core 模块 `init.jsons` 中的**开发种子数据**,开发数据库每次重建后都会恢复为此密码。**部署前必须修改。**
|
|
92
|
+
|
|
93
|
+
后端提供两个健康检查地址:
|
|
94
|
+
- <http://localhost:6288/api/metrics/status> 在服务开始接受请求后即返回 UP
|
|
95
|
+
- <http://localhost:6288/api/metrics/ready> 在数据库初始化完成之前返回 503,**判断服务是否可用应以它为准**。
|
|
96
|
+
|
|
97
|
+
## 目录结构
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
power-crm/
|
|
101
|
+
├── AGENTS.md AI 编码助手的项目指令。Claude Code 需要 2.1.277 或更高版本才会读取
|
|
102
|
+
├── README.md 项目说明
|
|
103
|
+
├── quicksilver.yaml 产品标识,包括标题、Kotlin 包、Maven 坐标、预占的命名空间、打包方式
|
|
104
|
+
├── publishing.yaml 发布目标与发布的包
|
|
105
|
+
├── package.json 项目脚本(pnpm dev 等)与开发工具依赖
|
|
106
|
+
├── pnpm-workspace.yaml pnpm 工作区与依赖版本目录
|
|
107
|
+
├── settings.gradle.kts Gradle 设置,指定平台版本并引入仓库声明
|
|
108
|
+
├── build.gradle.kts Gradle 根构建脚本,应用 Quicksilver 插件
|
|
109
|
+
├── gradle.properties 平台版本,以及平台构件仓库的地址(新建时为空)
|
|
110
|
+
├── gradlew, gradlew.bat Gradle Wrapper 启动脚本,配置位于 gradle/wrapper/
|
|
111
|
+
├── gradle/repo.settings.gradle.kts
|
|
112
|
+
│ 平台插件与构件的仓库声明,创建项目时写入,请勿修改。升级时的处理见 10 升级
|
|
113
|
+
├── eslint.config.js ESLint 配置
|
|
114
|
+
├── .gitignore 版本控制的忽略规则,决定哪些文件不纳入版本库
|
|
115
|
+
├── modules/sales/ 业务模块,日常开发主要在此进行
|
|
116
|
+
│ ├── module.yaml 模块标识,包括 id、code、namespaces、依赖、Web 包名
|
|
117
|
+
│ ├── api/ 后端(Kotlin + Spring Boot)
|
|
118
|
+
│ │ └── src/main/resources/QUICKSILVER-INF/data/init.jsons ← 初始化数据
|
|
119
|
+
│ └── web/ 前端(Preact + TypeScript)
|
|
120
|
+
│ └── src/module.ts 页面、插件、组件、样式、图标的注册表
|
|
121
|
+
├── run/
|
|
122
|
+
│ ├── api/ Spring Boot 启动工程
|
|
123
|
+
│ │ └── config/ 运行配置,每种数据库对应一份 application-<数据库>.yaml
|
|
124
|
+
│ └── web/ Vite 开发服务器入口
|
|
125
|
+
├── test/e2e/scenarios/ 端到端测试用例,编写第一个用例时创建,见 07 测试
|
|
126
|
+
├── local/ 本机的构建产物与配置覆盖(如 local/publishing.yaml),不纳入版本库
|
|
127
|
+
├── .quicksilver/
|
|
128
|
+
│ ├── .gitattributes 固定各语言 00-setup.md 的换行符,纳入版本库
|
|
129
|
+
│ ├── manual/ 本手册,按语言分目录。仅各语言的 `00-setup.md`
|
|
130
|
+
│ │ 纳入版本库,其余由 `pnpm install` 写入
|
|
131
|
+
│ └── generated/ `pnpm qs sources` 获取的参考资料,不纳入版本库
|
|
132
|
+
├── .agents/skills/ 产品手册与三个开发 skill,由 `pnpm install` 写入,不纳入版本库
|
|
133
|
+
└── .claude/skills/ 指向上述各 skill 的符号链接,供 Claude Code 发现。
|
|
134
|
+
仅供 Claude Code 使用的 skill 可直接放在此目录
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
手册与 skill 由 `pnpm install` 从 `@qs-platform/cli` 写入,随 CLI 版本更新,每次整体覆盖,已纳入版本库的 `00-setup.md` 同样会被覆盖。以 `qs-` 开头的名称归平台所有,自定义的 skill 请使用其他前缀。上述目录缺失时执行 `pnpm qs docs`。使用 `--ignore-scripts` 安装依赖时不会写入这些目录,依赖未变化时再次执行 `pnpm install` 也不会补回。
|
|
138
|
+
|
|
139
|
+
使用时注意以下两点:
|
|
140
|
+
|
|
141
|
+
- **`run/` 仅用于组装各模块并启动,不要在其中编写业务代码。** 该目录通常无需修改。
|
|
142
|
+
- **应用进程的工作目录是 `run/api`。** 配置中 `./local/...` 这类相对路径都相对于 `run/api/`,而不是项目根目录。路径写错时的典型表现是数据库为空,原因是应用在其他位置创建了新的数据库。
|
|
143
|
+
|
|
144
|
+
## 下一步
|
|
145
|
+
|
|
146
|
+
安装依赖后,本目录下会出现手册的其余章节。建议先阅读[手册目录](README.md),再阅读 [01 快速入门](01-getting-started.md),其中介绍创建项目时各选项的含义、常用命令以及如何切换数据库。
|
|
147
|
+
|
|
148
|
+
首次使用时建议执行一次 `pnpm qs sources`,将平台的接口文档、`init.jsons` 与前端 `.d.ts` 下载到 `.quicksilver/generated/`,手册后续多处会引用其中的内容。
|
|
149
|
+
|
|
150
|
+
## 可选配置
|
|
151
|
+
|
|
152
|
+
### 不同项目使用不同仓库
|
|
153
|
+
|
|
154
|
+
基础设置中的两个文件均位于用户目录,对本机的所有项目生效。单个项目需要使用其他仓库,或者需要仓库地址随项目一同分发、对克隆该项目的所有人生效时,改为在项目中配置。**npm 与 Gradle 的优先级相反**,两者的配置方式因此不同。
|
|
155
|
+
|
|
156
|
+
npm 方面,项目根目录 `pnpm-workspace.yaml` 中的 `registries` 优先于 `~/.npmrc`,在项目中添加该节即可生效,`~/.npmrc` 中的三行无需删除。新建的项目不预置该节。
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
registries:
|
|
160
|
+
'@qs-platform': NEXUS_NPM_URL
|
|
161
|
+
'@qs-elements': NEXUS_NPM_URL
|
|
162
|
+
'@qs-charts': NEXUS_NPM_URL
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Gradle 方面的优先级与此相反,`~/.gradle/gradle.properties` 中的配置项会覆盖所有项目的同名配置项,因此需先从该文件中删除 `quicksilver.repo.url`,改为在各项目根目录的 `gradle.properties` 中填写这个新建时为空的配置项。
|
|
166
|
+
|
|
167
|
+
各仓库使用不同的账户时,再为每个项目指定凭据前缀。`quicksilver.repo.credentials` 指定前缀,账户与密码的键名为前缀加 `.user` 与 `.password`,未设置时前缀为 `quicksilver.repo`。前缀的名称可以自定,以下示例使用 `acme.repo`。
|
|
168
|
+
|
|
169
|
+
```properties
|
|
170
|
+
# 项目根目录的 gradle.properties
|
|
171
|
+
quicksilver.repo.url=NEXUS_MAVEN_URL
|
|
172
|
+
quicksilver.repo.credentials=acme.repo
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`~/.gradle/gradle.properties` 中写入该前缀对应的账户与密码。
|
|
176
|
+
|
|
177
|
+
```properties
|
|
178
|
+
acme.repo.user=NEXUS_USER
|
|
179
|
+
acme.repo.password=NEXUS_PASSWORD
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
项目固定到其他仓库却未设置前缀时,构建会把用户目录中 `quicksilver.repo.user` 与 `quicksilver.repo.password` 这组账户发送给该仓库。因此固定到其他仓库时,应同时设置前缀。固定到允许匿名访问的仓库时,在项目根目录的 `gradle.properties` 中写一行留空的 `quicksilver.repo.credentials=`,构建将不发送任何账户。设置了前缀但缺少对应的账户或密码时,构建在启动时报错。
|
|
183
|
+
|
|
184
|
+
两者的账户与密码均只能配置在用户目录的文件中。`registries` 不接受凭据,项目根目录的 `gradle.properties` 纳入版本库,其中只宜配置仓库地址与前缀,前缀本身不属于机密信息。
|
|
185
|
+
|
|
186
|
+
## 故障排查
|
|
187
|
+
|
|
188
|
+
| 现象 | 可能的原因 |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `pnpm install` 重试约一分钟后报 `ERR_PNPM_META_FETCH_FAIL ... fetch failed` | 本机无法访问所配置的 npm 仓库地址,报错信息中包含实际请求的地址 |
|
|
191
|
+
| `pnpm install` 在 `@qs-platform/*`(或 `@qs-elements/*`、`@qs-charts/*`)上报 `ERR_PNPM_FETCH_404` | 所请求的仓库中没有该包。可能是该 scope 的仓库地址缺失或有误,请求被发往公网 npmjs(这三组包只发布在内部 Nexus 上),也可能是地址指向了错误的仓库。地址有两处来源,`pnpm-workspace.yaml` 的 `registries` 优先于 `~/.npmrc` 的 `@scope:registry`,两处均有配置时需确认实际生效的是哪一处。部分仓库在缺少凭据时返回 404 而不是 401 |
|
|
192
|
+
| `pnpm install` 报 `ERR_PNPM_FETCH_401` | 仓库需要身份验证,但 `~/.npmrc` 中没有该地址的凭据,或凭据所对应的地址与实际生效的仓库地址不一致 |
|
|
193
|
+
| Gradle 启动时报 `quicksilver.repo.url is not set` | 用户目录与项目中都没有设置 Maven 仓库地址,按[基础设置](#基础设置)配置 |
|
|
194
|
+
| Gradle 启动时报 `Half a login is set` | 账户与密码只设置了其中一项,补上报错信息中列出的配置项 |
|
|
195
|
+
| Gradle 启动时报 `must not be in this project's gradle.properties` | 账户或密码写入了项目根目录的 `gradle.properties`,将其移到报错信息给出的用户目录文件中 |
|
|
196
|
+
| Gradle 无法获取 `com.qsrun.quicksilver.*` 构件或插件 | 平台构件只发布在内部 Nexus 上,Maven Central 中没有。检查 `~/.gradle/gradle.properties` 中的 `quicksilver.repo.url`(插件与构件均读取该项)。此文件未设置时读取项目根目录 `gradle.properties` 中的同名配置项 |
|
|
197
|
+
| Gradle 报 `Plugin [id: 'com.qsrun.quicksilver.gradle.root', ...] was not found` | 无法访问仓库,或仓库需要身份验证。该错误不会提示 401,加 `--info` 重新执行可看到 `HTTP 401`。需要身份验证时,按上文配置 `quicksilver.repo.user` 与 `quicksilver.repo.password` |
|