create-qpq-app 0.1.18 → 0.1.20
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/lib/commonjs/steps/006_applyDomain.js +3 -8
- package/lib/commonjs/steps/006_applyDomain.js.map +1 -1
- package/lib/commonjs/steps/013_printNextSteps.js +1 -1
- package/lib/commonjs/steps/013_printNextSteps.js.map +1 -1
- package/lib/esm/steps/006_applyDomain.js +3 -8
- package/lib/esm/steps/006_applyDomain.js.map +1 -1
- package/lib/esm/steps/013_printNextSteps.js +1 -1
- package/lib/esm/steps/013_printNextSteps.js.map +1 -1
- package/package.json +2 -2
- package/template/README.md +6 -3
- package/template/apps/qpqjs/account.qpq.ts +5 -13
- package/template/apps/qpqjs/bootstrap.qpq.ts +29 -14
- package/template/apps/qpqjs/deploy.config.json +0 -1
- package/template/apps/qpqjs/packages/constants/src/domain.ts +3 -1
- package/template/apps/qpqjs/packages/service-utils/src/defineQpqjsService.ts +15 -9
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/Infrastructure.tsx +1 -2
- package/template/apps/qpqjs/services/shell/service/src/infrastructure.ts +1 -4
- package/template/apps/qpqjs/services/test/models/package.json +2 -1
- package/template/apps/qpqjs/services/test/models/src/EchoRequest.ts +8 -0
- package/template/apps/qpqjs/services/test/models/src/EchoResponse.ts +9 -0
- package/template/apps/qpqjs/services/test/models/src/SmokeRun.ts +11 -9
- package/template/apps/qpqjs/services/test/models/src/SmokeRunStarted.ts +8 -0
- package/template/apps/qpqjs/services/test/models/src/SmokeRunSummary.ts +10 -6
- package/template/apps/qpqjs/services/test/models/src/SmokeRunWithSummary.ts +9 -5
- package/template/apps/qpqjs/services/test/models/src/SmokeTestResult.ts +11 -9
- package/template/apps/qpqjs/services/test/models/src/index.ts +3 -0
- package/template/apps/qpqjs/services/test/service/src/echo/config/defineEcho.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/echo/controller/echo.ts +32 -0
- package/template/apps/qpqjs/services/test/service/src/echo/controller/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/infrastructure.ts +6 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/config/defineSmoke.ts +83 -18
- package/template/apps/qpqjs/services/test/service/src/smoke/constants/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/constants/smokeEventDoc.ts +27 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/constants/smokeRunQueue.ts +4 -4
- package/template/apps/qpqjs/services/test/service/src/smoke/controller/askRunSmokeTests.ts +5 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/data/askRecordSmokeTestResult.ts +32 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/data/askSetSmokeRunOutcome.ts +24 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/data/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/eventDoc/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/eventDoc/smokeProbeDocDefinition.ts +74 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/smokeRun/askExecuteSmokeTest.ts +97 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/smokeRun/askStartSmokeRun.ts +18 -10
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/smokeRun/index.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/models/SmokeEventDocAppendQueueEvent.ts +15 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/models/SmokeEventDocMark.ts +8 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/models/SmokeTestRequestedQueueEvent.ts +12 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/models/index.ts +3 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/queue/index.ts +2 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/queue/onSmokeEventDocAppend.ts +64 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/queue/onSmokeTestRequested.ts +17 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/SmokeTestDefinition.ts +7 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/eventDoc/askAssertContiguousEventIds.ts +18 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/eventDoc/askAssertSmokeProbeDocState.ts +32 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/eventDoc/askAwaitSmokeEventDocLog.ts +35 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/eventDoc/askRunEventDocConcurrentAppendTest.ts +82 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/eventDoc/askRunEventDocInterleavedBatchAppendTest.ts +110 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/eventDoc/index.ts +5 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/openApi/askRunEchoRoundTripTest.ts +45 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/openApi/askRunOpenApiDocumentTest.ts +42 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/openApi/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/schedule/askRunScheduleTest.ts +88 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/schedule/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/smokeTestRegistry.ts +20 -2
- package/template/apps/qpqjs/services/test/service/src/tick/config/defineTick.ts +50 -0
- package/template/apps/qpqjs/services/test/service/src/tick/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/tick/constants/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/tick/constants/scheduleTickName.ts +3 -0
- package/template/apps/qpqjs/services/test/service/src/tick/constants/scheduleTickStore.ts +3 -0
- package/template/apps/qpqjs/services/test/service/src/tick/entry/kvsStream/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/tick/entry/kvsStream/onScheduleTickStream.ts +41 -0
- package/template/apps/qpqjs/services/test/service/src/tick/entry/schedule/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/tick/entry/schedule/onTick.ts +45 -0
- package/template/apps/qpqjs/services/test/service/src/tick/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/tick/models/ScheduleTickRecord.ts +17 -0
- package/template/apps/qpqjs/services/test/service/src/tick/models/index.ts +1 -0
- package/template/apps/todo/deploy.config.json +0 -1
- package/template/apps/todo/packages/constants/src/domain.ts +2 -1
- package/template/apps/todo/packages/service-utils/src/defineTodoService.ts +5 -6
- package/template/apps/todo/services/shell/service/src/infrastructure.ts +1 -3
- package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-upsert-with-retry.md +2 -2
- package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-upsert.md +2 -1
- package/template/docusaurus/docs/actions/features/event-doc/ask-event-doc-append-server-event.md +1 -1
- package/template/docusaurus/docs/actions/features/event-doc/ask-event-doc-create.md +1 -1
- package/template/docusaurus/docs/actions/features/event-doc/ask-event-doc-event-append.md +18 -12
- package/template/docusaurus/docs/actions/features/event-doc/ask-event-doc-event-list.md +4 -4
- package/template/docusaurus/docs/actions/features/event-doc/ask-event-doc-event-write.md +6 -6
- package/template/docusaurus/docs/actions/features/event-doc/ask-event-doc-get-by-id.md +2 -2
- package/template/docusaurus/docs/actions/features/event-doc/ask-event-doc-get-draft.md +2 -2
- package/template/docusaurus/docs/actions/webserver/dns/ask-dns-list.md +9 -8
- package/template/docusaurus/docs/actions/webserver/dns/ask-dns-resolve-hosts.md +42 -0
- package/template/docusaurus/docs/actions/webserver/open-api/_category_.json +1 -0
- package/template/docusaurus/docs/actions/webserver/open-api/ask-open-api-get-document.md +41 -0
- package/template/docusaurus/docs/config/config-aws/account-github-oidc-provider.md +31 -0
- package/template/docusaurus/docs/config/config-aws/domain-certificate.md +16 -32
- package/template/docusaurus/docs/config/config-aws/email-sender-allow-list.md +7 -14
- package/template/docusaurus/docs/config/config-aws/github-deploy-role.md +68 -0
- package/template/docusaurus/docs/config/core/recurring-schedule.md +31 -28
- package/template/docusaurus/docs/config/core/user-directory.md +2 -3
- package/template/docusaurus/docs/config/features/admin-settings.md +2 -6
- package/template/docusaurus/docs/config/features/event-doc-summary.md +2 -2
- package/template/docusaurus/docs/config/features/open-api-routes.md +82 -0
- package/template/docusaurus/docs/config/features/tenanted-web-socket-queue.md +2 -3
- package/template/docusaurus/docs/config/features/web-socket-queue.md +1 -5
- package/template/docusaurus/docs/config/webserver/api.md +6 -9
- package/template/docusaurus/docs/config/webserver/cache.md +1 -1
- package/template/docusaurus/docs/config/webserver/dns.md +25 -17
- package/template/docusaurus/docs/config/webserver/domain-proxy.md +1 -5
- package/template/docusaurus/docs/config/webserver/email-sender.md +9 -15
- package/template/docusaurus/docs/config/webserver/route.md +1 -0
- package/template/docusaurus/docs/config/webserver/seo.md +1 -1
- package/template/docusaurus/docs/config/webserver/web-entry.md +0 -5
- package/template/docusaurus/docs/config/webserver/websocket.md +3 -7
- package/template/docusaurus/docs/domains.md +76 -0
- package/template/docusaurus/docs/use-cases.md +0 -6
- package/template/docusaurus/docusaurus.config.ts +38 -14
- package/template/docusaurus/sidebars.ts +5 -5
- package/template/docusaurus/src/components/HomepageFeatures/index.tsx +2 -2
- package/template/scripts/deployedSmoke.mjs +73 -87
- package/template/scripts/localSmoke.mjs +188 -0
- package/template/scripts/smoke/runEdgeChecks.mjs +152 -0
- package/template/scripts/smoke/runSmokeRun.mjs +100 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/logic/smokeRun/askExecuteSmokeRun.ts +0 -81
- package/template/apps/qpqjs/services/test/service/src/smoke/models/SmokeRunRequestedQueueEvent.ts +0 -9
- package/template/apps/qpqjs/services/test/service/src/smoke/queue/onSmokeRunRequested.ts +0 -15
- package/template/docusaurus/docs/actions/webserver/open-api-spec/_category_.json +0 -1
- package/template/docusaurus/docs/actions/webserver/open-api-spec/ask-get-open-api-spec.md +0 -43
- package/template/docusaurus/docs/config/webserver/open-api.md +0 -36
|
@@ -14,19 +14,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.applyDomain = void 0;
|
|
16
16
|
const path_1 = __importDefault(require("path"));
|
|
17
|
-
const readJsonFile_1 = require("../lib/readJsonFile");
|
|
18
17
|
const replaceInFileExact_1 = require("../lib/replaceInFileExact");
|
|
19
|
-
|
|
20
|
-
//
|
|
21
|
-
//
|
|
18
|
+
// The template's domain, replaced where it's authoritative: the app's domain
|
|
19
|
+
// constant (everything else derives from it). One root at scaffold time; more
|
|
20
|
+
// can be appended later.
|
|
22
21
|
const TEMPLATE_DOMAIN = 'todo.quidproquojs.com';
|
|
23
22
|
exports.applyDomain = {
|
|
24
23
|
name: 'Applying domain',
|
|
25
24
|
run: (_a) => __awaiter(void 0, [_a], void 0, function* ({ targetDirectory, answers }) {
|
|
26
|
-
const deployConfigPath = path_1.default.join(targetDirectory, 'apps', answers.appName, 'deploy.config.json');
|
|
27
|
-
const deployConfig = (0, readJsonFile_1.readJsonFile)(deployConfigPath);
|
|
28
|
-
deployConfig.domain = answers.domain;
|
|
29
|
-
(0, writeJsonFile_1.writeJsonFile)(deployConfigPath, deployConfig);
|
|
30
25
|
(0, replaceInFileExact_1.replaceInFileExact)(path_1.default.join(targetDirectory, 'apps', answers.appName, 'packages', 'constants', 'src', 'domain.ts'), TEMPLATE_DOMAIN, answers.domain);
|
|
31
26
|
}),
|
|
32
27
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"006_applyDomain.js","sourceRoot":"","sources":["../../../src/steps/006_applyDomain.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,gDAAwB;AAExB,
|
|
1
|
+
{"version":3,"file":"006_applyDomain.js","sourceRoot":"","sources":["../../../src/steps/006_applyDomain.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,gDAAwB;AAExB,kEAA+D;AAG/D,6EAA6E;AAC7E,8EAA8E;AAC9E,yBAAyB;AACzB,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAEnC,QAAA,WAAW,GAAqB;IAC3C,IAAI,EAAE,iBAAiB;IAEvB,GAAG,EAAE,KAAqC,EAAE,4CAAhC,EAAE,eAAe,EAAE,OAAO,EAAE;QACtC,IAAA,uCAAkB,EAChB,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,EAChG,eAAe,EACf,OAAO,CAAC,MAAM,CACf,CAAC;IACJ,CAAC,CAAA;CACF,CAAC","sourcesContent":["import path from 'path';\n\nimport { replaceInFileExact } from '../lib/replaceInFileExact';\nimport { CreateQpqAppStep } from '../types';\n\n// The template's domain, replaced where it's authoritative: the app's domain\n// constant (everything else derives from it). One root at scaffold time; more\n// can be appended later.\nconst TEMPLATE_DOMAIN = 'todo.quidproquojs.com';\n\nexport const applyDomain: CreateQpqAppStep = {\n name: 'Applying domain',\n\n run: async ({ targetDirectory, answers }) => {\n replaceInFileExact(\n path.join(targetDirectory, 'apps', answers.appName, 'packages', 'constants', 'src', 'domain.ts'),\n TEMPLATE_DOMAIN,\n answers.domain,\n );\n },\n};\n"]}
|
|
@@ -26,7 +26,7 @@ Next steps:
|
|
|
26
26
|
${install} npm run dev # api on http://localhost:8080, web on http://localhost:3080
|
|
27
27
|
npm run deploy # build the docker image (then run the printed docker command)
|
|
28
28
|
|
|
29
|
-
Deploy config lives in apps/${answers.appName}/deploy.config.json
|
|
29
|
+
Deploy config lives in apps/${answers.appName}/deploy.config.json; the domain (${answers.domain}) lives in the app's constants package.
|
|
30
30
|
`);
|
|
31
31
|
}),
|
|
32
32
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"013_printNextSteps.js","sourceRoot":"","sources":["../../../src/steps/013_printNextSteps.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEa,QAAA,cAAc,GAAqB;IAC9C,IAAI,EAAE,MAAM;IAEZ,GAAG,EAAE,KAAoB,EAAE,4CAAf,EAAE,OAAO,EAAE;QACrB,MAAM,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAAC;QAEtF,OAAO,CAAC,GAAG,CAAC;UACN,OAAO,CAAC,OAAO;;;;;;;OAOlB,OAAO,CAAC,OAAO;EACpB,OAAO;;;8BAGqB,OAAO,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"013_printNextSteps.js","sourceRoot":"","sources":["../../../src/steps/013_printNextSteps.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEa,QAAA,cAAc,GAAqB;IAC9C,IAAI,EAAE,MAAM;IAEZ,GAAG,EAAE,KAAoB,EAAE,4CAAf,EAAE,OAAO,EAAE;QACrB,MAAM,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAAC;QAEtF,OAAO,CAAC,GAAG,CAAC;UACN,OAAO,CAAC,OAAO;;;;;;;OAOlB,OAAO,CAAC,OAAO;EACpB,OAAO;;;8BAGqB,OAAO,CAAC,OAAO,oCAAoC,OAAO,CAAC,MAAM;CAC9F,CAAC,CAAC;IACD,CAAC,CAAA;CACF,CAAC","sourcesContent":["import { CreateQpqAppStep } from '../types';\n\nexport const printNextSteps: CreateQpqAppStep = {\n name: 'Done',\n\n run: async ({ answers }) => {\n const install = answers.installDependencies ? '' : ' npm install\\n npm run build\\n';\n\n console.log(`\nCreated ${answers.appName}!\n\nYour app has five services (admin, auth, design, shell and todo) and\ndeploys as a single docker image.\n\nNext steps:\n\n cd ${answers.appName}\n${install} npm run dev # api on http://localhost:8080, web on http://localhost:3080\n npm run deploy # build the docker image (then run the printed docker command)\n\nDeploy config lives in apps/${answers.appName}/deploy.config.json; the domain (${answers.domain}) lives in the app's constants package.\n`);\n },\n};\n"]}
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import { readJsonFile } from '../lib/readJsonFile';
|
|
3
2
|
import { replaceInFileExact } from '../lib/replaceInFileExact';
|
|
4
|
-
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// The template's domain, replaced where it's authoritative: the app's domain
|
|
4
|
+
// constant (everything else derives from it). One root at scaffold time; more
|
|
5
|
+
// can be appended later.
|
|
7
6
|
const TEMPLATE_DOMAIN = 'todo.quidproquojs.com';
|
|
8
7
|
export const applyDomain = {
|
|
9
8
|
name: 'Applying domain',
|
|
10
9
|
run: async ({ targetDirectory, answers }) => {
|
|
11
|
-
const deployConfigPath = path.join(targetDirectory, 'apps', answers.appName, 'deploy.config.json');
|
|
12
|
-
const deployConfig = readJsonFile(deployConfigPath);
|
|
13
|
-
deployConfig.domain = answers.domain;
|
|
14
|
-
writeJsonFile(deployConfigPath, deployConfig);
|
|
15
10
|
replaceInFileExact(path.join(targetDirectory, 'apps', answers.appName, 'packages', 'constants', 'src', 'domain.ts'), TEMPLATE_DOMAIN, answers.domain);
|
|
16
11
|
},
|
|
17
12
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"006_applyDomain.js","sourceRoot":"","sources":["../../../src/steps/006_applyDomain.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"006_applyDomain.js","sourceRoot":"","sources":["../../../src/steps/006_applyDomain.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,6EAA6E;AAC7E,8EAA8E;AAC9E,yBAAyB;AACzB,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAEhD,MAAM,CAAC,MAAM,WAAW,GAAqB;IAC3C,IAAI,EAAE,iBAAiB;IAEvB,GAAG,EAAE,KAAK,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,EAAE,EAAE;QAC1C,kBAAkB,CAChB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,EAChG,eAAe,EACf,OAAO,CAAC,MAAM,CACf,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import path from 'path';\n\nimport { replaceInFileExact } from '../lib/replaceInFileExact';\nimport { CreateQpqAppStep } from '../types';\n\n// The template's domain, replaced where it's authoritative: the app's domain\n// constant (everything else derives from it). One root at scaffold time; more\n// can be appended later.\nconst TEMPLATE_DOMAIN = 'todo.quidproquojs.com';\n\nexport const applyDomain: CreateQpqAppStep = {\n name: 'Applying domain',\n\n run: async ({ targetDirectory, answers }) => {\n replaceInFileExact(\n path.join(targetDirectory, 'apps', answers.appName, 'packages', 'constants', 'src', 'domain.ts'),\n TEMPLATE_DOMAIN,\n answers.domain,\n );\n },\n};\n"]}
|
|
@@ -14,7 +14,7 @@ Next steps:
|
|
|
14
14
|
${install} npm run dev # api on http://localhost:8080, web on http://localhost:3080
|
|
15
15
|
npm run deploy # build the docker image (then run the printed docker command)
|
|
16
16
|
|
|
17
|
-
Deploy config lives in apps/${answers.appName}/deploy.config.json
|
|
17
|
+
Deploy config lives in apps/${answers.appName}/deploy.config.json; the domain (${answers.domain}) lives in the app's constants package.
|
|
18
18
|
`);
|
|
19
19
|
},
|
|
20
20
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"013_printNextSteps.js","sourceRoot":"","sources":["../../../src/steps/013_printNextSteps.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAqB;IAC9C,IAAI,EAAE,MAAM;IAEZ,GAAG,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAAC;QAEtF,OAAO,CAAC,GAAG,CAAC;UACN,OAAO,CAAC,OAAO;;;;;;;OAOlB,OAAO,CAAC,OAAO;EACpB,OAAO;;;8BAGqB,OAAO,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"013_printNextSteps.js","sourceRoot":"","sources":["../../../src/steps/013_printNextSteps.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAqB;IAC9C,IAAI,EAAE,MAAM;IAEZ,GAAG,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAAC;QAEtF,OAAO,CAAC,GAAG,CAAC;UACN,OAAO,CAAC,OAAO;;;;;;;OAOlB,OAAO,CAAC,OAAO;EACpB,OAAO;;;8BAGqB,OAAO,CAAC,OAAO,oCAAoC,OAAO,CAAC,MAAM;CAC9F,CAAC,CAAC;IACD,CAAC;CACF,CAAC","sourcesContent":["import { CreateQpqAppStep } from '../types';\n\nexport const printNextSteps: CreateQpqAppStep = {\n name: 'Done',\n\n run: async ({ answers }) => {\n const install = answers.installDependencies ? '' : ' npm install\\n npm run build\\n';\n\n console.log(`\nCreated ${answers.appName}!\n\nYour app has five services (admin, auth, design, shell and todo) and\ndeploys as a single docker image.\n\nNext steps:\n\n cd ${answers.appName}\n${install} npm run dev # api on http://localhost:8080, web on http://localhost:3080\n npm run deploy # build the docker image (then run the printed docker command)\n\nDeploy config lives in apps/${answers.appName}/deploy.config.json; the domain (${answers.domain}) lives in the app's constants package.\n`);\n },\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-qpq-app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
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",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/node": "^22.13.13",
|
|
58
|
-
"quidproquo-tsconfig": "0.1.
|
|
58
|
+
"quidproquo-tsconfig": "0.1.20"
|
|
59
59
|
},
|
|
60
60
|
"bin": {
|
|
61
61
|
"create-qpq-app": "./lib/commonjs/bin/createQpqApp.js"
|
package/template/README.md
CHANGED
|
@@ -28,7 +28,7 @@ curl -H "Host: qpqjs.development.localhost" http://localhost:8080/api/shell/v1/h
|
|
|
28
28
|
|
|
29
29
|
```
|
|
30
30
|
apps/<app>/ # qpqjs
|
|
31
|
-
deploy.config.json # { "prefix", "
|
|
31
|
+
deploy.config.json # { "prefix", "environments" }: deploy identity per environment
|
|
32
32
|
tsconfig.federated.json # generated by `npm run prep`: cross-view type aliases
|
|
33
33
|
packages/ # app-wide libs (config, constants, service-utils)
|
|
34
34
|
services/<svc>/
|
|
@@ -85,14 +85,17 @@ Every app-facing command (`prep`, `synth`, `go`, `go:docker`, `go:dev`, `go:dev:
|
|
|
85
85
|
|
|
86
86
|
```bash
|
|
87
87
|
npm run deploy # docker deploy (qpq go:docker)
|
|
88
|
+
npx qpq setup # new account/environment: checked steps (creds, IAM, zones, bucket names,
|
|
89
|
+
# cdk bootstrap, account/domain/bootstrap stacks incl. the GitHub OIDC
|
|
90
|
+
# provider + deploy role), run in order; then deploy services with go:docker
|
|
88
91
|
npx qpq synth # writes dist/apps/<app>/infrastructure/<svc>-config.json for cdk
|
|
89
92
|
npx qpq go # interactive aws deploy: pick app, services, stacks (inf/api/web/views)
|
|
90
93
|
# bundles (rspack production), cdk deploy, and s3 sync per phase
|
|
91
94
|
```
|
|
92
95
|
|
|
93
|
-
`qpq go` needs AWS credentials plus a deploy identity: either an `"environments"` map in `apps/<app>/deploy.config.json` (`{ "prefix", "
|
|
96
|
+
`qpq go` needs AWS credentials plus a deploy identity: either an `"environments"` map in `apps/<app>/deploy.config.json` (`{ "prefix", "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
97
|
|
|
95
|
-
- Production views bundles get prod remote URLs (`
|
|
98
|
+
- Production views bundles get prod remote URLs (the `views` host on the primary root, under the app's domain resolver) derived from the service's qpq config. Dev bundles use localhost ports.
|
|
96
99
|
- `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
100
|
|
|
98
101
|
## Adding a service
|
|
@@ -7,33 +7,25 @@ import { QPQConfig } from 'quidproquo';
|
|
|
7
7
|
import {
|
|
8
8
|
AwsDataStoreRemovalPolicy,
|
|
9
9
|
defineAccountBudget,
|
|
10
|
-
|
|
10
|
+
defineAccountGithubOidcProvider,
|
|
11
11
|
defineAccountSecurityServices,
|
|
12
12
|
defineAwsDataStoreRemovalPolicy,
|
|
13
13
|
} from 'quidproquo-config-aws';
|
|
14
14
|
|
|
15
15
|
export default (): QPQConfig => [
|
|
16
|
-
// Dev account:
|
|
17
|
-
// (and its audit history) with it.
|
|
16
|
+
// Dev account: data stores created by the account stack are torn down with it.
|
|
18
17
|
defineAwsDataStoreRemovalPolicy(AwsDataStoreRemovalPolicy.destroy),
|
|
19
18
|
|
|
20
|
-
defineAccountCloudTrail('main', {
|
|
21
|
-
cloudWatchLogs: {
|
|
22
|
-
retentionDays: 30,
|
|
23
|
-
},
|
|
24
|
-
}),
|
|
25
|
-
|
|
26
19
|
defineAccountBudget('main', 30, ['joecoady@gmail.com']),
|
|
27
20
|
|
|
21
|
+
// GitHub Actions OIDC provider, trusted by every app's deploy role in this account.
|
|
22
|
+
defineAccountGithubOidcProvider(),
|
|
23
|
+
|
|
28
24
|
defineAccountSecurityServices({
|
|
29
25
|
// GuardDuty is org-managed for this account
|
|
30
26
|
// (delegated admin 816650600287 auto-enables detectors - a stack-created one
|
|
31
27
|
// would collide), and Security Hub is off pending the AWS Config cost decision.
|
|
32
28
|
enableGuardDuty: false,
|
|
33
29
|
enableSecurityHub: false,
|
|
34
|
-
cognitoAuthFailureAlert: {
|
|
35
|
-
emails: ['joecoady@gmail.com'],
|
|
36
|
-
thresholdPer5Minutes: 10,
|
|
37
|
-
},
|
|
38
30
|
}),
|
|
39
31
|
];
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// App-specific bootstrap extras
|
|
2
|
-
// identity plumbing (defineApplication +
|
|
3
|
-
// provided by quidproquo-deploy-awscdk's
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
import { defineApi, QPQConfig } from 'quidproquo';
|
|
1
|
+
// App-specific bootstrap extras: the root domains, WAF, the api domain, and the
|
|
2
|
+
// domain certificates. The identity plumbing (defineApplication +
|
|
3
|
+
// defineAwsServiceAccountInfo) is provided by quidproquo-deploy-awscdk's
|
|
4
|
+
// workspace CDK app; this fragment must not declare its own.
|
|
5
|
+
import { defineApi, defineDns, QPQConfig } from 'quidproquo';
|
|
7
6
|
import {
|
|
7
|
+
defineAwsGithubDeployRole,
|
|
8
8
|
defineBootstrapWaf,
|
|
9
9
|
defineDomainCertificate,
|
|
10
10
|
WafManagedRuleGroup,
|
|
@@ -12,7 +12,14 @@ import {
|
|
|
12
12
|
} from 'quidproquo-config-aws';
|
|
13
13
|
import { QpqAppDeployContext } from 'quidproquo-deploy-awscdk';
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
import { QPQJS_DOMAINS, QpqjsServiceEnum } from '@qpqjs/constants';
|
|
16
|
+
|
|
17
|
+
export default ({ region }: QpqAppDeployContext): QPQConfig => [
|
|
18
|
+
defineDns(QPQJS_DOMAINS),
|
|
19
|
+
|
|
20
|
+
// The role the deploy workflow assumes (ids from `gh api repos/qpqjs/quidproquo`).
|
|
21
|
+
defineAwsGithubDeployRole('qpqjs/quidproquo', { ownerId: 314167689, repositoryId: 571382961 }),
|
|
22
|
+
|
|
16
23
|
defineBootstrapWaf({
|
|
17
24
|
rateLimits: [{ name: 'all-traffic', limit: 2000 }],
|
|
18
25
|
managedRuleGroups: [
|
|
@@ -28,15 +35,23 @@ export default ({ domain, region }: QpqAppDeployContext): QPQConfig => [
|
|
|
28
35
|
},
|
|
29
36
|
}),
|
|
30
37
|
|
|
31
|
-
defineApi('api'
|
|
38
|
+
defineApi('api'),
|
|
32
39
|
|
|
40
|
+
// CloudFront (us-east-1): the site root plus every web entry, on every root domain.
|
|
33
41
|
defineDomainCertificate(
|
|
34
|
-
domain,
|
|
35
42
|
'us-east-1',
|
|
36
|
-
[
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
[
|
|
44
|
+
{ subdomain: 'www' },
|
|
45
|
+
{ subdomain: 'views' },
|
|
46
|
+
{ subdomain: 'docs' },
|
|
47
|
+
{ subdomain: 'storybook' },
|
|
48
|
+
],
|
|
49
|
+
{ includeApex: true }
|
|
40
50
|
),
|
|
41
|
-
|
|
51
|
+
|
|
52
|
+
// Regional API Gateway: the api and the admin websocket.
|
|
53
|
+
defineDomainCertificate(region, [
|
|
54
|
+
{ subdomain: 'api' },
|
|
55
|
+
{ subdomain: 'qpqadmin', service: QpqjsServiceEnum.Admin },
|
|
56
|
+
]),
|
|
42
57
|
];
|
|
@@ -11,19 +11,20 @@ import {
|
|
|
11
11
|
} from 'quidproquo';
|
|
12
12
|
import {
|
|
13
13
|
ApiLayer,
|
|
14
|
+
AwsDataStoreRemovalPolicy,
|
|
15
|
+
defineAwsDataStoreRemovalPolicy,
|
|
14
16
|
defineAwsServiceAccountInfo,
|
|
15
17
|
defineWafProtection,
|
|
16
|
-
AwsDataStoreRemovalPolicy,
|
|
17
|
-
defineAwsDataStoreRemovalPolicy
|
|
18
18
|
} from 'quidproquo-config-aws';
|
|
19
19
|
import {
|
|
20
20
|
defineAdminSettings,
|
|
21
21
|
defineAdminUserDirectory,
|
|
22
|
+
defineOpenApiRoutes,
|
|
22
23
|
} from 'quidproquo-features';
|
|
23
24
|
|
|
24
25
|
import { execSync } from 'child_process';
|
|
25
26
|
import {
|
|
26
|
-
|
|
27
|
+
QPQJS_DOMAINS,
|
|
27
28
|
QPQJS_USER_DIRECTORY,
|
|
28
29
|
QpqjsServiceEnum,
|
|
29
30
|
qpqjsServiceNames,
|
|
@@ -40,8 +41,7 @@ export const defineQpqjsService = (
|
|
|
40
41
|
configRoot: string,
|
|
41
42
|
apiBuildPath: string,
|
|
42
43
|
apiLayers: ApiLayer[] = [],
|
|
43
|
-
lambdaMemoryInMiB = 1024
|
|
44
|
-
domainName = QPQJS_DOMAIN
|
|
44
|
+
lambdaMemoryInMiB = 1024
|
|
45
45
|
): QPQConfig => [
|
|
46
46
|
defineApplicationModule(
|
|
47
47
|
modulePrefix,
|
|
@@ -58,7 +58,7 @@ export const defineQpqjsService = (
|
|
|
58
58
|
.trim()}-${new Date().toISOString()}`
|
|
59
59
|
),
|
|
60
60
|
|
|
61
|
-
defineDns(
|
|
61
|
+
defineDns(QPQJS_DOMAINS),
|
|
62
62
|
|
|
63
63
|
defineAdminUserDirectory({
|
|
64
64
|
owner: {
|
|
@@ -111,7 +111,7 @@ export const defineQpqjsService = (
|
|
|
111
111
|
sharedSingletons: ['chakra', 'zod'],
|
|
112
112
|
}),
|
|
113
113
|
|
|
114
|
-
defineApi('api'
|
|
114
|
+
defineApi('api'),
|
|
115
115
|
defineDefaultRouteOptions('api', {
|
|
116
116
|
allowedOrigins: [
|
|
117
117
|
'http://localhost:3080',
|
|
@@ -138,11 +138,17 @@ export const defineQpqjsService = (
|
|
|
138
138
|
}
|
|
139
139
|
),
|
|
140
140
|
|
|
141
|
-
defineAdminSettings(QpqjsServiceEnum.Admin,
|
|
141
|
+
defineAdminSettings(QpqjsServiceEnum.Admin, {
|
|
142
142
|
services: qpqjsServiceNames,
|
|
143
143
|
coldStorageAfterDays: 90,
|
|
144
144
|
}),
|
|
145
145
|
|
|
146
|
+
// Every service documents itself: reference page at /v1/docs, the generated
|
|
147
|
+
// OpenAPI document at /v1/docs/openapi.json. Public, like the docs site.
|
|
148
|
+
defineOpenApiRoutes({
|
|
149
|
+
info: { title: `${modulePrefix} ${service}`, version: '1.0.0' },
|
|
150
|
+
}),
|
|
151
|
+
|
|
146
152
|
// turning this off is super painful for maintaince, dont be a nubbet.
|
|
147
|
-
defineAwsDataStoreRemovalPolicy(AwsDataStoreRemovalPolicy.destroy)
|
|
153
|
+
defineAwsDataStoreRemovalPolicy(AwsDataStoreRemovalPolicy.destroy),
|
|
148
154
|
];
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import { defineDevServerOptions } from 'quidproquo-dev-server/config';
|
|
7
7
|
import { defineDynamicRoutes } from 'quidproquo-features';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { QpqjsServiceEnum } from '@qpqjs/constants';
|
|
10
10
|
import { defineQpqjsService } from '@qpqjs/service-utils';
|
|
11
11
|
|
|
12
12
|
import * as dynamicRoutes from './entry/controller';
|
|
@@ -23,7 +23,6 @@ const webEntryOptions: QPQConfigAdvancedWebEntrySettings = {
|
|
|
23
23
|
cacheSettingsName: 'default',
|
|
24
24
|
domain: {
|
|
25
25
|
onRootDomain: true,
|
|
26
|
-
rootDomain: QPQJS_DOMAIN,
|
|
27
26
|
},
|
|
28
27
|
storageDrive: {
|
|
29
28
|
sourceStorageDrive: websiteWebEntryStorageDriveName,
|
|
@@ -40,7 +39,6 @@ const mfeHostWebEntryOptions: QPQConfigAdvancedWebEntrySettings = {
|
|
|
40
39
|
domain: {
|
|
41
40
|
subDomainName: 'views',
|
|
42
41
|
onRootDomain: true,
|
|
43
|
-
rootDomain: QPQJS_DOMAIN,
|
|
44
42
|
},
|
|
45
43
|
storageDrive: {
|
|
46
44
|
sourceStorageDrive: mfeHostWebEntryStorageDriveName,
|
|
@@ -65,7 +63,6 @@ const docsWebEntryOptions: QPQConfigAdvancedWebEntrySettings = {
|
|
|
65
63
|
domain: {
|
|
66
64
|
subDomainName: 'docs',
|
|
67
65
|
onRootDomain: true,
|
|
68
|
-
rootDomain: QPQJS_DOMAIN,
|
|
69
66
|
},
|
|
70
67
|
};
|
|
71
68
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
|
|
3
|
+
// Body of POST /echo/{pathValue}: one value to be sent straight back.
|
|
4
|
+
export const EchoRequestSchema = z.object({
|
|
5
|
+
bodyValue: z.string().min(1).describe('Any text; it comes back unchanged'),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export type EchoRequest = z.infer<typeof EchoRequestSchema>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
|
|
3
|
+
// What POST /echo/{pathValue} returns: the path and body values, untouched.
|
|
4
|
+
export const EchoResponseSchema = z.object({
|
|
5
|
+
pathValue: z.string().describe('The {pathValue} segment of the url'),
|
|
6
|
+
bodyValue: z.string().describe('The bodyValue from the request body'),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export type EchoResponse = z.infer<typeof EchoResponseSchema>;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
2
|
|
|
3
3
|
import { SmokeRunStatus } from './SmokeRunStatus';
|
|
4
|
-
import {
|
|
4
|
+
import { SmokeTestResultSchema } from './SmokeTestResult';
|
|
5
5
|
|
|
6
6
|
// One smoke run: POST /smoke/run creates it, GET /smoke/run/{runId} polls it.
|
|
7
7
|
// The shape is the part-2 contract; part 3 only grows what `tests` contains.
|
|
8
|
-
export
|
|
9
|
-
runId: string
|
|
10
|
-
status: SmokeRunStatus
|
|
11
|
-
startedAt:
|
|
12
|
-
finishedAt:
|
|
13
|
-
tests:
|
|
14
|
-
};
|
|
8
|
+
export const SmokeRunSchema = z.object({
|
|
9
|
+
runId: z.string(),
|
|
10
|
+
status: z.enum(SmokeRunStatus),
|
|
11
|
+
startedAt: z.iso.datetime(),
|
|
12
|
+
finishedAt: z.iso.datetime().nullable(),
|
|
13
|
+
tests: z.array(SmokeTestResultSchema),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export type SmokeRun = z.infer<typeof SmokeRunSchema>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
|
|
3
|
+
// What POST /smoke/run returns: just the handle to poll with.
|
|
4
|
+
export const SmokeRunStartedSchema = z.object({
|
|
5
|
+
runId: z.string().describe('Poll GET /smoke/run/{runId} with this'),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export type SmokeRunStarted = z.infer<typeof SmokeRunStartedSchema>;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
|
|
1
3
|
// Counts derived from a run's test entries at read time, never stored, so they
|
|
2
4
|
// cannot drift from the entries themselves.
|
|
3
|
-
export
|
|
4
|
-
total:
|
|
5
|
-
completed:
|
|
6
|
-
passed:
|
|
7
|
-
failed:
|
|
8
|
-
};
|
|
5
|
+
export const SmokeRunSummarySchema = z.object({
|
|
6
|
+
total: z.int().nonnegative().describe('Tests registered for the run'),
|
|
7
|
+
completed: z.int().nonnegative().describe('Tests that have passed or failed'),
|
|
8
|
+
passed: z.int().nonnegative(),
|
|
9
|
+
failed: z.int().nonnegative(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export type SmokeRunSummary = z.infer<typeof SmokeRunSummarySchema>;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
|
|
3
|
+
import { SmokeRunSchema } from './SmokeRun';
|
|
4
|
+
import { SmokeRunSummarySchema } from './SmokeRunSummary';
|
|
3
5
|
|
|
4
6
|
// What GET /smoke/run/{runId} returns: the stored run plus derived counts.
|
|
5
|
-
export
|
|
6
|
-
summary:
|
|
7
|
-
};
|
|
7
|
+
export const SmokeRunWithSummarySchema = SmokeRunSchema.extend({
|
|
8
|
+
summary: SmokeRunSummarySchema,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export type SmokeRunWithSummary = z.infer<typeof SmokeRunWithSummarySchema>;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
2
|
|
|
3
3
|
import { SmokeTestStatus } from './SmokeTestStatus';
|
|
4
4
|
|
|
5
5
|
// One registered test's entry in a run. `name` is the stable key; `id` is the
|
|
6
6
|
// test's 1-based position in the registry, for humans, and shifts if the
|
|
7
7
|
// registry is reordered, so nothing should key on it.
|
|
8
|
-
export
|
|
9
|
-
id:
|
|
10
|
-
name: string
|
|
11
|
-
status: SmokeTestStatus
|
|
12
|
-
message: string
|
|
13
|
-
startedAt:
|
|
14
|
-
finishedAt:
|
|
15
|
-
};
|
|
8
|
+
export const SmokeTestResultSchema = z.object({
|
|
9
|
+
id: z.int().positive().describe('1-based position in the test registry'),
|
|
10
|
+
name: z.string().describe('Stable test name'),
|
|
11
|
+
status: z.enum(SmokeTestStatus),
|
|
12
|
+
message: z.string(),
|
|
13
|
+
startedAt: z.iso.datetime().nullable(),
|
|
14
|
+
finishedAt: z.iso.datetime().nullable(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export type SmokeTestResult = z.infer<typeof SmokeTestResultSchema>;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
export * from './EchoRequest';
|
|
2
|
+
export * from './EchoResponse';
|
|
1
3
|
export * from './SmokeProbeRecord';
|
|
2
4
|
export * from './SmokeRun';
|
|
5
|
+
export * from './SmokeRunStarted';
|
|
3
6
|
export * from './SmokeRunStatus';
|
|
4
7
|
export * from './SmokeRunSummary';
|
|
5
8
|
export * from './SmokeRunWithSummary';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { QPQConfig } from 'quidproquo';
|
|
2
|
+
import { defineDynamicRoutes } from 'quidproquo-features';
|
|
3
|
+
|
|
4
|
+
import * as controllers from '../controller';
|
|
5
|
+
|
|
6
|
+
// The echo routes carry their own method/path/schema on the handler; this just
|
|
7
|
+
// registers the controller module under the service's src root.
|
|
8
|
+
export const defineEcho = (): QPQConfig =>
|
|
9
|
+
defineDynamicRoutes(controllers, '/echo/controller');
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AskResponse, HTTPEventResponse, qpqWebServerUtils } from 'quidproquo';
|
|
2
|
+
import { dynamicRoute } from 'quidproquo-features';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
EchoRequestSchema,
|
|
6
|
+
EchoResponse,
|
|
7
|
+
EchoResponseSchema,
|
|
8
|
+
} from '@qpqjs/test-models';
|
|
9
|
+
|
|
10
|
+
// POST /echo/{pathValue}. Public. Exists to prove a value survives the trip
|
|
11
|
+
// through the url and the validated body: the response is both, unchanged.
|
|
12
|
+
export const echo = dynamicRoute(
|
|
13
|
+
['POST', '/echo/{pathValue}'],
|
|
14
|
+
function* (event, params, { body }): AskResponse<HTTPEventResponse> {
|
|
15
|
+
const response: EchoResponse = {
|
|
16
|
+
pathValue: params.pathValue,
|
|
17
|
+
bodyValue: body.bodyValue,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return qpqWebServerUtils.toJsonEventResponse(response);
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
schema: {
|
|
24
|
+
summary: 'Echo a path and body value',
|
|
25
|
+
description:
|
|
26
|
+
'Returns the {pathValue} url segment and the bodyValue from the JSON body, untouched. Public, for trying the docs UI.',
|
|
27
|
+
tags: ['echo'],
|
|
28
|
+
body: EchoRequestSchema,
|
|
29
|
+
response: EchoResponseSchema,
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './echo';
|
|
@@ -3,7 +3,9 @@ import { defineDevServerOptions } from 'quidproquo-dev-server/config';
|
|
|
3
3
|
import { QpqjsServiceEnum } from '@qpqjs/constants';
|
|
4
4
|
import { defineQpqjsService } from '@qpqjs/service-utils';
|
|
5
5
|
|
|
6
|
+
import { defineEcho } from './echo/config/defineEcho';
|
|
6
7
|
import { defineSmoke } from './smoke/config/defineSmoke';
|
|
8
|
+
import { defineTick } from './tick/config/defineTick';
|
|
7
9
|
|
|
8
10
|
export default [
|
|
9
11
|
defineDevServerOptions({ port: 3083 }),
|
|
@@ -16,4 +18,8 @@ export default [
|
|
|
16
18
|
),
|
|
17
19
|
|
|
18
20
|
defineSmoke(),
|
|
21
|
+
|
|
22
|
+
defineEcho(),
|
|
23
|
+
|
|
24
|
+
defineTick(),
|
|
19
25
|
];
|