@geekmidas/cli 10.0.0-alpha.5 → 10.0.0-alpha.50
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 +196 -257
- package/bin/adjacent-tsconfig.mjs +97 -0
- package/bin/gkm.mjs +16 -2
- package/bin/owning-tsconfig-jsx-register.mjs +18 -0
- package/bin/owning-tsconfig-jsx.mjs +108 -0
- package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-BZFGYYVA.cjs} +21 -22
- package/dist/HostingerProvider-BZFGYYVA.cjs.map +1 -0
- package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-GF6NAZAK.mjs} +20 -21
- package/dist/HostingerProvider-GF6NAZAK.mjs.map +1 -0
- package/dist/{LocalStateProvider-Db9SEjyH.cjs → LocalStateProvider-7HR6SS2t.cjs} +11 -6
- package/dist/LocalStateProvider-7HR6SS2t.cjs.map +1 -0
- package/dist/{LocalStateProvider-Bn6tS-oL.mjs → LocalStateProvider-D7QyJoLM.mjs} +10 -4
- package/dist/LocalStateProvider-D7QyJoLM.mjs.map +1 -0
- package/dist/{openapi-CA0yJUTN.cjs → OpenApiTsGenerator-BN0PIZxd.cjs} +157 -372
- package/dist/OpenApiTsGenerator-BN0PIZxd.cjs.map +1 -0
- package/dist/{openapi-kkQbsRVj.mjs → OpenApiTsGenerator-BzIGy8KE.mjs} +128 -324
- package/dist/OpenApiTsGenerator-BzIGy8KE.mjs.map +1 -0
- package/dist/{Route53Provider-RdpUDJQk.mjs → Route53Provider-Cvj40A8I.mjs} +12 -12
- package/dist/Route53Provider-Cvj40A8I.mjs.map +1 -0
- package/dist/{Route53Provider-di2fMM5N.cjs → Route53Provider-DVILBsvV.cjs} +20 -21
- package/dist/Route53Provider-DVILBsvV.cjs.map +1 -0
- package/dist/{SSMStateProvider-BRt2py-A.mjs → SSMStateProvider-B0Hu1MKZ.mjs} +13 -4
- package/dist/SSMStateProvider-B0Hu1MKZ.mjs.map +1 -0
- package/dist/{SSMStateProvider-DyX8s9HI.cjs → SSMStateProvider-VrQ-yeqd.cjs} +17 -9
- package/dist/SSMStateProvider-VrQ-yeqd.cjs.map +1 -0
- package/dist/aws-DkHdTV-p.cjs +61 -0
- package/dist/aws-DkHdTV-p.cjs.map +1 -0
- package/dist/aws-DojzQnLd.mjs +61 -0
- package/dist/aws-DojzQnLd.mjs.map +1 -0
- package/dist/backends-B9V2XD2M.cjs +82 -0
- package/dist/backends-B9V2XD2M.cjs.map +1 -0
- package/dist/backends-CSuLl0YP.mjs +59 -0
- package/dist/backends-CSuLl0YP.mjs.map +1 -0
- package/dist/{backup-provisioner-BrsHwYG0.cjs → backup-provisioner-BmhIO_Yr.cjs} +21 -19
- package/dist/backup-provisioner-BmhIO_Yr.cjs.map +1 -0
- package/dist/{backup-provisioner-Bgj5Vi_L.mjs → backup-provisioner-DIVCbfee.mjs} +10 -7
- package/dist/backup-provisioner-DIVCbfee.mjs.map +1 -0
- package/dist/{bundler-Be8Zg4Wd.mjs → bundler--fyybf1N.mjs} +19 -30
- package/dist/bundler--fyybf1N.mjs.map +1 -0
- package/dist/{bundler-BY1OmV1e.cjs → bundler-By6_sXiL.cjs} +20 -32
- package/dist/bundler-By6_sXiL.cjs.map +1 -0
- package/dist/{config-C21ocYNd.cjs → config-CsYSyUya.cjs} +209 -210
- package/dist/config-CsYSyUya.cjs.map +1 -0
- package/dist/{config-WRdsQYZK.mjs → config-D8J5rrTb.mjs} +142 -154
- package/dist/config-D8J5rrTb.mjs.map +1 -0
- package/dist/config.cjs +9 -6
- package/dist/config.d.cts +62 -33
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +62 -33
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -5
- package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
- package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
- package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
- package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
- package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
- package/dist/deploy/sniffer-hooks.cjs +13 -7
- package/dist/deploy/sniffer-hooks.cjs.map +1 -1
- package/dist/deploy/sniffer-hooks.d.cts +1 -2
- package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
- package/dist/deploy/sniffer-hooks.d.mts +1 -2
- package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
- package/dist/deploy/sniffer-hooks.mjs +9 -2
- package/dist/deploy/sniffer-hooks.mjs.map +1 -1
- package/dist/deploy/sniffer-loader.cjs +16 -7
- package/dist/deploy/sniffer-loader.cjs.map +1 -1
- package/dist/deploy/sniffer-loader.d.cts +1 -1
- package/dist/deploy/sniffer-loader.d.mts +1 -1
- package/dist/deploy/sniffer-loader.mjs +13 -2
- package/dist/deploy/sniffer-loader.mjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.cjs +11 -11
- package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
- package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
- package/dist/deploy/sniffer-routes-worker.mjs +3 -3
- package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
- package/dist/deploy/sniffer-worker.cjs +15 -6
- package/dist/deploy/sniffer-worker.cjs.map +1 -1
- package/dist/deploy/sniffer-worker.d.cts +1 -3
- package/dist/deploy/sniffer-worker.d.cts.map +1 -1
- package/dist/deploy/sniffer-worker.d.mts +1 -3
- package/dist/deploy/sniffer-worker.d.mts.map +1 -1
- package/dist/deploy/sniffer-worker.mjs +15 -4
- package/dist/deploy/sniffer-worker.mjs.map +1 -1
- package/dist/{discover-CAlFgYec.mjs → discover-Cf2jAcgF.mjs} +56 -63
- package/dist/discover-Cf2jAcgF.mjs.map +1 -0
- package/dist/{discover-DTmFeloL.cjs → discover-DXNviAh-.cjs} +86 -110
- package/dist/discover-DXNviAh-.cjs.map +1 -0
- package/dist/{emit-CiZS_5Ub.mjs → emit-C1e8qD08.mjs} +13 -26
- package/dist/emit-C1e8qD08.mjs.map +1 -0
- package/dist/{emit-CbcRolsa.cjs → emit-Dmc1nvdS.cjs} +31 -57
- package/dist/emit-Dmc1nvdS.cjs.map +1 -0
- package/dist/encryption-C7OGMve_.cjs +91 -0
- package/dist/encryption-C7OGMve_.cjs.map +1 -0
- package/dist/encryption-DyQnPsZN.mjs +90 -0
- package/dist/encryption-DyQnPsZN.mjs.map +1 -0
- package/dist/github-BfpadQWQ.mjs +213 -0
- package/dist/github-BfpadQWQ.mjs.map +1 -0
- package/dist/github-BrI1tv6u.cjs +213 -0
- package/dist/github-BrI1tv6u.cjs.map +1 -0
- package/dist/{index-CHB4tSzX.d.cts → index-BQhJXpaQ.d.mts} +4 -23
- package/dist/index-BQhJXpaQ.d.mts.map +1 -0
- package/dist/{index-BThUzEIp.d.mts → index-DHJePE0y.d.cts} +4 -23
- package/dist/index-DHJePE0y.d.cts.map +1 -0
- package/dist/index.cjs +9531 -7200
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +9412 -7108
- package/dist/index.mjs.map +1 -1
- package/dist/migrate-B00XpVaO.mjs +736 -0
- package/dist/migrate-B00XpVaO.mjs.map +1 -0
- package/dist/migrate-CNlew9Ek.cjs +743 -0
- package/dist/migrate-CNlew9Ek.cjs.map +1 -0
- package/dist/openapi.cjs +198 -8
- package/dist/openapi.cjs.map +1 -0
- package/dist/openapi.d.cts +53 -15
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.mts +53 -15
- package/dist/openapi.d.mts.map +1 -1
- package/dist/openapi.mjs +193 -5
- package/dist/openapi.mjs.map +1 -0
- package/dist/ready-WfT-eWlm.mjs +861 -0
- package/dist/ready-WfT-eWlm.mjs.map +1 -0
- package/dist/ready-lr2Fm-ep.cjs +932 -0
- package/dist/ready-lr2Fm-ep.cjs.map +1 -0
- package/dist/reconcile/public.cjs +3 -5
- package/dist/reconcile/public.d.cts +30 -33
- package/dist/reconcile/public.d.cts.map +1 -1
- package/dist/reconcile/public.d.mts +30 -33
- package/dist/reconcile/public.d.mts.map +1 -1
- package/dist/reconcile/public.mjs +3 -4
- package/dist/{reconcile-CFs8C_1a.mjs → reconcile--I7V4Klj.mjs} +4 -7
- package/dist/reconcile--I7V4Klj.mjs.map +1 -0
- package/dist/{reconcile-D0pimNiy.cjs → reconcile-CuCQBa5-.cjs} +5 -8
- package/dist/reconcile-CuCQBa5-.cjs.map +1 -0
- package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
- package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
- package/dist/storage-BzaUxmqe.mjs +124 -0
- package/dist/storage-BzaUxmqe.mjs.map +1 -0
- package/dist/storage-CSGoC3bK.cjs +152 -0
- package/dist/storage-CSGoC3bK.cjs.map +1 -0
- package/dist/store-DQgxT_WR.cjs +211 -0
- package/dist/store-DQgxT_WR.cjs.map +1 -0
- package/dist/store-DeGATCS-.mjs +182 -0
- package/dist/store-DeGATCS-.mjs.map +1 -0
- package/dist/types-BbrNu83u.d.mts +6229 -0
- package/dist/types-BbrNu83u.d.mts.map +1 -0
- package/dist/types-DNqEsctD.d.cts +6230 -0
- package/dist/types-DNqEsctD.d.cts.map +1 -0
- package/dist/vitest.cjs +65 -0
- package/dist/vitest.cjs.map +1 -0
- package/dist/vitest.d.cts +29 -0
- package/dist/vitest.d.cts.map +1 -0
- package/dist/vitest.d.mts +29 -0
- package/dist/vitest.d.mts.map +1 -0
- package/dist/vitest.mjs +65 -0
- package/dist/vitest.mjs.map +1 -0
- package/dist/workspace/index.cjs +3 -4
- package/dist/workspace/index.d.cts +3 -3
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +2 -3
- package/dist/{credentials-BBIRJVp4.mjs → workspace-BsbxbqV-.mjs} +2201 -1732
- package/dist/workspace-BsbxbqV-.mjs.map +1 -0
- package/dist/{workspace-BcucjwvA.cjs → workspace-DEibcoBe.cjs} +1038 -1118
- package/dist/workspace-DEibcoBe.cjs.map +1 -0
- package/dist/{workspace-BFMrAKqI.mjs → workspace-DNzWgM1J.mjs} +869 -972
- package/dist/workspace-DNzWgM1J.mjs.map +1 -0
- package/dist/{credentials-G1JwBoXH.cjs → workspace-j6ZxvJqq.cjs} +2337 -1849
- package/dist/workspace-j6ZxvJqq.cjs.map +1 -0
- package/package.json +29 -20
- package/dist/CachedStateProvider-BLo7zv7S.cjs +0 -3
- package/dist/CachedStateProvider-BxoAm-B2.mjs +0 -3
- package/dist/CachedStateProvider-CqPdW7CB.cjs +0 -60
- package/dist/CachedStateProvider-CqPdW7CB.cjs.map +0 -1
- package/dist/CachedStateProvider-DTniehMP.mjs +0 -54
- package/dist/CachedStateProvider-DTniehMP.mjs.map +0 -1
- package/dist/HostingerProvider-Cft7lEYr.mjs.map +0 -1
- package/dist/HostingerProvider-h3EbEp-Z.cjs.map +0 -1
- package/dist/LocalStateProvider-Bn6tS-oL.mjs.map +0 -1
- package/dist/LocalStateProvider-Db9SEjyH.cjs.map +0 -1
- package/dist/Route53Provider-RdpUDJQk.mjs.map +0 -1
- package/dist/Route53Provider-di2fMM5N.cjs.map +0 -1
- package/dist/SSMStateProvider-BRt2py-A.mjs.map +0 -1
- package/dist/SSMStateProvider-DyX8s9HI.cjs.map +0 -1
- package/dist/backup-provisioner-Bgj5Vi_L.mjs.map +0 -1
- package/dist/backup-provisioner-BrsHwYG0.cjs.map +0 -1
- package/dist/bundler-BY1OmV1e.cjs.map +0 -1
- package/dist/bundler-Be8Zg4Wd.mjs.map +0 -1
- package/dist/chunk-Duj1WY3L.mjs +0 -7
- package/dist/config-C21ocYNd.cjs.map +0 -1
- package/dist/config-WRdsQYZK.mjs.map +0 -1
- package/dist/credentials-B5zRHdAl.mjs +0 -141
- package/dist/credentials-B5zRHdAl.mjs.map +0 -1
- package/dist/credentials-BBIRJVp4.mjs.map +0 -1
- package/dist/credentials-BapzjyV5.cjs +0 -195
- package/dist/credentials-BapzjyV5.cjs.map +0 -1
- package/dist/credentials-G1JwBoXH.cjs.map +0 -1
- package/dist/discover-CAlFgYec.mjs.map +0 -1
- package/dist/discover-DTmFeloL.cjs.map +0 -1
- package/dist/dokploy-api-BS2xnJLZ.mjs +0 -3
- package/dist/dokploy-api-BsVH0y_s.cjs +0 -718
- package/dist/dokploy-api-BsVH0y_s.cjs.map +0 -1
- package/dist/dokploy-api-BuxDRo3l.cjs +0 -3
- package/dist/dokploy-api-aTFPz7_4.mjs +0 -706
- package/dist/dokploy-api-aTFPz7_4.mjs.map +0 -1
- package/dist/emit-CbcRolsa.cjs.map +0 -1
- package/dist/emit-CiZS_5Ub.mjs.map +0 -1
- package/dist/encryption-C6jaU0hE.cjs +0 -54
- package/dist/encryption-C6jaU0hE.cjs.map +0 -1
- package/dist/encryption-CHzzeR8a.cjs +0 -4
- package/dist/encryption-CQUncu7v.mjs +0 -3
- package/dist/encryption-D-abyhZx.mjs +0 -42
- package/dist/encryption-D-abyhZx.mjs.map +0 -1
- package/dist/fullstack-secrets-C-GGohke.cjs +0 -111
- package/dist/fullstack-secrets-C-GGohke.cjs.map +0 -1
- package/dist/fullstack-secrets-D1o9-G5l.mjs +0 -87
- package/dist/fullstack-secrets-D1o9-G5l.mjs.map +0 -1
- package/dist/generator-CNzBw7g5.cjs +0 -289
- package/dist/generator-CNzBw7g5.cjs.map +0 -1
- package/dist/generator-VE2JrFlY.mjs +0 -253
- package/dist/generator-VE2JrFlY.mjs.map +0 -1
- package/dist/index-BThUzEIp.d.mts.map +0 -1
- package/dist/index-CHB4tSzX.d.cts.map +0 -1
- package/dist/openapi-CA0yJUTN.cjs.map +0 -1
- package/dist/openapi-kkQbsRVj.mjs.map +0 -1
- package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
- package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
- package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
- package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
- package/dist/openapi-react-query.cjs +0 -4
- package/dist/openapi-react-query.d.cts +0 -11
- package/dist/openapi-react-query.d.cts.map +0 -1
- package/dist/openapi-react-query.d.mts +0 -11
- package/dist/openapi-react-query.d.mts.map +0 -1
- package/dist/openapi-react-query.mjs +0 -4
- package/dist/reconcile-CFs8C_1a.mjs.map +0 -1
- package/dist/reconcile-D0pimNiy.cjs.map +0 -1
- package/dist/setup-B5_oHHUj.cjs +0 -11
- package/dist/setup-Cm2UnAdh.cjs +0 -473
- package/dist/setup-Cm2UnAdh.cjs.map +0 -1
- package/dist/setup-DXvRLTZN.mjs +0 -443
- package/dist/setup-DXvRLTZN.mjs.map +0 -1
- package/dist/setup-ZijS4qeC.mjs +0 -11
- package/dist/storage-BJmzYxt8.cjs +0 -363
- package/dist/storage-BJmzYxt8.cjs.map +0 -1
- package/dist/storage-BM9hGpgv.cjs +0 -7
- package/dist/storage-Bi24WfoW.mjs +0 -297
- package/dist/storage-Bi24WfoW.mjs.map +0 -1
- package/dist/storage-CYlGwWTj.mjs +0 -3
- package/dist/sync-CmEuNZsB.mjs +0 -76
- package/dist/sync-CmEuNZsB.mjs.map +0 -1
- package/dist/sync-D306yOWu.cjs +0 -4
- package/dist/sync-SizaChmC.cjs +0 -93
- package/dist/sync-SizaChmC.cjs.map +0 -1
- package/dist/sync-hOqAWHR6.mjs +0 -3
- package/dist/types-C-arnQ1r.d.mts +0 -2184
- package/dist/types-C-arnQ1r.d.mts.map +0 -1
- package/dist/types-abJQuk7m.d.cts +0 -2184
- package/dist/types-abJQuk7m.d.cts.map +0 -1
- package/dist/workspace-BFMrAKqI.mjs.map +0 -1
- package/dist/workspace-BcucjwvA.cjs.map +0 -1
- package/dist/workspace-DdJss8I6.cjs +0 -9
- package/dist/workspace-k4l3rsFh.mjs +0 -8
package/README.md
CHANGED
|
@@ -54,6 +54,7 @@ Create a `gkm.config.ts` file in your project root:
|
|
|
54
54
|
import { defineConfig } from '@geekmidas/cli/config';
|
|
55
55
|
|
|
56
56
|
export default defineConfig({
|
|
57
|
+
stages: { local: 'dev', deployed: ['prod'] },
|
|
57
58
|
// Glob pattern to find endpoint files
|
|
58
59
|
routes: 'src/routes/**/*.ts',
|
|
59
60
|
|
|
@@ -142,36 +143,32 @@ export const createUser = api
|
|
|
142
143
|
|
|
143
144
|
### 5. Create Subscribers (Optional)
|
|
144
145
|
|
|
145
|
-
|
|
146
|
+
Declare the topic once, and a worker to run what has no port; a subscriber is
|
|
147
|
+
built from the worker and binds to the topic:
|
|
146
148
|
|
|
147
149
|
```typescript
|
|
150
|
+
// src/constructs/topics.ts
|
|
151
|
+
import { Topic } from '@geekmidas/constructs/topic';
|
|
152
|
+
import { z } from 'zod';
|
|
153
|
+
|
|
154
|
+
export const users = new Topic('Users', {
|
|
155
|
+
events: {
|
|
156
|
+
'user.created': z.object({ userId: z.string(), email: z.email() }),
|
|
157
|
+
'user.updated': z.object({ userId: z.string() }),
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// src/constructs/worker.ts
|
|
162
|
+
import { Worker } from '@geekmidas/constructs/worker';
|
|
163
|
+
|
|
164
|
+
export const worker = new Worker('Jobs', { logger });
|
|
165
|
+
|
|
148
166
|
// src/subscribers/userSubscriber.ts
|
|
149
|
-
import {
|
|
150
|
-
import
|
|
151
|
-
import type { EventPublisher, PublishableMessage } from '@geekmidas/events';
|
|
152
|
-
import type { EnvironmentParser } from '@geekmidas/envkit';
|
|
153
|
-
|
|
154
|
-
// Define event types
|
|
155
|
-
type UserEvents =
|
|
156
|
-
| PublishableMessage<'user.created', { userId: string; email: string }>
|
|
157
|
-
| PublishableMessage<'user.updated', { userId: string }>;
|
|
158
|
-
|
|
159
|
-
// Create event publisher service
|
|
160
|
-
const userEventPublisher = {
|
|
161
|
-
serviceName: 'userEventPublisher' as const,
|
|
162
|
-
async register(envParser: EnvironmentParser<{}>) {
|
|
163
|
-
const config = envParser.create((get) => ({
|
|
164
|
-
publisherUrl: get('EVENT_PUBLISHER_URL').string()
|
|
165
|
-
})).parse();
|
|
166
|
-
|
|
167
|
-
const { Publisher } = await import('@geekmidas/events');
|
|
168
|
-
return Publisher.fromConnectionString<UserEvents>(config.publisherUrl);
|
|
169
|
-
}
|
|
170
|
-
} satisfies Service<'userEventPublisher', EventPublisher<UserEvents>>;
|
|
167
|
+
import { users } from '../constructs/topics';
|
|
168
|
+
import { worker } from '../constructs/worker';
|
|
171
169
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
.publisher(userEventPublisher)
|
|
170
|
+
export const userCreatedSubscriber = worker
|
|
171
|
+
.topic(users)
|
|
175
172
|
.subscribe(['user.created'])
|
|
176
173
|
.handle(async ({ events, logger }) => {
|
|
177
174
|
for (const event of events) {
|
|
@@ -181,11 +178,16 @@ export const userCreatedSubscriber = new SubscriberBuilder()
|
|
|
181
178
|
});
|
|
182
179
|
```
|
|
183
180
|
|
|
181
|
+
An endpoint publishes to the topic with `.event(users, { type: 'user.created',
|
|
182
|
+
payload: (user) => ({ userId: user.id, email: user.email }) })`. Declaring the
|
|
183
|
+
topic is what puts a broker in the local plan and resolves
|
|
184
|
+
`USERS_PUBLISHER_CONNECTION_STRING` for whatever publishes to it.
|
|
185
|
+
|
|
184
186
|
### 6. Build Handlers
|
|
185
187
|
|
|
186
188
|
```bash
|
|
187
|
-
#
|
|
188
|
-
npx gkm build
|
|
189
|
+
# Build for where gkm.config.ts deploys (AWS for `deploy: { default: 'sst' }`)
|
|
190
|
+
npx gkm build
|
|
189
191
|
|
|
190
192
|
# Generate server application
|
|
191
193
|
npx gkm build --provider server
|
|
@@ -309,17 +311,20 @@ Generate handlers from your endpoints.
|
|
|
309
311
|
gkm build [options]
|
|
310
312
|
```
|
|
311
313
|
|
|
314
|
+
By default it builds for where the project deploys: `deploy: { default: 'sst' }`
|
|
315
|
+
builds for AWS, one Lambda per construct; `dokploy` (the default when nothing
|
|
316
|
+
is declared) builds a server.
|
|
317
|
+
|
|
312
318
|
**Options:**
|
|
313
|
-
- `--provider <provider>`:
|
|
314
|
-
- `aws
|
|
315
|
-
- `aws-apigatewayv2`: AWS API Gateway v2 Lambda handlers
|
|
319
|
+
- `--provider <provider>`: Override the deploy target
|
|
320
|
+
- `aws`: One Lambda handler per construct (API Gateway v2 for endpoints)
|
|
316
321
|
- `server`: Server application with Hono
|
|
317
322
|
- `--production`: Generate production-optimized bundle (server provider only)
|
|
318
323
|
|
|
319
324
|
**Example:**
|
|
320
325
|
```bash
|
|
321
|
-
#
|
|
322
|
-
gkm build
|
|
326
|
+
# Build for where gkm.config.ts deploys
|
|
327
|
+
gkm build
|
|
323
328
|
|
|
324
329
|
# Generate server application
|
|
325
330
|
gkm build --provider server
|
|
@@ -443,7 +448,7 @@ gkm docker [options]
|
|
|
443
448
|
|
|
444
449
|
**Generated Files:**
|
|
445
450
|
- `.gkm/docker/Dockerfile` - Multi-stage or slim Dockerfile
|
|
446
|
-
-
|
|
451
|
+
- `docker-compose.constructs.yml` - the containers the constructs imply, and the app (project root)
|
|
447
452
|
- `.gkm/docker/docker-entrypoint.sh` - Entrypoint script
|
|
448
453
|
- `.dockerignore` - Docker ignore file (project root)
|
|
449
454
|
|
|
@@ -490,6 +495,7 @@ Configure Docker settings in `gkm.config.ts`:
|
|
|
490
495
|
import { defineConfig } from '@geekmidas/cli/config';
|
|
491
496
|
|
|
492
497
|
export default defineConfig({
|
|
498
|
+
stages: { local: 'dev', deployed: ['prod'] },
|
|
493
499
|
routes: 'src/routes/**/*.ts',
|
|
494
500
|
envParser: './src/env.ts',
|
|
495
501
|
logger: './src/logger.ts',
|
|
@@ -503,38 +509,20 @@ export default defineConfig({
|
|
|
503
509
|
baseImage: 'node:22-alpine',
|
|
504
510
|
// Port to expose (default: 3000)
|
|
505
511
|
port: 3000,
|
|
506
|
-
// Docker Compose services
|
|
507
|
-
compose: {
|
|
508
|
-
services: {
|
|
509
|
-
postgres: { image: 'postgis/postgis:16-3.4-alpine' }, // Custom image
|
|
510
|
-
redis: true, // Default version
|
|
511
|
-
rabbitmq: { version: '3.12-management-alpine' }, // Custom version
|
|
512
|
-
},
|
|
513
|
-
},
|
|
514
512
|
},
|
|
515
513
|
});
|
|
516
514
|
```
|
|
517
515
|
|
|
518
|
-
**
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
```typescript
|
|
523
|
-
// Object format (recommended)
|
|
524
|
-
services: {
|
|
525
|
-
postgres: { version: '15-alpine' }, // Custom version
|
|
526
|
-
redis: true, // Default: redis:7-alpine
|
|
527
|
-
rabbitmq: { version: '3.12-management-alpine' },
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// Custom images (e.g., PostGIS, Redis Stack)
|
|
531
|
-
services: {
|
|
532
|
-
postgres: { image: 'postgis/postgis:16-3.4-alpine' }, // Full image reference
|
|
533
|
-
redis: { image: 'redis/redis-stack:latest' },
|
|
534
|
-
}
|
|
516
|
+
**Compose:** there is no `compose` option. `gkm docker` writes
|
|
517
|
+
`docker-compose.constructs.yml` at the project root from the declared
|
|
518
|
+
constructs; an image pin or an extra service goes in your own
|
|
519
|
+
`docker-compose.yml`, which is merged over it:
|
|
535
520
|
|
|
536
|
-
|
|
537
|
-
|
|
521
|
+
```yaml
|
|
522
|
+
# docker-compose.yml
|
|
523
|
+
services:
|
|
524
|
+
postgres:
|
|
525
|
+
image: postgis/postgis:16-3.4-alpine
|
|
538
526
|
```
|
|
539
527
|
|
|
540
528
|
**Service Configuration Options:**
|
|
@@ -682,8 +670,8 @@ gkm secrets:init --stage production --force
|
|
|
682
670
|
```
|
|
683
671
|
|
|
684
672
|
**Generated:**
|
|
685
|
-
-
|
|
686
|
-
|
|
673
|
+
- Custom secrets for the stage; the containers' credentials are provisioned by
|
|
674
|
+
reconcile from the declared constructs, not stored here
|
|
687
675
|
- Stored in `.gkm/secrets/<stage>.json` (gitignored)
|
|
688
676
|
|
|
689
677
|
### `gkm secrets:set`
|
|
@@ -929,6 +917,7 @@ This allows the CLI to validate that all required secrets are configured before
|
|
|
929
917
|
```typescript
|
|
930
918
|
// gkm.config.ts
|
|
931
919
|
export default defineConfig({
|
|
920
|
+
stages: { local: 'dev', deployed: ['prod'] },
|
|
932
921
|
routes: 'src/endpoints/**/*.ts',
|
|
933
922
|
envParser: './src/env.ts',
|
|
934
923
|
logger: './src/logger.ts',
|
|
@@ -937,15 +926,6 @@ export default defineConfig({
|
|
|
937
926
|
registry: 'ghcr.io/myorg',
|
|
938
927
|
imageName: 'my-api',
|
|
939
928
|
},
|
|
940
|
-
|
|
941
|
-
// For Dokploy deployments
|
|
942
|
-
providers: {
|
|
943
|
-
dokploy: {
|
|
944
|
-
endpoint: 'https://dokploy.example.com',
|
|
945
|
-
projectId: 'proj_xxx',
|
|
946
|
-
applicationId: 'app_xxx',
|
|
947
|
-
},
|
|
948
|
-
},
|
|
949
929
|
});
|
|
950
930
|
```
|
|
951
931
|
|
|
@@ -955,7 +935,7 @@ export default defineConfig({
|
|
|
955
935
|
|
|
956
936
|
### `gkm deploy:init`
|
|
957
937
|
|
|
958
|
-
Initialize a new Dokploy deployment by creating a project and application via the Dokploy API.
|
|
938
|
+
Initialize a new Dokploy deployment by creating a project and application via the Dokploy API. Nothing is written to `gkm.config.ts`: the ids are rediscovered by name on each run and kept in the deploy state file.
|
|
959
939
|
|
|
960
940
|
```bash
|
|
961
941
|
gkm deploy:init --project <name> --app <name> [options]
|
|
@@ -990,8 +970,7 @@ gkm deploy:init \
|
|
|
990
970
|
1. Searches for existing project by name, or creates a new one
|
|
991
971
|
2. Creates a new application in the project
|
|
992
972
|
3. Configures registry if `--registry-id` is provided
|
|
993
|
-
4.
|
|
994
|
-
5. Shows next steps for secrets and deployment
|
|
973
|
+
4. Shows next steps for secrets and deployment
|
|
995
974
|
|
|
996
975
|
### `gkm deploy:list`
|
|
997
976
|
|
|
@@ -1059,21 +1038,16 @@ The following commands are planned for future releases:
|
|
|
1059
1038
|
The `gkm.config.ts` file defines how the CLI discovers and processes your endpoints:
|
|
1060
1039
|
|
|
1061
1040
|
```typescript
|
|
1062
|
-
// Construct types accept a
|
|
1063
|
-
type Routes = string | string[]
|
|
1064
|
-
|
|
1065
|
-
interface PartitionedRoutes {
|
|
1066
|
-
paths: string | string[];
|
|
1067
|
-
partition: (filepath: string) => string;
|
|
1068
|
-
}
|
|
1041
|
+
// Construct types accept a glob string or an array of them
|
|
1042
|
+
type Routes = string | string[];
|
|
1069
1043
|
|
|
1070
1044
|
interface GkmConfig {
|
|
1071
|
-
routes: Routes; // Glob patterns
|
|
1045
|
+
routes: Routes; // Glob patterns
|
|
1072
1046
|
envParser: string; // Path to environment parser
|
|
1073
1047
|
logger: string; // Path to logger configuration
|
|
1074
|
-
functions?: Routes; // Glob patterns
|
|
1075
|
-
crons?: Routes; // Glob patterns
|
|
1076
|
-
subscribers?: Routes; // Glob patterns
|
|
1048
|
+
functions?: Routes; // Glob patterns
|
|
1049
|
+
crons?: Routes; // Glob patterns
|
|
1050
|
+
subscribers?: Routes; // Glob patterns
|
|
1077
1051
|
runtime?: 'node' | 'bun'; // Runtime environment (default: 'node')
|
|
1078
1052
|
telescope?: boolean | TelescopeConfig; // Telescope debugging config
|
|
1079
1053
|
}
|
|
@@ -1092,7 +1066,7 @@ interface TelescopeConfig {
|
|
|
1092
1066
|
|
|
1093
1067
|
#### `routes`
|
|
1094
1068
|
|
|
1095
|
-
Glob pattern(s) to discover endpoint files. Can be a single pattern
|
|
1069
|
+
Glob pattern(s) to discover endpoint files. Can be a single pattern or an array of patterns:
|
|
1096
1070
|
|
|
1097
1071
|
```typescript
|
|
1098
1072
|
// Single pattern
|
|
@@ -1104,19 +1078,8 @@ routes: [
|
|
|
1104
1078
|
'src/api/**/*.ts',
|
|
1105
1079
|
'src/handlers/**/*.ts'
|
|
1106
1080
|
]
|
|
1107
|
-
|
|
1108
|
-
// Partitioned — groups constructs in the generated manifest
|
|
1109
|
-
routes: {
|
|
1110
|
-
paths: './src/endpoints/**/*.ts',
|
|
1111
|
-
partition: (filepath) => {
|
|
1112
|
-
const match = filepath.match(/endpoints\/([^/]+)\//);
|
|
1113
|
-
return match?.[1] ?? 'default';
|
|
1114
|
-
},
|
|
1115
|
-
}
|
|
1116
1081
|
```
|
|
1117
1082
|
|
|
1118
|
-
The same partitioned format works for `functions`, `crons`, and `subscribers`. When a `partition` callback is provided, the generated manifest groups constructs by partition name (e.g., `manifest.routes.admin`). Without it, manifest fields remain flat arrays.
|
|
1119
|
-
|
|
1120
1083
|
#### `envParser`
|
|
1121
1084
|
|
|
1122
1085
|
Path to your environment parser configuration. Supports both default and named exports.
|
|
@@ -1216,6 +1179,7 @@ import { defineWorkspace } from '@geekmidas/cli/config';
|
|
|
1216
1179
|
|
|
1217
1180
|
export default defineWorkspace({
|
|
1218
1181
|
name: 'my-project',
|
|
1182
|
+
stages: { local: 'dev', deployed: ['prod'] },
|
|
1219
1183
|
constructs: './constructs/**/*.ts',
|
|
1220
1184
|
shared: {
|
|
1221
1185
|
packages: ['packages/*'],
|
|
@@ -1239,7 +1203,7 @@ them out of the manifest; none of them is listed in config.
|
|
|
1239
1203
|
|
|
1240
1204
|
```typescript
|
|
1241
1205
|
// constructs/api.ts
|
|
1242
|
-
export const api = new RestApi('Api', { defaultAuthorizer: 'none', logger });
|
|
1206
|
+
export const api = new RestApi('Api', { path: 'apps/api', defaultAuthorizer: 'none', logger });
|
|
1243
1207
|
```
|
|
1244
1208
|
|
|
1245
1209
|
`gkm build --provider server` generates a Hono server from the endpoints built
|
|
@@ -1253,6 +1217,7 @@ An auth server mounts a wildcard, so there is nothing for a glob to find:
|
|
|
1253
1217
|
```typescript
|
|
1254
1218
|
// constructs/auth.ts
|
|
1255
1219
|
export const auth = new BetterAuth('Auth', {
|
|
1220
|
+
path: 'apps/auth',
|
|
1256
1221
|
database: authDb,
|
|
1257
1222
|
basePath: '/api/auth',
|
|
1258
1223
|
});
|
|
@@ -1271,8 +1236,8 @@ from being read by it.
|
|
|
1271
1236
|
|
|
1272
1237
|
```typescript
|
|
1273
1238
|
// constructs/site.ts
|
|
1274
|
-
export const web = new StaticSite('Web').dependsOn([api, auth]);
|
|
1275
|
-
export const admin = new StaticSite('Admin', { variant: 'next' }).dependsOn([api]);
|
|
1239
|
+
export const web = new StaticSite('Web', { path: 'apps/web' }).dependsOn([api, auth]);
|
|
1240
|
+
export const admin = new StaticSite('Admin', { path: 'apps/admin', variant: 'next' }).dependsOn([api]);
|
|
1276
1241
|
```
|
|
1277
1242
|
|
|
1278
1243
|
`.dependsOn()` is the single fact behind four things that are hand-maintained
|
|
@@ -1291,7 +1256,7 @@ gkm docker
|
|
|
1291
1256
|
- `.gkm/docker/Dockerfile.api` - Routes-based backend (uses `gkm build`)
|
|
1292
1257
|
- `.gkm/docker/Dockerfile.auth` - Entry-based backend (uses esbuild bundling)
|
|
1293
1258
|
- `.gkm/docker/Dockerfile.web` - Next.js standalone output
|
|
1294
|
-
-
|
|
1259
|
+
- `docker-compose.constructs.yml` - every container the constructs imply, and each app behind the `apps` profile (project root)
|
|
1295
1260
|
- `.dockerignore` - Optimized ignore patterns
|
|
1296
1261
|
|
|
1297
1262
|
**Dockerfile types by app:**
|
|
@@ -1358,12 +1323,10 @@ interface WorkspaceConfig {
|
|
|
1358
1323
|
What an app is comes from the declaration, not from here:
|
|
1359
1324
|
|
|
1360
1325
|
```typescript
|
|
1361
|
-
/**
|
|
1326
|
+
/** How a site is built and run. A surface declares only its `path`. */
|
|
1362
1327
|
interface AppSpec {
|
|
1363
|
-
/**
|
|
1364
|
-
path
|
|
1365
|
-
/** Default: the conventional directories under `path`. */
|
|
1366
|
-
code?: string;
|
|
1328
|
+
/** Required: where the app lives, relative to the workspace root. */
|
|
1329
|
+
path: string;
|
|
1367
1330
|
/** Default: assigned in a stable order, so adding an app renumbers nothing. */
|
|
1368
1331
|
port?: number;
|
|
1369
1332
|
entry?: string;
|
|
@@ -1371,42 +1334,24 @@ interface AppSpec {
|
|
|
1371
1334
|
}
|
|
1372
1335
|
```
|
|
1373
1336
|
|
|
1374
|
-
##
|
|
1375
|
-
|
|
1376
|
-
### AWS API Gateway v1
|
|
1377
|
-
|
|
1378
|
-
Generates Lambda handlers compatible with AWS API Gateway v1 (REST API).
|
|
1379
|
-
|
|
1380
|
-
```bash
|
|
1381
|
-
gkm build --provider aws-apigatewayv1
|
|
1382
|
-
```
|
|
1383
|
-
|
|
1384
|
-
**Generated Handler:**
|
|
1385
|
-
```typescript
|
|
1386
|
-
import { AmazonApiGatewayV1Endpoint } from '@geekmidas/constructs/aws';
|
|
1387
|
-
import { myEndpoint } from '../src/routes/example.js';
|
|
1388
|
-
import { envParser } from '../src/env.js';
|
|
1389
|
-
|
|
1390
|
-
const adapter = new AmazonApiGatewayV1Endpoint(envParser, myEndpoint);
|
|
1337
|
+
## Build Targets
|
|
1391
1338
|
|
|
1392
|
-
|
|
1393
|
-
```
|
|
1339
|
+
### AWS
|
|
1394
1340
|
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
Generates Lambda handlers compatible with AWS API Gateway v2 (HTTP API).
|
|
1341
|
+
Generates one Lambda handler per construct. Endpoints get an API Gateway v2
|
|
1342
|
+
(HTTP API) adapter.
|
|
1398
1343
|
|
|
1399
1344
|
```bash
|
|
1400
|
-
gkm build
|
|
1345
|
+
gkm build # with deploy: { default: 'sst' }
|
|
1346
|
+
gkm build --provider aws # whatever the deploy target
|
|
1401
1347
|
```
|
|
1402
1348
|
|
|
1403
1349
|
**Generated Handler:**
|
|
1404
1350
|
```typescript
|
|
1405
1351
|
import { AmazonApiGatewayV2Endpoint } from '@geekmidas/constructs/aws';
|
|
1406
|
-
import { myEndpoint } from '
|
|
1407
|
-
import { envParser } from '../src/env.js';
|
|
1352
|
+
import { myEndpoint } from '../../../src/routes/example.js';
|
|
1408
1353
|
|
|
1409
|
-
const adapter = new AmazonApiGatewayV2Endpoint(
|
|
1354
|
+
const adapter = new AmazonApiGatewayV2Endpoint(myEndpoint);
|
|
1410
1355
|
|
|
1411
1356
|
export const handler = adapter.handler;
|
|
1412
1357
|
```
|
|
@@ -1448,139 +1393,141 @@ export default createApp;
|
|
|
1448
1393
|
|
|
1449
1394
|
## Output Structure
|
|
1450
1395
|
|
|
1451
|
-
|
|
1396
|
+
Handlers are generated beside the app, in `<app>/.gkm/<target>`; the manifest
|
|
1397
|
+
at the workspace root, where `sst.config.ts` runs:
|
|
1452
1398
|
|
|
1453
1399
|
```
|
|
1454
|
-
|
|
1455
|
-
├──
|
|
1456
|
-
│ ├──
|
|
1457
|
-
│
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
│ ├──
|
|
1461
|
-
├──
|
|
1462
|
-
│ ├──
|
|
1463
|
-
│
|
|
1464
|
-
└──
|
|
1400
|
+
<root>/
|
|
1401
|
+
├── .gkm/manifest/
|
|
1402
|
+
│ ├── aws.ts # AWS manifest with types
|
|
1403
|
+
│ └── server.ts # Server manifest with types
|
|
1404
|
+
└── apps/api/.gkm/
|
|
1405
|
+
├── aws/
|
|
1406
|
+
│ ├── routes/getUsers.ts # One Lambda handler per endpoint
|
|
1407
|
+
│ ├── functions/
|
|
1408
|
+
│ ├── crons/
|
|
1409
|
+
│ ├── queues/
|
|
1410
|
+
│ └── subscribers/
|
|
1411
|
+
└── server/
|
|
1412
|
+
├── app.ts # Server application
|
|
1413
|
+
└── endpoints.ts # Endpoint exports
|
|
1465
1414
|
```
|
|
1466
1415
|
|
|
1467
1416
|
### Build Manifest
|
|
1468
1417
|
|
|
1469
|
-
The
|
|
1418
|
+
The manifest is the application's, not an app's: the root `gkm build` builds
|
|
1419
|
+
every backend and writes it once, to `.gkm/manifest/aws.ts` or
|
|
1420
|
+
`.gkm/manifest/server.ts` at the workspace root. An app's own build writes no
|
|
1421
|
+
manifest. Every handler path in it is relative to the workspace root. `gkm init`
|
|
1422
|
+
adds a root tsconfig alias for the manifest, `@<project>/manifest`.
|
|
1470
1423
|
|
|
1471
|
-
|
|
1424
|
+
It exports two values — every declared construct keyed by id, and the backends
|
|
1425
|
+
the build resolved — and the types derived from them:
|
|
1472
1426
|
|
|
1473
1427
|
```typescript
|
|
1474
|
-
export const
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1428
|
+
export const constructs = {
|
|
1429
|
+
Database: { id: 'Database', kind: 'database' },
|
|
1430
|
+
Api: {
|
|
1431
|
+
id: 'Api',
|
|
1432
|
+
kind: 'rest-api',
|
|
1433
|
+
path: 'apps/api',
|
|
1434
|
+
endpoints: [
|
|
1435
|
+
{
|
|
1436
|
+
id: 'ApiGET/users',
|
|
1437
|
+
method: 'GET',
|
|
1438
|
+
path: '/users',
|
|
1439
|
+
handler: 'apps/api/.gkm/aws/routes/getUsers.handler',
|
|
1440
|
+
dependencies: [{ target: 'Database', kind: 'database' }],
|
|
1441
|
+
authorizer: 'iam',
|
|
1442
|
+
},
|
|
1443
|
+
],
|
|
1444
|
+
},
|
|
1445
|
+
ProcessData: {
|
|
1446
|
+
id: 'ProcessData',
|
|
1447
|
+
kind: 'function',
|
|
1448
|
+
handler: 'apps/api/.gkm/aws/functions/processData.handler',
|
|
1449
|
+
dependencies: [],
|
|
1450
|
+
},
|
|
1451
|
+
DailyCleanup: {
|
|
1452
|
+
id: 'DailyCleanup',
|
|
1453
|
+
kind: 'cron',
|
|
1454
|
+
handler: 'apps/api/.gkm/aws/crons/dailyCleanup.handler',
|
|
1455
|
+
schedule: 'rate(1 day)',
|
|
1456
|
+
dependencies: [{ target: 'Database', kind: 'database' }],
|
|
1457
|
+
},
|
|
1458
|
+
Emails: {
|
|
1459
|
+
id: 'Emails',
|
|
1460
|
+
kind: 'queue',
|
|
1461
|
+
// The queue's consumer is nested in it
|
|
1462
|
+
worker: {
|
|
1463
|
+
id: 'emails',
|
|
1464
|
+
handler: 'apps/api/.gkm/aws/queues/emails.handler',
|
|
1465
|
+
dependencies: [],
|
|
1504
1466
|
},
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1467
|
+
},
|
|
1468
|
+
Users: {
|
|
1469
|
+
id: 'Users',
|
|
1470
|
+
kind: 'topic',
|
|
1471
|
+
events: ['user.created'],
|
|
1472
|
+
// As are a topic's subscribers
|
|
1473
|
+
subscribers: [
|
|
1474
|
+
{
|
|
1475
|
+
id: 'onUser',
|
|
1476
|
+
handler: 'apps/api/.gkm/aws/subscribers/onUser.handler',
|
|
1477
|
+
events: ['user.created'],
|
|
1478
|
+
dependencies: [],
|
|
1479
|
+
},
|
|
1480
|
+
],
|
|
1481
|
+
},
|
|
1482
|
+
} as const satisfies ConstructManifest;
|
|
1483
|
+
|
|
1484
|
+
export const backends = { cache: 'upstash', email: 'ses' } as const;
|
|
1508
1485
|
|
|
1509
1486
|
// Derived types
|
|
1510
|
-
export type
|
|
1511
|
-
export type
|
|
1512
|
-
export type
|
|
1513
|
-
export type Subscriber = (typeof manifest.subscribers)[number];
|
|
1487
|
+
export type Ids = IdsOf<typeof constructs>;
|
|
1488
|
+
export type Construct<Id extends Ids> = DeclarationOf<typeof constructs, Id>;
|
|
1489
|
+
export type Kind = Construct<Ids>['kind'];
|
|
1514
1490
|
|
|
1515
1491
|
// Useful union types
|
|
1516
|
-
export type
|
|
1517
|
-
export type
|
|
1518
|
-
export type
|
|
1492
|
+
export type ProvidedKeys = AllProvidedKeys<typeof constructs>;
|
|
1493
|
+
export type Surfaces = IdsOfKind<typeof constructs, 'rest-api'>;
|
|
1494
|
+
export type CacheBackend = (typeof backends)['cache'];
|
|
1495
|
+
export type EmailBackend = (typeof backends)['email'];
|
|
1519
1496
|
```
|
|
1520
1497
|
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
},
|
|
1529
|
-
functions: [...], // flat if not partitioned
|
|
1530
|
-
} as const;
|
|
1498
|
+
A `RestApi` carries its endpoints, each with its method, path, handler, the
|
|
1499
|
+
dependencies it declared and its authorizer. On AWS the handler is the
|
|
1500
|
+
endpoint's own Lambda (`apps/api/.gkm/aws/routes/<export>.handler`); in the
|
|
1501
|
+
server manifest every endpoint's handler is the app entry
|
|
1502
|
+
(`apps/api/.gkm/server/app.ts`). Functions and crons are top-level
|
|
1503
|
+
declarations; a queue's worker and a topic's subscribers are nested in the
|
|
1504
|
+
queue or topic.
|
|
1531
1505
|
|
|
1532
|
-
|
|
1533
|
-
export type RoutePartition = keyof typeof manifest.routes;
|
|
1534
|
-
export type Route<P extends RoutePartition = RoutePartition> =
|
|
1535
|
-
(typeof manifest.routes)[P][number];
|
|
1536
|
-
```
|
|
1506
|
+
#### Using the Manifest
|
|
1537
1507
|
|
|
1538
|
-
|
|
1508
|
+
On AWS, `fromManifest` from `@geekmidas/cloud/sst` provisions all of it —
|
|
1509
|
+
resources, each API's endpoints, queue consumers, functions and crons:
|
|
1539
1510
|
|
|
1540
1511
|
```typescript
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
endpoints: '.gkm/server/endpoints.ts',
|
|
1545
|
-
},
|
|
1546
|
-
routes: [
|
|
1547
|
-
{ path: '/users', method: 'GET', authorizer: 'jwt' },
|
|
1548
|
-
{ path: '/users', method: 'POST', authorizer: 'jwt' },
|
|
1549
|
-
],
|
|
1550
|
-
subscribers: [
|
|
1551
|
-
{ name: 'orderHandler', subscribedEvents: ['order.created'] },
|
|
1552
|
-
],
|
|
1553
|
-
} as const;
|
|
1554
|
-
|
|
1555
|
-
// Derived types
|
|
1556
|
-
export type Route = (typeof manifest.routes)[number];
|
|
1557
|
-
export type Subscriber = (typeof manifest.subscribers)[number];
|
|
1512
|
+
// sst.config.ts
|
|
1513
|
+
const { App, fromManifest, Stack } = await import('@geekmidas/cloud/sst');
|
|
1514
|
+
const { backends, constructs } = await import('./.gkm/manifest/aws.js');
|
|
1558
1515
|
|
|
1559
|
-
|
|
1560
|
-
export type Authorizer = Route['authorizer'];
|
|
1561
|
-
export type HttpMethod = Route['method'];
|
|
1562
|
-
export type RoutePath = Route['path'];
|
|
1516
|
+
fromManifest(new Stack(app, 'Shop'), constructs, { Database: { vpc } }, backends);
|
|
1563
1517
|
```
|
|
1564
1518
|
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
Import the manifest types for type-safe infrastructure configuration:
|
|
1519
|
+
The types narrow to what was declared:
|
|
1568
1520
|
|
|
1569
1521
|
```typescript
|
|
1570
|
-
import {
|
|
1522
|
+
import { constructs, type Construct, type Surfaces } from './.gkm/manifest/aws';
|
|
1571
1523
|
|
|
1572
|
-
|
|
1573
|
-
for (const route of manifest.routes) {
|
|
1574
|
-
console.log(`${route.method} ${route.path} -> ${route.handler}`);
|
|
1575
|
-
}
|
|
1524
|
+
const api: Construct<'Api'> = constructs.Api;
|
|
1576
1525
|
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
return manifest.routes.some((r) => r.method === method);
|
|
1526
|
+
for (const endpoint of api.endpoints) {
|
|
1527
|
+
console.log(`${endpoint.method} ${endpoint.path} -> ${endpoint.handler}`);
|
|
1580
1528
|
}
|
|
1581
1529
|
|
|
1582
|
-
//
|
|
1583
|
-
const authorizers = new Set(manifest.routes.map((r) => r.authorizer));
|
|
1530
|
+
const surface: Surfaces = 'Api'; // any other id is a type error
|
|
1584
1531
|
```
|
|
1585
1532
|
|
|
1586
1533
|
## OpenAPI Generation
|
|
@@ -1675,17 +1622,17 @@ provider:
|
|
|
1675
1622
|
|
|
1676
1623
|
functions:
|
|
1677
1624
|
getUsers:
|
|
1678
|
-
handler: .gkm/aws
|
|
1625
|
+
handler: .gkm/aws/routes/getUsers.handler
|
|
1679
1626
|
events:
|
|
1680
|
-
-
|
|
1681
|
-
path: users
|
|
1627
|
+
- httpApi:
|
|
1628
|
+
path: /users
|
|
1682
1629
|
method: get
|
|
1683
|
-
|
|
1630
|
+
|
|
1684
1631
|
createUser:
|
|
1685
|
-
handler: .gkm/aws
|
|
1632
|
+
handler: .gkm/aws/routes/createUser.handler
|
|
1686
1633
|
events:
|
|
1687
|
-
-
|
|
1688
|
-
path: users
|
|
1634
|
+
- httpApi:
|
|
1635
|
+
path: /users
|
|
1689
1636
|
method: post
|
|
1690
1637
|
```
|
|
1691
1638
|
|
|
@@ -1883,6 +1830,7 @@ Configure multiple patterns for complex project structures:
|
|
|
1883
1830
|
import { defineConfig } from '@geekmidas/cli/config';
|
|
1884
1831
|
|
|
1885
1832
|
export default defineConfig({
|
|
1833
|
+
stages: { local: 'dev', deployed: ['prod'] },
|
|
1886
1834
|
routes: [
|
|
1887
1835
|
'src/routes/**/*.ts',
|
|
1888
1836
|
'src/api/v1/**/*.ts',
|
|
@@ -1935,7 +1883,7 @@ Error: OpenAPI generation failed: Invalid endpoint schema
|
|
|
1935
1883
|
"dev": "gkm dev",
|
|
1936
1884
|
"dev:port": "gkm dev --port 8080",
|
|
1937
1885
|
"build": "gkm build",
|
|
1938
|
-
"build:lambda": "gkm build --provider aws
|
|
1886
|
+
"build:lambda": "gkm build --provider aws",
|
|
1939
1887
|
"build:server": "gkm build --provider server",
|
|
1940
1888
|
"docs": "gkm openapi --output src/api.ts"
|
|
1941
1889
|
}
|
|
@@ -2029,8 +1977,8 @@ DEBUG=gkm:* npx gkm build
|
|
|
2029
1977
|
### Types
|
|
2030
1978
|
|
|
2031
1979
|
```typescript
|
|
2032
|
-
//
|
|
2033
|
-
type Provider = '
|
|
1980
|
+
// Build targets
|
|
1981
|
+
type Provider = 'aws' | 'server';
|
|
2034
1982
|
|
|
2035
1983
|
// Runtime options
|
|
2036
1984
|
type Runtime = 'node' | 'bun';
|
|
@@ -2054,17 +2002,8 @@ interface DockerConfig {
|
|
|
2054
2002
|
imageName?: string; // Image name (defaults to package.json name)
|
|
2055
2003
|
baseImage?: string; // Base image (default: node:22-alpine)
|
|
2056
2004
|
port?: number; // Port to expose (default: 3000)
|
|
2057
|
-
compose?: {
|
|
2058
|
-
services?: ComposeServicesConfig | ComposeServiceName[];
|
|
2059
|
-
};
|
|
2060
2005
|
}
|
|
2061
2006
|
|
|
2062
|
-
// Service configuration for docker-compose
|
|
2063
|
-
type ComposeServiceName = 'postgres' | 'redis' | 'rabbitmq';
|
|
2064
|
-
type ComposeServicesConfig = {
|
|
2065
|
-
[K in ComposeServiceName]?: boolean | { version?: string };
|
|
2066
|
-
};
|
|
2067
|
-
|
|
2068
2007
|
// Telescope configuration
|
|
2069
2008
|
interface TelescopeConfig {
|
|
2070
2009
|
enabled?: boolean;
|
|
@@ -2077,7 +2016,7 @@ interface TelescopeConfig {
|
|
|
2077
2016
|
|
|
2078
2017
|
// Build options
|
|
2079
2018
|
interface BuildOptions {
|
|
2080
|
-
provider
|
|
2019
|
+
provider?: Provider; // default: where gkm.config.ts deploys
|
|
2081
2020
|
}
|
|
2082
2021
|
|
|
2083
2022
|
// Dev options
|