create-qpq-app 0.1.16 → 0.1.18
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 +28 -10
- package/package.json +9 -6
- package/template/README.md +55 -103
- package/template/apps/qpqjs/packages/constants/src/QpqjsServiceEnum.ts +2 -0
- package/template/apps/qpqjs/packages/constants/src/index.ts +1 -0
- package/template/apps/qpqjs/packages/constants/src/smokeProbe.ts +13 -0
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/LandingPage.tsx +8 -6
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Actions.tsx +53 -0
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/CodeWindow.tsx +4 -4
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Footer.tsx +18 -29
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Hero.tsx +23 -32
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Infrastructure.tsx +130 -0
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/NavBar.tsx +24 -7
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Replay.tsx +221 -0
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Testing.tsx +123 -0
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/YieldLoop.tsx +15 -13
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/landing.css +652 -721
- package/template/apps/qpqjs/services/shell/views/src/index.html +2 -2
- package/template/apps/qpqjs/services/test/config/package.json +22 -0
- package/template/apps/qpqjs/services/test/config/src/index.ts +2 -0
- package/template/apps/qpqjs/services/test/config/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/test/config/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/test/models/package.json +22 -0
- package/template/apps/qpqjs/services/test/models/src/SmokeProbeRecord.ts +8 -0
- package/template/apps/qpqjs/services/test/models/src/SmokeRun.ts +14 -0
- package/template/apps/qpqjs/services/test/models/src/SmokeRunStatus.ts +5 -0
- package/template/apps/qpqjs/services/test/models/src/SmokeRunSummary.ts +8 -0
- package/template/apps/qpqjs/services/test/models/src/SmokeRunWithSummary.ts +7 -0
- package/template/apps/qpqjs/services/test/models/src/SmokeTestResult.ts +15 -0
- package/template/apps/qpqjs/services/test/models/src/SmokeTestStatus.ts +6 -0
- package/template/apps/qpqjs/services/test/models/src/index.ts +7 -0
- package/template/apps/qpqjs/services/test/models/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/test/models/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/test/service/package.json +9 -0
- package/template/apps/qpqjs/services/test/service/src/infrastructure.ts +19 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/config/defineSmoke.ts +102 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/constants/SMOKE_RUNS_STORE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/constants/githubOidc.ts +19 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/constants/index.ts +4 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/constants/smokeProbe.ts +14 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/constants/smokeRunQueue.ts +6 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/controller/askGetSmokeRun.ts +27 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/controller/askRunSmokeTests.ts +19 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/controller/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/data/askGetSmokeRunById.ts +16 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/data/askSaveSmokeRun.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/data/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/index.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/github/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/github/verifyGithubOidcToken.ts +105 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/smokeRun/askExecuteSmokeRun.ts +81 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/smokeRun/askFindSmokeRun.ts +11 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/smokeRun/askStartSmokeRun.ts +62 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/smokeRun/index.ts +4 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/smokeRun/summarizeSmokeRun.ts +25 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/models/GithubOidcClaims.ts +11 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/models/SmokeProbeEventQueueEvent.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/models/SmokeRunRequestedQueueEvent.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/models/index.ts +3 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/processors/github/getGithubOidcAuthProcessors.ts +67 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/processors/github/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/processors/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/queue/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/queue/onSmokeProbeEvent.ts +27 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/queue/onSmokeRunRequested.ts +15 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/SmokeTestDefinition.ts +8 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/askSmokeAssert.ts +12 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/crossService/askRunCrossServiceKeyValueStoreTest.ts +47 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/crossService/askRunCrossServiceStorageDriveTest.ts +46 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/crossService/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/eventBus/askRunEventBusTest.ts +57 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/eventBus/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/index.ts +10 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/keyValueStore/askRunKeyValueStoreTest.ts +71 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/keyValueStore/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/noop/askRunNoopTest.ts +7 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/noop/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/parameter/askRunParameterTest.ts +27 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/parameter/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/secret/askRunSecretTest.ts +16 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/secret/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/smokeTestRegistry.ts +29 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/storageDrive/askRunStorageDriveTest.ts +46 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/storageDrive/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/tsconfig.app.json +17 -0
- package/template/apps/qpqjs/services/test/service/tsconfig.json +8 -0
- package/template/apps/qpqjs/services/test/service-utils/package.json +22 -0
- package/template/apps/qpqjs/services/test/service-utils/src/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service-utils/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/test/service-utils/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/test/shared-logic/package.json +22 -0
- package/template/apps/qpqjs/services/test/shared-logic/src/index.ts +2 -0
- package/template/apps/qpqjs/services/test/shared-logic/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/test/shared-logic/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/test/x-logic/package.json +22 -0
- package/template/apps/qpqjs/services/test/x-logic/src/index.ts +2 -0
- package/template/apps/qpqjs/services/test/x-logic/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/test/x-logic/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/test/x-models/package.json +22 -0
- package/template/apps/qpqjs/services/test/x-models/src/index.ts +2 -0
- package/template/apps/qpqjs/services/test/x-models/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/test/x-models/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/testa/config/package.json +22 -0
- package/template/apps/qpqjs/services/testa/config/src/index.ts +2 -0
- package/template/apps/qpqjs/services/testa/config/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/testa/config/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/testa/models/package.json +22 -0
- package/template/apps/qpqjs/services/testa/models/src/CrossServiceKeyValueStoreProbeResult.ts +5 -0
- package/template/apps/qpqjs/services/testa/models/src/CrossServiceProbePayload.ts +4 -0
- package/template/apps/qpqjs/services/testa/models/src/CrossServiceStorageDriveProbeResult.ts +6 -0
- package/template/apps/qpqjs/services/testa/models/src/index.ts +3 -0
- package/template/apps/qpqjs/services/testa/models/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/testa/models/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/testa/service/package.json +9 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/config/defineCrossServiceProbe.ts +52 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/config/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/entry/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/entry/serviceFunction/index.ts +2 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/entry/serviceFunction/smokeCrossServiceKeyValueStoreProbe.ts +16 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/entry/serviceFunction/smokeCrossServiceStorageDriveProbe.ts +16 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/index.ts +3 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/logic/askProbeForeignKeyValueStore.ts +39 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/logic/askProbeForeignStorageDrive.ts +30 -0
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/logic/index.ts +2 -0
- package/template/apps/qpqjs/services/testa/service/src/infrastructure.ts +22 -0
- package/template/apps/qpqjs/services/testa/service/tsconfig.app.json +17 -0
- package/template/apps/qpqjs/services/testa/service/tsconfig.json +8 -0
- package/template/apps/qpqjs/services/testa/service-utils/package.json +22 -0
- package/template/apps/qpqjs/services/testa/service-utils/src/index.ts +2 -0
- package/template/apps/qpqjs/services/testa/service-utils/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/testa/service-utils/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/testa/shared-logic/package.json +22 -0
- package/template/apps/qpqjs/services/testa/shared-logic/src/index.ts +2 -0
- package/template/apps/qpqjs/services/testa/shared-logic/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/testa/shared-logic/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/testa/x-logic/package.json +22 -0
- package/template/apps/qpqjs/services/testa/x-logic/src/index.ts +2 -0
- package/template/apps/qpqjs/services/testa/x-logic/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/testa/x-logic/tsconfig.lib.json +19 -0
- package/template/apps/qpqjs/services/testa/x-models/package.json +22 -0
- package/template/apps/qpqjs/services/testa/x-models/src/index.ts +2 -0
- package/template/apps/qpqjs/services/testa/x-models/tsconfig.json +18 -0
- package/template/apps/qpqjs/services/testa/x-models/tsconfig.lib.json +19 -0
- package/template/docusaurus/DOCUMENTATION_CHECKLIST.md +0 -7
- package/template/docusaurus/docs/actions/core/config/ask-config-get-secret.md +15 -9
- package/template/docusaurus/docs/actions/core/network/ask-network-request.md +2 -1
- package/template/docusaurus/docs/actions/core/system/ask-batch.md +1 -0
- package/template/docusaurus/docs/actions/webserver/route-auth-validation/ask-route-auth-validation-decode.md +21 -10
- package/template/docusaurus/docs/index.md +2 -2
- package/template/docusaurus/docusaurus.config.ts +4 -4
- package/template/scripts/deployedSmoke.mjs +134 -0
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Features.tsx +0 -83
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Packages.tsx +0 -62
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Pipeline.tsx +0 -58
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/TronGrid.tsx +0 -587
- package/template/docusaurus/docs/actions/core/claude-ai/_category_.json +0 -7
- package/template/docusaurus/docs/actions/core/claude-ai/ask-claude-ai-messages-api.md +0 -70
- package/template/docusaurus/docs/config/core/claude-ai.md +0 -52
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# create-qpq-app
|
|
2
2
|
|
|
3
|
-
Scaffold a new [quidproquo](https://github.com/
|
|
3
|
+
Scaffold a new [quidproquo](https://github.com/qpqjs/quidproquo) app:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npx create-qpq-app my-app
|
|
@@ -8,9 +8,16 @@ cd my-app
|
|
|
8
8
|
npm run dev
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
You get a full
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
You get a full workspace with five services (`admin`, `auth`, `design`, `shell` and `todo`) that builds, runs locally on the qpq dev server, and deploys as a single docker image with `npm run deploy`.
|
|
12
|
+
|
|
13
|
+
The api comes up on `http://localhost:8080` and the web on `http://localhost:3080`:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
curl http://localhost:8080/api/shell/v1/health
|
|
17
|
+
# {"status":"healthy","service":"shell","checkedAt":"..."}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Node.js 24 or newer is required. Docker is only needed to deploy.
|
|
14
21
|
|
|
15
22
|
## Options
|
|
16
23
|
|
|
@@ -23,11 +30,22 @@ npx create-qpq-app <app-name> [options]
|
|
|
23
30
|
--no-install skip npm install
|
|
24
31
|
```
|
|
25
32
|
|
|
33
|
+
Pass `--language javascript` and you get the same app with type annotations stripped and JSX preserved, running on the same toolchain.
|
|
34
|
+
|
|
26
35
|
## How it works
|
|
27
36
|
|
|
28
|
-
The template is a snapshot of quidproquojs.com
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
The template is a snapshot of quidproquojs.com, a real and continuously built qpq workspace, captured into this package at publish time. Scaffolding runs a pipeline of self-contained steps: prune the docs site, prune the website app, apply your app's identity and domain, pin the quidproquo versions, git init, install.
|
|
38
|
+
|
|
39
|
+
The generated app pins the `quidproquo-*` versions this package was published with. The whole family releases in lockstep, so those versions are always a set that was built and tested together.
|
|
40
|
+
|
|
41
|
+
## Status
|
|
42
|
+
|
|
43
|
+
Pre-1.0 and under active development. The generated app changes shape between releases.
|
|
44
|
+
|
|
45
|
+
## Documentation
|
|
46
|
+
|
|
47
|
+
[docs.quidproquojs.com](https://docs.quidproquojs.com)
|
|
48
|
+
|
|
49
|
+
## License
|
|
50
|
+
|
|
51
|
+
MIT. See [LICENSE](https://github.com/qpqjs/quidproquo/blob/main/LICENSE).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-qpq-app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "Scaffold a new quidproquo app: npx create-qpq-app my-app",
|
|
5
5
|
"main": "./lib/commonjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"lib/**/*",
|
|
14
14
|
"template"
|
|
15
15
|
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
16
19
|
"scripts": {
|
|
17
20
|
"test": "vitest run",
|
|
18
21
|
"test:watch": "vitest",
|
|
@@ -23,7 +26,7 @@
|
|
|
23
26
|
"build:esm": "tsc -p tsconfig.esm.json",
|
|
24
27
|
"build:bin-perms": "node -e \"require('fs').chmodSync('lib/commonjs/bin/createQpqApp.js', 0o755)\"",
|
|
25
28
|
"snapshot-template": "node ./scripts/snapshotTemplate.mjs",
|
|
26
|
-
"
|
|
29
|
+
"scaffold-test": "node ./scripts/scaffoldTest.mjs",
|
|
27
30
|
"prepack": "npm run snapshot-template",
|
|
28
31
|
"lint": "npx eslint .",
|
|
29
32
|
"lint:fix": "npx eslint . --fix",
|
|
@@ -31,7 +34,7 @@
|
|
|
31
34
|
},
|
|
32
35
|
"repository": {
|
|
33
36
|
"type": "git",
|
|
34
|
-
"url": "git+https://github.com/
|
|
37
|
+
"url": "git+https://github.com/qpqjs/quidproquo.git"
|
|
35
38
|
},
|
|
36
39
|
"keywords": [
|
|
37
40
|
"quidproquo",
|
|
@@ -42,9 +45,9 @@
|
|
|
42
45
|
"author": "",
|
|
43
46
|
"license": "MIT",
|
|
44
47
|
"bugs": {
|
|
45
|
-
"url": "https://github.com/
|
|
48
|
+
"url": "https://github.com/qpqjs/quidproquo/issues"
|
|
46
49
|
},
|
|
47
|
-
"homepage": "https://github.com/
|
|
50
|
+
"homepage": "https://github.com/qpqjs/quidproquo#readme",
|
|
48
51
|
"dependencies": {
|
|
49
52
|
"@inquirer/prompts": "^8.5.2",
|
|
50
53
|
"prettier": "^3.2.5",
|
|
@@ -52,7 +55,7 @@
|
|
|
52
55
|
},
|
|
53
56
|
"devDependencies": {
|
|
54
57
|
"@types/node": "^22.13.13",
|
|
55
|
-
"quidproquo-tsconfig": "0.1.
|
|
58
|
+
"quidproquo-tsconfig": "0.1.18"
|
|
56
59
|
},
|
|
57
60
|
"bin": {
|
|
58
61
|
"create-qpq-app": "./lib/commonjs/bin/createQpqApp.js"
|
package/template/README.md
CHANGED
|
@@ -1,150 +1,102 @@
|
|
|
1
1
|
# quidproquojs.com
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
TypeScript npm workspaces, AWS Lambda service backends bundled with Rspack,
|
|
5
|
-
React microfrontend views built with Rspack + Module Federation, deployed with
|
|
6
|
-
AWS CDK.
|
|
3
|
+
The quidproquo framework's own website (app **qpqjs**), built with quidproquo itself: TypeScript npm workspaces, AWS Lambda service backends bundled with Rspack, React microfrontend views built with Rspack and Module Federation, deployed with AWS CDK.
|
|
7
4
|
|
|
8
|
-
This folder lives inside the quidproquo monorepo but is **not** one of its
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
always runs against the in-repo HEAD. Build the framework first
|
|
12
|
-
(`npm install && npm run build` at the repo root) before installing here.
|
|
5
|
+
This folder lives inside the quidproquo monorepo but is **not** one of its workspaces. It is a self-contained consumer app. All `quidproquo-*` dependencies are `file:../<pkg>` refs to the sibling packages, so the site always runs against the in-repo HEAD. Build the framework first (`npm install && npm run build` at the repo root) before installing here.
|
|
6
|
+
|
|
7
|
+
It doubles as the `create-qpq-app` template: the scaffolder snapshots this workspace at publish time, so anything broken here is broken in every new app.
|
|
13
8
|
|
|
14
9
|
## Getting started
|
|
15
10
|
|
|
16
|
-
>
|
|
17
|
-
> Run `nvm use` **before** `npm install` — on an older Node, `npm install`
|
|
18
|
-
> refuses to run (`engines` + `engine-strict`).
|
|
11
|
+
> Requires the repo's pinned Node version (see `.nvmrc`, currently 24.x). Run `nvm use` **before** `npm install`. On an older Node, `npm install` refuses to run (`engines` plus `engine-strict`).
|
|
19
12
|
|
|
20
13
|
```bash
|
|
21
|
-
nvm use #
|
|
22
|
-
npm install #
|
|
23
|
-
npm run build # build every workspace (libs
|
|
24
|
-
npm run
|
|
14
|
+
nvm use # always first: switches to the Node version in .nvmrc
|
|
15
|
+
npm install # deps, plus symlinks to the sibling quidproquo-* packages (file: refs)
|
|
16
|
+
npm run build # build every workspace (libs: tsc -b to dist; services: type-check)
|
|
17
|
+
npm run dev # full local dev stack: api dev server (:8080) and all views dev servers
|
|
25
18
|
```
|
|
26
19
|
|
|
27
|
-
Smoke test once
|
|
20
|
+
Smoke test once the dev server is up:
|
|
28
21
|
|
|
29
22
|
```bash
|
|
30
23
|
curl -H "Host: qpqjs.development.localhost" http://localhost:8080/api/shell/v1/health
|
|
31
|
-
#
|
|
24
|
+
# healthy response from the shell service
|
|
32
25
|
```
|
|
33
26
|
|
|
34
27
|
## Layout
|
|
35
28
|
|
|
36
29
|
```
|
|
37
30
|
apps/<app>/ # qpqjs
|
|
38
|
-
deploy.config.json # { "prefix", "domain" }
|
|
39
|
-
tsconfig.federated.json #
|
|
31
|
+
deploy.config.json # { "prefix", "domain" }: dns config for deploy
|
|
32
|
+
tsconfig.federated.json # generated by `npm run prep`: cross-view type aliases
|
|
40
33
|
packages/ # app-wide libs (config, constants, service-utils)
|
|
41
34
|
services/<svc>/
|
|
42
|
-
config, models, x-models, # per-service libs
|
|
35
|
+
config, models, x-models, # per-service libs, each builds to its own dist/
|
|
43
36
|
shared-logic, x-logic,
|
|
44
37
|
service-utils
|
|
45
|
-
service/ #
|
|
46
|
-
views/ #
|
|
47
|
-
docusaurus/ # docs site (docs.quidproquojs.com)
|
|
38
|
+
service/ # lambda backend (rspack bundle, built at deploy time)
|
|
39
|
+
views/ # react microfrontend (rspack + module federation)
|
|
40
|
+
docusaurus/ # docs site (docs.quidproquojs.com), built first
|
|
48
41
|
# (listed first in workspaces); the shell's 'docs'
|
|
49
42
|
# web entry auto-uploads docusaurus/build at deploy
|
|
50
43
|
```
|
|
51
44
|
|
|
52
|
-
There is no tools/ directory
|
|
53
|
-
`quidproquo-cli` package (the `qpq` bin — the root npm scripts are thin
|
|
54
|
-
aliases), with the rspack config builders in `quidproquo-deploy-rspack` and the
|
|
55
|
-
generic CDK app in `quidproquo-deploy-awscdk`.
|
|
45
|
+
There is no tools/ directory. All build, dev, and deploy orchestration ships in the `quidproquo-cli` package (the `qpq` bin, which the root npm scripts alias), with the rspack config builders in `quidproquo-deploy-rspack` and the generic CDK app in `quidproquo-deploy-awscdk`.
|
|
56
46
|
|
|
57
47
|
## How it fits together
|
|
58
48
|
|
|
59
|
-
- **Libraries** build to their own `dist/` with `tsc -b` (TypeScript project
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
`workspaces` array lists all lib globs ahead of `apps/*/services/*/service`.
|
|
65
|
-
- **Service backends** are bundled to AWS Lambda by Rspack, programmatically
|
|
66
|
-
at deploy time (`qpq go` calls `getServiceRspackConfig` from
|
|
67
|
-
`quidproquo-deploy-rspack`) — there are no per-service `rspack.config.ts`
|
|
68
|
-
files or `bundle` scripts. A service's `build` script only type-checks.
|
|
69
|
-
- **Views** are microfrontends built by Rspack + `@module-federation/enhanced`.
|
|
70
|
-
There are no per-view federation config files: exposes are computed at build
|
|
71
|
-
time from `// federated.export` markers, and remotes are discovered from
|
|
72
|
-
sibling views packages (dev port from each service's
|
|
73
|
-
`defineDevServerOptions({ port })` in its `infrastructure.ts`). The
|
|
74
|
-
only generated artifact is `apps/<app>/tsconfig.federated.json` — regenerate
|
|
75
|
-
with `npm run prep` after adding or removing a marker.
|
|
76
|
-
- **The dev server** (`qpq go:dev:api`, powered by `quidproquo-dev-server`) loads each service's
|
|
77
|
-
`infrastructure.ts` directly — no synth needed, just built libs. Its bundle
|
|
78
|
-
externalizes `node_modules` (an externals function in its rspack config) so native modules like
|
|
79
|
-
`sqlite3` load at runtime from their install location.
|
|
80
|
-
- **The `admin` service** owns the QPQ log/admin backbone: every service's
|
|
81
|
-
config references `defineAdminSettings(Admin, …)` + `logServiceName: Admin`,
|
|
82
|
-
so the dev server resolves log globals from the `admin` module. Running a
|
|
83
|
-
single service without `admin` spams `Global config qpq-log-retention-days
|
|
84
|
-
not found`.
|
|
49
|
+
- **Libraries** build to their own `dist/` with `tsc -b` (TypeScript project references, so only what changed rebuilds). Each lib's `package.json` `main`, `types`, and `exports` point at `dist/src`, and npm workspaces symlink it into `node_modules/@qpqjs/*`, so imports resolve like any npm package. Libs build before services because the root `workspaces` array lists all lib globs ahead of `apps/*/services/*/service`.
|
|
50
|
+
- **Service backends** are bundled to AWS Lambda by Rspack, programmatically at deploy time (`qpq go` calls `getServiceRspackConfig` from `quidproquo-deploy-rspack`). There are no per-service `rspack.config.ts` files or `bundle` scripts, and a service's `build` script only type-checks.
|
|
51
|
+
- **Views** are microfrontends built by Rspack and `@module-federation/enhanced`. There are no per-view federation config files: exposes are computed at build time from `// federated.export` markers, and remotes are discovered from sibling views packages (dev port from each service's `defineDevServerOptions({ port })` in its `infrastructure.ts`). The only generated artifact is `apps/<app>/tsconfig.federated.json`, regenerated with `npm run prep` after adding or removing a marker.
|
|
52
|
+
- **The dev server** (`npx qpq go:dev:api`, powered by `quidproquo-dev-server`) loads each service's `infrastructure.ts` directly, so no synth is needed, just built libs. Its bundle externalizes `node_modules` (an externals function in its rspack config) so native modules like `sqlite3` load at runtime from their install location.
|
|
53
|
+
- **The `admin` service** owns the log and admin backbone. Every service's config references `defineAdminSettings(Admin, …)` and `logServiceName: Admin`, so the dev server resolves log globals from the `admin` module. Running a single service without `admin` spams `Global config qpq-log-retention-days not found`.
|
|
85
54
|
|
|
86
55
|
## Commands
|
|
87
56
|
|
|
57
|
+
The root scripts are `build`, `validate-ts`, `lint`, `lint:fix`, `dev`, `deploy`, and `prep`. Anything else is a direct `npx qpq` call.
|
|
58
|
+
|
|
88
59
|
```bash
|
|
89
|
-
npm run build
|
|
90
|
-
|
|
91
|
-
npm run
|
|
92
|
-
npm run
|
|
93
|
-
npm run
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
60
|
+
npm run build # build only the libs (services and views are bundled, not built)
|
|
61
|
+
# scope with --workspace=@qpqjs/constants
|
|
62
|
+
npm run validate-ts # ts check: build libs, then typecheck every service and views
|
|
63
|
+
npm run prep # regenerate tsconfig.federated.json from // federated.export markers
|
|
64
|
+
npm run dev # api and web dev servers in one process (one ctrl+c stops the lot)
|
|
65
|
+
|
|
66
|
+
npx qpq go:dev:api # backend dev server only, on :8080, every service at /api/<svc>
|
|
67
|
+
npx qpq go:dev:web # all views rspack dev servers (host shell :3080, remotes on their
|
|
68
|
+
# ports); remotes resolve at runtime via mf-manifest.json
|
|
69
|
+
# subset: npx qpq go:dev:web --only host,shell,design
|
|
97
70
|
```
|
|
98
71
|
|
|
99
72
|
### App selection (multi-app)
|
|
100
73
|
|
|
101
|
-
Every app-facing
|
|
102
|
-
`go:dev:api`, `go:dev:web`) resolves its target app the same way:
|
|
74
|
+
Every app-facing command (`prep`, `synth`, `go`, `go:docker`, `go:dev`, `go:dev:api`, `go:dev:web`) resolves its target app the same way:
|
|
103
75
|
|
|
104
|
-
1. `--app <name
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
4. interactive prompt (TTY)
|
|
76
|
+
1. `--app <name>`. Through an npm script it **must come after `--`**: `npm run dev -- --app qpqjs`, because npm silently swallows flags before `--`
|
|
77
|
+
2. the command's env var (`QPQ_DEV_APP` for dev, `DEPLOY_APP_NAME` for synth and deploy)
|
|
78
|
+
3. exactly one app under `apps/`, which is then auto-selected
|
|
79
|
+
4. interactive prompt, when attached to a TTY
|
|
109
80
|
5. otherwise it prints the valid app list and exits 1
|
|
110
81
|
|
|
111
|
-
`prep` and `synth` also accept `--app all`. `synth <service>`
|
|
112
|
-
still infers the owning app. Unknown names print the valid list and exit 1.
|
|
82
|
+
`prep` and `synth` also accept `--app all`. A bare `qpq synth <service>` still infers the owning app. Unknown names print the valid list and exit 1.
|
|
113
83
|
|
|
114
84
|
## Deployment
|
|
115
85
|
|
|
116
86
|
```bash
|
|
117
|
-
npm run
|
|
118
|
-
|
|
119
|
-
|
|
87
|
+
npm run deploy # docker deploy (qpq go:docker)
|
|
88
|
+
npx qpq synth # writes dist/apps/<app>/infrastructure/<svc>-config.json for cdk
|
|
89
|
+
npx qpq go # interactive aws deploy: pick app, services, stacks (inf/api/web/views)
|
|
90
|
+
# bundles (rspack production), cdk deploy, and s3 sync per phase
|
|
120
91
|
```
|
|
121
92
|
|
|
122
|
-
`go` needs AWS credentials plus a deploy identity: either an
|
|
123
|
-
|
|
124
|
-
(`
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
-
|
|
131
|
-
|
|
132
|
-
`deploy.config.json` + the service's QPQ config; dev bundles use localhost
|
|
133
|
-
ports.
|
|
134
|
-
- `cdk.context.json` at the repo root is CDK's regenerable Route53 lookup
|
|
135
|
-
cache (written on first deploy; check it in so later synths need no live
|
|
136
|
-
AWS lookups).
|
|
137
|
-
|
|
138
|
-
## Adding a service (pattern from `mini`)
|
|
139
|
-
|
|
140
|
-
1. Create its `config/models/x-models/shared-logic/x-logic/service-utils` + `service`.
|
|
141
|
-
2. Each lib: `package.json` with `"build": "tsc -b"` (+ the dist-pointing
|
|
142
|
-
`main`/`types`/`exports`); `tsconfig.json` (extends root base, **no paths**,
|
|
143
|
-
references `./tsconfig.lib.json`) + `tsconfig.lib.json` (`composite`,
|
|
144
|
-
`outDir ./dist`, `rootDir .`, `references` to its workspace deps'
|
|
145
|
-
`tsconfig.lib.json`). No root-level list to touch — `npm run build --workspaces`
|
|
146
|
-
discovers the new lib automatically.
|
|
147
|
-
3. `service/`: add a `package.json` (`@qpqjs/<svc>-service`, `private`,
|
|
148
|
-
`"build": "tsc -p tsconfig.app.json"`) and a `tsconfig.app.json`.
|
|
149
|
-
No rspack.config.ts, no bundle script — `qpq go` bundles it by convention.
|
|
150
|
-
`npm run build` then picks it up automatically.
|
|
93
|
+
`qpq go` needs AWS credentials plus a deploy identity: either an `"environments"` map in `apps/<app>/deploy.config.json` (`{ "prefix", "domain", "environments": { "<env>": { "accountId", "region" } } }`, selected with `--env <name>`) or the legacy `ENVIRONMENT` and `AWS_DEFAULT_*` env vars. App-specific bootstrap and account extras live in `apps/<app>/bootstrap.qpq.ts` and `apps/<app>/account.qpq.ts` as config fragments; the identity plumbing is provided by the generic CDK app in `quidproquo-deploy-awscdk`.
|
|
94
|
+
|
|
95
|
+
- Production views bundles get prod remote URLs (`https://views.<feature>.<env>.<domain>/<svc>`) derived from `deploy.config.json` plus the service's qpq config. Dev bundles use localhost ports.
|
|
96
|
+
- `cdk.context.json` at the repo root is CDK's regenerable Route53 lookup cache. It is written on the first deploy, and checking it in means later synths need no live AWS lookups.
|
|
97
|
+
|
|
98
|
+
## Adding a service
|
|
99
|
+
|
|
100
|
+
1. Create its `config`, `models`, `x-models`, `shared-logic`, `x-logic`, `service-utils`, and `service` packages.
|
|
101
|
+
2. Each lib gets a `package.json` with `"build": "tsc -b"` and the dist-pointing `main`, `types`, and `exports`; a `tsconfig.json` (extends the root base, **no paths**, references `./tsconfig.lib.json`); and a `tsconfig.lib.json` (`composite`, `outDir ./dist`, `rootDir .`, with `references` to its workspace deps' `tsconfig.lib.json`). There is no root-level list to touch, since `npm run build --workspaces` discovers the new lib automatically.
|
|
102
|
+
3. `service/` gets a `package.json` (`@qpqjs/<svc>-service`, `private`, `"build": "tsc -p tsconfig.app.json"`) and a `tsconfig.app.json`. No rspack.config.ts and no bundle script, because `qpq go` bundles it by convention. `npm run build` then picks it up automatically.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Smoke probe resources owned by the test service and reached cross-service
|
|
2
|
+
// by testa (which declares them with owner: { module: test }). App-level
|
|
3
|
+
// because both services must agree on the names.
|
|
4
|
+
export const SMOKE_PROBE_STORE = 'smokeProbe';
|
|
5
|
+
// Lowercase with a hyphen: this becomes an S3 bucket name, which must be lowercase.
|
|
6
|
+
export const SMOKE_PROBE_DRIVE = 'smoke-probe';
|
|
7
|
+
|
|
8
|
+
// The testa service functions the cross-service smoke tests invoke, one per
|
|
9
|
+
// foreign grant (the store and the drive are separate IAM statements).
|
|
10
|
+
export const SMOKE_CROSS_SERVICE_KEY_VALUE_STORE_PROBE_FUNCTION_NAME =
|
|
11
|
+
'crossKvsProbe';
|
|
12
|
+
export const SMOKE_CROSS_SERVICE_STORAGE_DRIVE_PROBE_FUNCTION_NAME =
|
|
13
|
+
'crossDriveProbe';
|
package/template/apps/qpqjs/services/design/views/src/components/LandingPage/LandingPage.tsx
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
// federated.export: This file will be exported using module federation
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { Actions } from './components/Actions';
|
|
4
4
|
import { Footer } from './components/Footer';
|
|
5
5
|
import { Hero } from './components/Hero';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { Infrastructure } from './components/Infrastructure';
|
|
7
|
+
import { Replay } from './components/Replay';
|
|
8
|
+
import { Testing } from './components/Testing';
|
|
8
9
|
import { YieldLoop } from './components/YieldLoop';
|
|
9
10
|
import './landing.css';
|
|
10
11
|
|
|
11
12
|
export const LandingPage = () => (
|
|
12
13
|
<main>
|
|
13
14
|
<Hero />
|
|
14
|
-
<Features />
|
|
15
15
|
<YieldLoop />
|
|
16
|
-
<
|
|
17
|
-
<
|
|
16
|
+
<Replay />
|
|
17
|
+
<Testing />
|
|
18
|
+
<Infrastructure />
|
|
19
|
+
<Actions />
|
|
18
20
|
<Footer />
|
|
19
21
|
</main>
|
|
20
22
|
);
|
package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Actions.tsx
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
type ActionDomain = {
|
|
2
|
+
domain: string;
|
|
3
|
+
requester: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
// A sample, not the catalogue: enough to show the shape and the reach without
|
|
7
|
+
// turning the section into a reference page.
|
|
8
|
+
const DOMAINS: ActionDomain[] = [
|
|
9
|
+
{ domain: 'key value store', requester: 'askKeyValueStoreGet' },
|
|
10
|
+
{ domain: 'file', requester: 'askFileWriteTextContents' },
|
|
11
|
+
{ domain: 'queue', requester: 'askQueueSendMessages' },
|
|
12
|
+
{ domain: 'event bus', requester: 'askEventBusSendMessages' },
|
|
13
|
+
{ domain: 'user directory', requester: 'askUserDirectoryCreateUser' },
|
|
14
|
+
{ domain: 'websocket', requester: 'askWebsocketSendMessage' },
|
|
15
|
+
{ domain: 'network', requester: 'askNetworkRequest' },
|
|
16
|
+
{ domain: 'ai', requester: 'askAiPrompt' },
|
|
17
|
+
{
|
|
18
|
+
domain: 'graph database',
|
|
19
|
+
requester: 'askGraphDatabaseExecuteOpenCypherQuery',
|
|
20
|
+
},
|
|
21
|
+
{ domain: 'crypto', requester: 'askCryptoEncrypt' },
|
|
22
|
+
{ domain: 'metric', requester: 'askMetricPut' },
|
|
23
|
+
{ domain: 'config', requester: 'askConfigGetSecret' },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export function Actions() {
|
|
27
|
+
return (
|
|
28
|
+
<section className="section" id="actions">
|
|
29
|
+
<div className="section__head">
|
|
30
|
+
<p className="section__kicker">the surface</p>
|
|
31
|
+
<h2 className="section__title">What a story can ask for</h2>
|
|
32
|
+
<p className="section__sub">
|
|
33
|
+
Every capability is an action with a typed payload and a typed result.
|
|
34
|
+
Each platform supplies its own processor, so the story stays the same
|
|
35
|
+
wherever it runs.
|
|
36
|
+
</p>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div className="action-grid">
|
|
40
|
+
{DOMAINS.map((entry) => (
|
|
41
|
+
<div key={entry.domain} className="action-cell">
|
|
42
|
+
<span className="action-cell__domain">{entry.domain}</span>
|
|
43
|
+
<code className="action-cell__requester">{entry.requester}</code>
|
|
44
|
+
</div>
|
|
45
|
+
))}
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<p className="action-note">
|
|
49
|
+
25 domains · 91 action types · and your own, when you need one
|
|
50
|
+
</p>
|
|
51
|
+
</section>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -8,7 +8,7 @@ const cm = (text: string) => <span className="tok-cm">{text}</span>;
|
|
|
8
8
|
const pr = (text: string) => <span className="tok-pr">{text}</span>;
|
|
9
9
|
|
|
10
10
|
const LINES: ReactNode[] = [
|
|
11
|
-
<>{cm('//
|
|
11
|
+
<>{cm('// no SDK imports, no platform APIs')}</>,
|
|
12
12
|
<>
|
|
13
13
|
{kw('export function')}* {fn('askSendWelcomeEmail')}(
|
|
14
14
|
</>,
|
|
@@ -23,7 +23,7 @@ const LINES: ReactNode[] = [
|
|
|
23
23
|
<> </>,
|
|
24
24
|
<>
|
|
25
25
|
{' '}
|
|
26
|
-
{kw('yield')}* {fn('
|
|
26
|
+
{kw('yield')}* {fn('askQueueSendMessages')}({str("'email'")}, {'{'}
|
|
27
27
|
</>,
|
|
28
28
|
<>
|
|
29
29
|
{' '}
|
|
@@ -37,7 +37,7 @@ const LINES: ReactNode[] = [
|
|
|
37
37
|
<> </>,
|
|
38
38
|
<>
|
|
39
39
|
{' '}
|
|
40
|
-
{kw('yield')}* {fn('
|
|
40
|
+
{kw('yield')}* {fn('askEventBusSendMessages')}({'{'} userId {'}'});
|
|
41
41
|
</>,
|
|
42
42
|
<> </>,
|
|
43
43
|
<>
|
|
@@ -59,7 +59,7 @@ export function CodeWindow() {
|
|
|
59
59
|
<pre className="code-window__body">
|
|
60
60
|
<code>
|
|
61
61
|
{LINES.map((line, index) => (
|
|
62
|
-
<span className="code-line"
|
|
62
|
+
<span key={index} className="code-line">
|
|
63
63
|
<span className="code-line__num">{index + 1}</span>
|
|
64
64
|
<span className="code-line__text">{line}</span>
|
|
65
65
|
</span>
|
package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Footer.tsx
CHANGED
|
@@ -1,40 +1,29 @@
|
|
|
1
|
-
import { useRef } from 'react';
|
|
2
|
-
|
|
3
1
|
import { InstallChip } from './InstallChip';
|
|
4
|
-
import { TronGrid } from './TronGrid';
|
|
5
2
|
|
|
6
3
|
export function Footer() {
|
|
7
|
-
const panelRef = useRef<HTMLDivElement>(null);
|
|
8
|
-
|
|
9
4
|
return (
|
|
10
5
|
<footer className="footer">
|
|
11
6
|
<div className="footer__cta">
|
|
12
|
-
<
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
href="https://github.com/joe-coady/quidproquo"
|
|
30
|
-
rel="noreferrer"
|
|
31
|
-
target="_blank"
|
|
32
|
-
>
|
|
33
|
-
Star on GitHub
|
|
34
|
-
</a>
|
|
35
|
-
</div>
|
|
7
|
+
<p className="section__kicker">get started</p>
|
|
8
|
+
<h2 className="footer__cta-title">Write your first story</h2>
|
|
9
|
+
<p className="footer__cta-sub">
|
|
10
|
+
One command scaffolds a full app: five services, a local dev server
|
|
11
|
+
and a one-image docker deploy. Yield an action, and the runtime takes
|
|
12
|
+
it from there.
|
|
13
|
+
</p>
|
|
14
|
+
<div className="footer__cta-actions">
|
|
15
|
+
<InstallChip />
|
|
16
|
+
<a
|
|
17
|
+
className="btn btn--ghost"
|
|
18
|
+
href="https://github.com/qpqjs/quidproquo"
|
|
19
|
+
rel="noreferrer"
|
|
20
|
+
target="_blank"
|
|
21
|
+
>
|
|
22
|
+
Star on GitHub
|
|
23
|
+
</a>
|
|
36
24
|
</div>
|
|
37
25
|
</div>
|
|
26
|
+
|
|
38
27
|
<div className="footer__base">
|
|
39
28
|
<div className="footer__base-inner">
|
|
40
29
|
<span>quidproquo · MIT license</span>
|
package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Hero.tsx
CHANGED
|
@@ -1,60 +1,51 @@
|
|
|
1
|
-
import { useRef } from 'react';
|
|
2
|
-
|
|
3
1
|
import { CodeWindow } from './CodeWindow';
|
|
4
2
|
import { InstallChip } from './InstallChip';
|
|
5
3
|
import { NavBar } from './NavBar';
|
|
6
|
-
import { TronGrid } from './TronGrid';
|
|
7
4
|
|
|
8
5
|
export function Hero() {
|
|
9
|
-
const copyRef = useRef<HTMLDivElement>(null);
|
|
10
|
-
const panelRef = useRef<HTMLDivElement>(null);
|
|
11
|
-
|
|
12
6
|
return (
|
|
13
|
-
|
|
14
|
-
<TronGrid avoidRefs={[copyRef, panelRef]} />
|
|
7
|
+
<>
|
|
15
8
|
<NavBar />
|
|
16
9
|
|
|
17
|
-
<
|
|
18
|
-
<div
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
</
|
|
10
|
+
<section className="hero" id="top">
|
|
11
|
+
<div aria-hidden="true" className="hero__grid" />
|
|
12
|
+
<div aria-hidden="true" className="hero__glow" />
|
|
13
|
+
|
|
14
|
+
<div className="hero__inner">
|
|
15
|
+
<p className="hero__kicker">functional · action-based · typescript</p>
|
|
23
16
|
|
|
24
17
|
<h1 className="hero__title">
|
|
25
|
-
|
|
18
|
+
Pure business logic.
|
|
26
19
|
<br />
|
|
27
|
-
<span className="hero__title-
|
|
20
|
+
<span className="hero__title-dim">Platform agnostic.</span>
|
|
28
21
|
</h1>
|
|
29
22
|
|
|
30
23
|
<p className="hero__sub">
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
Your logic is a generator function (a <em>story</em>) that yields
|
|
25
|
+
typed actions, never a platform API. A processor per platform
|
|
26
|
+
decides how each action actually runs: Lambda, a container, the
|
|
27
|
+
browser.
|
|
35
28
|
</p>
|
|
36
29
|
|
|
37
30
|
<div className="hero__cta">
|
|
38
|
-
<
|
|
39
|
-
|
|
31
|
+
<InstallChip />
|
|
32
|
+
<a className="btn btn--ghost" href="#loop">
|
|
33
|
+
See how it works
|
|
40
34
|
<span className="btn__arrow">→</span>
|
|
41
35
|
</a>
|
|
42
|
-
<InstallChip />
|
|
43
36
|
</div>
|
|
44
37
|
|
|
45
|
-
<
|
|
38
|
+
<p className="hero__meta">
|
|
46
39
|
<span>MIT licensed</span>
|
|
47
|
-
<span>zero side effects</span>
|
|
48
|
-
<span>
|
|
49
|
-
</
|
|
40
|
+
<span>zero side effects in your logic</span>
|
|
41
|
+
<span>infrastructure from config</span>
|
|
42
|
+
</p>
|
|
50
43
|
</div>
|
|
51
44
|
|
|
52
|
-
<div
|
|
45
|
+
<div className="hero__panel">
|
|
53
46
|
<CodeWindow />
|
|
54
47
|
</div>
|
|
55
|
-
</
|
|
56
|
-
|
|
57
|
-
<div aria-hidden="true" className="hero__fade" />
|
|
58
|
-
</section>
|
|
48
|
+
</section>
|
|
49
|
+
</>
|
|
59
50
|
);
|
|
60
51
|
}
|