create-qpq-app 0.1.26 → 0.1.27
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/package.json +2 -2
- package/template/apps/qpqjs/services/test/models/src/SmokeProbeRecord.ts +3 -0
- package/template/apps/qpqjs/services/test/service/src/infrastructure.ts +0 -6
- 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 +2 -2
- 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/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/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/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
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SmokeSuite } from '../../harness/types/SmokeSuite';
|
|
2
|
+
import { defineSigningKeySmoke } from './config/defineSigningKeySmoke';
|
|
3
|
+
import { askRunCrossServiceSigningKeyTest } from './logic/askRunCrossServiceSigningKeyTest';
|
|
4
|
+
import { askRunSigningKeyTest } from './logic/askRunSigningKeyTest';
|
|
5
|
+
|
|
6
|
+
/** An owned signing key, and testa verifying (but never signing) with it. */
|
|
7
|
+
export const signingKeySmokeSuite: SmokeSuite = {
|
|
8
|
+
defineConfig: defineSigningKeySmoke,
|
|
9
|
+
tests: [
|
|
10
|
+
{ name: 'signingKey', askRun: askRunSigningKeyTest },
|
|
11
|
+
{
|
|
12
|
+
name: 'crossServiceSigningKey',
|
|
13
|
+
askRun: askRunCrossServiceSigningKeyTest,
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { SmokeSuite } from '../harness/types/SmokeSuite';
|
|
2
|
+
import { emailReceiveSmokeSuite } from './emailReceive/emailReceiveSmokeSuite';
|
|
3
|
+
import { encryptedResourcesSmokeSuite } from './encryptedResources/encryptedResourcesSmokeSuite';
|
|
4
|
+
import { eventBusSmokeSuite } from './eventBus/eventBusSmokeSuite';
|
|
5
|
+
import { eventDocSmokeSuite } from './eventDoc/eventDocSmokeSuite';
|
|
6
|
+
import { keyValueStoreSmokeSuite } from './keyValueStore/keyValueStoreSmokeSuite';
|
|
7
|
+
import { keyValueStoreStreamSmokeSuite } from './keyValueStoreStream/keyValueStoreStreamSmokeSuite';
|
|
8
|
+
import { noopSmokeSuite } from './noop/noopSmokeSuite';
|
|
9
|
+
import { openApiSmokeSuite } from './openApi/openApiSmokeSuite';
|
|
10
|
+
import { parameterSmokeSuite } from './parameter/parameterSmokeSuite';
|
|
11
|
+
import { scheduleSmokeSuite } from './schedule/scheduleSmokeSuite';
|
|
12
|
+
import { scopedKeyValueStoreSmokeSuite } from './scopedKeyValueStore/scopedKeyValueStoreSmokeSuite';
|
|
13
|
+
import { scopedStorageDriveSmokeSuite } from './scopedStorageDrive/scopedStorageDriveSmokeSuite';
|
|
14
|
+
import { secretSmokeSuite } from './secret/secretSmokeSuite';
|
|
15
|
+
import { signingKeySmokeSuite } from './signingKey/signingKeySmokeSuite';
|
|
16
|
+
import { storageDriveSmokeSuite } from './storageDrive/storageDriveSmokeSuite';
|
|
17
|
+
import { storageDriveEventSmokeSuite } from './storageDriveEvent/storageDriveEventSmokeSuite';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Every suite a smoke run executes. Adding one: a folder under suites/
|
|
21
|
+
* exporting a SmokeSuite, and a line here. A suite with a cross-service half
|
|
22
|
+
* also has a folder of the same name under testa's smoke/suites.
|
|
23
|
+
*
|
|
24
|
+
* Every test runs in parallel on its own queue message, so none may depend on
|
|
25
|
+
* another having finished. A test's name is the key its queue message carries
|
|
26
|
+
* and must be unique across suites; its id in the run record is its position
|
|
27
|
+
* across this list, so append rather than reorder where possible.
|
|
28
|
+
*/
|
|
29
|
+
export const smokeSuites: SmokeSuite[] = [
|
|
30
|
+
noopSmokeSuite,
|
|
31
|
+
keyValueStoreSmokeSuite,
|
|
32
|
+
parameterSmokeSuite,
|
|
33
|
+
secretSmokeSuite,
|
|
34
|
+
storageDriveSmokeSuite,
|
|
35
|
+
eventBusSmokeSuite,
|
|
36
|
+
scheduleSmokeSuite,
|
|
37
|
+
openApiSmokeSuite,
|
|
38
|
+
eventDocSmokeSuite,
|
|
39
|
+
signingKeySmokeSuite,
|
|
40
|
+
scopedStorageDriveSmokeSuite,
|
|
41
|
+
storageDriveEventSmokeSuite,
|
|
42
|
+
scopedKeyValueStoreSmokeSuite,
|
|
43
|
+
keyValueStoreStreamSmokeSuite,
|
|
44
|
+
encryptedResourcesSmokeSuite,
|
|
45
|
+
emailReceiveSmokeSuite,
|
|
46
|
+
];
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
CrossServiceStorageDriveProbeResult,
|
|
17
17
|
} from '@qpqjs/testa-models';
|
|
18
18
|
|
|
19
|
-
import { askSmokeAssert } from '
|
|
19
|
+
import { askSmokeAssert } from '../../../harness/assert/askSmokeAssert';
|
|
20
20
|
|
|
21
21
|
// testa writes a file into the drive THIS service owns, through its foreign
|
|
22
22
|
// (exact-ARN) S3 grant. An error from inside testa is that grant; the
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
|
|
11
11
|
import { SMOKE_PROBE_DRIVE } from '@qpqjs/constants';
|
|
12
12
|
|
|
13
|
-
import { askSmokeAssert } from '
|
|
13
|
+
import { askSmokeAssert } from '../../../harness/assert/askSmokeAssert';
|
|
14
14
|
|
|
15
15
|
// Every S3 action the owned-drive grant covers (PutObject, GetObject,
|
|
16
16
|
// ListBucket, DeleteObject). Unlike the other kinds this grant is a bucket
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SmokeSuite } from '../../harness/types/SmokeSuite';
|
|
2
|
+
import { askRunCrossServiceStorageDriveTest } from './logic/askRunCrossServiceStorageDriveTest';
|
|
3
|
+
import { askRunStorageDriveTest } from './logic/askRunStorageDriveTest';
|
|
4
|
+
|
|
5
|
+
/** Every S3 action on the probe drive, from this service and from testa. No config: the drive belongs to the harness. */
|
|
6
|
+
export const storageDriveSmokeSuite: SmokeSuite = {
|
|
7
|
+
tests: [
|
|
8
|
+
{ name: 'storageDrive', askRun: askRunStorageDriveTest },
|
|
9
|
+
{
|
|
10
|
+
name: 'crossServiceStorageDrive',
|
|
11
|
+
askRun: askRunCrossServiceStorageDriveTest,
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defineStorageDrive, QPQConfig, QpqFunctionRuntime } from 'quidproquo';
|
|
2
|
+
|
|
3
|
+
import { SMOKE_FILE_EVENT_DRIVE } from '../constants/SMOKE_FILE_EVENT_DRIVE';
|
|
4
|
+
import { SMOKE_SCOPED_FILE_EVENT_DRIVE } from '../constants/SMOKE_SCOPED_FILE_EVENT_DRIVE';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A write or delete on either drive fires the handler, which writes a marker
|
|
8
|
+
* into the probe store for the test to poll. The scoped drive's events must
|
|
9
|
+
* arrive with the scope split off.
|
|
10
|
+
*/
|
|
11
|
+
export const defineStorageDriveEventSmoke = (): QPQConfig => {
|
|
12
|
+
const onSmokeFileEvent: QpqFunctionRuntime = {
|
|
13
|
+
basePath: __dirname,
|
|
14
|
+
relativePath: '../entry/storageDrive/onSmokeFileEvent',
|
|
15
|
+
functionName: 'onSmokeFileEvent',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
return [
|
|
19
|
+
defineStorageDrive(SMOKE_FILE_EVENT_DRIVE, {
|
|
20
|
+
onEvent: { create: onSmokeFileEvent, delete: onSmokeFileEvent },
|
|
21
|
+
}),
|
|
22
|
+
defineStorageDrive(SMOKE_SCOPED_FILE_EVENT_DRIVE, {
|
|
23
|
+
scoped: true,
|
|
24
|
+
onEvent: { create: onSmokeFileEvent, delete: onSmokeFileEvent },
|
|
25
|
+
}),
|
|
26
|
+
];
|
|
27
|
+
};
|
package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/config/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './defineStorageDriveEventSmoke';
|
package/template/apps/qpqjs/services/test/service/src/smoke/suites/storageDriveEvent/entry/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './storageDrive';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './onSmokeFileEvent';
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { SMOKE_PROBE_STORE } from '@qpqjs/constants';
|
|
10
10
|
import { SmokeProbeRecord } from '@qpqjs/test-models';
|
|
11
11
|
|
|
12
|
-
import { smokeFileEventMarkerId } from '
|
|
12
|
+
import { smokeFileEventMarkerId } from '../../logic/smokeFileEventMarkerId';
|
|
13
13
|
|
|
14
14
|
// Fan-in for the file event test: both the scoped and the unscoped event
|
|
15
15
|
// drive point create and delete here. The marker records what the event
|
|
@@ -6,13 +6,11 @@ import {
|
|
|
6
6
|
StorageDriveEventType,
|
|
7
7
|
} from 'quidproquo';
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from '
|
|
13
|
-
import { smokeFileEventMarkerId } from '
|
|
14
|
-
import { askSmokeAssert } from '../askSmokeAssert';
|
|
15
|
-
import { askSmokePollForMarker } from '../askSmokePollForMarker';
|
|
9
|
+
import { askSmokeAssert } from '../../../harness/assert/askSmokeAssert';
|
|
10
|
+
import { askSmokePollForMarker } from '../../../harness/assert/askSmokePollForMarker';
|
|
11
|
+
import { SMOKE_FILE_EVENT_DRIVE } from '../constants/SMOKE_FILE_EVENT_DRIVE';
|
|
12
|
+
import { SMOKE_SCOPED_FILE_EVENT_DRIVE } from '../constants/SMOKE_SCOPED_FILE_EVENT_DRIVE';
|
|
13
|
+
import { smokeFileEventMarkerId } from './smokeFileEventMarkerId';
|
|
16
14
|
|
|
17
15
|
// The storage drive event path end to end: a write fires the create handler
|
|
18
16
|
// and a delete fires the delete handler, locally through the file watcher and
|
|
@@ -43,7 +41,7 @@ export function* askRunStorageDriveEventTest(): AskResponse<void> {
|
|
|
43
41
|
);
|
|
44
42
|
|
|
45
43
|
yield* askFileWriteTextContents(
|
|
46
|
-
|
|
44
|
+
SMOKE_SCOPED_FILE_EVENT_DRIVE,
|
|
47
45
|
filepath,
|
|
48
46
|
fileId,
|
|
49
47
|
undefined,
|
|
@@ -67,7 +65,7 @@ export function* askRunStorageDriveEventTest(): AskResponse<void> {
|
|
|
67
65
|
'scoped create handler did not run under the event scope'
|
|
68
66
|
);
|
|
69
67
|
|
|
70
|
-
yield* askFileDelete(
|
|
68
|
+
yield* askFileDelete(SMOKE_SCOPED_FILE_EVENT_DRIVE, [filepath], scope);
|
|
71
69
|
|
|
72
70
|
const scopedDeleted = yield* askSmokePollForMarker(
|
|
73
71
|
smokeFileEventMarkerId(filepath, StorageDriveEventType.Delete),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SmokeSuite } from '../../harness/types/SmokeSuite';
|
|
2
|
+
import { defineStorageDriveEventSmoke } from './config/defineStorageDriveEventSmoke';
|
|
3
|
+
import { askRunStorageDriveEventTest } from './logic/askRunStorageDriveEventTest';
|
|
4
|
+
|
|
5
|
+
/** File create and delete events off an unscoped and a scoped drive. */
|
|
6
|
+
export const storageDriveEventSmokeSuite: SmokeSuite = {
|
|
7
|
+
defineConfig: defineStorageDriveEventSmoke,
|
|
8
|
+
tests: [{ name: 'storageDriveEvent', askRun: askRunStorageDriveEventTest }],
|
|
9
|
+
};
|
|
@@ -3,7 +3,7 @@ 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 {
|
|
6
|
+
import { defineSmokeProbes } from './smoke/config/defineSmokeProbes';
|
|
7
7
|
|
|
8
8
|
// testa exists to be "the other service" in the smoke suite: it owns nothing
|
|
9
9
|
// of its own and exercises the cross-service (foreign ARN) IAM grants against
|
|
@@ -18,5 +18,5 @@ export default [
|
|
|
18
18
|
'../../../../../../dist/apps/qpqjs/services/testa/service'
|
|
19
19
|
),
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
defineSmokeProbes(),
|
|
22
22
|
];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QPQConfig } from 'quidproquo';
|
|
2
|
+
|
|
3
|
+
import { defineKeyValueStoreSmokeProbe } from '../suites/keyValueStore/config/defineKeyValueStoreSmokeProbe';
|
|
4
|
+
import { defineSigningKeySmokeProbe } from '../suites/signingKey/config/defineSigningKeySmokeProbe';
|
|
5
|
+
import { defineStorageDriveSmokeProbe } from '../suites/storageDrive/config/defineStorageDriveSmokeProbe';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The cross-service half of the test service's smoke suites. Each folder under
|
|
9
|
+
* suites/ mirrors the test service suite of the same name and exercises that
|
|
10
|
+
* suite's foreign grant against a resource the test service owns.
|
|
11
|
+
*/
|
|
12
|
+
export const defineSmokeProbes = (): QPQConfig => [
|
|
13
|
+
defineKeyValueStoreSmokeProbe(),
|
|
14
|
+
defineStorageDriveSmokeProbe(),
|
|
15
|
+
defineSigningKeySmokeProbe(),
|
|
16
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './defineSmokeProbes';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineKeyValueStore,
|
|
3
|
+
defineServiceFunction,
|
|
4
|
+
QPQConfig,
|
|
5
|
+
} from 'quidproquo';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
QpqjsServiceEnum,
|
|
9
|
+
SMOKE_CROSS_SERVICE_KEY_VALUE_STORE_PROBE_FUNCTION_NAME,
|
|
10
|
+
SMOKE_PROBE_STORE,
|
|
11
|
+
} from '@qpqjs/constants';
|
|
12
|
+
import { SmokeProbeRecord } from '@qpqjs/test-models';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The test service's probe store declared FOREIGN (owned by test), which is
|
|
16
|
+
* what grants this service's role exact-ARN access to it, plus the service
|
|
17
|
+
* function the test service's crossServiceKeyValueStore test invokes.
|
|
18
|
+
*/
|
|
19
|
+
export const defineKeyValueStoreSmokeProbe = (): QPQConfig => [
|
|
20
|
+
defineKeyValueStore<SmokeProbeRecord>(SMOKE_PROBE_STORE, 'probeId', [], {
|
|
21
|
+
indexes: ['category'],
|
|
22
|
+
owner: { module: QpqjsServiceEnum.Test },
|
|
23
|
+
}),
|
|
24
|
+
defineServiceFunction(
|
|
25
|
+
{
|
|
26
|
+
basePath: __dirname,
|
|
27
|
+
relativePath:
|
|
28
|
+
'../entry/serviceFunction/smokeCrossServiceKeyValueStoreProbe',
|
|
29
|
+
functionName: 'smokeCrossServiceKeyValueStoreProbe',
|
|
30
|
+
},
|
|
31
|
+
{ functionName: SMOKE_CROSS_SERVICE_KEY_VALUE_STORE_PROBE_FUNCTION_NAME }
|
|
32
|
+
),
|
|
33
|
+
];
|
package/template/apps/qpqjs/services/testa/service/src/smoke/suites/keyValueStore/config/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './defineKeyValueStoreSmokeProbe';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './smokeCrossServiceKeyValueStoreProbe';
|
package/template/apps/qpqjs/services/testa/service/src/smoke/suites/keyValueStore/logic/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './askProbeForeignKeyValueStore';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { defineServiceFunction, defineSigningKey, QPQConfig } from 'quidproquo';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
QpqjsServiceEnum,
|
|
5
|
+
SMOKE_CROSS_SERVICE_SIGNING_KEY_PROBE_FUNCTION_NAME,
|
|
6
|
+
SMOKE_PROBE_SIGNING_KEY,
|
|
7
|
+
} from '@qpqjs/constants';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The test service's signing key declared FOREIGN (owned by test), plus the
|
|
11
|
+
* service function the test service's crossServiceSigningKey test invokes.
|
|
12
|
+
* The one foreign grant that is alias-conditioned rather than exact-ARN: the
|
|
13
|
+
* owner's alias name is what this declaration must resolve to, or
|
|
14
|
+
* GetPublicKey is denied.
|
|
15
|
+
*/
|
|
16
|
+
export const defineSigningKeySmokeProbe = (): QPQConfig => [
|
|
17
|
+
defineSigningKey(SMOKE_PROBE_SIGNING_KEY, {
|
|
18
|
+
owner: { module: QpqjsServiceEnum.Test },
|
|
19
|
+
}),
|
|
20
|
+
defineServiceFunction(
|
|
21
|
+
{
|
|
22
|
+
basePath: __dirname,
|
|
23
|
+
relativePath: '../entry/serviceFunction/smokeCrossServiceSigningKeyProbe',
|
|
24
|
+
functionName: 'smokeCrossServiceSigningKeyProbe',
|
|
25
|
+
},
|
|
26
|
+
{ functionName: SMOKE_CROSS_SERVICE_SIGNING_KEY_PROBE_FUNCTION_NAME }
|
|
27
|
+
),
|
|
28
|
+
];
|
package/template/apps/qpqjs/services/testa/service/src/smoke/suites/signingKey/config/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './defineSigningKeySmokeProbe';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './serviceFunction';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './smokeCrossServiceSigningKeyProbe';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './askProbeForeignSigningKey';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineServiceFunction,
|
|
3
|
+
defineStorageDrive,
|
|
4
|
+
QPQConfig,
|
|
5
|
+
} from 'quidproquo';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
QpqjsServiceEnum,
|
|
9
|
+
SMOKE_CROSS_SERVICE_STORAGE_DRIVE_PROBE_FUNCTION_NAME,
|
|
10
|
+
SMOKE_PROBE_DRIVE,
|
|
11
|
+
} from '@qpqjs/constants';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The test service's probe drive declared FOREIGN (owned by test), which is
|
|
15
|
+
* what grants this service's role exact-ARN access to it, plus the service
|
|
16
|
+
* function the test service's crossServiceStorageDrive test invokes.
|
|
17
|
+
*/
|
|
18
|
+
export const defineStorageDriveSmokeProbe = (): QPQConfig => [
|
|
19
|
+
defineStorageDrive(SMOKE_PROBE_DRIVE, {
|
|
20
|
+
owner: { module: QpqjsServiceEnum.Test },
|
|
21
|
+
}),
|
|
22
|
+
defineServiceFunction(
|
|
23
|
+
{
|
|
24
|
+
basePath: __dirname,
|
|
25
|
+
relativePath:
|
|
26
|
+
'../entry/serviceFunction/smokeCrossServiceStorageDriveProbe',
|
|
27
|
+
functionName: 'smokeCrossServiceStorageDriveProbe',
|
|
28
|
+
},
|
|
29
|
+
{ functionName: SMOKE_CROSS_SERVICE_STORAGE_DRIVE_PROBE_FUNCTION_NAME }
|
|
30
|
+
),
|
|
31
|
+
];
|
package/template/apps/qpqjs/services/testa/service/src/smoke/suites/storageDrive/config/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './defineStorageDriveSmokeProbe';
|
package/template/apps/qpqjs/services/testa/service/src/smoke/suites/storageDrive/entry/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './serviceFunction';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './smokeCrossServiceStorageDriveProbe';
|
package/template/apps/qpqjs/services/testa/service/src/smoke/suites/storageDrive/logic/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './askProbeForeignStorageDrive';
|
|
@@ -53,7 +53,7 @@ function* askKeyValueStoreDelete(
|
|
|
53
53
|
| --- | --- |
|
|
54
54
|
| `KeyValueStoreDeleteErrorTypeEnum.ServiceUnavailable` | DynamoDB internal error or throttling. |
|
|
55
55
|
| `KeyValueStoreDeleteErrorTypeEnum.ResourceNotFound` | The underlying table does not exist. |
|
|
56
|
-
| `KeyValueStoreDeleteErrorTypeEnum.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, or the partition-key value contains the reserved `@@
|
|
56
|
+
| `KeyValueStoreDeleteErrorTypeEnum.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, or the partition-key value contains the reserved `@@QPQ` marker (reserved on string-pk stores, so unscoped calls reject it too). |
|
|
57
57
|
| `KeyValueStoreDeleteErrorTypeEnum.StoreNotFound` | The key value store is not declared in the qpq config (misconfiguration, e.g. a wrong name or a missing `defineKeyValueStore`). |
|
|
58
58
|
|
|
59
59
|
Catch errors with `askCatch` — it returns `{ success: true, result }` or `{ success: false, error }`.
|
package/template/docusaurus/docs/actions/core/key-value-store/ask-key-value-store-get-all.md
CHANGED
|
@@ -55,7 +55,7 @@ function* askKeyValueStoreGetAll<Value>(
|
|
|
55
55
|
| --- | --- |
|
|
56
56
|
| `KeyValueStoreGetAllErrorTypeEnum.ServiceUnavailable` | DynamoDB internal error or throttling. |
|
|
57
57
|
| `KeyValueStoreGetAllErrorTypeEnum.ResourceNotFound` | The underlying table does not exist. |
|
|
58
|
-
| `KeyValueStoreGetAllErrorTypeEnum.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, or a scoped call's partition-key value contains the reserved `@@
|
|
58
|
+
| `KeyValueStoreGetAllErrorTypeEnum.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, or a scoped call's partition-key value contains the reserved `@@QPQ` marker. |
|
|
59
59
|
| `KeyValueStoreGetAllErrorTypeEnum.StoreNotFound` | The key value store is not declared in the qpq config (misconfiguration, e.g. a wrong name or a missing `defineKeyValueStore`). |
|
|
60
60
|
|
|
61
61
|
Catch errors with `askCatch` — it returns `{ success: true, result }` or `{ success: false, error }`.
|
|
@@ -57,7 +57,7 @@ function* askKeyValueStoreGet<Value>(
|
|
|
57
57
|
| --- | --- |
|
|
58
58
|
| `KeyValueStoreGetErrorTypeEnum.ServiceUnavailable` | DynamoDB internal error or throttling. |
|
|
59
59
|
| `KeyValueStoreGetErrorTypeEnum.ResourceNotFound` | The underlying table does not exist. |
|
|
60
|
-
| `KeyValueStoreGetErrorTypeEnum.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, or the partition-key value contains the reserved `@@
|
|
60
|
+
| `KeyValueStoreGetErrorTypeEnum.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, or the partition-key value contains the reserved `@@QPQ` marker (reserved on string-pk stores, so unscoped calls reject it too). |
|
|
61
61
|
| `KeyValueStoreGetErrorTypeEnum.StoreNotFound` | The key value store is not declared in the qpq config (misconfiguration, e.g. a wrong name or a missing `defineKeyValueStore`). |
|
|
62
62
|
|
|
63
63
|
Errors thrown by actions can be caught with `askCatch` from quidproquo-core. It returns an object — `{ success: true, result }` on success, or `{ success: false, error }` on failure:
|
|
@@ -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`.
|