@geekmidas/cli 10.0.0-alpha.46 → 10.0.0-alpha.48

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.
Files changed (32) hide show
  1. package/bin/gkm.mjs +9 -1
  2. package/bin/owning-tsconfig-jsx-register.mjs +18 -0
  3. package/bin/owning-tsconfig-jsx.mjs +108 -0
  4. package/dist/backends-B9V2XD2M.cjs +82 -0
  5. package/dist/backends-B9V2XD2M.cjs.map +1 -0
  6. package/dist/backends-CSuLl0YP.mjs +59 -0
  7. package/dist/backends-CSuLl0YP.mjs.map +1 -0
  8. package/dist/encryption-C7OGMve_.cjs +91 -0
  9. package/dist/encryption-C7OGMve_.cjs.map +1 -0
  10. package/dist/encryption-DyQnPsZN.mjs +90 -0
  11. package/dist/encryption-DyQnPsZN.mjs.map +1 -0
  12. package/dist/index.cjs +131 -51
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.mjs +123 -43
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/{migrate-Dp5HFzuQ.cjs → migrate-BgEY9pdP.cjs} +2 -2
  17. package/dist/{migrate-Dp5HFzuQ.cjs.map → migrate-BgEY9pdP.cjs.map} +1 -1
  18. package/dist/{migrate-B3opyC3o.mjs → migrate-DhxTIA0z.mjs} +2 -2
  19. package/dist/{migrate-B3opyC3o.mjs.map → migrate-DhxTIA0z.mjs.map} +1 -1
  20. package/dist/{ready-V6Ou6-B6.mjs → ready-WfT-eWlm.mjs} +2 -1
  21. package/dist/{ready-V6Ou6-B6.mjs.map → ready-WfT-eWlm.mjs.map} +1 -1
  22. package/dist/{ready-L7I68yXf.cjs → ready-lr2Fm-ep.cjs} +2 -1
  23. package/dist/{ready-L7I68yXf.cjs.map → ready-lr2Fm-ep.cjs.map} +1 -1
  24. package/dist/vitest.cjs +1 -1
  25. package/dist/vitest.mjs +1 -1
  26. package/dist/{workspace-CHEC80sp.mjs → workspace-cb6U29EL.mjs} +56 -77
  27. package/dist/workspace-cb6U29EL.mjs.map +1 -0
  28. package/dist/{workspace-D9z2ymBW.cjs → workspace-vafrzZTC.cjs} +60 -99
  29. package/dist/workspace-vafrzZTC.cjs.map +1 -0
  30. package/package.json +14 -14
  31. package/dist/workspace-CHEC80sp.mjs.map +0 -1
  32. package/dist/workspace-D9z2ymBW.cjs.map +0 -1
package/bin/gkm.mjs CHANGED
@@ -19,6 +19,10 @@ if (
19
19
  const { createRequire } = await import('node:module');
20
20
  const require = createRequire(import.meta.url);
21
21
  const tsxPath = pathToFileURL(require.resolve('tsx')).href;
22
+ // Before tsx, so tsx reads each `.tsx` through it and compiles its JSX the
23
+ // way the file's own tsconfig says. See `owning-tsconfig-jsx.mjs`.
24
+ const jsxPath = new URL('./owning-tsconfig-jsx-register.mjs', import.meta.url)
25
+ .href;
22
26
 
23
27
  const { execFileSync } = await import('node:child_process');
24
28
  try {
@@ -26,7 +30,11 @@ if (
26
30
  stdio: 'inherit',
27
31
  env: {
28
32
  ...process.env,
29
- NODE_OPTIONS: `${nodeOptions} --import ${tsxPath}`.trim(),
33
+ // `--import=<url>`, never `--import <url>`: Next.js re-parses
34
+ // NODE_OPTIONS for its workers, and with two space-separated imports
35
+ // its parser glued them into one specifier `next build` could not find.
36
+ NODE_OPTIONS:
37
+ `${nodeOptions} --import=${jsxPath} --import=${tsxPath}`.trim(),
30
38
  },
31
39
  });
32
40
  } catch (e) {
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The `--import` that installs `owning-tsconfig-jsx.mjs` — it must come before
3
+ * tsx's own `--import`, so that tsx reads the source through it.
4
+ *
5
+ * Registered with `module.register()` whatever tsx chose: tsx's in-thread hooks
6
+ * (`registerHooks`, Node 22.22.3+ / 24.11.1+) hand off to the off-thread chain
7
+ * when they load a file, and on older Node tsx registers off-thread too, after
8
+ * this — so either way this hook is asked after tsx, for the file's source.
9
+ */
10
+
11
+ import { register } from 'node:module';
12
+ import { isInternalThread } from 'node:worker_threads';
13
+
14
+ // As tsx guards its own: where Node runs preloads in the hooks thread too,
15
+ // registering from there would hook the hooks.
16
+ if (!isInternalThread) {
17
+ register('./owning-tsconfig-jsx.mjs', import.meta.url);
18
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Compile a `.tsx` file's JSX the way the tsconfig that owns it says to.
3
+ *
4
+ * tsx applies one tsconfig to the whole process — the one in the directory the
5
+ * command ran from — and only to the files that tsconfig's `include` covers.
6
+ * `gkm dev` runs each app from its own directory, so a construct's template in
7
+ * the workspace (`constructs/templates/MagicLink.tsx`) was outside the app's
8
+ * `include` and compiled with esbuild's defaults: the classic runtime, which
9
+ * calls `React.createElement` in a file that never imported React, because the
10
+ * root tsconfig's `"jsx": "react-jsx"` said it need not. It threw
11
+ * `React is not defined` at render under `gkm dev` and rendered under
12
+ * `gkm test`, where Vitest compiles each file with its nearest tsconfig.
13
+ *
14
+ * Pointing tsx at the root tsconfig instead would only move the problem: an
15
+ * app may set its own `jsx` or `jsxImportSource` (a Hono app's `hono/jsx`), and
16
+ * one tsconfig per process is the same mistake `adjacent-tsconfig.mjs` exists
17
+ * to undo for path aliases. tsx has no per-file tsconfig, but esbuild — which
18
+ * tsx compiles with — honours JSX pragmas in a file over its options. So this
19
+ * hook, registered before tsx so that it sits between tsx and the file on disk,
20
+ * appends the owning tsconfig's JSX settings to the source as pragmas.
21
+ *
22
+ * The owning tsconfig is the nearest one above the file, as Vitest and
23
+ * `adjacent-tsconfig.mjs` choose it. A file that already carries its own JSX
24
+ * pragma, or whose tsconfig asks for nothing a pragma can say (`preserve`, or
25
+ * no `jsx` at all), is left exactly as it is. The pragma goes at the end, so no
26
+ * line of the file moves and its stack traces still point at the right place.
27
+ *
28
+ * Only ESM sources pass through here: for a CommonJS module tsx reads the file
29
+ * itself, and those keep the process tsconfig's behaviour.
30
+ */
31
+
32
+ import { dirname } from 'node:path';
33
+ import { fileURLToPath } from 'node:url';
34
+ import { getTsconfig } from 'get-tsconfig';
35
+
36
+ const JSX_SOURCE = /\.[jt]sx$/;
37
+ /** A pragma the file chose for itself, which this hook never overrides. */
38
+ const OWN_PRAGMA = /@jsx(?:Runtime|ImportSource|Frag)?\s/;
39
+
40
+ /** Directory → the pragma its owning tsconfig implies, or `null`. */
41
+ const pragmas = new Map();
42
+ /** Shared with `get-tsconfig`, so a config `extends` is read once. */
43
+ const tsconfigCache = new Map();
44
+
45
+ /**
46
+ * The pragma comment that tells esbuild what these compiler options tell
47
+ * TypeScript, or `null` when there is nothing to say.
48
+ */
49
+ export function jsxPragma(compilerOptions = {}) {
50
+ const jsx = compilerOptions.jsx?.toLowerCase();
51
+
52
+ if (jsx === 'react-jsx' || jsx === 'react-jsxdev') {
53
+ const source = compilerOptions.jsxImportSource ?? 'react';
54
+ return `/* @jsxRuntime automatic @jsxImportSource ${source} */`;
55
+ }
56
+
57
+ if (jsx === 'react') {
58
+ const parts = ['@jsxRuntime classic'];
59
+ if (compilerOptions.jsxFactory) {
60
+ parts.push(`@jsx ${compilerOptions.jsxFactory}`);
61
+ }
62
+ if (compilerOptions.jsxFragmentFactory) {
63
+ parts.push(`@jsxFrag ${compilerOptions.jsxFragmentFactory}`);
64
+ }
65
+ return `/* ${parts.join(' ')} */`;
66
+ }
67
+
68
+ // `preserve` and `react-native` leave JSX in the output, which no pragma
69
+ // can ask for; without `jsx` TypeScript compiles no `.tsx` at all.
70
+ return null;
71
+ }
72
+
73
+ function pragmaFor(directory) {
74
+ if (!pragmas.has(directory)) {
75
+ const tsconfig = getTsconfig(directory, 'tsconfig.json', tsconfigCache);
76
+ pragmas.set(directory, jsxPragma(tsconfig?.config.compilerOptions));
77
+ }
78
+ return pragmas.get(directory);
79
+ }
80
+
81
+ /** The JSX file at this URL, when it is one of the project's own. */
82
+ function jsxFilePath(url) {
83
+ if (!url.startsWith('file:')) return null;
84
+
85
+ const path = fileURLToPath(url.split(/[?#]/)[0]);
86
+ if (!JSX_SOURCE.test(path) || path.includes('/node_modules/')) return null;
87
+
88
+ return path;
89
+ }
90
+
91
+ /** For `module.register()`, so it runs behind tsx however tsx registered. */
92
+ export async function load(url, context, nextLoad) {
93
+ const loaded = await nextLoad(url, context);
94
+
95
+ const path = jsxFilePath(url);
96
+ if (!path || loaded.source == null) return loaded;
97
+
98
+ const pragma = pragmaFor(dirname(path));
99
+ if (!pragma) return loaded;
100
+
101
+ const source =
102
+ typeof loaded.source === 'string'
103
+ ? loaded.source
104
+ : new TextDecoder().decode(loaded.source);
105
+ if (OWN_PRAGMA.test(source)) return loaded;
106
+
107
+ return { ...loaded, source: `${source}\n${pragma}\n` };
108
+ }
@@ -0,0 +1,82 @@
1
+ const require_ready = require("./ready-lr2Fm-ep.cjs");
2
+ //#region src/workspace/backends.ts
3
+ /**
4
+ * Which backend each declared kind resolves to — decided by where the project
5
+ * deploys, and by nothing else.
6
+ *
7
+ * These used to be read out of a `services:` block, where one key answered two
8
+ * questions: *does this exist* and *what backs it*. The first is the manifest's
9
+ * — a declared `Cache` is why there is a cache — and the second is the deploy
10
+ * target's, because the right cache for a Lambda is not the right cache for a
11
+ * box already running Postgres. With both answered elsewhere there was nothing
12
+ * left for the block to say, so it is gone and these read the target.
13
+ *
14
+ * Mail has no answer here at all: every provider speaks SMTP, so the provider
15
+ * is whichever one the stage's mail URL points at.
16
+ */
17
+ /**
18
+ * Which family of defaults a workspace's deploy target belongs to.
19
+ *
20
+ * One question, asked once: **does this target run containers the project
21
+ * controls?** Dokploy and a bare server do, so a bucket or a cache can live
22
+ * beside the app; AWS, Vercel and Cloudflare do not, so the default has to be
23
+ * something managed. That is the whole of the distinction, and it is why
24
+ * `MainProvider` is the right axis rather than the deploy target's own name —
25
+ * three targets share one answer.
26
+ *
27
+ * An AWS deploy names `deploy.default: 'sst'`, because it goes through SST.
28
+ */
29
+ function providerOf(workspace) {
30
+ const target = workspace.deploy?.default;
31
+ return target === "dokploy" || target === "server" ? "server" : "aws";
32
+ }
33
+ /**
34
+ * The cache backend a target implies.
35
+ *
36
+ * The same answer locally and deployed: a local `gkm dev` for an AWS app still
37
+ * uses the Upstash protocol, because a backend that differed between the two
38
+ * would be worse than a slower one.
39
+ */
40
+ function cacheBackendFor(on) {
41
+ return require_ready.DEFAULT_CACHE[on];
42
+ }
43
+ /** Where a declared bucket lives on a target. */
44
+ function storageBackendFor(on) {
45
+ return require_ready.DEFAULT_STORAGE[on];
46
+ }
47
+ /**
48
+ * Which broker carries declared queues and topics on a target.
49
+ *
50
+ * Only consulted when something declares one; a project with no `Topic` or
51
+ * `Queue` has no events at all, whatever the target.
52
+ */
53
+ function eventsBackendFor(on) {
54
+ return require_ready.DEFAULT_EVENTS[on];
55
+ }
56
+ //#endregion
57
+ Object.defineProperty(exports, "cacheBackendFor", {
58
+ enumerable: true,
59
+ get: function() {
60
+ return cacheBackendFor;
61
+ }
62
+ });
63
+ Object.defineProperty(exports, "eventsBackendFor", {
64
+ enumerable: true,
65
+ get: function() {
66
+ return eventsBackendFor;
67
+ }
68
+ });
69
+ Object.defineProperty(exports, "providerOf", {
70
+ enumerable: true,
71
+ get: function() {
72
+ return providerOf;
73
+ }
74
+ });
75
+ Object.defineProperty(exports, "storageBackendFor", {
76
+ enumerable: true,
77
+ get: function() {
78
+ return storageBackendFor;
79
+ }
80
+ });
81
+
82
+ //# sourceMappingURL=backends-B9V2XD2M.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backends-B9V2XD2M.cjs","names":["DEFAULT_CACHE","DEFAULT_STORAGE","DEFAULT_EVENTS"],"sources":["../src/workspace/backends.ts"],"sourcesContent":["/**\n * Which backend each declared kind resolves to — decided by where the project\n * deploys, and by nothing else.\n *\n * These used to be read out of a `services:` block, where one key answered two\n * questions: *does this exist* and *what backs it*. The first is the manifest's\n * — a declared `Cache` is why there is a cache — and the second is the deploy\n * target's, because the right cache for a Lambda is not the right cache for a\n * box already running Postgres. With both answered elsewhere there was nothing\n * left for the block to say, so it is gone and these read the target.\n *\n * Mail has no answer here at all: every provider speaks SMTP, so the provider\n * is whichever one the stage's mail URL points at.\n */\n\nimport {\n\ttype CacheBackend,\n\tDEFAULT_CACHE,\n\tDEFAULT_EVENTS,\n\tDEFAULT_STORAGE,\n\ttype EventsBackend,\n\ttype MainProvider,\n\ttype StorageBackend,\n} from '../types.js';\n\n/**\n * Which family of defaults a workspace's deploy target belongs to.\n *\n * One question, asked once: **does this target run containers the project\n * controls?** Dokploy and a bare server do, so a bucket or a cache can live\n * beside the app; AWS, Vercel and Cloudflare do not, so the default has to be\n * something managed. That is the whole of the distinction, and it is why\n * `MainProvider` is the right axis rather than the deploy target's own name —\n * three targets share one answer.\n *\n * An AWS deploy names `deploy.default: 'sst'`, because it goes through SST.\n */\nexport function providerOf(workspace: {\n\tdeploy?: { default?: string } | undefined;\n}): MainProvider {\n\tconst target = workspace.deploy?.default;\n\n\treturn target === 'dokploy' || target === 'server' ? 'server' : 'aws';\n}\n\n/**\n * The cache backend a target implies.\n *\n * The same answer locally and deployed: a local `gkm dev` for an AWS app still\n * uses the Upstash protocol, because a backend that differed between the two\n * would be worse than a slower one.\n */\nexport function cacheBackendFor(on: MainProvider): CacheBackend {\n\treturn DEFAULT_CACHE[on];\n}\n\n/** Where a declared bucket lives on a target. */\nexport function storageBackendFor(on: MainProvider): StorageBackend {\n\treturn DEFAULT_STORAGE[on];\n}\n\n/**\n * Which broker carries declared queues and topics on a target.\n *\n * Only consulted when something declares one; a project with no `Topic` or\n * `Queue` has no events at all, whatever the target.\n */\nexport function eventsBackendFor(on: MainProvider): EventsBackend {\n\treturn DEFAULT_EVENTS[on];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,SAAgB,WAAW,WAEV;CAChB,MAAM,SAAS,UAAU,QAAQ;CAEjC,OAAO,WAAW,aAAa,WAAW,WAAW,WAAW;AACjE;;;;;;;;AASA,SAAgB,gBAAgB,IAAgC;CAC/D,OAAOA,cAAAA,cAAc;AACtB;;AAGA,SAAgB,kBAAkB,IAAkC;CACnE,OAAOC,cAAAA,gBAAgB;AACxB;;;;;;;AAQA,SAAgB,iBAAiB,IAAiC;CACjE,OAAOC,cAAAA,eAAe;AACvB"}
@@ -0,0 +1,59 @@
1
+ import { d as DEFAULT_EVENTS, f as DEFAULT_STORAGE, u as DEFAULT_CACHE } from "./ready-WfT-eWlm.mjs";
2
+ //#region src/workspace/backends.ts
3
+ /**
4
+ * Which backend each declared kind resolves to — decided by where the project
5
+ * deploys, and by nothing else.
6
+ *
7
+ * These used to be read out of a `services:` block, where one key answered two
8
+ * questions: *does this exist* and *what backs it*. The first is the manifest's
9
+ * — a declared `Cache` is why there is a cache — and the second is the deploy
10
+ * target's, because the right cache for a Lambda is not the right cache for a
11
+ * box already running Postgres. With both answered elsewhere there was nothing
12
+ * left for the block to say, so it is gone and these read the target.
13
+ *
14
+ * Mail has no answer here at all: every provider speaks SMTP, so the provider
15
+ * is whichever one the stage's mail URL points at.
16
+ */
17
+ /**
18
+ * Which family of defaults a workspace's deploy target belongs to.
19
+ *
20
+ * One question, asked once: **does this target run containers the project
21
+ * controls?** Dokploy and a bare server do, so a bucket or a cache can live
22
+ * beside the app; AWS, Vercel and Cloudflare do not, so the default has to be
23
+ * something managed. That is the whole of the distinction, and it is why
24
+ * `MainProvider` is the right axis rather than the deploy target's own name —
25
+ * three targets share one answer.
26
+ *
27
+ * An AWS deploy names `deploy.default: 'sst'`, because it goes through SST.
28
+ */
29
+ function providerOf(workspace) {
30
+ const target = workspace.deploy?.default;
31
+ return target === "dokploy" || target === "server" ? "server" : "aws";
32
+ }
33
+ /**
34
+ * The cache backend a target implies.
35
+ *
36
+ * The same answer locally and deployed: a local `gkm dev` for an AWS app still
37
+ * uses the Upstash protocol, because a backend that differed between the two
38
+ * would be worse than a slower one.
39
+ */
40
+ function cacheBackendFor(on) {
41
+ return DEFAULT_CACHE[on];
42
+ }
43
+ /** Where a declared bucket lives on a target. */
44
+ function storageBackendFor(on) {
45
+ return DEFAULT_STORAGE[on];
46
+ }
47
+ /**
48
+ * Which broker carries declared queues and topics on a target.
49
+ *
50
+ * Only consulted when something declares one; a project with no `Topic` or
51
+ * `Queue` has no events at all, whatever the target.
52
+ */
53
+ function eventsBackendFor(on) {
54
+ return DEFAULT_EVENTS[on];
55
+ }
56
+ //#endregion
57
+ export { storageBackendFor as i, eventsBackendFor as n, providerOf as r, cacheBackendFor as t };
58
+
59
+ //# sourceMappingURL=backends-CSuLl0YP.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backends-CSuLl0YP.mjs","names":[],"sources":["../src/workspace/backends.ts"],"sourcesContent":["/**\n * Which backend each declared kind resolves to — decided by where the project\n * deploys, and by nothing else.\n *\n * These used to be read out of a `services:` block, where one key answered two\n * questions: *does this exist* and *what backs it*. The first is the manifest's\n * — a declared `Cache` is why there is a cache — and the second is the deploy\n * target's, because the right cache for a Lambda is not the right cache for a\n * box already running Postgres. With both answered elsewhere there was nothing\n * left for the block to say, so it is gone and these read the target.\n *\n * Mail has no answer here at all: every provider speaks SMTP, so the provider\n * is whichever one the stage's mail URL points at.\n */\n\nimport {\n\ttype CacheBackend,\n\tDEFAULT_CACHE,\n\tDEFAULT_EVENTS,\n\tDEFAULT_STORAGE,\n\ttype EventsBackend,\n\ttype MainProvider,\n\ttype StorageBackend,\n} from '../types.js';\n\n/**\n * Which family of defaults a workspace's deploy target belongs to.\n *\n * One question, asked once: **does this target run containers the project\n * controls?** Dokploy and a bare server do, so a bucket or a cache can live\n * beside the app; AWS, Vercel and Cloudflare do not, so the default has to be\n * something managed. That is the whole of the distinction, and it is why\n * `MainProvider` is the right axis rather than the deploy target's own name —\n * three targets share one answer.\n *\n * An AWS deploy names `deploy.default: 'sst'`, because it goes through SST.\n */\nexport function providerOf(workspace: {\n\tdeploy?: { default?: string } | undefined;\n}): MainProvider {\n\tconst target = workspace.deploy?.default;\n\n\treturn target === 'dokploy' || target === 'server' ? 'server' : 'aws';\n}\n\n/**\n * The cache backend a target implies.\n *\n * The same answer locally and deployed: a local `gkm dev` for an AWS app still\n * uses the Upstash protocol, because a backend that differed between the two\n * would be worse than a slower one.\n */\nexport function cacheBackendFor(on: MainProvider): CacheBackend {\n\treturn DEFAULT_CACHE[on];\n}\n\n/** Where a declared bucket lives on a target. */\nexport function storageBackendFor(on: MainProvider): StorageBackend {\n\treturn DEFAULT_STORAGE[on];\n}\n\n/**\n * Which broker carries declared queues and topics on a target.\n *\n * Only consulted when something declares one; a project with no `Topic` or\n * `Queue` has no events at all, whatever the target.\n */\nexport function eventsBackendFor(on: MainProvider): EventsBackend {\n\treturn DEFAULT_EVENTS[on];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,SAAgB,WAAW,WAEV;CAChB,MAAM,SAAS,UAAU,QAAQ;CAEjC,OAAO,WAAW,aAAa,WAAW,WAAW,WAAW;AACjE;;;;;;;;AASA,SAAgB,gBAAgB,IAAgC;CAC/D,OAAO,cAAc;AACtB;;AAGA,SAAgB,kBAAkB,IAAkC;CACnE,OAAO,gBAAgB;AACxB;;;;;;;AAQA,SAAgB,iBAAiB,IAAiC;CACjE,OAAO,eAAe;AACvB"}
@@ -0,0 +1,91 @@
1
+ const require_config = require("./config-CsYSyUya.cjs");
2
+ const require_workspace = require("./workspace-DEibcoBe.cjs");
3
+ const require_storage = require("./storage-CSGoC3bK.cjs");
4
+ const require_store = require("./store-DQgxT_WR.cjs");
5
+ const require_backends = require("./backends-B9V2XD2M.cjs");
6
+ let _geekmidas_manifest = require("@geekmidas/manifest");
7
+ let _geekmidas_constructs_encryption = require("@geekmidas/constructs/encryption");
8
+ //#region src/encryption/index.ts
9
+ /**
10
+ * `gkm encryption:rotate` and `gkm encryption:retire` — the keyring of an
11
+ * `Encryption` construct on a server stage.
12
+ *
13
+ * Rotating adds a key in front and keeps every older one, so what they wrote
14
+ * still opens. Retiring removes one, and is the half that makes rotating worth
15
+ * doing: until a key is gone, it still opens everything it ever wrote. It is
16
+ * never automatic, because the only thing that knows nothing is left under a
17
+ * key is the sweep that re-encrypted the column — so it is done after one,
18
+ * deliberately, by name.
19
+ *
20
+ * Neither applies everywhere, and each says so rather than doing something
21
+ * that looks right: a local stage's keyring is derived and would be replaced on
22
+ * the next `gkm dev`, and on AWS the key is KMS's, which rotates it itself and
23
+ * never strands a value.
24
+ */
25
+ const logger = console;
26
+ var LocalKeyringIsDerived = class extends Error {
27
+ construct;
28
+ stage;
29
+ constructor(construct, stage) {
30
+ super(`'${stage}' is the local stage, where ${construct}'s keyring is derived from the project and stage — nothing stored there would be read. Rotate a deployed stage: gkm encryption:rotate ${construct} --stage <stage>.`);
31
+ this.construct = construct;
32
+ this.stage = stage;
33
+ this.name = "LocalKeyringIsDerived";
34
+ }
35
+ };
36
+ var KmsRotatesItself = class extends Error {
37
+ construct;
38
+ constructor(construct) {
39
+ super(`${construct} is a KMS key on AWS: KMS rotates it yearly and keeps every version, so no value is ever stranded and there is no key to retire. Nothing to do here.`);
40
+ this.construct = construct;
41
+ this.name = "KmsRotatesItself";
42
+ }
43
+ };
44
+ var NoKeyringYet = class extends Error {
45
+ construct;
46
+ stage;
47
+ key;
48
+ constructor(construct, stage, key) {
49
+ super(`'${stage}' has no ${key} yet. The first deploy generates ${construct}'s keyring: gkm deploy --stage ${stage}.`);
50
+ this.construct = construct;
51
+ this.stage = stage;
52
+ this.key = key;
53
+ this.name = "NoKeyringYet";
54
+ }
55
+ };
56
+ async function encryptionRotateCommand(construct, options, context = {}) {
57
+ return updateKeyring(construct, options, context, (id, url) => {
58
+ const next = (0, _geekmidas_constructs_encryption.rotateKeyring)(id, url);
59
+ const [current, ...older] = (0, _geekmidas_constructs_encryption.parseKeyring)(id, next).keys.map(({ id }) => id);
60
+ logger.log(`\n✓ ${id} on '${options.stage}' now writes with '${current}'.`);
61
+ logger.log(` Still opening: ${older.join(", ")}. Redeploy to start writing with '${current}', reencrypt what is stored, then: gkm encryption:retire ${id} <key> --stage ${options.stage}`);
62
+ return next;
63
+ });
64
+ }
65
+ async function encryptionRetireCommand(construct, keyId, options, context = {}) {
66
+ return updateKeyring(construct, options, context, (id, url) => {
67
+ const next = (0, _geekmidas_constructs_encryption.retireKey)(id, url, keyId);
68
+ logger.log(`\n✓ ${id} on '${options.stage}' no longer holds '${keyId}'. Anything still under it cannot be read after the next deploy.`);
69
+ return next;
70
+ });
71
+ }
72
+ async function updateKeyring(construct, { stage }, context, update) {
73
+ const workspace = context.workspace ?? await require_config.loadWorkspaceSettings();
74
+ const id = (0, _geekmidas_manifest.canonicalId)(construct);
75
+ if (stage === workspace.stages.local) throw new LocalKeyringIsDerived(id, stage);
76
+ require_workspace.assertDeployedStage(workspace.stages, stage);
77
+ if (require_backends.providerOf(workspace) === "aws") throw new KmsRotatesItself(id);
78
+ const store = context.store ?? await require_store.secretsStoreFor(workspace, stage);
79
+ const key = (0, _geekmidas_manifest.provideKey)(id, "url");
80
+ const secrets = await store.read(stage);
81
+ const url = secrets?.custom[key];
82
+ if (!secrets || !url) throw new NoKeyringYet(id, stage, key);
83
+ const next = update(id, url);
84
+ await store.write(stage, require_storage.withCustomSecret(secrets, key, next));
85
+ return next;
86
+ }
87
+ //#endregion
88
+ exports.encryptionRetireCommand = encryptionRetireCommand;
89
+ exports.encryptionRotateCommand = encryptionRotateCommand;
90
+
91
+ //# sourceMappingURL=encryption-C7OGMve_.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encryption-C7OGMve_.cjs","names":["rotateKeyring","parseKeyring","retireKey","loadWorkspaceSettings","canonicalId","providerOf","secretsStoreFor","provideKey","withCustomSecret"],"sources":["../src/encryption/index.ts"],"sourcesContent":["/**\n * `gkm encryption:rotate` and `gkm encryption:retire` — the keyring of an\n * `Encryption` construct on a server stage.\n *\n * Rotating adds a key in front and keeps every older one, so what they wrote\n * still opens. Retiring removes one, and is the half that makes rotating worth\n * doing: until a key is gone, it still opens everything it ever wrote. It is\n * never automatic, because the only thing that knows nothing is left under a\n * key is the sweep that re-encrypted the column — so it is done after one,\n * deliberately, by name.\n *\n * Neither applies everywhere, and each says so rather than doing something\n * that looks right: a local stage's keyring is derived and would be replaced on\n * the next `gkm dev`, and on AWS the key is KMS's, which rotates it itself and\n * never strands a value.\n */\n\nimport {\n\tparseKeyring,\n\tretireKey,\n\trotateKeyring,\n} from '@geekmidas/constructs/encryption';\nimport { canonicalId, provideKey } from '@geekmidas/manifest';\nimport { loadWorkspaceSettings } from '../config';\nimport { withCustomSecret } from '../secrets/storage.js';\nimport { type SecretsStore, secretsStoreFor } from '../secrets/store.js';\nimport { providerOf } from '../workspace/backends.js';\nimport { assertDeployedStage } from '../workspace/stages.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\n\nconst logger = console;\n\nexport class LocalKeyringIsDerived extends Error {\n\tconstructor(\n\t\treadonly construct: string,\n\t\treadonly stage: string,\n\t) {\n\t\tsuper(\n\t\t\t`'${stage}' is the local stage, where ${construct}'s keyring is derived from the project and stage — nothing stored there would be read. Rotate a deployed stage: gkm encryption:rotate ${construct} --stage <stage>.`,\n\t\t);\n\t\tthis.name = 'LocalKeyringIsDerived';\n\t}\n}\n\nexport class KmsRotatesItself extends Error {\n\tconstructor(readonly construct: string) {\n\t\tsuper(\n\t\t\t`${construct} is a KMS key on AWS: KMS rotates it yearly and keeps every version, so no value is ever stranded and there is no key to retire. Nothing to do here.`,\n\t\t);\n\t\tthis.name = 'KmsRotatesItself';\n\t}\n}\n\nexport class NoKeyringYet extends Error {\n\tconstructor(\n\t\treadonly construct: string,\n\t\treadonly stage: string,\n\t\treadonly key: string,\n\t) {\n\t\tsuper(\n\t\t\t`'${stage}' has no ${key} yet. The first deploy generates ${construct}'s keyring: gkm deploy --stage ${stage}.`,\n\t\t);\n\t\tthis.name = 'NoKeyringYet';\n\t}\n}\n\nexport interface EncryptionCommandOptions {\n\tstage: string;\n}\n\n/** Where a command reads and writes; the real ones unless a test says. */\nexport interface EncryptionCommandContext {\n\tworkspace?: NormalizedWorkspace;\n\tstore?: SecretsStore;\n}\n\nexport async function encryptionRotateCommand(\n\tconstruct: string,\n\toptions: EncryptionCommandOptions,\n\tcontext: EncryptionCommandContext = {},\n): Promise<string> {\n\treturn updateKeyring(construct, options, context, (id, url) => {\n\t\tconst next = rotateKeyring(id, url);\n\t\tconst [current, ...older] = parseKeyring(id, next).keys.map(({ id }) => id);\n\n\t\tlogger.log(`\\n✓ ${id} on '${options.stage}' now writes with '${current}'.`);\n\t\tlogger.log(\n\t\t\t` Still opening: ${older.join(', ')}. Redeploy to start writing with '${current}', reencrypt what is stored, then: gkm encryption:retire ${id} <key> --stage ${options.stage}`,\n\t\t);\n\t\treturn next;\n\t});\n}\n\nexport async function encryptionRetireCommand(\n\tconstruct: string,\n\tkeyId: string,\n\toptions: EncryptionCommandOptions,\n\tcontext: EncryptionCommandContext = {},\n): Promise<string> {\n\treturn updateKeyring(construct, options, context, (id, url) => {\n\t\tconst next = retireKey(id, url, keyId);\n\n\t\tlogger.log(\n\t\t\t`\\n✓ ${id} on '${options.stage}' no longer holds '${keyId}'. Anything still under it cannot be read after the next deploy.`,\n\t\t);\n\t\treturn next;\n\t});\n}\n\nasync function updateKeyring(\n\tconstruct: string,\n\t{ stage }: EncryptionCommandOptions,\n\tcontext: EncryptionCommandContext,\n\tupdate: (id: string, url: string) => string,\n): Promise<string> {\n\tconst workspace = context.workspace ?? (await loadWorkspaceSettings());\n\tconst id = canonicalId(construct);\n\n\tif (stage === workspace.stages.local) {\n\t\tthrow new LocalKeyringIsDerived(id, stage);\n\t}\n\tassertDeployedStage(workspace.stages, stage);\n\tif (providerOf(workspace) === 'aws') throw new KmsRotatesItself(id);\n\n\tconst store = context.store ?? (await secretsStoreFor(workspace, stage));\n\tconst key = provideKey(id, 'url');\n\tconst secrets = await store.read(stage);\n\tconst url = secrets?.custom[key];\n\tif (!secrets || !url) throw new NoKeyringYet(id, stage, key);\n\n\tconst next = update(id, url);\n\tawait store.write(stage, withCustomSecret(secrets, key, next));\n\treturn next;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,SAAS;AAEf,IAAa,wBAAb,cAA2C,MAAM;CAEtC;CACA;CAFV,YACC,WACA,OACC;EACD,MACC,IAAI,MAAM,8BAA8B,UAAU,wIAAwI,UAAU,kBACrM;EALS,KAAA,YAAA;EACA,KAAA,QAAA;EAKT,KAAK,OAAO;CACb;AACD;AAEA,IAAa,mBAAb,cAAsC,MAAM;CACtB;CAArB,YAAY,WAA4B;EACvC,MACC,GAAG,UAAU,qJACd;EAHoB,KAAA,YAAA;EAIpB,KAAK,OAAO;CACb;AACD;AAEA,IAAa,eAAb,cAAkC,MAAM;CAE7B;CACA;CACA;CAHV,YACC,WACA,OACA,KACC;EACD,MACC,IAAI,MAAM,WAAW,IAAI,mCAAmC,UAAU,iCAAiC,MAAM,EAC9G;EANS,KAAA,YAAA;EACA,KAAA,QAAA;EACA,KAAA,MAAA;EAKT,KAAK,OAAO;CACb;AACD;AAYA,eAAsB,wBACrB,WACA,SACA,UAAoC,CAAC,GACnB;CAClB,OAAO,cAAc,WAAW,SAAS,UAAU,IAAI,QAAQ;EAC9D,MAAM,QAAA,GAAOA,iCAAAA,cAAAA,CAAc,IAAI,GAAG;EAClC,MAAM,CAAC,SAAS,GAAG,UAAA,GAASC,iCAAAA,aAAAA,CAAa,IAAI,IAAI,CAAC,CAAC,KAAK,KAAK,EAAE,SAAS,EAAE;EAE1E,OAAO,IAAI,OAAO,GAAG,OAAO,QAAQ,MAAM,qBAAqB,QAAQ,GAAG;EAC1E,OAAO,IACN,oBAAoB,MAAM,KAAK,IAAI,EAAE,oCAAoC,QAAQ,2DAA2D,GAAG,iBAAiB,QAAQ,OACzK;EACA,OAAO;CACR,CAAC;AACF;AAEA,eAAsB,wBACrB,WACA,OACA,SACA,UAAoC,CAAC,GACnB;CAClB,OAAO,cAAc,WAAW,SAAS,UAAU,IAAI,QAAQ;EAC9D,MAAM,QAAA,GAAOC,iCAAAA,UAAAA,CAAU,IAAI,KAAK,KAAK;EAErC,OAAO,IACN,OAAO,GAAG,OAAO,QAAQ,MAAM,qBAAqB,MAAM,iEAC3D;EACA,OAAO;CACR,CAAC;AACF;AAEA,eAAe,cACd,WACA,EAAE,SACF,SACA,QACkB;CAClB,MAAM,YAAY,QAAQ,aAAc,MAAMC,eAAAA,sBAAsB;CACpE,MAAM,MAAA,GAAKC,oBAAAA,YAAAA,CAAY,SAAS;CAEhC,IAAI,UAAU,UAAU,OAAO,OAC9B,MAAM,IAAI,sBAAsB,IAAI,KAAK;CAE1C,kBAAA,oBAAoB,UAAU,QAAQ,KAAK;CAC3C,IAAIC,iBAAAA,WAAW,SAAS,MAAM,OAAO,MAAM,IAAI,iBAAiB,EAAE;CAElE,MAAM,QAAQ,QAAQ,SAAU,MAAMC,cAAAA,gBAAgB,WAAW,KAAK;CACtE,MAAM,OAAA,GAAMC,oBAAAA,WAAAA,CAAW,IAAI,KAAK;CAChC,MAAM,UAAU,MAAM,MAAM,KAAK,KAAK;CACtC,MAAM,MAAM,SAAS,OAAO;CAC5B,IAAI,CAAC,WAAW,CAAC,KAAK,MAAM,IAAI,aAAa,IAAI,OAAO,GAAG;CAE3D,MAAM,OAAO,OAAO,IAAI,GAAG;CAC3B,MAAM,MAAM,MAAM,OAAOC,gBAAAA,iBAAiB,SAAS,KAAK,IAAI,CAAC;CAC7D,OAAO;AACR"}
@@ -0,0 +1,90 @@
1
+ import { u as loadWorkspaceSettings } from "./config-D8J5rrTb.mjs";
2
+ import { D as assertDeployedStage } from "./workspace-DNzWgM1J.mjs";
3
+ import { a as withCustomSecret } from "./storage-BzaUxmqe.mjs";
4
+ import { n as secretsStoreFor } from "./store-DeGATCS-.mjs";
5
+ import { r as providerOf } from "./backends-CSuLl0YP.mjs";
6
+ import { canonicalId, provideKey } from "@geekmidas/manifest";
7
+ import { parseKeyring, retireKey, rotateKeyring } from "@geekmidas/constructs/encryption";
8
+ //#region src/encryption/index.ts
9
+ /**
10
+ * `gkm encryption:rotate` and `gkm encryption:retire` — the keyring of an
11
+ * `Encryption` construct on a server stage.
12
+ *
13
+ * Rotating adds a key in front and keeps every older one, so what they wrote
14
+ * still opens. Retiring removes one, and is the half that makes rotating worth
15
+ * doing: until a key is gone, it still opens everything it ever wrote. It is
16
+ * never automatic, because the only thing that knows nothing is left under a
17
+ * key is the sweep that re-encrypted the column — so it is done after one,
18
+ * deliberately, by name.
19
+ *
20
+ * Neither applies everywhere, and each says so rather than doing something
21
+ * that looks right: a local stage's keyring is derived and would be replaced on
22
+ * the next `gkm dev`, and on AWS the key is KMS's, which rotates it itself and
23
+ * never strands a value.
24
+ */
25
+ const logger = console;
26
+ var LocalKeyringIsDerived = class extends Error {
27
+ construct;
28
+ stage;
29
+ constructor(construct, stage) {
30
+ super(`'${stage}' is the local stage, where ${construct}'s keyring is derived from the project and stage — nothing stored there would be read. Rotate a deployed stage: gkm encryption:rotate ${construct} --stage <stage>.`);
31
+ this.construct = construct;
32
+ this.stage = stage;
33
+ this.name = "LocalKeyringIsDerived";
34
+ }
35
+ };
36
+ var KmsRotatesItself = class extends Error {
37
+ construct;
38
+ constructor(construct) {
39
+ super(`${construct} is a KMS key on AWS: KMS rotates it yearly and keeps every version, so no value is ever stranded and there is no key to retire. Nothing to do here.`);
40
+ this.construct = construct;
41
+ this.name = "KmsRotatesItself";
42
+ }
43
+ };
44
+ var NoKeyringYet = class extends Error {
45
+ construct;
46
+ stage;
47
+ key;
48
+ constructor(construct, stage, key) {
49
+ super(`'${stage}' has no ${key} yet. The first deploy generates ${construct}'s keyring: gkm deploy --stage ${stage}.`);
50
+ this.construct = construct;
51
+ this.stage = stage;
52
+ this.key = key;
53
+ this.name = "NoKeyringYet";
54
+ }
55
+ };
56
+ async function encryptionRotateCommand(construct, options, context = {}) {
57
+ return updateKeyring(construct, options, context, (id, url) => {
58
+ const next = rotateKeyring(id, url);
59
+ const [current, ...older] = parseKeyring(id, next).keys.map(({ id }) => id);
60
+ logger.log(`\n✓ ${id} on '${options.stage}' now writes with '${current}'.`);
61
+ logger.log(` Still opening: ${older.join(", ")}. Redeploy to start writing with '${current}', reencrypt what is stored, then: gkm encryption:retire ${id} <key> --stage ${options.stage}`);
62
+ return next;
63
+ });
64
+ }
65
+ async function encryptionRetireCommand(construct, keyId, options, context = {}) {
66
+ return updateKeyring(construct, options, context, (id, url) => {
67
+ const next = retireKey(id, url, keyId);
68
+ logger.log(`\n✓ ${id} on '${options.stage}' no longer holds '${keyId}'. Anything still under it cannot be read after the next deploy.`);
69
+ return next;
70
+ });
71
+ }
72
+ async function updateKeyring(construct, { stage }, context, update) {
73
+ const workspace = context.workspace ?? await loadWorkspaceSettings();
74
+ const id = canonicalId(construct);
75
+ if (stage === workspace.stages.local) throw new LocalKeyringIsDerived(id, stage);
76
+ assertDeployedStage(workspace.stages, stage);
77
+ if (providerOf(workspace) === "aws") throw new KmsRotatesItself(id);
78
+ const store = context.store ?? await secretsStoreFor(workspace, stage);
79
+ const key = provideKey(id, "url");
80
+ const secrets = await store.read(stage);
81
+ const url = secrets?.custom[key];
82
+ if (!secrets || !url) throw new NoKeyringYet(id, stage, key);
83
+ const next = update(id, url);
84
+ await store.write(stage, withCustomSecret(secrets, key, next));
85
+ return next;
86
+ }
87
+ //#endregion
88
+ export { encryptionRetireCommand, encryptionRotateCommand };
89
+
90
+ //# sourceMappingURL=encryption-DyQnPsZN.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encryption-DyQnPsZN.mjs","names":[],"sources":["../src/encryption/index.ts"],"sourcesContent":["/**\n * `gkm encryption:rotate` and `gkm encryption:retire` — the keyring of an\n * `Encryption` construct on a server stage.\n *\n * Rotating adds a key in front and keeps every older one, so what they wrote\n * still opens. Retiring removes one, and is the half that makes rotating worth\n * doing: until a key is gone, it still opens everything it ever wrote. It is\n * never automatic, because the only thing that knows nothing is left under a\n * key is the sweep that re-encrypted the column — so it is done after one,\n * deliberately, by name.\n *\n * Neither applies everywhere, and each says so rather than doing something\n * that looks right: a local stage's keyring is derived and would be replaced on\n * the next `gkm dev`, and on AWS the key is KMS's, which rotates it itself and\n * never strands a value.\n */\n\nimport {\n\tparseKeyring,\n\tretireKey,\n\trotateKeyring,\n} from '@geekmidas/constructs/encryption';\nimport { canonicalId, provideKey } from '@geekmidas/manifest';\nimport { loadWorkspaceSettings } from '../config';\nimport { withCustomSecret } from '../secrets/storage.js';\nimport { type SecretsStore, secretsStoreFor } from '../secrets/store.js';\nimport { providerOf } from '../workspace/backends.js';\nimport { assertDeployedStage } from '../workspace/stages.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\n\nconst logger = console;\n\nexport class LocalKeyringIsDerived extends Error {\n\tconstructor(\n\t\treadonly construct: string,\n\t\treadonly stage: string,\n\t) {\n\t\tsuper(\n\t\t\t`'${stage}' is the local stage, where ${construct}'s keyring is derived from the project and stage — nothing stored there would be read. Rotate a deployed stage: gkm encryption:rotate ${construct} --stage <stage>.`,\n\t\t);\n\t\tthis.name = 'LocalKeyringIsDerived';\n\t}\n}\n\nexport class KmsRotatesItself extends Error {\n\tconstructor(readonly construct: string) {\n\t\tsuper(\n\t\t\t`${construct} is a KMS key on AWS: KMS rotates it yearly and keeps every version, so no value is ever stranded and there is no key to retire. Nothing to do here.`,\n\t\t);\n\t\tthis.name = 'KmsRotatesItself';\n\t}\n}\n\nexport class NoKeyringYet extends Error {\n\tconstructor(\n\t\treadonly construct: string,\n\t\treadonly stage: string,\n\t\treadonly key: string,\n\t) {\n\t\tsuper(\n\t\t\t`'${stage}' has no ${key} yet. The first deploy generates ${construct}'s keyring: gkm deploy --stage ${stage}.`,\n\t\t);\n\t\tthis.name = 'NoKeyringYet';\n\t}\n}\n\nexport interface EncryptionCommandOptions {\n\tstage: string;\n}\n\n/** Where a command reads and writes; the real ones unless a test says. */\nexport interface EncryptionCommandContext {\n\tworkspace?: NormalizedWorkspace;\n\tstore?: SecretsStore;\n}\n\nexport async function encryptionRotateCommand(\n\tconstruct: string,\n\toptions: EncryptionCommandOptions,\n\tcontext: EncryptionCommandContext = {},\n): Promise<string> {\n\treturn updateKeyring(construct, options, context, (id, url) => {\n\t\tconst next = rotateKeyring(id, url);\n\t\tconst [current, ...older] = parseKeyring(id, next).keys.map(({ id }) => id);\n\n\t\tlogger.log(`\\n✓ ${id} on '${options.stage}' now writes with '${current}'.`);\n\t\tlogger.log(\n\t\t\t` Still opening: ${older.join(', ')}. Redeploy to start writing with '${current}', reencrypt what is stored, then: gkm encryption:retire ${id} <key> --stage ${options.stage}`,\n\t\t);\n\t\treturn next;\n\t});\n}\n\nexport async function encryptionRetireCommand(\n\tconstruct: string,\n\tkeyId: string,\n\toptions: EncryptionCommandOptions,\n\tcontext: EncryptionCommandContext = {},\n): Promise<string> {\n\treturn updateKeyring(construct, options, context, (id, url) => {\n\t\tconst next = retireKey(id, url, keyId);\n\n\t\tlogger.log(\n\t\t\t`\\n✓ ${id} on '${options.stage}' no longer holds '${keyId}'. Anything still under it cannot be read after the next deploy.`,\n\t\t);\n\t\treturn next;\n\t});\n}\n\nasync function updateKeyring(\n\tconstruct: string,\n\t{ stage }: EncryptionCommandOptions,\n\tcontext: EncryptionCommandContext,\n\tupdate: (id: string, url: string) => string,\n): Promise<string> {\n\tconst workspace = context.workspace ?? (await loadWorkspaceSettings());\n\tconst id = canonicalId(construct);\n\n\tif (stage === workspace.stages.local) {\n\t\tthrow new LocalKeyringIsDerived(id, stage);\n\t}\n\tassertDeployedStage(workspace.stages, stage);\n\tif (providerOf(workspace) === 'aws') throw new KmsRotatesItself(id);\n\n\tconst store = context.store ?? (await secretsStoreFor(workspace, stage));\n\tconst key = provideKey(id, 'url');\n\tconst secrets = await store.read(stage);\n\tconst url = secrets?.custom[key];\n\tif (!secrets || !url) throw new NoKeyringYet(id, stage, key);\n\n\tconst next = update(id, url);\n\tawait store.write(stage, withCustomSecret(secrets, key, next));\n\treturn next;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,SAAS;AAEf,IAAa,wBAAb,cAA2C,MAAM;CAEtC;CACA;CAFV,YACC,WACA,OACC;EACD,MACC,IAAI,MAAM,8BAA8B,UAAU,wIAAwI,UAAU,kBACrM;EALS,KAAA,YAAA;EACA,KAAA,QAAA;EAKT,KAAK,OAAO;CACb;AACD;AAEA,IAAa,mBAAb,cAAsC,MAAM;CACtB;CAArB,YAAY,WAA4B;EACvC,MACC,GAAG,UAAU,qJACd;EAHoB,KAAA,YAAA;EAIpB,KAAK,OAAO;CACb;AACD;AAEA,IAAa,eAAb,cAAkC,MAAM;CAE7B;CACA;CACA;CAHV,YACC,WACA,OACA,KACC;EACD,MACC,IAAI,MAAM,WAAW,IAAI,mCAAmC,UAAU,iCAAiC,MAAM,EAC9G;EANS,KAAA,YAAA;EACA,KAAA,QAAA;EACA,KAAA,MAAA;EAKT,KAAK,OAAO;CACb;AACD;AAYA,eAAsB,wBACrB,WACA,SACA,UAAoC,CAAC,GACnB;CAClB,OAAO,cAAc,WAAW,SAAS,UAAU,IAAI,QAAQ;EAC9D,MAAM,OAAO,cAAc,IAAI,GAAG;EAClC,MAAM,CAAC,SAAS,GAAG,SAAS,aAAa,IAAI,IAAI,CAAC,CAAC,KAAK,KAAK,EAAE,SAAS,EAAE;EAE1E,OAAO,IAAI,OAAO,GAAG,OAAO,QAAQ,MAAM,qBAAqB,QAAQ,GAAG;EAC1E,OAAO,IACN,oBAAoB,MAAM,KAAK,IAAI,EAAE,oCAAoC,QAAQ,2DAA2D,GAAG,iBAAiB,QAAQ,OACzK;EACA,OAAO;CACR,CAAC;AACF;AAEA,eAAsB,wBACrB,WACA,OACA,SACA,UAAoC,CAAC,GACnB;CAClB,OAAO,cAAc,WAAW,SAAS,UAAU,IAAI,QAAQ;EAC9D,MAAM,OAAO,UAAU,IAAI,KAAK,KAAK;EAErC,OAAO,IACN,OAAO,GAAG,OAAO,QAAQ,MAAM,qBAAqB,MAAM,iEAC3D;EACA,OAAO;CACR,CAAC;AACF;AAEA,eAAe,cACd,WACA,EAAE,SACF,SACA,QACkB;CAClB,MAAM,YAAY,QAAQ,aAAc,MAAM,sBAAsB;CACpE,MAAM,KAAK,YAAY,SAAS;CAEhC,IAAI,UAAU,UAAU,OAAO,OAC9B,MAAM,IAAI,sBAAsB,IAAI,KAAK;CAE1C,oBAAoB,UAAU,QAAQ,KAAK;CAC3C,IAAI,WAAW,SAAS,MAAM,OAAO,MAAM,IAAI,iBAAiB,EAAE;CAElE,MAAM,QAAQ,QAAQ,SAAU,MAAM,gBAAgB,WAAW,KAAK;CACtE,MAAM,MAAM,WAAW,IAAI,KAAK;CAChC,MAAM,UAAU,MAAM,MAAM,KAAK,KAAK;CACtC,MAAM,MAAM,SAAS,OAAO;CAC5B,IAAI,CAAC,WAAW,CAAC,KAAK,MAAM,IAAI,aAAa,IAAI,OAAO,GAAG;CAE3D,MAAM,OAAO,OAAO,IAAI,GAAG;CAC3B,MAAM,MAAM,MAAM,OAAO,iBAAiB,SAAS,KAAK,IAAI,CAAC;CAC7D,OAAO;AACR"}