create-qpq-app 0.1.26 → 0.1.28
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 +4 -0
- package/lib/commonjs/cli/runCreateQpqApp.js +15 -1
- package/lib/commonjs/cli/runCreateQpqApp.js.map +1 -1
- package/lib/commonjs/lib/index.d.ts +1 -1
- package/lib/commonjs/lib/index.js +1 -1
- package/lib/commonjs/lib/index.js.map +1 -1
- package/lib/commonjs/lib/promptText.d.ts +1 -0
- package/lib/commonjs/lib/promptText.js +53 -0
- package/lib/commonjs/lib/promptText.js.map +1 -0
- package/lib/commonjs/steps/005_applyAppIdentity.js +6 -5
- package/lib/commonjs/steps/005_applyAppIdentity.js.map +1 -1
- package/lib/commonjs/steps/006_applyDomain.js +11 -6
- package/lib/commonjs/steps/006_applyDomain.js.map +1 -1
- package/lib/commonjs/steps/007_applyDockerHost.d.ts +2 -0
- package/lib/commonjs/steps/007_applyDockerHost.js +40 -0
- package/lib/commonjs/steps/007_applyDockerHost.js.map +1 -0
- package/lib/commonjs/steps/{007_pinRegistryVersions.js → 008_pinRegistryVersions.js} +1 -1
- package/lib/commonjs/steps/{007_pinRegistryVersions.js.map → 008_pinRegistryVersions.js.map} +1 -1
- package/lib/commonjs/steps/{008_transpileToJavaScript.js → 009_transpileToJavaScript.js} +1 -1
- package/lib/commonjs/steps/{008_transpileToJavaScript.js.map → 009_transpileToJavaScript.js.map} +1 -1
- package/lib/commonjs/steps/{009_restoreGitignore.js → 010_restoreGitignore.js} +1 -1
- package/lib/commonjs/steps/{009_restoreGitignore.js.map → 010_restoreGitignore.js.map} +1 -1
- package/lib/commonjs/steps/{010_gitInit.js → 011_gitInit.js} +1 -1
- package/lib/commonjs/steps/{010_gitInit.js.map → 011_gitInit.js.map} +1 -1
- package/lib/commonjs/steps/{011_npmInstall.js → 012_npmInstall.js} +1 -1
- package/lib/commonjs/steps/{011_npmInstall.js.map → 012_npmInstall.js.map} +1 -1
- package/lib/commonjs/steps/{012_buildWorkspaces.js → 013_buildWorkspaces.js} +1 -1
- package/lib/commonjs/steps/{012_buildWorkspaces.js.map → 013_buildWorkspaces.js.map} +1 -1
- package/lib/commonjs/steps/{013_printNextSteps.js → 014_printNextSteps.js} +6 -3
- package/lib/commonjs/steps/014_printNextSteps.js.map +1 -0
- package/lib/commonjs/steps/index.d.ts +9 -8
- package/lib/commonjs/steps/index.js +25 -22
- package/lib/commonjs/steps/index.js.map +1 -1
- package/lib/commonjs/types/CreateQpqAppAnswers.d.ts +2 -0
- package/lib/commonjs/types/CreateQpqAppAnswers.js.map +1 -1
- package/lib/esm/cli/runCreateQpqApp.js +15 -1
- package/lib/esm/cli/runCreateQpqApp.js.map +1 -1
- package/lib/esm/lib/index.d.ts +1 -1
- package/lib/esm/lib/index.js +1 -1
- package/lib/esm/lib/index.js.map +1 -1
- package/lib/esm/lib/promptText.d.ts +1 -0
- package/lib/esm/lib/promptText.js +7 -0
- package/lib/esm/lib/promptText.js.map +1 -0
- package/lib/esm/steps/005_applyAppIdentity.js +6 -5
- package/lib/esm/steps/005_applyAppIdentity.js.map +1 -1
- package/lib/esm/steps/006_applyDomain.js +11 -6
- package/lib/esm/steps/006_applyDomain.js.map +1 -1
- package/lib/esm/steps/007_applyDockerHost.d.ts +2 -0
- package/lib/esm/steps/007_applyDockerHost.js +30 -0
- package/lib/esm/steps/007_applyDockerHost.js.map +1 -0
- package/lib/esm/steps/{007_pinRegistryVersions.js → 008_pinRegistryVersions.js} +1 -1
- package/lib/esm/steps/{007_pinRegistryVersions.js.map → 008_pinRegistryVersions.js.map} +1 -1
- package/lib/esm/steps/{008_transpileToJavaScript.js → 009_transpileToJavaScript.js} +1 -1
- package/lib/esm/steps/{008_transpileToJavaScript.js.map → 009_transpileToJavaScript.js.map} +1 -1
- package/lib/esm/steps/{009_restoreGitignore.js → 010_restoreGitignore.js} +1 -1
- package/lib/esm/steps/{009_restoreGitignore.js.map → 010_restoreGitignore.js.map} +1 -1
- package/lib/esm/steps/{010_gitInit.js → 011_gitInit.js} +1 -1
- package/lib/esm/steps/{010_gitInit.js.map → 011_gitInit.js.map} +1 -1
- package/lib/esm/steps/{011_npmInstall.js → 012_npmInstall.js} +1 -1
- package/lib/esm/steps/{011_npmInstall.js.map → 012_npmInstall.js.map} +1 -1
- package/lib/esm/steps/{012_buildWorkspaces.js → 013_buildWorkspaces.js} +1 -1
- package/lib/esm/steps/{012_buildWorkspaces.js.map → 013_buildWorkspaces.js.map} +1 -1
- package/lib/esm/steps/014_printNextSteps.js +24 -0
- package/lib/esm/steps/014_printNextSteps.js.map +1 -0
- package/lib/esm/steps/index.d.ts +9 -8
- package/lib/esm/steps/index.js +10 -8
- package/lib/esm/steps/index.js.map +1 -1
- package/lib/esm/types/CreateQpqAppAnswers.d.ts +2 -0
- package/lib/esm/types/CreateQpqAppAnswers.js.map +1 -1
- package/package.json +2 -2
- package/template/README.md +4 -3
- package/template/apps/qpqjs/bootstrap.qpq.ts +3 -2
- package/template/apps/qpqjs/deploy.config.json +42 -9
- package/template/apps/qpqjs/devServer.config.ts +13 -0
- package/template/apps/qpqjs/packages/constants/src/index.ts +0 -1
- package/template/apps/qpqjs/packages/service-utils/src/defineQpqjsService.ts +12 -29
- package/template/apps/qpqjs/services/admin/service/src/infrastructure.ts +1 -1
- package/template/apps/qpqjs/services/admin/views/src/app/app.tsx +9 -19
- package/template/apps/qpqjs/services/design/service/src/infrastructure.ts +1 -1
- package/template/apps/qpqjs/services/design/views/src/components/LandingPage/components/NavBar.tsx +2 -10
- package/template/apps/qpqjs/services/design/views/src/components/WelcomeScreen/WelcomeScreen.tsx +3 -11
- package/template/apps/qpqjs/services/shell/service/src/infrastructure.ts +5 -1
- package/template/apps/qpqjs/services/test/models/src/SmokeProbeRecord.ts +3 -0
- package/template/apps/qpqjs/services/test/service/src/infrastructure.ts +1 -7
- package/template/apps/qpqjs/services/test/service/src/smoke/config/defineSmoke.ts +8 -264
- package/template/apps/qpqjs/services/test/service/src/smoke/harness/assert/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/harness/config/defineSmokeHarness.ts +115 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/harness/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{constants → harness/constants}/index.ts +0 -2
- package/template/apps/qpqjs/services/test/service/src/smoke/harness/index.ts +10 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{logic → harness/logic}/smokeRun/askExecuteSmokeTest.ts +3 -3
- package/template/apps/qpqjs/services/test/service/src/smoke/{logic → harness/logic}/smokeRun/askStartSmokeRun.ts +5 -4
- package/template/apps/qpqjs/services/test/service/src/smoke/{logic → harness/logic}/smokeRun/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/harness/logic/smokeRun/listSmokeTests.ts +6 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{models → harness/models}/SmokeTestRequestedQueueEvent.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/harness/models/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/harness/queue/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/harness/types/SmokeSuite.ts +13 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/harness/types/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/index.ts +2 -12
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/emailReceive/config/defineEmailReceiveSmoke.ts +20 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/emailReceive/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/emailReceive/constants/SMOKE_EMAIL_RECEIVER.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/emailReceive/constants/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/emailReceive/emailReceiveSmokeSuite.ts +15 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{email → suites/emailReceive/entry/email}/index.ts +0 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/{email → suites/emailReceive/entry/email}/onSmokeEmailReceived.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/emailReceive/entry/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/emailReceive/index.ts +5 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/emailReceive → suites/emailReceive/logic}/askRunEmailReceiveTest.ts +3 -3
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/emailReceive → suites/emailReceive/logic}/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/encryptedResources/config/defineEncryptedResourcesSmoke.ts +29 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/encryptedResources/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/encryptedResources/constants/SMOKE_CRYPTO_KEY.ts +5 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/encryptedResources/constants/SMOKE_ENCRYPTED_PROBE_DRIVE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/encryptedResources/constants/SMOKE_ENCRYPTED_PROBE_STORE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/encryptedResources/constants/index.ts +3 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/encryptedResources/encryptedResourcesSmokeSuite.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/encryptedResources/index.ts +4 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/encryptedResources → suites/encryptedResources/logic}/askRunEncryptedResourcesTest.ts +3 -5
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/config/defineEventBusSmoke.ts +21 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/constants/SMOKE_PROBE_EVENT_BUS.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/constants/SMOKE_PROBE_EVENT_QUEUE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/constants/SMOKE_PROBE_EVENT_TYPE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/constants/index.ts +3 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/entry/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/entry/queue/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{queue → suites/eventBus/entry/queue}/onSmokeProbeEvent.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/eventBusSmokeSuite.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/index.ts +6 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/eventBus → suites/eventBus/logic}/askRunEventBusTest.ts +4 -6
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventBus/models/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventDoc/config/defineEventDocSmoke.ts +44 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventDoc/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventDoc/constants/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{constants → suites/eventDoc/constants}/smokeEventDoc.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventDoc/entry/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventDoc/entry/queue/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{queue → suites/eventDoc/entry/queue}/onSmokeEventDocAppend.ts +3 -3
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventDoc/eventDocSmokeSuite.ts +19 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventDoc/index.ts +7 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/eventDoc → suites/eventDoc/logic}/askAssertContiguousEventIds.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/eventDoc → suites/eventDoc/logic}/askAssertSmokeProbeDocState.ts +2 -2
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/eventDoc → suites/eventDoc/logic}/askAwaitSmokeEventDocLog.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/eventDoc → suites/eventDoc/logic}/askRunEventDocConcurrentAppendTest.ts +5 -5
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/eventDoc → suites/eventDoc/logic}/askRunEventDocInterleavedBatchAppendTest.ts +4 -4
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/eventDoc/models/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests → suites}/index.ts +4 -5
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStore/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStore/keyValueStoreSmokeSuite.ts +14 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/crossService → suites/keyValueStore/logic}/askRunCrossServiceKeyValueStoreTest.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/keyValueStore → suites/keyValueStore/logic}/askRunKeyValueStoreTest.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStore/logic/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStoreStream/config/defineKeyValueStoreStreamSmoke.ts +30 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStoreStream/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStoreStream/constants/SMOKE_STREAM_PROBE_STORE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStoreStream/constants/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStoreStream/entry/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{kvsStream → suites/keyValueStoreStream/entry/kvsStream}/index.ts +0 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/{kvsStream → suites/keyValueStoreStream/entry/kvsStream}/onSmokeStreamRecord.ts +6 -4
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStoreStream/index.ts +5 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/keyValueStoreStream/keyValueStoreStreamSmokeSuite.ts +11 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/keyValueStoreStream → suites/keyValueStoreStream/logic}/askRunKeyValueStoreStreamTest.ts +15 -6
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/keyValueStoreStream → suites/keyValueStoreStream/logic}/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/noop/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/noop/noopSmokeSuite.ts +7 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/openApi/config/defineOpenApiSmoke.ts +13 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/openApi/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/openApi/index.ts +4 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/openApi → suites/openApi/logic}/askRunEchoRoundTripTest.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/openApi → suites/openApi/logic}/askRunOpenApiDocumentTest.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/openApi/openApiSmokeSuite.ts +13 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/parameter/config/defineParameterSmoke.ts +11 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/parameter/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/parameter/constants/SMOKE_PROBE_PARAMETER.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/parameter/constants/SMOKE_PROBE_PARAMETER_VALUE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/parameter/constants/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/parameter/index.ts +4 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/parameter → suites/parameter/logic}/askRunParameterTest.ts +3 -5
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/parameter/parameterSmokeSuite.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/{tick/config/defineTick.ts → smoke/suites/schedule/config/defineScheduleSmoke.ts} +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/schedule/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/schedule/entry/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/schedule/index.ts +6 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/schedule → suites/schedule/logic}/askRunScheduleTest.ts +4 -4
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/schedule/scheduleSmokeSuite.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedKeyValueStore/config/defineScopedKeyValueStoreSmoke.ts +19 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedKeyValueStore/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedKeyValueStore/constants/SMOKE_SCOPED_PROBE_STORE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedKeyValueStore/constants/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedKeyValueStore/index.ts +4 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedKeyValueStore/logic/askRunScopedKeyValueStoreTest.ts +256 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedKeyValueStore/scopedKeyValueStoreSmokeSuite.ts +11 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedStorageDrive/config/defineScopedStorageDriveSmoke.ts +12 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedStorageDrive/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedStorageDrive/constants/SMOKE_SCOPED_PROBE_DRIVE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedStorageDrive/constants/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedStorageDrive/index.ts +4 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/scopedStorageDrive → suites/scopedStorageDrive/logic}/askRunScopedStorageDriveTest.ts +2 -2
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/scopedStorageDrive/scopedStorageDriveSmokeSuite.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/secret/config/defineSecretSmoke.ts +8 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/secret/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/secret/constants/SMOKE_PROBE_SECRET.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/secret/constants/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/secret/index.ts +4 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/secret → suites/secret/logic}/askRunSecretTest.ts +2 -2
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/secret/secretSmokeSuite.ts +9 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/signingKey/config/defineSigningKeySmoke.ts +12 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/signingKey/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/signingKey/index.ts +3 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/crossService → suites/signingKey/logic}/askRunCrossServiceSigningKeyTest.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/signingKey → suites/signingKey/logic}/askRunSigningKeyTest.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/signingKey/logic/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/signingKey/signingKeySmokeSuite.ts +16 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/smokeSuites.ts +46 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDrive/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/crossService → suites/storageDrive/logic}/askRunCrossServiceStorageDriveTest.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/storageDrive → suites/storageDrive/logic}/askRunStorageDriveTest.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDrive/logic/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDrive/storageDriveSmokeSuite.ts +14 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/config/defineStorageDriveEventSmoke.ts +27 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/config/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/constants/SMOKE_FILE_EVENT_DRIVE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/constants/SMOKE_SCOPED_FILE_EVENT_DRIVE.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/constants/index.ts +2 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/entry/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/entry/storageDrive/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{storageDrive → suites/storageDriveEvent/entry/storageDrive}/onSmokeFileEvent.ts +1 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/index.ts +5 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/storageDriveEvent → suites/storageDriveEvent/logic}/askRunStorageDriveEventTest.ts +7 -9
- package/template/apps/qpqjs/services/test/service/src/smoke/{tests/storageDriveEvent → suites/storageDriveEvent/logic}/index.ts +1 -0
- package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/storageDriveEventSmokeSuite.ts +9 -0
- package/template/apps/qpqjs/services/testa/models/src/CrossServiceProbePayload.ts +1 -1
- package/template/apps/qpqjs/services/testa/service/src/infrastructure.ts +3 -3
- package/template/apps/qpqjs/services/testa/service/src/smoke/config/defineSmokeProbes.ts +16 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/config/index.ts +1 -0
- package/template/apps/qpqjs/services/{test/service/src/tick → testa/service/src/smoke}/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/index.ts +3 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/keyValueStore/config/defineKeyValueStoreSmokeProbe.ts +33 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/keyValueStore/config/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/keyValueStore/entry/serviceFunction/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/keyValueStore/logic/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/signingKey/config/defineSigningKeySmokeProbe.ts +28 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/signingKey/config/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/signingKey/entry/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/signingKey/entry/serviceFunction/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/signingKey/index.ts +3 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/signingKey/logic/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/storageDrive/config/defineStorageDriveSmokeProbe.ts +31 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/storageDrive/config/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/storageDrive/entry/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/storageDrive/entry/serviceFunction/index.ts +1 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/storageDrive/index.ts +3 -0
- package/template/apps/qpqjs/services/testa/service/src/smoke/suites/storageDrive/logic/index.ts +1 -0
- package/template/apps/todo/deploy.config.json +13 -4
- package/template/apps/todo/packages/constants/src/index.ts +0 -1
- package/template/apps/todo/packages/service-utils/src/defineTodoService.ts +9 -7
- package/template/apps/todo/services/admin/service/src/infrastructure.ts +1 -1
- package/template/apps/todo/services/admin/views/src/app/app.tsx +9 -19
- package/template/apps/todo/services/auth/service/src/infrastructure.ts +1 -1
- package/template/apps/todo/services/design/service/src/infrastructure.ts +1 -1
- package/template/apps/todo/services/shell/service/src/infrastructure.ts +1 -1
- package/template/apps/todo/services/todo/service/src/infrastructure.ts +1 -1
- package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-delete.md +1 -1
- package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-get-all.md +1 -1
- package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-get.md +1 -1
- package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-query.md +3 -1
- package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-scan.md +1 -1
- package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-update.md +1 -1
- package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-upsert.md +1 -1
- package/template/docusaurus/docs/config/core/key-value-store.md +12 -2
- package/template/docusaurus/docs/config/features/event-doc.md +22 -1
- package/template/docusaurus/docs/getting-started.md +5 -5
- package/template/scripts/deployedSmoke.mjs +27 -22
- package/template/scripts/localSmoke.mjs +7 -7
- package/lib/commonjs/lib/replaceInFileExact.d.ts +0 -1
- package/lib/commonjs/lib/replaceInFileExact.js +0 -18
- package/lib/commonjs/lib/replaceInFileExact.js.map +0 -1
- package/lib/commonjs/steps/013_printNextSteps.js.map +0 -1
- package/lib/esm/lib/replaceInFileExact.d.ts +0 -1
- package/lib/esm/lib/replaceInFileExact.js +0 -11
- package/lib/esm/lib/replaceInFileExact.js.map +0 -1
- package/lib/esm/steps/013_printNextSteps.js +0 -21
- package/lib/esm/steps/013_printNextSteps.js.map +0 -1
- package/template/apps/qpqjs/packages/constants/src/domain.ts +0 -3
- package/template/apps/qpqjs/services/test/service/src/echo/config/defineEcho.ts +0 -9
- package/template/apps/qpqjs/services/test/service/src/smoke/constants/smokeProbe.ts +0 -39
- package/template/apps/qpqjs/services/test/service/src/smoke/models/index.ts +0 -5
- package/template/apps/qpqjs/services/test/service/src/smoke/queue/index.ts +0 -3
- package/template/apps/qpqjs/services/test/service/src/smoke/storageDrive/index.ts +0 -4
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/crossService/index.ts +0 -3
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/keyValueStore/index.ts +0 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/scopedKeyValueStore/askRunScopedKeyValueStoreTest.ts +0 -102
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/signingKey/index.ts +0 -1
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/smokeTestRegistry.ts +0 -66
- package/template/apps/qpqjs/services/test/service/src/smoke/tests/storageDrive/index.ts +0 -1
- package/template/apps/qpqjs/services/test/service/src/tick/config/index.ts +0 -1
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/config/defineCrossServiceProbe.ts +0 -68
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/config/index.ts +0 -1
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/entry/serviceFunction/index.ts +0 -3
- package/template/apps/qpqjs/services/testa/service/src/crossServiceProbe/logic/index.ts +0 -3
- package/template/apps/todo/packages/constants/src/domain.ts +0 -2
- /package/lib/commonjs/steps/{007_pinRegistryVersions.d.ts → 008_pinRegistryVersions.d.ts} +0 -0
- /package/lib/commonjs/steps/{008_transpileToJavaScript.d.ts → 009_transpileToJavaScript.d.ts} +0 -0
- /package/lib/commonjs/steps/{009_restoreGitignore.d.ts → 010_restoreGitignore.d.ts} +0 -0
- /package/lib/commonjs/steps/{010_gitInit.d.ts → 011_gitInit.d.ts} +0 -0
- /package/lib/commonjs/steps/{011_npmInstall.d.ts → 012_npmInstall.d.ts} +0 -0
- /package/lib/commonjs/steps/{012_buildWorkspaces.d.ts → 013_buildWorkspaces.d.ts} +0 -0
- /package/lib/commonjs/steps/{013_printNextSteps.d.ts → 014_printNextSteps.d.ts} +0 -0
- /package/lib/esm/steps/{007_pinRegistryVersions.d.ts → 008_pinRegistryVersions.d.ts} +0 -0
- /package/lib/esm/steps/{008_transpileToJavaScript.d.ts → 009_transpileToJavaScript.d.ts} +0 -0
- /package/lib/esm/steps/{009_restoreGitignore.d.ts → 010_restoreGitignore.d.ts} +0 -0
- /package/lib/esm/steps/{010_gitInit.d.ts → 011_gitInit.d.ts} +0 -0
- /package/lib/esm/steps/{011_npmInstall.d.ts → 012_npmInstall.d.ts} +0 -0
- /package/lib/esm/steps/{012_buildWorkspaces.d.ts → 013_buildWorkspaces.d.ts} +0 -0
- /package/lib/esm/steps/{013_printNextSteps.d.ts → 014_printNextSteps.d.ts} +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests → harness/assert}/askSmokeAssert.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests → harness/assert}/askSmokePollForMarker.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{constants → harness/constants}/SMOKE_RUNS_STORE.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{constants → harness/constants}/githubOidc.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{constants → harness/constants}/smokeRunQueue.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{controller → harness/controller}/askGetSmokeRun.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{controller → harness/controller}/askRunSmokeTests.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{controller → harness/controller}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{data → harness/data}/askGetSmokeRunById.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{data → harness/data}/askRecordSmokeTestResult.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{data → harness/data}/askSaveSmokeRun.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{data → harness/data}/askSetSmokeRunOutcome.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{data → harness/data}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{logic → harness/logic}/github/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{logic → harness/logic}/github/verifyGithubOidcToken.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{logic → harness/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{logic → harness/logic}/smokeRun/askFindSmokeRun.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{logic → harness/logic}/smokeRun/summarizeSmokeRun.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{models → harness/models}/GithubOidcClaims.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{processors → harness/processors}/github/getGithubOidcAuthProcessors.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{processors → harness/processors}/github/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{processors → harness/processors}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{queue → harness/queue}/onSmokeTestRequested.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests → harness/types}/SmokeTestDefinition.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{email → suites/emailReceive/logic}/smokeEmailMarkerId.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/encryptedResources → suites/encryptedResources/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/eventBus → suites/eventBus/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{models → suites/eventBus/models}/SmokeProbeEventQueueEvent.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{eventDoc → suites/eventDoc/definition}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{eventDoc → suites/eventDoc/definition}/smokeProbeDocDefinition.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/eventDoc → suites/eventDoc/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{models → suites/eventDoc/models}/SmokeEventDocAppendQueueEvent.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{models → suites/eventDoc/models}/SmokeEventDocMark.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{kvsStream → suites/keyValueStoreStream/logic}/smokeStreamMarkerId.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/noop → suites/noop/logic}/askRunNoopTest.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/noop → suites/noop/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{echo → smoke/suites/openApi}/controller/echo.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{echo → smoke/suites/openApi}/controller/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/openApi → suites/openApi/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/parameter → suites/parameter/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{tick → smoke/suites/schedule}/constants/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{tick → smoke/suites/schedule}/constants/scheduleTickName.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{tick → smoke/suites/schedule}/constants/scheduleTickStore.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{tick → smoke/suites/schedule}/entry/kvsStream/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{tick → smoke/suites/schedule}/entry/kvsStream/onScheduleTickStream.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{tick → smoke/suites/schedule}/entry/schedule/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{tick → smoke/suites/schedule}/entry/schedule/onTick.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/schedule → suites/schedule/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{tick → smoke/suites/schedule}/models/ScheduleTickRecord.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/{tick → smoke/suites/schedule}/models/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/scopedKeyValueStore → suites/scopedKeyValueStore/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/scopedStorageDrive → suites/scopedStorageDrive/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{tests/secret → suites/secret/logic}/index.ts +0 -0
- /package/template/apps/qpqjs/services/test/service/src/smoke/{storageDrive → suites/storageDriveEvent/logic}/smokeFileEventMarkerId.ts +0 -0
- /package/template/apps/qpqjs/services/testa/service/src/{crossServiceProbe → smoke/suites/keyValueStore}/entry/index.ts +0 -0
- /package/template/apps/qpqjs/services/testa/service/src/{crossServiceProbe → smoke/suites/keyValueStore}/entry/serviceFunction/smokeCrossServiceKeyValueStoreProbe.ts +0 -0
- /package/template/apps/qpqjs/services/testa/service/src/{crossServiceProbe → smoke/suites/keyValueStore}/index.ts +0 -0
- /package/template/apps/qpqjs/services/testa/service/src/{crossServiceProbe → smoke/suites/keyValueStore}/logic/askProbeForeignKeyValueStore.ts +0 -0
- /package/template/apps/qpqjs/services/testa/service/src/{crossServiceProbe → smoke/suites/signingKey}/entry/serviceFunction/smokeCrossServiceSigningKeyProbe.ts +0 -0
- /package/template/apps/qpqjs/services/testa/service/src/{crossServiceProbe → smoke/suites/signingKey}/logic/askProbeForeignSigningKey.ts +0 -0
- /package/template/apps/qpqjs/services/testa/service/src/{crossServiceProbe → smoke/suites/storageDrive}/entry/serviceFunction/smokeCrossServiceStorageDriveProbe.ts +0 -0
- /package/template/apps/qpqjs/services/testa/service/src/{crossServiceProbe → smoke/suites/storageDrive}/logic/askProbeForeignStorageDrive.ts +0 -0
|
@@ -52,6 +52,7 @@ function* askKeyValueStoreQuery<KvsItem>(
|
|
|
52
52
|
| Property | Type | Default | Description |
|
|
53
53
|
| --- | --- | --- | --- |
|
|
54
54
|
| `filter` | `KvsQueryOperation` | – | An extra condition applied to non-key attributes **after** the key match. Filtered-out rows still count against `limit`. |
|
|
55
|
+
| `indexName` | `string` | – | Force the query onto the [index](../../../config/core/key-value-store.md#indexes-gsis) declared with this name, read in its sort order. Without it, the table serves the query if its keys cover the key condition, otherwise the first declared index whose keys do — so an index sharing the table's keys is only reached by naming it here. An undeclared name throws `IndexNotFound`. |
|
|
55
56
|
| `sortAscending` | `boolean` | `true` | Order results by the sort key. `false` returns the newest/highest first. |
|
|
56
57
|
| `limit` | `number` | – | Maximum number of records to return in this page. |
|
|
57
58
|
| `nextPageKey` | `string` | – | Opaque cursor from a previous page's `nextPageKey`; pass it to fetch the following page. |
|
|
@@ -118,8 +119,9 @@ When `nextPageKey` is set, pass it back as `options.nextPageKey` to fetch the ne
|
|
|
118
119
|
| --- | --- |
|
|
119
120
|
| `KeyValueStoreQueryErrorTypeEnum.ServiceUnavailable` | DynamoDB internal error or throttling. |
|
|
120
121
|
| `KeyValueStoreQueryErrorTypeEnum.ResourceNotFound` | The underlying table does not exist. |
|
|
121
|
-
| `KeyValueStoreQueryErrorTypeEnum.InvalidScope` | The `scope` option is malformed (empty, `.`, over 128 characters, or containing path separators, `..`, `@`, or null bytes), the store's partition key is not string-typed, a scoped query's key condition does not constrain the partition key (or constrains
|
|
122
|
+
| `KeyValueStoreQueryErrorTypeEnum.InvalidScope` | The `scope` option is malformed (empty, `.`, over 128 characters, or containing path separators, `..`, `@`, or null bytes), the store's partition key is not string-typed, a scoped query's key condition does not constrain the partition key or an [index](../../../config/core/key-value-store.md#indexes-gsis) partition key (or constrains one with an operator that cannot be scoped: an index partition key only takes `=`), a condition names an attribute containing `@@QPQ`, an index partition-key condition value doesn't match that index's declared type, or a partition-key condition value contains the reserved `@@QPQ` marker (reserved on string-pk stores, so unscoped queries reject it too). |
|
|
122
123
|
| `KeyValueStoreQueryErrorTypeEnum.StoreNotFound` | The key value store is not declared in the qpq config (misconfiguration, e.g. a wrong name or a missing `defineKeyValueStore`). |
|
|
124
|
+
| `KeyValueStoreQueryErrorTypeEnum.IndexNotFound` | The `indexName` option names an index the store doesn't declare. |
|
|
123
125
|
|
|
124
126
|
Catch errors with `askCatch` — it returns `{ success: true, result }` or `{ success: false, error }`.
|
|
125
127
|
|
|
@@ -70,7 +70,7 @@ When `nextPageKey` is set, pass it back as the third argument to fetch the next
|
|
|
70
70
|
| --- | --- |
|
|
71
71
|
| `KeyValueStoreScanErrorTypeEnum.ServiceUnavailable` | DynamoDB internal error or throttling. |
|
|
72
72
|
| `KeyValueStoreScanErrorTypeEnum.ResourceNotFound` | The underlying table does not exist. |
|
|
73
|
-
| `KeyValueStoreScanErrorTypeEnum.InvalidScope` | The `scope` option is malformed (empty, `.`, over 128 characters, or containing path separators, `..`, `@`, or null bytes), the store's partition key is not string-typed,
|
|
73
|
+
| `KeyValueStoreScanErrorTypeEnum.InvalidScope` | The `scope` option is malformed (empty, `.`, over 128 characters, or containing path separators, `..`, `@`, or null bytes), the store's partition key is not string-typed, a scoped call's partition-key value contains the reserved `@@QPQ` marker, a scoped call's `filterCondition` names an attribute containing `@@QPQ`, or a scoped `filterCondition`'s partition-key comparison uses an operator that cannot be scoped. |
|
|
74
74
|
| `KeyValueStoreScanErrorTypeEnum.StoreNotFound` | The key value store is not declared in the qpq config (misconfiguration, e.g. a wrong name or a missing `defineKeyValueStore`). |
|
|
75
75
|
|
|
76
76
|
Catch errors with `askCatch` — it returns `{ success: true, result }` or `{ success: false, error }`.
|
|
@@ -101,7 +101,7 @@ Each `path` is a `KvsAttributePath` — either a top-level attribute name (`'bal
|
|
|
101
101
|
| --- | --- |
|
|
102
102
|
| `KeyValueStoreUpdateErrorTypeEnum.ServiceUnavailable` | DynamoDB internal error or throttling. |
|
|
103
103
|
| `KeyValueStoreUpdateErrorTypeEnum.ResourceNotFound` | The underlying table does not exist. |
|
|
104
|
-
| `KeyValueStoreUpdateErrorTypeEnum.InvalidScope` | The `scope` option is malformed (empty, `.`, over 128 characters, or containing path separators, `..`, `@`, or null bytes), the store's partition key is not string-typed,
|
|
104
|
+
| `KeyValueStoreUpdateErrorTypeEnum.InvalidScope` | The `scope` option is malformed (empty, `.`, over 128 characters, or containing path separators, `..`, `@`, or null bytes), the store's partition key is not string-typed, the partition-key value contains the reserved `@@QPQ` marker (reserved on string-pk stores, so unscoped calls reject it too), a scoped update names an attribute containing `@@QPQ`, or a scoped update targets an [index](../../../config/core/key-value-store.md#indexes-gsis) partition key with anything other than a whole-value `Set`/`SetIfNotExists`/`Remove` of the declared type (`Increment`, `Add`, `Delete`, and nested paths are refused). |
|
|
105
105
|
| `KeyValueStoreUpdateErrorTypeEnum.StoreNotFound` | The key value store is not declared in the qpq config (misconfiguration, e.g. a wrong name or a missing `defineKeyValueStore`). |
|
|
106
106
|
|
|
107
107
|
Catch errors with `askCatch` — it returns `{ success: true, result }` or `{ success: false, error }`.
|
|
@@ -61,7 +61,7 @@ function* askKeyValueStoreUpsert<KvsItem>(
|
|
|
61
61
|
| `KeyValueStoreUpsertErrorTypeEnum.ResourceNotFound` | The underlying table does not exist. |
|
|
62
62
|
| `KeyValueStoreUpsertErrorTypeEnum.Conflict` | A conditional (`ifNotExists`) write lost to an existing item — final, the slot is taken. Namespaced — not the generic `ErrorTypeEnum.Conflict` — so retry logic can target the write race specifically without also catching domain-level conflicts. |
|
|
63
63
|
| `KeyValueStoreUpsertErrorTypeEnum.WriteContention` | A conditional (`ifNotExists`) write lost to another write (a transaction) holding the item right now — transient, the item may still be absent once it settles. |
|
|
64
|
-
| `KeyValueStoreUpsertErrorTypeEnum.InvalidScope` | The `scope` option is malformed (empty, `.`, over 128 characters, or containing path separators, `..`, `@`, or null bytes), the store's partition key is not string-typed,
|
|
64
|
+
| `KeyValueStoreUpsertErrorTypeEnum.InvalidScope` | The `scope` option is malformed (empty, `.`, over 128 characters, or containing path separators, `..`, `@`, or null bytes), the store's partition key is not string-typed, the partition-key value contains the reserved `@@QPQ` marker (reserved on string-pk stores, so unscoped calls reject it too), a scoped item has an attribute name containing `@@QPQ`, or a scoped item's [index](../../../config/core/key-value-store.md#indexes-gsis) partition-key value doesn't match that index's declared type. |
|
|
65
65
|
| `KeyValueStoreUpsertErrorTypeEnum.StoreNotFound` | The key value store is not declared in the qpq config (misconfiguration, e.g. a wrong name or a missing `defineKeyValueStore`). |
|
|
66
66
|
|
|
67
67
|
Catch errors with `askCatch` — it returns `{ success: true, result }` or `{ success: false, error }`.
|
|
@@ -83,7 +83,7 @@ defineKeyValueStore('events', kvsKey('deviceId'), [kvsKey('timestamp', 'number')
|
|
|
83
83
|
|
|
84
84
|
## Indexes (GSIs)
|
|
85
85
|
|
|
86
|
-
Each entry in `options.indexes` is a `CompositeKvsIndex<T>` — either a bare attribute name (a partition-key-only index) or an object with a `partitionKey` and optional `
|
|
86
|
+
Each entry in `options.indexes` is a `CompositeKvsIndex<T>` — either a bare attribute name (a partition-key-only index) or an object with a `partitionKey`, optional `sortKey`, and optional `name`:
|
|
87
87
|
|
|
88
88
|
```typescript
|
|
89
89
|
import { defineKeyValueStore, kvsKey } from 'quidproquo-core';
|
|
@@ -94,11 +94,21 @@ defineKeyValueStore('orders', 'orderId', [], {
|
|
|
94
94
|
{ partitionKey: 'customerId', sortKey: kvsKey('createdAt', 'number') },
|
|
95
95
|
// Query orders by status (partition-only index)
|
|
96
96
|
'status',
|
|
97
|
+
// Two indexes on the same partition key need an explicit name
|
|
98
|
+
{ name: 'byStatusAndTotal', partitionKey: 'status', sortKey: kvsKey('total', 'number') },
|
|
97
99
|
],
|
|
98
100
|
});
|
|
99
101
|
```
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
`name` defaults to the partition-key attribute (`customerId`, `status` above) and is what [askKeyValueStoreQuery](../../actions/core/key-value-store/ask-key-value-store-query.md)'s `indexName` option targets; `defineKeyValueStore` throws if two indexes resolve to the same name. On AWS each index becomes a Global Secondary Index deployed under this name.
|
|
104
|
+
|
|
105
|
+
A query without `indexName` runs against the table if its keys cover every attribute in the key condition, otherwise the first declared index whose keys do.
|
|
106
|
+
|
|
107
|
+
### Indexes on a scoped store
|
|
108
|
+
|
|
109
|
+
A store with `scoped: true` (see [`scoped`](#options--qpqconfigadvancedkeyvaluestoresettingst-optional)) can still declare `indexes`. On AWS, an index whose partition key isn't the table's partition key is keyed on a hidden `@@QPQGSI_<attribute>@@` attribute holding the scope-composed value; the index keeps its declared name and sort key, and stories never see the hidden attribute. A scoped store's index partition key must be a `'string'` or `'number'` key, since a scope can't be composed onto a `'binary'` key — `defineKeyValueStore` throws at config time otherwise.
|
|
110
|
+
|
|
111
|
+
Adding or removing an index on an already-deployed scoped store needs two deploys: remove the index and deploy, then re-add it and deploy. CloudFormation can't change a GSI's key schema in place, and rows written before the new index exists only appear in it once they're rewritten.
|
|
102
112
|
|
|
103
113
|
## Change data capture (`onStream`)
|
|
104
114
|
|
|
@@ -25,7 +25,7 @@ export default [
|
|
|
25
25
|
|
|
26
26
|
## Registering a collection's functions
|
|
27
27
|
|
|
28
|
-
`functions` is an `EventDocFunctions` object: `{ storeName, type, foldSnapshotViews, foldDocumentState, collectReferences, collectReferencesFromState, validateEvent, render? }`. The object `createEventDocDefinition` returns — given `storeName`/`type` in its config — satisfies this shape directly, so a collection with no service-only render can register its definition verbatim. A collection that needs a render step only service code can perform (resolving linked docs, reading blob-drive assets) layers it on with `extendEventDocFunctions(definition, { render })`, which returns a new object and never mutates the definition itself.
|
|
28
|
+
`functions` is an `EventDocFunctions` object: `{ storeName, type, getSnapshotCacheKey, foldSnapshotViews, foldDocumentState, collectReferences, collectReferencesFromState, validateEvent, render? }`. The object `createEventDocDefinition` returns — given `storeName`/`type` in its config — satisfies this shape directly, so a collection with no service-only render can register its definition verbatim. A collection that needs a render step only service code can perform (resolving linked docs, reading blob-drive assets) layers it on with `extendEventDocFunctions(definition, { render })`, which returns a new object and never mutates the definition itself.
|
|
29
29
|
|
|
30
30
|
`runtime` is a [`QpqFunctionRuntime`](../core/dynamic-functions.md#runtime--qpqfunctionruntime-required) path to that SAME export — the dynamic-functions pattern: identity is read off the object here at config time, behaviour is loaded from the path by the processors at request time. Both must point at the exact object being registered, or the registration and the runtime will disagree about what the collection can do.
|
|
31
31
|
|
|
@@ -55,6 +55,7 @@ The collection's callable surface, read for its identity (`storeName`, `type`) a
|
|
|
55
55
|
| --- | --- | --- | --- |
|
|
56
56
|
| `storeName` | `string` | yes | Name of the summary store to create and serve. Also derives the events table and asset bucket names. |
|
|
57
57
|
| `type` | `string` | yes | The document type this collection holds — the store's partition value, so one store can (via the split helpers) hold several types. |
|
|
58
|
+
| `getSnapshotCacheKey` | `() => string` | yes | The key this collection's snapshots are filed under (see [Snapshot cache key](#snapshot-cache-key)). `''` is the legacy layout. A member rather than a value because the data layer reaches a definition only through dynamic functions. |
|
|
58
59
|
| `foldSnapshotViews` | `(events, seedViews?) => Nullable<EventDocSnapshotViews>` | yes | Every view of a log prefix, era-pinned — what a snapshot stores. Invoked by the event store's stream projector (which also writes the summary row from the fold's `summary` view). |
|
|
59
60
|
| `foldDocumentState` | `(events, seedState?) => unknown` | yes | The document view at one point, LATEST-shaped, resumable from a stored snapshot's era-pinned document state. The read side's fold: render, references, as-of reads, and the append hooks' state derivation all go through it. |
|
|
60
61
|
| `collectReferences` | `(events) => EventDocLink[]` | yes | The `EventDocLink`s this doc's whole HISTORY depends on; `[]` for a leaf doc type. Invoked by the transfer manifest walk (it exports the whole history). |
|
|
@@ -62,6 +63,26 @@ The collection's callable surface, read for its identity (`storeName`, `type`) a
|
|
|
62
63
|
| `validateEvent` | `(event, state) => Nullable<string> \| AskResponse<Nullable<string>>` | yes | The append pre-write gate: checked against the state the event will land on, before the write (see [askEventDocEventAppend](../../actions/features/event-doc/ask-event-doc-event-append.md)). Return a rejection reason string to refuse the append, `null` to allow it. A collection with no domain rules can pass `() => null`. |
|
|
63
64
|
| `render` | `(input: EventDocRenderInput) => EventDocRenderResult \| AskResponse<EventDocRenderResult>` | no | Render the resolved, already-folded document state (`input.state`, resolved snapshot-seeded by the route). Omit and `GET {basePath}/{id}/render` 404s as "no renderer configured". Plain function or story — the dynamic-functions processor runs either. |
|
|
64
65
|
|
|
66
|
+
#### Snapshot cache key
|
|
67
|
+
|
|
68
|
+
A snapshot is a memo of "fold these events with this seed and reducer". The events are immutable, so the memo stays valid until the fold code changes. A change to the MEANING of existing events is a schema version bump with a migration. An additive change — a new defaulted field in a version's seed, a new event type, a new reducer case — needs no migration, but every stored snapshot is now the output of code you no longer run, and a reader resuming from one would see the old shape (a `undefined` where the new field should be).
|
|
69
|
+
|
|
70
|
+
`snapshotCacheKey` on `createEventDocDefinition` names the fold code. It is part of the snapshot row's partition key (`docId#viewName#key`) and the offloaded blob's path, so after you change it every reader finds no snapshot, refolds the whole log from the seed, and the stream projector files a fresh snapshot under the new key on the document's next append. The bootstrap base handed to the editor carries the key too, so a workspace snapshot held in the browser across a deploy is refetched rather than trusted. Rows under an old key are left to persist.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
export const contentItemEventDoc = createEventDocDefinition({
|
|
74
|
+
storeName: CONTENT_STORE,
|
|
75
|
+
type: 'content',
|
|
76
|
+
schemaVersion: 1,
|
|
77
|
+
versions: [contentItemV1],
|
|
78
|
+
// Bump when v1's seed or reducer changes in place; every stored snapshot is then refolded.
|
|
79
|
+
snapshotCacheKey: '2026-09-23-image-assets',
|
|
80
|
+
api,
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Refolding is lazy: a document pays one whole-log fold per reader until its next append reprojects it. To pay that up front, an admin job can walk each collection's documents (inside each storage scope) and call `askEventDocReprojectHead(docId)`, which re-runs the projector at the log head under the current key.
|
|
85
|
+
|
|
65
86
|
### `runtime` — `QpqFunctionRuntime` (required)
|
|
66
87
|
|
|
67
88
|
A reference to the module exporting `functions`, usually a relative path string of the form `'/path/to/file::exportedObjectName'` — see [defineDynamicFunctions](../core/dynamic-functions.md#runtime--qpqfunctionruntime-required). Must resolve to the SAME object passed as `functions`.
|
|
@@ -45,9 +45,9 @@ curl http://localhost:8080/api/shell/v1/health
|
|
|
45
45
|
myapp/
|
|
46
46
|
├── package.json # workspace root — run all commands from here
|
|
47
47
|
└── apps/myapp/
|
|
48
|
-
├── deploy.config.json #
|
|
48
|
+
├── deploy.config.json # deployments: development + production (docker)
|
|
49
49
|
├── packages/
|
|
50
|
-
│ ├── constants/ #
|
|
50
|
+
│ ├── constants/ # service enum, user directory name
|
|
51
51
|
│ ├── config/
|
|
52
52
|
│ └── service-utils/ # the shared config every service starts from
|
|
53
53
|
└── services/
|
|
@@ -106,14 +106,14 @@ itself.
|
|
|
106
106
|
|
|
107
107
|
## Deploy it
|
|
108
108
|
|
|
109
|
-
Both scaffolded
|
|
109
|
+
Both scaffolded deployments build a single docker image — the whole
|
|
110
110
|
app, one container:
|
|
111
111
|
|
|
112
112
|
```bash
|
|
113
113
|
npm run go
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
Pick
|
|
116
|
+
Pick a deployment when prompted (or pass `--deployment development`), and the
|
|
117
117
|
build prints the `docker run` command when the image is ready:
|
|
118
118
|
|
|
119
119
|
```bash
|
|
@@ -122,7 +122,7 @@ docker run --rm -p 80:8080 -p 8080:8080 -p 8888:8888 -p 3001:3001 \
|
|
|
122
122
|
qpq-myapp:development
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
Then open [http://localhost](http://localhost).
|
|
125
|
+
Then open [http://localhost](http://localhost). Deployments live in
|
|
126
126
|
`apps/myapp/deploy.config.json` — an app can move platforms (docker → AWS)
|
|
127
127
|
with a config change, not a rewrite.
|
|
128
128
|
|
|
@@ -11,13 +11,14 @@
|
|
|
11
11
|
// ACTIONS_ID_TOKEN_REQUEST_TOKEN provided by Actions when the job has id-token: write
|
|
12
12
|
// SMOKE_ROOTS optional comma list to run a subset of the roots
|
|
13
13
|
//
|
|
14
|
-
// Urls are derived, not configured: the roots come from the
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
14
|
+
// Urls are derived, not configured: the roots come from the deployment's
|
|
15
|
+
// ROOT_DOMAINS setting in apps/qpqjs/deploy.config.json (the same list every
|
|
16
|
+
// service's defineDns reads; the deployment is named after the environment),
|
|
17
|
+
// hosts follow the app's default domain shape (see getRootHosts), and the api
|
|
18
|
+
// gateway maps each service under its own base path:
|
|
18
19
|
// https://api.<environment>.<root>/<service>
|
|
19
20
|
|
|
20
|
-
import {
|
|
21
|
+
import { readFileSync } from 'node:fs';
|
|
21
22
|
import { dirname, join } from 'node:path';
|
|
22
23
|
import { fileURLToPath } from 'node:url';
|
|
23
24
|
|
|
@@ -25,10 +26,9 @@ import { getRootHosts, runEdgeChecks } from './smoke/runEdgeChecks.mjs';
|
|
|
25
26
|
import { runSmokeRun } from './smoke/runSmokeRun.mjs';
|
|
26
27
|
|
|
27
28
|
const SERVICE_NAME = 'test';
|
|
28
|
-
|
|
29
|
-
const DOMAIN_CONSTANTS_PATH = join(
|
|
29
|
+
const DEPLOY_CONFIG_PATH = join(
|
|
30
30
|
dirname(fileURLToPath(import.meta.url)),
|
|
31
|
-
'../apps/qpqjs/
|
|
31
|
+
'../apps/qpqjs/deploy.config.json'
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
const log = (message) => console.log(`deployed-smoke: ${message}`);
|
|
@@ -46,24 +46,29 @@ const requireEnv = (name) => {
|
|
|
46
46
|
return value;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
const splitList = (value) =>
|
|
50
|
+
(value ?? '')
|
|
51
|
+
.split(',')
|
|
52
|
+
.map((item) => item.trim())
|
|
53
|
+
.filter(Boolean);
|
|
54
|
+
|
|
55
|
+
const getRoots = (environment) => {
|
|
56
|
+
const { deployments } = JSON.parse(readFileSync(DEPLOY_CONFIG_PATH, 'utf8'));
|
|
57
|
+
const allRoots = splitList(deployments[environment]?.settings?.ROOT_DOMAINS);
|
|
58
|
+
if (!allRoots.length) {
|
|
59
|
+
fail(
|
|
60
|
+
`deployment '${environment}' in ${DEPLOY_CONFIG_PATH} has no ROOT_DOMAINS setting`
|
|
61
|
+
);
|
|
55
62
|
}
|
|
56
63
|
|
|
57
|
-
const subset = process.env.SMOKE_ROOTS
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (!subset?.length) {
|
|
61
|
-
return QPQJS_DOMAINS;
|
|
64
|
+
const subset = splitList(process.env.SMOKE_ROOTS);
|
|
65
|
+
if (!subset.length) {
|
|
66
|
+
return allRoots;
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
const unknown = subset.filter((root) => !
|
|
69
|
+
const unknown = subset.filter((root) => !allRoots.includes(root));
|
|
65
70
|
if (unknown.length > 0) {
|
|
66
|
-
fail(`SMOKE_ROOTS names roots not in
|
|
71
|
+
fail(`SMOKE_ROOTS names roots not in ROOT_DOMAINS: ${unknown.join(', ')}`);
|
|
67
72
|
}
|
|
68
73
|
return subset;
|
|
69
74
|
};
|
|
@@ -101,7 +106,7 @@ const smokeRoot = async (hosts, allHosts) => {
|
|
|
101
106
|
};
|
|
102
107
|
|
|
103
108
|
const environment = requireEnv('SMOKE_ENVIRONMENT');
|
|
104
|
-
const roots = getRoots();
|
|
109
|
+
const roots = getRoots(environment);
|
|
105
110
|
const allHosts = roots.map((root) => getRootHosts(root, environment));
|
|
106
111
|
|
|
107
112
|
log(`environment=${environment} roots=${roots.join(', ')}`);
|
|
@@ -30,10 +30,11 @@ import { fileURLToPath } from 'node:url';
|
|
|
30
30
|
|
|
31
31
|
import { runSmokeRun } from './smoke/runSmokeRun.mjs';
|
|
32
32
|
|
|
33
|
-
// The
|
|
34
|
-
//
|
|
35
|
-
// the smoke routes expect from the token.
|
|
36
|
-
|
|
33
|
+
// The deployment (an entry in apps/qpqjs/deploy.config.json) the dev server
|
|
34
|
+
// runs as. There are several, so it has to be named or a headless cli exits.
|
|
35
|
+
// Its environment must match what the smoke routes expect from the token, i.e.
|
|
36
|
+
// the job's `environment:`.
|
|
37
|
+
const DEPLOYMENT = 'development';
|
|
37
38
|
|
|
38
39
|
// There is more than one app under apps/, so the app has to be named: without
|
|
39
40
|
// it the cli exits with the app list rather than picking one.
|
|
@@ -134,7 +135,7 @@ const stopServer = (server) =>
|
|
|
134
135
|
});
|
|
135
136
|
|
|
136
137
|
const main = async () => {
|
|
137
|
-
log(`starting dev server (app=${APP_NAME}
|
|
138
|
+
log(`starting dev server (app=${APP_NAME} deployment=${DEPLOYMENT})`);
|
|
138
139
|
|
|
139
140
|
// node on the cli directly, NOT `npx qpq`: npx is another process in front
|
|
140
141
|
// of the one we need to signal, and SIGTERM stops at it. The cli would never
|
|
@@ -143,11 +144,10 @@ const main = async () => {
|
|
|
143
144
|
// the handler is.
|
|
144
145
|
const server = spawn(
|
|
145
146
|
process.execPath,
|
|
146
|
-
[QPQ_BIN, 'go:dev:api', '--app', APP_NAME],
|
|
147
|
+
[QPQ_BIN, 'go:dev:api', '--app', APP_NAME, '--deployment', DEPLOYMENT],
|
|
147
148
|
{
|
|
148
149
|
cwd: APP_ROOT,
|
|
149
150
|
stdio: 'inherit',
|
|
150
|
-
env: { ...process.env, ENVIRONMENT },
|
|
151
151
|
}
|
|
152
152
|
);
|
|
153
153
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const replaceInFileExact: (filePath: string, from: string, to: string) => void;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.replaceInFileExact = void 0;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
// Replace an exact string in one file, throwing if it isn't there. Targeted
|
|
9
|
-
// edits should fail loudly when the template drifts.
|
|
10
|
-
const replaceInFileExact = (filePath, from, to) => {
|
|
11
|
-
const original = fs_1.default.readFileSync(filePath, 'utf8');
|
|
12
|
-
if (!original.includes(from)) {
|
|
13
|
-
throw new Error(`Expected to find "${from}" in ${filePath}. Has the template changed?`);
|
|
14
|
-
}
|
|
15
|
-
fs_1.default.writeFileSync(filePath, original.split(from).join(to));
|
|
16
|
-
};
|
|
17
|
-
exports.replaceInFileExact = replaceInFileExact;
|
|
18
|
-
//# sourceMappingURL=replaceInFileExact.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replaceInFileExact.js","sourceRoot":"","sources":["../../../src/lib/replaceInFileExact.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AAEpB,4EAA4E;AAC5E,qDAAqD;AAC9C,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAE,IAAY,EAAE,EAAU,EAAQ,EAAE;IACrF,MAAM,QAAQ,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,QAAQ,QAAQ,6BAA6B,CAAC,CAAC;IAC1F,CAAC;IACD,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5D,CAAC,CAAC;AANW,QAAA,kBAAkB,sBAM7B","sourcesContent":["import fs from 'fs';\n\n// Replace an exact string in one file, throwing if it isn't there. Targeted\n// edits should fail loudly when the template drifts.\nexport const replaceInFileExact = (filePath: string, from: string, to: string): void => {\n const original = fs.readFileSync(filePath, 'utf8');\n if (!original.includes(from)) {\n throw new Error(`Expected to find \"${from}\" in ${filePath}. Has the template changed?`);\n }\n fs.writeFileSync(filePath, original.split(from).join(to));\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
1
|
-
export declare const replaceInFileExact: (filePath: string, from: string, to: string) => void;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
// Replace an exact string in one file, throwing if it isn't there. Targeted
|
|
3
|
-
// edits should fail loudly when the template drifts.
|
|
4
|
-
export const replaceInFileExact = (filePath, from, to) => {
|
|
5
|
-
const original = fs.readFileSync(filePath, 'utf8');
|
|
6
|
-
if (!original.includes(from)) {
|
|
7
|
-
throw new Error(`Expected to find "${from}" in ${filePath}. Has the template changed?`);
|
|
8
|
-
}
|
|
9
|
-
fs.writeFileSync(filePath, original.split(from).join(to));
|
|
10
|
-
};
|
|
11
|
-
//# sourceMappingURL=replaceInFileExact.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replaceInFileExact.js","sourceRoot":"","sources":["../../../src/lib/replaceInFileExact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,4EAA4E;AAC5E,qDAAqD;AACrD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAE,IAAY,EAAE,EAAU,EAAQ,EAAE;IACrF,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,QAAQ,QAAQ,6BAA6B,CAAC,CAAC;IAC1F,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5D,CAAC,CAAC","sourcesContent":["import fs from 'fs';\n\n// Replace an exact string in one file, throwing if it isn't there. Targeted\n// edits should fail loudly when the template drifts.\nexport const replaceInFileExact = (filePath: string, from: string, to: string): void => {\n const original = fs.readFileSync(filePath, 'utf8');\n if (!original.includes(from)) {\n throw new Error(`Expected to find \"${from}\" in ${filePath}. Has the template changed?`);\n }\n fs.writeFileSync(filePath, original.split(from).join(to));\n};\n"]}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export const printNextSteps = {
|
|
2
|
-
name: 'Done',
|
|
3
|
-
run: async ({ answers }) => {
|
|
4
|
-
const install = answers.installDependencies ? '' : ' npm install\n npm run build\n';
|
|
5
|
-
console.log(`
|
|
6
|
-
Created ${answers.appName}!
|
|
7
|
-
|
|
8
|
-
Your app has five services (admin, auth, design, shell and todo) and
|
|
9
|
-
deploys as a single docker image.
|
|
10
|
-
|
|
11
|
-
Next steps:
|
|
12
|
-
|
|
13
|
-
cd ${answers.appName}
|
|
14
|
-
${install} npm run dev # api on http://localhost:8080, web on http://localhost:3080
|
|
15
|
-
npm run deploy # build the docker image (then run the printed docker command)
|
|
16
|
-
|
|
17
|
-
Deploy config lives in apps/${answers.appName}/deploy.config.json; the domain (${answers.domain}) lives in the app's constants package.
|
|
18
|
-
`);
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
//# sourceMappingURL=013_printNextSteps.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1,9 +0,0 @@
|
|
|
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');
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// Throwaway resources the smoke tests exercise, one per kind of owned
|
|
2
|
-
// resource the service role is granted by tag / name convention (see the
|
|
3
|
-
// tag-based IAM grants in quidproquo-deploy-awscdk). Nothing else uses them.
|
|
4
|
-
// The store and drive names live in @qpqjs/constants because testa reaches
|
|
5
|
-
// them cross-service.
|
|
6
|
-
export const SMOKE_PROBE_PARAMETER = 'smokeProbe';
|
|
7
|
-
export const SMOKE_PROBE_PARAMETER_VALUE = 'smoke-probe-parameter';
|
|
8
|
-
export const SMOKE_PROBE_SECRET = 'smokeProbe';
|
|
9
|
-
export const SMOKE_PROBE_EVENT_BUS = 'smokeProbe';
|
|
10
|
-
|
|
11
|
-
// The queue subscribed to the probe event bus, and the message type that
|
|
12
|
-
// flows bus -> queue -> store marker for the event bus test.
|
|
13
|
-
export const SMOKE_PROBE_EVENT_QUEUE = 'smokeProbeEvents';
|
|
14
|
-
export const SMOKE_PROBE_EVENT_TYPE = 'smokeProbeEvent';
|
|
15
|
-
|
|
16
|
-
// Scoped probe resources: every call must carry a scope, an unscoped one is
|
|
17
|
-
// refused. Only the test service uses them, so they stay service-level.
|
|
18
|
-
export const SMOKE_SCOPED_PROBE_STORE = 'smokeScopedProbe';
|
|
19
|
-
export const SMOKE_SCOPED_PROBE_DRIVE = 'smoke-scoped-probe';
|
|
20
|
-
|
|
21
|
-
// The file event drives: an unscoped and a scoped one, both with create and
|
|
22
|
-
// delete handlers that write a marker row the file event test polls for.
|
|
23
|
-
export const SMOKE_FILE_EVENT_DRIVE = 'smoke-file-event';
|
|
24
|
-
|
|
25
|
-
// A scoped store with a change stream; the handler writes a marker row the
|
|
26
|
-
// kvs stream test polls for.
|
|
27
|
-
export const SMOKE_STREAM_PROBE_STORE = 'smokeStreamProbe';
|
|
28
|
-
|
|
29
|
-
// The crypto key the encrypted probe drive and store name: proves the
|
|
30
|
-
// alias-conditioned KMS grant lets the service role write and read data
|
|
31
|
-
// encrypted with a defineCryptoKey. Not 'smokeProbe': the signing key of that
|
|
32
|
-
// name is a KMS alias too, and the two would collide.
|
|
33
|
-
export const SMOKE_CRYPTO_KEY = 'smokeCrypto';
|
|
34
|
-
export const SMOKE_ENCRYPTED_PROBE_STORE = 'smokeEncryptedProbe';
|
|
35
|
-
export const SMOKE_ENCRYPTED_PROBE_DRIVE = 'smoke-encrypted-probe';
|
|
36
|
-
|
|
37
|
-
// Inbound email: the receiver's onEmail writes a marker the email test polls for.
|
|
38
|
-
// Deployed only.
|
|
39
|
-
export const SMOKE_EMAIL_RECEIVER = 'smoke';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './askRunKeyValueStoreTest';
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
askCatch,
|
|
3
|
-
askKeyValueStoreDelete,
|
|
4
|
-
askKeyValueStoreGet,
|
|
5
|
-
askKeyValueStoreGetBase,
|
|
6
|
-
askKeyValueStoreQuery,
|
|
7
|
-
askKeyValueStoreUpsert,
|
|
8
|
-
askKeyValueStoreUpsertBase,
|
|
9
|
-
askNewGuid,
|
|
10
|
-
AskResponse,
|
|
11
|
-
kvsEqual,
|
|
12
|
-
} from 'quidproquo';
|
|
13
|
-
|
|
14
|
-
import { SMOKE_PROBE_STORE } from '@qpqjs/constants';
|
|
15
|
-
import { SmokeProbeRecord } from '@qpqjs/test-models';
|
|
16
|
-
|
|
17
|
-
import { SMOKE_SCOPED_PROBE_STORE } from '../../constants/smokeProbe';
|
|
18
|
-
import { askSmokeAssert } from '../askSmokeAssert';
|
|
19
|
-
|
|
20
|
-
// The scope gate on a store, on whichever backend is running: a scoped store
|
|
21
|
-
// serves scoped calls (including a query) and keeps two scopes apart,
|
|
22
|
-
// refuses an unscoped call, and an unscoped store refuses a scoped one. On
|
|
23
|
-
// dynamo the scope is composed into the partition key, so the read-back also
|
|
24
|
-
// proves the composed form never leaks to the caller.
|
|
25
|
-
export function* askRunScopedKeyValueStoreTest(): AskResponse<void> {
|
|
26
|
-
const probeId = yield* askNewGuid();
|
|
27
|
-
const scopeA = `smoke-a-${probeId}`;
|
|
28
|
-
const scopeB = `smoke-b-${probeId}`;
|
|
29
|
-
const category = `scoped-kvs-${probeId}`;
|
|
30
|
-
|
|
31
|
-
const record: SmokeProbeRecord = { probeId, category, value: 1 };
|
|
32
|
-
yield* askKeyValueStoreUpsert<SmokeProbeRecord>(
|
|
33
|
-
SMOKE_SCOPED_PROBE_STORE,
|
|
34
|
-
record,
|
|
35
|
-
{ scope: scopeA }
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const written = yield* askKeyValueStoreGet<SmokeProbeRecord>(
|
|
39
|
-
SMOKE_SCOPED_PROBE_STORE,
|
|
40
|
-
probeId,
|
|
41
|
-
{ scope: scopeA }
|
|
42
|
-
);
|
|
43
|
-
yield* askSmokeAssert(
|
|
44
|
-
written?.probeId === probeId && written.value === 1,
|
|
45
|
-
'scoped get did not return the record with its raw key'
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
// A scoped query must constrain the partition key (the scope is composed
|
|
49
|
-
// into it on dynamo), so the query is on probeId, not the category index.
|
|
50
|
-
const byKey = yield* askKeyValueStoreQuery<SmokeProbeRecord>(
|
|
51
|
-
SMOKE_SCOPED_PROBE_STORE,
|
|
52
|
-
kvsEqual('probeId', probeId),
|
|
53
|
-
{ scope: scopeA }
|
|
54
|
-
);
|
|
55
|
-
yield* askSmokeAssert(
|
|
56
|
-
byKey.items.some((item) => item.category === category),
|
|
57
|
-
'scoped query by partition key did not return the record'
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
const fromB = yield* askKeyValueStoreGet<SmokeProbeRecord>(
|
|
61
|
-
SMOKE_SCOPED_PROBE_STORE,
|
|
62
|
-
probeId,
|
|
63
|
-
{ scope: scopeB }
|
|
64
|
-
);
|
|
65
|
-
yield* askSmokeAssert(
|
|
66
|
-
!fromB,
|
|
67
|
-
'record written under scope A is visible from scope B'
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
const unscopedGet = yield* askCatch(
|
|
71
|
-
askKeyValueStoreGet<SmokeProbeRecord>(SMOKE_SCOPED_PROBE_STORE, probeId)
|
|
72
|
-
);
|
|
73
|
-
yield* askSmokeAssert(
|
|
74
|
-
!unscopedGet.success &&
|
|
75
|
-
unscopedGet.error.errorType ===
|
|
76
|
-
askKeyValueStoreGetBase.errorType.InvalidScope,
|
|
77
|
-
'unscoped get on the scoped store was not refused with InvalidScope'
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
const scopedUpsertOnUnscopedStore = yield* askCatch(
|
|
81
|
-
askKeyValueStoreUpsert<SmokeProbeRecord>(SMOKE_PROBE_STORE, record, {
|
|
82
|
-
scope: scopeA,
|
|
83
|
-
})
|
|
84
|
-
);
|
|
85
|
-
yield* askSmokeAssert(
|
|
86
|
-
!scopedUpsertOnUnscopedStore.success &&
|
|
87
|
-
scopedUpsertOnUnscopedStore.error.errorType ===
|
|
88
|
-
askKeyValueStoreUpsertBase.errorType.InvalidScope,
|
|
89
|
-
'scoped upsert on the unscoped store was not refused with InvalidScope'
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
yield* askKeyValueStoreDelete(SMOKE_SCOPED_PROBE_STORE, probeId, undefined, {
|
|
93
|
-
scope: scopeA,
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const deleted = yield* askKeyValueStoreGet<SmokeProbeRecord>(
|
|
97
|
-
SMOKE_SCOPED_PROBE_STORE,
|
|
98
|
-
probeId,
|
|
99
|
-
{ scope: scopeA }
|
|
100
|
-
);
|
|
101
|
-
yield* askSmokeAssert(!deleted, 'scoped record still present after delete');
|
|
102
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './askRunSigningKeyTest';
|