@vendure/cloud-config 0.0.0

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 (70) hide show
  1. package/README.md +298 -0
  2. package/dist/cloud-config.d.ts +55 -0
  3. package/dist/cloud-config.d.ts.map +1 -0
  4. package/dist/cloud-config.js +2 -0
  5. package/dist/cloud-config.js.map +1 -0
  6. package/dist/cloud-dashboard-plugin.d.ts +28 -0
  7. package/dist/cloud-dashboard-plugin.d.ts.map +1 -0
  8. package/dist/cloud-dashboard-plugin.js +91 -0
  9. package/dist/cloud-dashboard-plugin.js.map +1 -0
  10. package/dist/cloud-plugin-declaration.d.ts +12 -0
  11. package/dist/cloud-plugin-declaration.d.ts.map +1 -0
  12. package/dist/cloud-plugin-declaration.js +53 -0
  13. package/dist/cloud-plugin-declaration.js.map +1 -0
  14. package/dist/composition.d.ts +23 -0
  15. package/dist/composition.d.ts.map +1 -0
  16. package/dist/composition.js +147 -0
  17. package/dist/composition.js.map +1 -0
  18. package/dist/define-cloud-config.d.ts +19 -0
  19. package/dist/define-cloud-config.d.ts.map +1 -0
  20. package/dist/define-cloud-config.js +47 -0
  21. package/dist/define-cloud-config.js.map +1 -0
  22. package/dist/errors.d.ts +4 -0
  23. package/dist/errors.d.ts.map +1 -0
  24. package/dist/errors.js +13 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/index.d.ts +15 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +14 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/migrations.d.ts +32 -0
  31. package/dist/migrations.d.ts.map +1 -0
  32. package/dist/migrations.js +250 -0
  33. package/dist/migrations.js.map +1 -0
  34. package/dist/outbound-hosts.d.ts +16 -0
  35. package/dist/outbound-hosts.d.ts.map +1 -0
  36. package/dist/outbound-hosts.js +211 -0
  37. package/dist/outbound-hosts.js.map +1 -0
  38. package/dist/path.d.ts +2 -0
  39. package/dist/path.d.ts.map +1 -0
  40. package/dist/path.js +18 -0
  41. package/dist/path.js.map +1 -0
  42. package/dist/platform-fields.d.ts +71 -0
  43. package/dist/platform-fields.d.ts.map +1 -0
  44. package/dist/platform-fields.js +94 -0
  45. package/dist/platform-fields.js.map +1 -0
  46. package/dist/plugin-attribution.d.ts +27 -0
  47. package/dist/plugin-attribution.d.ts.map +1 -0
  48. package/dist/plugin-attribution.js +97 -0
  49. package/dist/plugin-attribution.js.map +1 -0
  50. package/dist/runtime-backstop.d.ts +8 -0
  51. package/dist/runtime-backstop.d.ts.map +1 -0
  52. package/dist/runtime-backstop.js +20 -0
  53. package/dist/runtime-backstop.js.map +1 -0
  54. package/dist/secrets.d.ts +14 -0
  55. package/dist/secrets.d.ts.map +1 -0
  56. package/dist/secrets.js +109 -0
  57. package/dist/secrets.js.map +1 -0
  58. package/dist/stack.d.ts +3 -0
  59. package/dist/stack.d.ts.map +1 -0
  60. package/dist/stack.js +58 -0
  61. package/dist/stack.js.map +1 -0
  62. package/dist/superseded-plugins.d.ts +19 -0
  63. package/dist/superseded-plugins.d.ts.map +1 -0
  64. package/dist/superseded-plugins.js +41 -0
  65. package/dist/superseded-plugins.js.map +1 -0
  66. package/dist/vendure-extension.d.ts +38 -0
  67. package/dist/vendure-extension.d.ts.map +1 -0
  68. package/dist/vendure-extension.js +111 -0
  69. package/dist/vendure-extension.js.map +1 -0
  70. package/package.json +64 -0
package/README.md ADDED
@@ -0,0 +1,298 @@
1
+ # @vendure/cloud-config
2
+
3
+ The interface package a Vendure Cloud application depends on. It holds the Cloud Config
4
+ type and the checks that keep the ownership boundary honest, per
5
+ [ADR-0017](../../internal/adr/0017-cloud-config.md),
6
+ [ADR-0043](../../internal/adr/0043-cloud-config-composition-and-the-platform-entrypoint.md),
7
+ [ADR-0044](../../internal/adr/0044-which-vendure-plugins-the-platform-supplies.md) and
8
+ [ADR-0047](../../internal/adr/0047-vendure-extensions-are-declared-in-the-cloud-config.md).
9
+
10
+ A customer writes a configuration file and no entrypoint, importing from `@vendure/cloud`
11
+ rather than from here:
12
+
13
+ ```ts
14
+ import { defineCloudConfig, defineVendureExtension } from "@vendure/cloud";
15
+ import { DefaultSearchPlugin } from "@vendure/core";
16
+ import { ErpPlugin } from "./plugins/erp/erp.plugin.js";
17
+
18
+ export default defineCloudConfig({
19
+ plugins: [
20
+ DefaultSearchPlugin.init({ bufferUpdates: false }),
21
+ defineVendureExtension({
22
+ id: "acme.erp",
23
+ plugins: [ErpPlugin],
24
+ migrations: ["./migrations/*.js"],
25
+ outboundHosts: ["erp.acme.com"],
26
+ }),
27
+ ],
28
+ });
29
+ ```
30
+
31
+ ## Vendure Extensions
32
+
33
+ A **Vendure Extension** is a named group of the customer's own plugins carrying the three
34
+ pieces of metadata the platform reads
35
+ ([ADR-0047](../../internal/adr/0047-vendure-extensions-are-declared-in-the-cloud-config.md)).
36
+ It is written inline as above, or exported by a package and referenced by name; the wrapper
37
+ does not distinguish the two, and a third-party extension's author declares its metadata so a
38
+ consumer does not restate it. That ADR's table records why every other field the original
39
+ proposal carried was removed, and the input is a function argument so an object literal
40
+ reintroducing one fails the build.
41
+
42
+ `defineCloudConfig` flattens the extensions out of the plugins array before anything else
43
+ sees it, keeping declaration order, and records which extension declared each plugin.
44
+ `PlatformFieldSetByPluginError` reads that map, so a plugin inside an extension that writes a
45
+ platform-owned field is named together with the extension it came from. Everything
46
+ downstream — `hoistCloudPluginsLast`, `recordPlatformFieldWrites`, the two assertions —
47
+ operates on the flattened array and needed no change.
48
+
49
+ **A `migrations` glob resolves against the file that declared the extension**, not against
50
+ the configuration file that references it. `defineVendureExtension` reads its own call site
51
+ off the stack for this, which is the one piece of machinery here that is not obvious; the
52
+ reasoning, including why `import.meta.url` is not asked for and why the stack has to be read
53
+ through our own `Error.prepareStackTrace`, is at the function in `src/vendure-extension.ts`.
54
+ `test/managed-build.test.ts` proves it against compiled output laid out and run the way the
55
+ managed build produces it, because nothing about the trap survives being tested against this
56
+ package's own TypeScript sources.
57
+
58
+ ### Migrations are resolved into an ordered class list
59
+
60
+ A glob never reaches TypeORM. The config handle carries `loadMigrations()`, which expands each
61
+ extension's globs, imports what they match, and returns the migration classes with the
62
+ extension that declared each one:
63
+
64
+ ```ts
65
+ const { loadMigrations } = readCloudConfig(handle);
66
+ const loaded = await loadMigrations();
67
+ // loaded[n] is { migration, name, timestamp, file, extension }
68
+ // dbConnectionOptions.migrations = loaded.map((entry) => entry.migration)
69
+ ```
70
+
71
+ It is a function on the handle rather than a value on it, and it is bound to that handle's own
72
+ extensions rather than callable with any array. ADR-0048's "Ordering is a property of the array
73
+ we build" argues both, and is the place to change if either stops being true.
74
+
75
+ The order is **ascending timestamp, then extension declaration order, then class name.**
76
+ TypeORM sorts the set by timestamp and `Array.prototype.sort` is stable, so equal timestamps
77
+ run in whatever order the array holds them; today that order comes from `glob.sync`, which
78
+ does not sort, so a tie resolves by filesystem walk order and can differ between the
79
+ customer's machine and the managed build. The last two keys make the tie a value the platform
80
+ computed. **Ordering across extensions is not a contract**
81
+ ([ADR-0048](../../internal/adr/0048-extension-migrations-keep-typeorms-ledger-identity.md)):
82
+ an extension cannot declare that it must migrate after another, and nothing here adds a way
83
+ to say so.
84
+
85
+ The ledger identity is TypeORM's own — the migration class name, read off an instance so that
86
+ a migration declaring `name` as an instance field is called here what it is called in the
87
+ ledger. A glob that contributes no migrations raises `MigrationGlobMatchedNoMigrationsError`
88
+ naming the extension and the glob as it was written. It distinguishes a glob that matched
89
+ nothing at all, which is far more often a wrong path than an extension with no migrations,
90
+ from one whose every match was filtered out as not being a migration file.
91
+
92
+ ## Secrets
93
+
94
+ `secret('NAME')` reads a customer-supplied value, registers the name, and returns a plain
95
+ string. Values arrive as ordinary environment variables (ADR-0030), so this is a read helper
96
+ over `process.env` rather than a second delivery mechanism.
97
+
98
+ ```ts
99
+ export default defineCloudConfig({
100
+ plugins: [
101
+ PaymentPlugin.init({ apiKey: secret("STRIPE_SECRET_KEY") }),
102
+ ],
103
+ });
104
+ ```
105
+
106
+ It exists because `process.env` gives the platform no hook. Three things follow from the call
107
+ that a direct read cannot provide:
108
+
109
+ - **Every missing name is reported at once.** A name that is unset — or set to an empty or
110
+ whitespace-only value, which counts as unset because an empty credential fails inside a
111
+ payment call rather than at boot — is recorded rather than thrown on. `defineCloudConfig`
112
+ then raises `MissingSecretsError` naming all of them, so a configuration with four unset
113
+ secrets takes one deploy to fix rather than four.
114
+ - **The value is trimmed**, so a credential that picked up a trailing newline from a
115
+ file-based secret store or a `.env` loader does not reach the caller intact and fail in the
116
+ same place an empty one would. Only the ends: a multi-line value such as a PEM key keeps its
117
+ interior exactly, per ADR-0030's note that customers put private keys in these variables.
118
+ - **The declared set is exactly what the code asked for.** Registration is a side effect of
119
+ the call, so it cannot drift from the code the way a hand-written `requirements.secrets`
120
+ list would. `listDeclaredSecrets()` is the entrypoint's accessor after composition.
121
+ - **The value can be redacted.** `redactSecrets(text)` replaces every resolved value wherever
122
+ it appears. A value read straight out of `process.env` is an ordinary string that nothing
123
+ downstream can recognise.
124
+
125
+ **The argument has to be a string literal**, enforced by the type rather than by a lint rule.
126
+ Passing a variable makes the parameter type `never` and fails the build. A literal is what
127
+ makes the declared set readable by static analysis, and a type constraint needs no tooling in
128
+ the customer's project.
129
+
130
+ ### Reading a secret at request time is not supported
131
+
132
+ `secret()` resolves once, while the configuration object is being built. A call made later —
133
+ inside a request handler, a job processor, or a lazily constructed client — happens after
134
+ `defineCloudConfig` has already checked the registry, so a missing value is not reported at
135
+ boot and is not part of the declared set.
136
+
137
+ The answer is to read the secret during composition and hold it, which is the natural shape
138
+ when secrets are plugin options:
139
+
140
+ ```ts
141
+ // Yes: resolved once, declared, redactable.
142
+ PaymentPlugin.init({ apiKey: secret("STRIPE_SECRET_KEY") })
143
+
144
+ // No: resolved per request, invisible to the missing-secret report.
145
+ class PaymentService {
146
+ charge() {
147
+ const key = secret("STRIPE_SECRET_KEY");
148
+ }
149
+ }
150
+ ```
151
+
152
+ A plugin that genuinely needs the value later should take it as an option and keep it, rather
153
+ than reaching for it at the point of use.
154
+
155
+ ## Declared outbound hosts
156
+
157
+ A Vendure Extension declares the hosts it talks to, and `installOutboundHostCheck` reports a
158
+ call to a host it did not declare, naming the extension
159
+ ([ADR-0028's amendment](../../internal/adr/0028-cell-network-topology.md)).
160
+
161
+ ```
162
+ Vendure Cloud: Extension acme.erp attempted outbound access to api.other-erp.example.
163
+ Declared outbound hosts: erp.acme.com
164
+ ```
165
+
166
+ The check runs inside the customer's own process rather than in the network path, and
167
+ attribution is the reason. A firewall sees a source address and a TLS server name and cannot
168
+ say which extension made the call, so it cannot produce that message. Reading the stack can.
169
+
170
+ **It is reported and never blocked** (CLO-412 records the reasoning). This is a hygiene
171
+ control over trusted code, not a security boundary — code written to bypass it will succeed,
172
+ and a compromised dependency can exfiltrate through a *declared* host anyway. So blocking
173
+ stops no attacker, and everything it would stop is an honest extension whose declaration is
174
+ incomplete. Escalating to a block is left available and would need its own stated, announced
175
+ decision, the same condition ADR-0045 put on its own advisory.
176
+
177
+ **An extension that declares no hosts is not checked.** The declaration is the opt-in. Reading
178
+ "declared nothing" as "may reach nothing" would report against every extension in existence
179
+ today, and a report that fires on everything is not read. Note that `defineVendureExtension`
180
+ normalises an absent `outboundHosts` and an explicit `[]` to the same empty array, so
181
+ "deliberately talks to nothing" cannot currently be expressed distinctly from "did not say".
182
+
183
+ **A call the stack attributes to no extension is not checked either.** Vendure core's own
184
+ traffic, the database driver's, and anything reached from platform code land there, and
185
+ reporting them would drown the signal.
186
+
187
+ That is also the one real limit of reading the stack, and it is about where the code is rather
188
+ than about async boundaries. Attribution needs a frame belonging to the extension somewhere on
189
+ the stack when the socket opens. An extension that supplies a host as *data* and lets other
190
+ code dial it has no such frame, and that call is dropped. Crossing a timer, an await, or a
191
+ helper the extension did not write does not cause this — the extension's own frame is still
192
+ further down the same stack, and the suite covers all three.
193
+
194
+ ### What it costs, and where it is imprecise
195
+
196
+ An allowed call costs one `Set` lookup. The host is compared against the union of every
197
+ declared host first, and only a host that appears in none of them is attributed, because
198
+ capturing a stack is the expensive part. The cost of that ordering is that an extension
199
+ reaching a host *another* extension declared is not reported.
200
+
201
+ Interception is `globalThis.fetch` plus `net.Socket.prototype.connect`. The socket is where
202
+ `http.request`, `https.request`, `net.connect` and every client library end up, and — unlike
203
+ replacing `net.connect` on the module object — it behaves the same whether the caller is ESM
204
+ or CommonJS. An ES module's named import is a snapshot taken at link time, so rewriting the
205
+ module object reaches CommonJS callers only, which would be the same control behaving
206
+ differently in the two module systems.
207
+
208
+ Each extension and host pair is reported once per process. An extension polling an undeclared
209
+ host every second has one thing wrong with it, and the same interception seeing it at both
210
+ `fetch` and the socket underneath is not two mistakes.
211
+
212
+ ## The boundary, and where each half is enforced
213
+
214
+ A **Cloud Plugin** is a plugin Vendure Cloud supplies in place of one the customer would
215
+ otherwise declare — `CloudAssetServerPlugin` for `AssetServerPlugin`, and the three ADR-0044
216
+ lists as injected. The term is deliberately not "platform plugin", which reads as a plugin
217
+ belonging to Vendure Platform.
218
+
219
+ `PLATFORM_OWNED_FIELDS` is the single source for all four checks below, so they cannot
220
+ disagree about which `VendureConfig` fields Vendure Cloud owns.
221
+
222
+ | Check | Runs at | Catches |
223
+ | --- | --- | --- |
224
+ | The branded Cloud Config type | build | a config literal setting a platform-owned field |
225
+ | `listPlatformOwnedFieldsSetIn` | boot | a config assembled programmatically, past the type |
226
+ | `assertPlatformFieldsHold` | boot, after composition | a plugin that rewrote a platform-owned value after the Cloud Plugin ran |
227
+ | `assertNoCustomerPluginWroteAPlatformField` | boot, after composition | ADR-0044's converse check — a customer plugin whose write a Cloud Plugin overwrote |
228
+
229
+ Platform-owned keys stay *present* in the type carrying a brand that explains itself,
230
+ rather than being removed with `Omit`. ADR-0043 requires the build-time error to carry a
231
+ message we wrote, and an omitted key yields TypeScript's own wording instead. The brand's
232
+ text is derived from `PLATFORM_OWNED_FIELDS`, so the compile-time and runtime messages are
233
+ the same string.
234
+
235
+ ## Three things worth knowing before changing this package
236
+
237
+ **A customer installs `@vendure/cloud` and imports from it, not from here.**
238
+ [ADR-0045](../../internal/adr/0045-cloud-ships-as-ordinary-npm-packages-the-customer-pins.md)
239
+ makes that package a facade whose exact-pinned dependencies are this package and the
240
+ separately published plugin packages. What it re-exports today and what is still to join it
241
+ is in [`packages/cloud/README.md`](../cloud/README.md).
242
+
243
+ **This package is a peer dependency of every plugin package, and a direct dependency of
244
+ nothing but the facade.** That is what stops a customer's tree holding two copies of it. Two
245
+ copies mean `instanceof CloudConfigError` stops holding across the seam, and a boot failure a
246
+ caller catches becomes an uncaught one — ADR-0045 argues the case, and the peer dependency is
247
+ what turns it from a silent boot failure into an install-time resolution error naming both
248
+ versions. Importing this package directly still works and is supported; it is what a plugin
249
+ package does.
250
+
251
+ **Nothing published is bundled or minified**, which is a decision rather than a property of
252
+ how the build happens to be written. A bundler is the route back to a second copy of
253
+ `@vendure/core`, and a minifier rewrites the class names that `CloudConfigError` and
254
+ `pluginName` read at runtime to build the messages ADR-0044 requires. `tsc` can do neither,
255
+ and `packages/cloud/test/published-output.test.ts` builds every publishable package and
256
+ asserts it: one emitted file per source file, every dependency still a bare import, and every
257
+ exported class still carrying its own name.
258
+
259
+ Read ADR-0045's packaging decision only. Its delivery decision — that the customer pins these
260
+ packages in their own lockfile and the platform reports a vulnerable version rather than
261
+ replacing it — is superseded by
262
+ [ADR-0046](../../internal/adr/0046-host-packages-are-dev-dependencies-and-the-runtime-supplies-production-copies.md).
263
+ Customers declare these as development dependencies and the Cloud Runtime supplies the
264
+ production copies, resolved from the `@vendure/core` version they declared.
265
+
266
+ **It has to stay loadable from CommonJS, and that constrains the code.**
267
+ [ADR-0049](../../internal/adr/0049-the-cloud-config-packages-are-consumable-from-commonjs.md):
268
+ this package emits ESM and lists `require` alongside `import` in its `exports` map, pointing at
269
+ the same file, so a customer whose application emits CommonJS can load it through Node's
270
+ `require(esm)`. Vendure's own application template emits CommonJS, so that is most customers
271
+ arriving from a self-hosted store.
272
+
273
+ The standing cost is that **no top-level await may appear anywhere in this package's module
274
+ graph**, ever. `require(esm)` refuses a graph containing one, at runtime in the customer's
275
+ container, and nothing here would notice: every suite in this repository loads the package as
276
+ ESM, where top-level await is legal. `test/managed-build.test.ts` builds and runs its fixture
277
+ in both module systems, which is what catches it.
278
+
279
+ **No runtime dependency on `@vendure/core`.** `@vendure/core` is a peer dependency and is
280
+ imported for types only. The plugin metadata key core reads is restated as a constant and
281
+ pinned to core's real value by a test, so a rename there fails our build rather than
282
+ silently disabling attribution.
283
+
284
+ ## Runtime implementation
285
+
286
+ CLO-355 supplies the platform-owned server, worker and migrate entrypoints, managed Postgres
287
+ connection with rotating IAM credentials, structured logger, default cache/job queue/scheduler,
288
+ shallow health check, one-copy core guard and local substitutes. The managed build typechecks the
289
+ Cloud Config and installs the private implementation beside the single supplied copy of
290
+ `@vendure/core`.
291
+
292
+ The four wrapper plugins remain separate delivery work: CLO-399, CLO-400, CLO-401 and CLO-402.
293
+ Extension migration globs are resolved into the managed database configuration at boot. The
294
+ ownership snapshot on the Deployment row and the migration transaction, timeout and
295
+ orphaned-schema controls remain CLO-423 and CLO-424.
296
+
297
+ `apps/demo-store` is the reference Cloud Config: it contains only `vendure-config.ts`, with no
298
+ customer-owned run-mode entrypoints.
@@ -0,0 +1,55 @@
1
+ import type { VendureConfig } from "@vendure/core";
2
+ import type { PlatformOwnedFieldPath, PlatformOwnedFieldSpec } from "./platform-fields.js";
3
+ import type { CloudPluginEntry, VendurePluginEntry } from "./vendure-extension.js";
4
+ declare const platformOwnedBrand: unique symbol;
5
+ export type PlatformOwned<Explanation extends string> = {
6
+ readonly [platformOwnedBrand]: Explanation;
7
+ };
8
+ type ReasonFor<Path extends PlatformOwnedFieldPath> = Extract<PlatformOwnedFieldSpec, {
9
+ path: Path;
10
+ }>["reason"];
11
+ type ApiOptions = VendureConfig["apiOptions"];
12
+ type AuthOptions = VendureConfig["authOptions"];
13
+ type AssetOptions = NonNullable<VendureConfig["assetOptions"]>;
14
+ type SystemOptions = NonNullable<VendureConfig["systemOptions"]>;
15
+ type JobQueueOptions = NonNullable<VendureConfig["jobQueueOptions"]>;
16
+ type SchedulerOptions = NonNullable<VendureConfig["schedulerOptions"]>;
17
+ export type CloudApiOptions = Omit<ApiOptions, "port" | "hostname"> & {
18
+ port?: PlatformOwned<ReasonFor<"apiOptions.port">>;
19
+ hostname?: PlatformOwned<ReasonFor<"apiOptions.hostname">>;
20
+ };
21
+ export type CloudAuthOptions = Omit<AuthOptions, "superadminCredentials" | "sessionCacheStrategy" | "sessionCacheTTL"> & {
22
+ superadminCredentials?: PlatformOwned<ReasonFor<"authOptions.superadminCredentials">>;
23
+ sessionCacheStrategy?: PlatformOwned<ReasonFor<"authOptions.sessionCacheStrategy">>;
24
+ sessionCacheTTL?: PlatformOwned<ReasonFor<"authOptions.sessionCacheTTL">>;
25
+ };
26
+ export type CloudAssetOptions = Omit<AssetOptions, "assetStorageStrategy"> & {
27
+ assetStorageStrategy?: PlatformOwned<ReasonFor<"assetOptions.assetStorageStrategy">>;
28
+ };
29
+ export type CloudSystemOptions = Omit<SystemOptions, "cacheStrategy" | "healthChecks"> & {
30
+ cacheStrategy?: PlatformOwned<ReasonFor<"systemOptions.cacheStrategy">>;
31
+ healthChecks?: PlatformOwned<ReasonFor<"systemOptions.healthChecks">>;
32
+ };
33
+ export type CloudJobQueueOptions = Omit<JobQueueOptions, "jobQueueStrategy"> & {
34
+ jobQueueStrategy?: PlatformOwned<ReasonFor<"jobQueueOptions.jobQueueStrategy">>;
35
+ };
36
+ export type CloudSchedulerOptions = Omit<SchedulerOptions, "schedulerStrategy" | "runTasksInWorkerOnly"> & {
37
+ schedulerStrategy?: PlatformOwned<ReasonFor<"schedulerOptions.schedulerStrategy">>;
38
+ runTasksInWorkerOnly?: PlatformOwned<ReasonFor<"schedulerOptions.runTasksInWorkerOnly">>;
39
+ };
40
+ export type CloudConfig = Partial<Omit<VendureConfig, "plugins" | "dbConnectionOptions" | "logger" | "apiOptions" | "authOptions" | "assetOptions" | "systemOptions" | "jobQueueOptions" | "schedulerOptions">> & {
41
+ plugins?: CloudPluginEntry[];
42
+ dbConnectionOptions?: PlatformOwned<ReasonFor<"dbConnectionOptions">>;
43
+ logger?: PlatformOwned<ReasonFor<"logger">>;
44
+ apiOptions?: CloudApiOptions;
45
+ authOptions?: CloudAuthOptions;
46
+ assetOptions?: CloudAssetOptions;
47
+ systemOptions?: CloudSystemOptions;
48
+ jobQueueOptions?: CloudJobQueueOptions;
49
+ schedulerOptions?: CloudSchedulerOptions;
50
+ };
51
+ export type FlattenedCloudConfig = Omit<CloudConfig, "plugins"> & {
52
+ plugins: VendurePluginEntry[];
53
+ };
54
+ export {};
55
+ //# sourceMappingURL=cloud-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-config.d.ts","sourceRoot":"","sources":["../src/cloud-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cloud-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-config.js","sourceRoot":"","sources":["../src/cloud-config.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import type { FlattenedCloudConfig, PlatformOwned } from "./cloud-config.js";
2
+ import { CloudConfigError } from "./errors.js";
3
+ import type { VendurePluginEntry } from "./vendure-extension.js";
4
+ export declare const CLOUD_DASHBOARD_PLUGIN_KIND = "dashboard";
5
+ export declare const DEFAULT_DASHBOARD_ROUTE = "dashboard";
6
+ export declare const PLATFORM_SUPPLIED_DASHBOARD_OPTIONS: {
7
+ readonly appDir: "The Dashboard's files are produced by the managed build, and Vendure Cloud tells the plugin where they are. A path set here would not exist in the runtime image. Remove appDir.";
8
+ readonly viteDevServerPort: "The Vite dev server does not run in a Vendure Cloud process, so there is nothing to probe for and no request is proxied to it. Remove viteDevServerPort. It still applies when you run the same configuration locally.";
9
+ };
10
+ export interface CloudDashboardPluginOptions {
11
+ route?: string;
12
+ appDir?: PlatformOwned<(typeof PLATFORM_SUPPLIED_DASHBOARD_OPTIONS)["appDir"]>;
13
+ viteDevServerPort?: PlatformOwned<(typeof PLATFORM_SUPPLIED_DASHBOARD_OPTIONS)["viteDevServerPort"]>;
14
+ }
15
+ export interface CloudDashboardSettings {
16
+ route: string;
17
+ }
18
+ export declare class InvalidDashboardRouteError extends CloudConfigError {
19
+ readonly route: string;
20
+ constructor(route: string, reason: string);
21
+ }
22
+ export declare const CloudDashboardPlugin: {
23
+ new (): {};
24
+ } & {
25
+ init(options?: CloudDashboardPluginOptions): VendurePluginEntry;
26
+ };
27
+ export declare function resolveDashboardSettings(config: FlattenedCloudConfig): CloudDashboardSettings;
28
+ //# sourceMappingURL=cloud-dashboard-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-dashboard-plugin.d.ts","sourceRoot":"","sources":["../src/cloud-dashboard-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAOjE,eAAO,MAAM,2BAA2B,cAAc,CAAC;AAIvD,eAAO,MAAM,uBAAuB,cAAc,CAAC;AAMnD,eAAO,MAAM,mCAAmC;;;CAKtC,CAAC;AAEX,MAAM,WAAW,2BAA2B;IAG1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,OAAO,mCAAmC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/E,iBAAiB,CAAC,EAAE,aAAa,CAC/B,CAAC,OAAO,mCAAmC,CAAC,CAAC,mBAAmB,CAAC,CAClE,CAAC;CACH;AAID,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;CACf;AAeD,qBAAa,0BAA2B,SAAQ,gBAAgB;IAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAM1C;AAsBD,eAAO,MAAM,oBAAoB;;;mBAOf,2BAA2B,GAAQ,kBAAkB;CAUtE,CAAC;AAaF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,GAAG,sBAAsB,CAS7F"}
@@ -0,0 +1,91 @@
1
+ import { declareCloudPlugin, listCloudPluginDeclarations } from "./cloud-plugin-declaration.js";
2
+ import { CloudConfigError } from "./errors.js";
3
+ // ADR-0044 rules `DashboardPlugin` platform-supplied and wrapped, with `route` the only option the
4
+ // customer keeps. This is the wrapper's declaration side: what a customer writes in their
5
+ // configuration file. The plugin that serves the Dashboard is built by the platform runtime, which
6
+ // is the only place that knows where the managed build put the Dashboard's files.
7
+ export const CLOUD_DASHBOARD_PLUGIN_KIND = "dashboard";
8
+ // The same default the upstream plugin documents, so a customer moving an existing store onto
9
+ // Vendure Cloud finds the Dashboard where they left it.
10
+ export const DEFAULT_DASHBOARD_ROUTE = "dashboard";
11
+ // The two options that leave the type, with the explanation each one's build-time error carries.
12
+ // Written as literals rather than assembled, for the reason `platform-fields.ts` records: the
13
+ // explanation is what TypeScript prints when the field is set, so it is the message and not a key
14
+ // into one.
15
+ export const PLATFORM_SUPPLIED_DASHBOARD_OPTIONS = {
16
+ appDir: "The Dashboard's files are produced by the managed build, and Vendure Cloud tells the plugin where they are. A path set here would not exist in the runtime image. Remove appDir.",
17
+ viteDevServerPort: "The Vite dev server does not run in a Vendure Cloud process, so there is nothing to probe for and no request is proxied to it. Remove viteDevServerPort. It still applies when you run the same configuration locally.",
18
+ };
19
+ const DEFAULT_DASHBOARD_SETTINGS = { route: DEFAULT_DASHBOARD_ROUTE };
20
+ // The route is one path segment. Nest mounts the Dashboard's middleware at it, and the Dashboard's
21
+ // own `index.html` carries it as a `<base>` tag, so a value with a slash in it produces a mount
22
+ // path and a base tag that disagree and a Dashboard that loads nothing. Starting at a letter or a
23
+ // digit rules out `.` and `..`, which resolve to somewhere else again.
24
+ const ROUTE_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._~-]*$/;
25
+ // Vendure's own defaults for the two API paths, restated because a Cloud Config that sets neither
26
+ // still serves them there and this check runs before core has filled them in.
27
+ const DEFAULT_ADMIN_API_PATH = "admin-api";
28
+ const DEFAULT_SHOP_API_PATH = "shop-api";
29
+ export class InvalidDashboardRouteError extends CloudConfigError {
30
+ route;
31
+ constructor(route, reason) {
32
+ super(`Vendure Cloud: the Dashboard cannot be served at "${route}".\n ${reason}\n Give CloudDashboardPlugin one path segment, such as { route: "${DEFAULT_DASHBOARD_ROUTE}" }.\n`);
33
+ this.route = route;
34
+ }
35
+ }
36
+ // Runs where the customer wrote the route, so the message arrives before anything is deployed.
37
+ // Nothing in the type system can reach this: `route` is an ordinary string and the values it
38
+ // rejects are ordinary strings too.
39
+ function assertRouteShape(route) {
40
+ if (route.length === 0) {
41
+ throw new InvalidDashboardRouteError(route, "The route is empty.");
42
+ }
43
+ if (!ROUTE_PATTERN.test(route)) {
44
+ throw new InvalidDashboardRouteError(route, "A route is one path segment: letters, digits, and then any of . _ ~ - after the first character. Slashes, spaces and a leading dot are not part of one.");
45
+ }
46
+ }
47
+ // A class carrying the default declaration, with `init` on it. A customer who moves the Dashboard
48
+ // writes `CloudDashboardPlugin.init({ route })`; one who wants the default route but wants the
49
+ // Dashboard visible in their file can write a bare `CloudDashboardPlugin`. The second is
50
+ // redundant, because the platform injects the default declaration when the customer writes
51
+ // neither, and it is supported so that writing it is not read as a plugin nobody recognises.
52
+ export const CloudDashboardPlugin = Object.assign(declareCloudPlugin("CloudDashboardPlugin", CLOUD_DASHBOARD_PLUGIN_KIND, DEFAULT_DASHBOARD_SETTINGS), {
53
+ init(options = {}) {
54
+ const route = options.route ?? DEFAULT_DASHBOARD_ROUTE;
55
+ assertRouteShape(route);
56
+ return declareCloudPlugin("CloudDashboardPlugin", CLOUD_DASHBOARD_PLUGIN_KIND, { route });
57
+ },
58
+ });
59
+ // ADR-0044's rule that a wrapped plugin the customer declared replaces the platform's injected
60
+ // default rather than joining it: the customer's declaration when there is one, the default when
61
+ // there is not, and never both.
62
+ //
63
+ // A configuration declaring it more than once takes the last, which is what the upstream plugin's
64
+ // static options do and therefore what a customer who has met that plugin expects. ADR-0044 calls a
65
+ // double declaration a documentation problem rather than something to defend against, so this
66
+ // resolves it quietly rather than refusing the boot over it.
67
+ //
68
+ // It takes the whole configuration rather than the plugins array, because the route has to be
69
+ // checked against the paths the customer's own API options claim.
70
+ export function resolveDashboardSettings(config) {
71
+ const declarations = listCloudPluginDeclarations(config.plugins, CLOUD_DASHBOARD_PLUGIN_KIND);
72
+ const settings = declarations[declarations.length - 1] ?? { options: DEFAULT_DASHBOARD_SETTINGS };
73
+ assertRouteShape(settings.options.route);
74
+ assertRouteIsFree(settings.options.route, config);
75
+ return settings.options;
76
+ }
77
+ // A route matching an API path is served by whichever of the two Nest matches first, so the
78
+ // customer loses one of them with nothing said. Checked here rather than in `init`, because it is
79
+ // the only point at which the route and the API paths are both known.
80
+ function assertRouteIsFree(route, config) {
81
+ const claimed = [
82
+ ["the Admin API", config.apiOptions?.adminApiPath ?? DEFAULT_ADMIN_API_PATH],
83
+ ["the Shop API", config.apiOptions?.shopApiPath ?? DEFAULT_SHOP_API_PATH],
84
+ ];
85
+ for (const [what, path] of claimed) {
86
+ if (path === route) {
87
+ throw new InvalidDashboardRouteError(route, `${what} is served at the same path. Move one of the two.`);
88
+ }
89
+ }
90
+ }
91
+ //# sourceMappingURL=cloud-dashboard-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-dashboard-plugin.js","sourceRoot":"","sources":["../src/cloud-dashboard-plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { PluginLike } from "./plugin-attribution.js";
2
+ export interface CloudPluginDeclaration<Options = unknown> {
3
+ readonly kind: string;
4
+ readonly options: Options;
5
+ }
6
+ export declare function declareCloudPlugin<Options>(name: string, kind: string, options: Options): {
7
+ new (): {};
8
+ };
9
+ export declare function readCloudPluginDeclaration(entry: unknown): CloudPluginDeclaration | undefined;
10
+ export declare function isCloudPluginDeclaration(entry: unknown): boolean;
11
+ export declare function listCloudPluginDeclarations<Options>(plugins: readonly PluginLike[], kind: string): CloudPluginDeclaration<Options>[];
12
+ //# sourceMappingURL=cloud-plugin-declaration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-plugin-declaration.d.ts","sourceRoot":"","sources":["../src/cloud-plugin-declaration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAkB1D,MAAM,WAAW,sBAAsB,CAAC,OAAO,GAAG,OAAO;IAGvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAMD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;;EAWvF;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,GAAG,SAAS,CAK7F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEhE;AAKD,wBAAgB,2BAA2B,CAAC,OAAO,EACjD,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,IAAI,EAAE,MAAM,GACX,sBAAsB,CAAC,OAAO,CAAC,EAAE,CASnC"}
@@ -0,0 +1,53 @@
1
+ // How a customer declares a wrapped platform plugin (ADR-0044, shape 2). What they write is not
2
+ // the plugin that runs. The plugin that runs needs `@vendure/core` and the platform's own values,
3
+ // and build tooling imports the configuration file where neither is available. So
4
+ // `CloudDashboardPlugin.init({ route })` returns a marker carrying the options and nothing else,
5
+ // and the platform runtime builds the plugin that implements it during composition.
6
+ //
7
+ // The marker is a class rather than a plain object so that it is an ordinary member of the plugins
8
+ // array. It satisfies `VendurePluginEntry`, it reads as a plugin in the file, and the extension
9
+ // flattening and the attribution wrapping walk past it without a special case. Composition removes
10
+ // it before core sees it.
11
+ //
12
+ // Registered rather than a module-local symbol, for the reason the config handle's symbol is
13
+ // (ADR-0043): a second copy of this package in the tree would otherwise produce markers the
14
+ // composing copy does not recognise, and the customer's declared route would be silently ignored.
15
+ const DECLARATION = Symbol.for("vendure-cloud.cloud-plugin-declaration");
16
+ // The return type is inferred rather than written as `VendurePluginEntry`, so a caller can add a
17
+ // static `init` to the result and still have an ordinary member of the plugins array.
18
+ export function declareCloudPlugin(name, kind, options) {
19
+ // Named through a computed key because a class expression takes its name from the binding it is
20
+ // assigned to, and this one is returned rather than assigned. The name reaches boot messages and
21
+ // build logs, and `pluginName` reports a class without one as "an anonymous plugin".
22
+ const marker = { [name]: class {
23
+ } }[name];
24
+ const declaration = { kind, options };
25
+ // Non-enumerable, so the marker spreads and serialises as an ordinary empty class. A visible
26
+ // property would appear in anything that inspects the plugins array — a build log, a diagnostic
27
+ // dump — as configuration the customer did not write.
28
+ Object.defineProperty(marker, DECLARATION, { value: declaration });
29
+ return marker;
30
+ }
31
+ export function readCloudPluginDeclaration(entry) {
32
+ if (typeof entry !== "function" && (typeof entry !== "object" || entry === null)) {
33
+ return undefined;
34
+ }
35
+ return entry[DECLARATION];
36
+ }
37
+ export function isCloudPluginDeclaration(entry) {
38
+ return readCloudPluginDeclaration(entry) !== undefined;
39
+ }
40
+ // The declarations of one kind, in the order the customer wrote them. The platform runtime reads
41
+ // these to build the plugins that implement them, and composition drops the markers from the array
42
+ // it hands core.
43
+ export function listCloudPluginDeclarations(plugins, kind) {
44
+ const declarations = [];
45
+ for (const plugin of plugins) {
46
+ const declaration = readCloudPluginDeclaration(plugin);
47
+ if (declaration?.kind === kind) {
48
+ declarations.push(declaration);
49
+ }
50
+ }
51
+ return declarations;
52
+ }
53
+ //# sourceMappingURL=cloud-plugin-declaration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-plugin-declaration.js","sourceRoot":"","sources":["../src/cloud-plugin-declaration.ts"],"names":[],"mappings":"AAEA,gGAAgG;AAChG,kGAAkG;AAClG,kFAAkF;AAClF,iGAAiG;AACjG,oFAAoF;AACpF,EAAE;AACF,mGAAmG;AACnG,gGAAgG;AAChG,mGAAmG;AACnG,0BAA0B;AAC1B,EAAE;AACF,6FAA6F;AAC7F,4FAA4F;AAC5F,kGAAkG;AAClG,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AAWzE,iGAAiG;AACjG,sFAAsF;AACtF,MAAM,UAAU,kBAAkB,CAAU,IAAY,EAAE,IAAY,EAAE,OAAgB;IACtF,gGAAgG;IAChG,iGAAiG;IACjG,qFAAqF;IACrF,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE;SAAQ,EAAE,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAoC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACvE,6FAA6F;IAC7F,gGAAgG;IAChG,sDAAsD;IACtD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IACnE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAAc;IACvD,IAAI,OAAO,KAAK,KAAK,UAAU,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC;QACjF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAQ,KAA2B,CAAC,WAAW,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,KAAc;IACrD,OAAO,0BAA0B,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;AACzD,CAAC;AAED,iGAAiG;AACjG,mGAAmG;AACnG,iBAAiB;AACjB,MAAM,UAAU,2BAA2B,CACzC,OAA8B,EAC9B,IAAY;IAEZ,MAAM,YAAY,GAAsC,EAAE,CAAC;IAC3D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,WAAW,EAAE,IAAI,KAAK,IAAI,EAAE,CAAC;YAC/B,YAAY,CAAC,IAAI,CAAC,WAA8C,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { VendureConfig, VendurePluginMetadata } from "@vendure/core";
2
+ import { type CloudConfigHandle } from "./define-cloud-config.js";
3
+ import { CloudConfigError } from "./errors.js";
4
+ import { type PlatformOwnedField, type PlatformOwnedFieldPath } from "./platform-fields.js";
5
+ import { type PluginLike } from "./plugin-attribution.js";
6
+ export declare const CLOUD_PLUGIN_COMPATIBILITY = "^3.7.0";
7
+ export type PlatformFieldValues = Partial<Record<PlatformOwnedFieldPath, unknown>>;
8
+ export declare function platformDefaultFieldValues(sessionCacheStrategy: unknown): PlatformFieldValues;
9
+ export interface ComposeCloudConfigOptions {
10
+ values: PlatformFieldValues;
11
+ cloudPlugins: readonly PluginLike[];
12
+ guardPluginName: string;
13
+ vendurePlugin: (metadata: VendurePluginMetadata) => ClassDecorator;
14
+ }
15
+ export declare function composeCloudConfig(handle: CloudConfigHandle, options: ComposeCloudConfigOptions): VendureConfig;
16
+ export declare function hoistCloudPluginsLast(customerPlugins: readonly PluginLike[], cloudPlugins: readonly PluginLike[]): PluginLike[];
17
+ export declare function applyPlatformFields(config: object, values: PlatformFieldValues): void;
18
+ export declare class PlatformFieldOverwrittenError extends CloudConfigError {
19
+ readonly fields: readonly PlatformOwnedField[];
20
+ constructor(fields: readonly PlatformOwnedField[]);
21
+ }
22
+ export declare function assertPlatformFieldsHold(config: unknown, values: PlatformFieldValues): void;
23
+ //# sourceMappingURL=composition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composition.d.ts","sourceRoot":"","sources":["../src/composition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE1E,OAAO,EAAE,KAAK,iBAAiB,EAAmB,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAE5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,UAAU,EAIhB,MAAM,yBAAyB,CAAC;AAMjC,eAAO,MAAM,0BAA0B,WAAW,CAAC;AAKnD,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC,CAAC;AAEnF,wBAAgB,0BAA0B,CAAC,oBAAoB,EAAE,OAAO,GAAG,mBAAmB,CAS7F;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,YAAY,EAAE,SAAS,UAAU,EAAE,CAAC;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,cAAc,CAAC;CACpE;AAKD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,yBAAyB,GACjC,aAAa,CA8Cf;AAuBD,wBAAgB,qBAAqB,CACnC,eAAe,EAAE,SAAS,UAAU,EAAE,EACtC,YAAY,EAAE,SAAS,UAAU,EAAE,GAClC,UAAU,EAAE,CAGd;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAMrF;AAQD,qBAAa,6BAA8B,SAAQ,gBAAgB;IACjE,QAAQ,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,CAAC;gBAEnC,MAAM,EAAE,SAAS,kBAAkB,EAAE;CASlD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAU3F"}