@aglyn/aglyn 1.0.0-beta.232 → 1.0.0-beta.234
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -11
- package/src/lib/app-utils/admin-audit-index.d.ts +3 -1
- package/src/lib/app-utils/admin-audit-index.js +9 -1
- package/src/lib/app-utils/admin-audit-index.js.map +1 -1
- package/src/lib/app-utils/analytics-summary.d.ts +95 -0
- package/src/lib/app-utils/analytics-summary.js +113 -0
- package/src/lib/app-utils/analytics-summary.js.map +1 -0
- package/src/lib/app-utils/artifact-list-keys.js +12 -0
- package/src/lib/app-utils/artifact-list-keys.js.map +1 -1
- package/src/lib/app-utils/artifact-list-queries.d.ts +16 -0
- package/src/lib/app-utils/artifact-list-queries.js +122 -4
- package/src/lib/app-utils/artifact-list-queries.js.map +1 -1
- package/src/lib/app-utils/crm.d.ts +30 -2
- package/src/lib/app-utils/crm.js +77 -15
- package/src/lib/app-utils/crm.js.map +1 -1
- package/src/lib/app-utils/docs-help.generated.d.ts +17 -5
- package/src/lib/app-utils/docs-help.generated.js +35 -1
- package/src/lib/app-utils/docs-help.generated.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.js +139 -6
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/lockdown.js +1 -1
- package/src/lib/app-utils/lockdown.js.map +1 -1
- package/src/lib/app-utils/message-search.js +5 -2
- package/src/lib/app-utils/message-search.js.map +1 -1
- package/src/lib/app-utils/name-search.js +15 -3
- package/src/lib/app-utils/name-search.js.map +1 -1
- package/src/lib/app-utils/screen-analytics-aggregate.d.ts +70 -0
- package/src/lib/app-utils/screen-analytics-aggregate.js +82 -0
- package/src/lib/app-utils/screen-analytics-aggregate.js.map +1 -0
- package/src/lib/app-utils/screen-kind.d.ts +25 -0
- package/src/lib/app-utils/screen-kind.js +25 -0
- package/src/lib/app-utils/screen-kind.js.map +1 -0
- package/src/lib/app-utils/screen-route.d.ts +1 -5
- package/src/lib/app-utils/screen-route.js +2 -4
- package/src/lib/app-utils/screen-route.js.map +1 -1
- package/src/lib/app-utils/site-journey-steps.d.ts +38 -0
- package/src/lib/app-utils/site-journey-steps.js +54 -0
- package/src/lib/app-utils/site-journey-steps.js.map +1 -0
- package/src/lib/app-utils/site-journey.d.ts +2 -22
- package/src/lib/app-utils/site-journey.js +2 -32
- package/src/lib/app-utils/site-journey.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +33 -0
- package/src/lib/foundation/definitions/platform.types.js.map +1 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.js +20 -2
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
- package/src/lib/plugin-manager/plugin-checkout-credits.d.ts +288 -0
- package/src/lib/plugin-manager/plugin-checkout-credits.js +196 -0
- package/src/lib/plugin-manager/plugin-checkout-credits.js.map +1 -0
- package/src/lib/plugin-manager/plugin-media-ingest.d.ts +87 -0
- package/src/lib/plugin-manager/plugin-media-ingest.js +34 -0
- package/src/lib/plugin-manager/plugin-media-ingest.js.map +1 -0
- package/src/lib/plugin-manager/plugin-shipping-rates.d.ts +10 -0
- package/src/lib/plugin-manager/plugin-shipping-rates.js.map +1 -1
- package/src/lib/plugin-manager/stock-photo-provider.d.ts +141 -0
- package/src/lib/plugin-manager/stock-photo-provider.js +59 -0
- package/src/lib/plugin-manager/stock-photo-provider.js.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-media-ingest.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { AglynHostMediaStockSource } from '../foundation/definitions/platform.types'\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginService,\n} from './plugin-services'\n\n/**\n * A SERVER PROCESS STORES A PICTURE IN A SITE'S MEDIA LIBRARY (AGL-3660).\n *\n * The media library takes bytes through the console's own ingress — the\n * upload routes and the v1 API — which check the caller, the site's\n * lockdown, the bytes' structure, the takedown list, the plan and the\n * storage band before anything is written. A plugin that holds a picture on\n * the server with no browser request behind it (an AI job copying a stock\n * photo) has no route to post to. This is that route's door for it: the\n * console registers the one implementation at boot (`instrumentation.ts`),\n * the same direction as `core.site-cache`, and it applies the ingress checks\n * as the member named, so a plugin never writes a media document or a\n * Storage object itself.\n *\n * Images only: a server-held video or document has no caller yet.\n *\n * A process with no implementation answers `null` from\n * {@link pluginMediaIngest}, and a caller keeps its own fallback.\n */\n\nexport interface PluginMediaIngestRequest {\n hostId: string\n /**\n * The member the asset is stored as. Their access to the site, the site's\n * lockdown and the workspace's plan and storage band are checked as for\n * an upload they made themselves.\n */\n uid: string\n fileName: string\n /** A raster image type: `image/jpeg`, `image/png`, `image/webp` or `image/gif`. */\n contentType: string\n bytes: Uint8Array\n alt?: string\n description?: string\n /** Where a photo copied from a stock library came from (`stockPhoto` on the asset). */\n stockPhoto?: Omit<AglynHostMediaStockSource, 'importedAt'>\n}\n\n/** A stored asset, as a page names it. */\nexport interface PluginMediaAsset {\n mediaId: string\n /** What an `image` node's `src` holds: the asset's media reference, else its URL. */\n src: string\n width?: number\n height?: number\n}\n\nexport type PluginMediaIngestResult =\n | ({ ok: true } & PluginMediaAsset)\n | { ok: false; status: number; reason: string }\n\nexport interface PluginMediaIngest {\n /** Stores one picture in the site's own library. */\n ingest(request: PluginMediaIngestRequest): Promise<PluginMediaIngestResult>\n /**\n * The site's live, public asset copied from a stock photo with this source\n * key (`{provider}:{id}`), so a photo is never stored twice in one library.\n */\n findStockPhoto(input: { hostId: string; sourceKey: string }): Promise<PluginMediaAsset | null>\n}\n\n/** One implementation: the app that holds the media ingress. */\nexport const PLUGIN_MEDIA_INGEST = definePluginServiceContract<PluginMediaIngest>(\n 'core.media-ingest',\n { multiple: false },\n)\n\nexport function registerPluginMediaIngest(\n ingest: PluginMediaIngest,\n options?: { pluginId?: string },\n): void {\n if (typeof ingest?.ingest !== 'function' || typeof ingest?.findStockPhoto !== 'function') {\n throw new Error('a media ingest needs ingest and findStockPhoto')\n }\n registerPluginService(PLUGIN_MEDIA_INGEST, ingest, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\n/** The registered ingest, or `null` in a process that registered none. */\nexport function pluginMediaIngest(): PluginMediaIngest | null {\n return resolvePluginService(PLUGIN_MEDIA_INGEST) ?? null\n}\n"],"names":["definePluginServiceContract","registerPluginService","resolvePluginService","PLUGIN_MEDIA_INGEST","multiple","registerPluginMediaIngest","ingest","options","findStockPhoto","Error","pluginId","pluginMediaIngest"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SACEA,2BAA2B,EAC3BC,qBAAqB,EACrBC,oBAAoB,QACf,uBAAmB;AA+D1B,8DAA8D,GAC9D,OAAO,MAAMC,sBAAsBH,4BACjC,qBACA;IAAEI,UAAU;AAAM,GACnB;AAED,OAAO,SAASC,0BACdC,MAAyB,EACzBC,OAA+B;IAE/B,IAAI,QAAOD,0BAAAA,OAAQA,MAAM,MAAK,cAAc,QAAOA,0BAAAA,OAAQE,cAAc,MAAK,YAAY;QACxF,MAAM,IAAIC,MAAM;IAClB;IACAR,sBAAsBE,qBAAqBG,QAAQ,aAC7CC,CAAAA,2BAAAA,QAASG,QAAQ,IAAG;QAAEA,UAAUH,QAAQG,QAAQ;IAAC,IAAI,CAAC;AAE9D;AAEA,wEAAwE,GACxE,OAAO,SAASC;QACPT;IAAP,QAAOA,wBAAAA,qBAAqBC,gCAArBD,wBAA6C;AACtD"}
|
|
@@ -119,6 +119,16 @@ export interface PluginShippingAddressCheck {
|
|
|
119
119
|
suggested?: PluginShippingAddress;
|
|
120
120
|
/** Why it is not deliverable, in the carrier's words. */
|
|
121
121
|
messages: string[];
|
|
122
|
+
/**
|
|
123
|
+
* Where the address is on a map, when the provider placed it. Optional:
|
|
124
|
+
* only some providers return it, and only for addresses they verified. A
|
|
125
|
+
* caller measuring distance (local delivery radius zones) treats its
|
|
126
|
+
* absence as "cannot measure", never as zero.
|
|
127
|
+
*/
|
|
128
|
+
coordinates?: {
|
|
129
|
+
lat: number;
|
|
130
|
+
lng: number;
|
|
131
|
+
};
|
|
122
132
|
}
|
|
123
133
|
export interface PluginShippingRateQuoter {
|
|
124
134
|
/** Whether quotes can be asked for this site now: configured and switched on. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-shipping-rates.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * Live parcel rates, answered by the one plugin that talks to carriers\n * (AGL-3612).\n *\n * A plugin that sells goods prices delivery from its own table until the\n * merchant asks for live rates; then it needs a carrier's quote for an\n * address and a parcel, and it must not learn which carrier network, which\n * account or which vendor answers. A plugin that buys labels registers here;\n * a plugin that sells asks here, and neither imports the other.\n *\n * ## The shape is a parcel and an address, nothing more\n *\n * Every type below is postal: where it goes, what it weighs, how big it is,\n * and what it is worth for insurance and customs. Nothing names a catalog, an\n * order or a store, so a booking plugin shipping a rental kit asks the same\n * question in the same words.\n *\n * ## Nobody home is `null`, never a refusal\n *\n * Unlike the tax profile, an absent quoter is a perfectly good answer: the\n * seller falls back to its own rates, which is what it did before anyone\n * registered. {@link pluginShippingRateQuoter} answers `null`, and a quoter\n * whose deployment is not configured answers `available() === false`, which\n * a caller must read the same way.\n *\n * ## A quote is advisory until a label is bought\n *\n * `amountCents` is what the carrier quoted the platform for that parcel at\n * that moment, BEFORE any markup or handling the seller adds. The seller\n * decides what the shopper pays; the quoter never does.\n *\n * Import this module by its own subpath\n * (`@aglyn/aglyn/plugin-manager/plugin-shipping-rates`); it is not in the\n * barrel.\n */\n\n/** A postal address. `country` is ISO-3166 alpha-2; everything else is optional. */\nexport interface PluginShippingAddress {\n name?: string\n company?: string\n line1?: string\n line2?: string\n city?: string\n /** State, province or region code, as the destination writes it. */\n state?: string\n postalCode?: string\n country: string\n phone?: string\n email?: string\n /** Whether the address is a home, when the caller knows; carriers price it. */\n residential?: boolean\n}\n\n/** One parcel. Metric throughout; an adapter converts to its vendor's units. */\nexport interface PluginShippingParcel {\n weightGrams: number\n lengthCm?: number\n widthCm?: number\n heightCm?: number\n}\n\n/** What a seller asks: one shipment's rates to one address. */\nexport interface PluginShippingQuoteRequest {\n /** The site the shipment leaves from; the quoter resolves its ship-from address. */\n hostId: string\n to: PluginShippingAddress\n parcels: PluginShippingParcel[]\n /** ISO-4217, lower case, of the amounts the caller will charge in. */\n currency: string\n /** The goods' value, for insurance and customs; 0 when unknown. */\n valueCents: number\n /**\n * Service keys the seller offers (`'usps:priority'`), as\n * {@link PluginShippingRateQuoter.listServices} names them. Empty or\n * absent means every service the quoter can price.\n */\n services?: string[]\n /** Aborted when the caller stops waiting; a quoter passes it to its fetches. */\n signal?: AbortSignal\n}\n\n/** One carrier service's price for the shipment. */\nexport interface PluginShippingQuote {\n /** Stable across quotes: `carrier:service`, the key a seller stores. */\n serviceKey: string\n carrier: string\n service: string\n /** What a shopper reads: `'USPS Priority Mail'`. */\n label: string\n /** The carrier's price to the platform, before any markup or handling. */\n amountCents: number\n currency: string\n /** Transit estimate in business days, when the carrier gives one. */\n estimatedDays?: number\n}\n\n/** A service a seller may choose to offer. */\nexport interface PluginShippingService {\n serviceKey: string\n carrier: string\n label: string\n}\n\n/** What address validation answers. */\nexport interface PluginShippingAddressCheck {\n /** `valid` deliverable as written; `corrected` deliverable as `suggested`; `invalid` not deliverable. */\n verdict: 'valid' | 'corrected' | 'invalid' | 'unknown'\n /** The address the carrier would deliver to, when it differs. */\n suggested?: PluginShippingAddress\n /** Why it is not deliverable, in the carrier's words. */\n messages: string[]\n}\n\nexport interface PluginShippingRateQuoter {\n /** Whether quotes can be asked for this site now: configured and switched on. */\n available(hostId: string): Promise<boolean>\n /**\n * The rates. Throws on a provider failure; a caller that cannot wait\n * aborts `signal` and falls back to its own rates.\n */\n quote(request: PluginShippingQuoteRequest): Promise<PluginShippingQuote[]>\n /** The services a seller can pick from for this site. */\n listServices(hostId: string): Promise<PluginShippingService[]>\n /** Whether an address is deliverable, and the carrier's correction. */\n validateAddress?(\n hostId: string,\n address: PluginShippingAddress,\n ): Promise<PluginShippingAddressCheck>\n}\n\nexport const PLUGIN_SHIPPING_RATE_QUOTER =\n definePluginServiceContract<PluginShippingRateQuoter>('core.shipping-rate-quoter', {\n multiple: false,\n })\n\n/** Registers the plugin that quotes carrier rates. A second plugin is refused. */\nexport function registerPluginShippingRateQuoter(\n quoter: PluginShippingRateQuoter,\n options?: { pluginId?: string },\n): void {\n registerPluginService(PLUGIN_SHIPPING_RATE_QUOTER, quoter, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\n/** The quoter, or `null` when no plugin registered one. */\nexport function pluginShippingRateQuoter(): PluginShippingRateQuoter | null {\n return resolvePluginServices(PLUGIN_SHIPPING_RATE_QUOTER)[0]?.impl ?? null\n}\n\n/**\n * Asks the quoter and gives up after `timeoutMs`: `null` when nobody is\n * registered, the site is not available, the provider failed, or the wait\n * ran out. Never throws. The caller's fallback is its own rates, so every\n * failure reads the same.\n */\nexport async function quotePluginShippingRates(\n request: Omit<PluginShippingQuoteRequest, 'signal'>,\n options: { timeoutMs: number },\n): Promise<PluginShippingQuote[] | null> {\n const quoter = pluginShippingRateQuoter()\n if (!quoter) return null\n const controller = new AbortController()\n let timer: ReturnType<typeof setTimeout> | undefined\n const deadline = new Promise<null>((resolve) => {\n timer = setTimeout(() => {\n controller.abort()\n resolve(null)\n }, Math.max(0, options.timeoutMs))\n })\n try {\n return await Promise.race([\n (async (): Promise<PluginShippingQuote[] | null> => {\n if (!(await quoter.available(request.hostId))) return null\n return quoter.quote({ ...request, signal: controller.signal })\n })().catch((): null => null),\n deadline,\n ])\n } finally {\n if (timer) clearTimeout(timer)\n }\n}\n"],"names":["definePluginServiceContract","registerPluginService","resolvePluginServices","PLUGIN_SHIPPING_RATE_QUOTER","multiple","registerPluginShippingRateQuoter","quoter","options","pluginId","pluginShippingRateQuoter","impl","quotePluginShippingRates","request","controller","AbortController","timer","deadline","Promise","resolve","setTimeout","abort","Math","max","timeoutMs","race","available","hostId","quote","signal","catch","clearTimeout"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-shipping-rates.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * Live parcel rates, answered by the one plugin that talks to carriers\n * (AGL-3612).\n *\n * A plugin that sells goods prices delivery from its own table until the\n * merchant asks for live rates; then it needs a carrier's quote for an\n * address and a parcel, and it must not learn which carrier network, which\n * account or which vendor answers. A plugin that buys labels registers here;\n * a plugin that sells asks here, and neither imports the other.\n *\n * ## The shape is a parcel and an address, nothing more\n *\n * Every type below is postal: where it goes, what it weighs, how big it is,\n * and what it is worth for insurance and customs. Nothing names a catalog, an\n * order or a store, so a booking plugin shipping a rental kit asks the same\n * question in the same words.\n *\n * ## Nobody home is `null`, never a refusal\n *\n * Unlike the tax profile, an absent quoter is a perfectly good answer: the\n * seller falls back to its own rates, which is what it did before anyone\n * registered. {@link pluginShippingRateQuoter} answers `null`, and a quoter\n * whose deployment is not configured answers `available() === false`, which\n * a caller must read the same way.\n *\n * ## A quote is advisory until a label is bought\n *\n * `amountCents` is what the carrier quoted the platform for that parcel at\n * that moment, BEFORE any markup or handling the seller adds. The seller\n * decides what the shopper pays; the quoter never does.\n *\n * Import this module by its own subpath\n * (`@aglyn/aglyn/plugin-manager/plugin-shipping-rates`); it is not in the\n * barrel.\n */\n\n/** A postal address. `country` is ISO-3166 alpha-2; everything else is optional. */\nexport interface PluginShippingAddress {\n name?: string\n company?: string\n line1?: string\n line2?: string\n city?: string\n /** State, province or region code, as the destination writes it. */\n state?: string\n postalCode?: string\n country: string\n phone?: string\n email?: string\n /** Whether the address is a home, when the caller knows; carriers price it. */\n residential?: boolean\n}\n\n/** One parcel. Metric throughout; an adapter converts to its vendor's units. */\nexport interface PluginShippingParcel {\n weightGrams: number\n lengthCm?: number\n widthCm?: number\n heightCm?: number\n}\n\n/** What a seller asks: one shipment's rates to one address. */\nexport interface PluginShippingQuoteRequest {\n /** The site the shipment leaves from; the quoter resolves its ship-from address. */\n hostId: string\n to: PluginShippingAddress\n parcels: PluginShippingParcel[]\n /** ISO-4217, lower case, of the amounts the caller will charge in. */\n currency: string\n /** The goods' value, for insurance and customs; 0 when unknown. */\n valueCents: number\n /**\n * Service keys the seller offers (`'usps:priority'`), as\n * {@link PluginShippingRateQuoter.listServices} names them. Empty or\n * absent means every service the quoter can price.\n */\n services?: string[]\n /** Aborted when the caller stops waiting; a quoter passes it to its fetches. */\n signal?: AbortSignal\n}\n\n/** One carrier service's price for the shipment. */\nexport interface PluginShippingQuote {\n /** Stable across quotes: `carrier:service`, the key a seller stores. */\n serviceKey: string\n carrier: string\n service: string\n /** What a shopper reads: `'USPS Priority Mail'`. */\n label: string\n /** The carrier's price to the platform, before any markup or handling. */\n amountCents: number\n currency: string\n /** Transit estimate in business days, when the carrier gives one. */\n estimatedDays?: number\n}\n\n/** A service a seller may choose to offer. */\nexport interface PluginShippingService {\n serviceKey: string\n carrier: string\n label: string\n}\n\n/** What address validation answers. */\nexport interface PluginShippingAddressCheck {\n /** `valid` deliverable as written; `corrected` deliverable as `suggested`; `invalid` not deliverable. */\n verdict: 'valid' | 'corrected' | 'invalid' | 'unknown'\n /** The address the carrier would deliver to, when it differs. */\n suggested?: PluginShippingAddress\n /** Why it is not deliverable, in the carrier's words. */\n messages: string[]\n /**\n * Where the address is on a map, when the provider placed it. Optional:\n * only some providers return it, and only for addresses they verified. A\n * caller measuring distance (local delivery radius zones) treats its\n * absence as \"cannot measure\", never as zero.\n */\n coordinates?: { lat: number; lng: number }\n}\n\nexport interface PluginShippingRateQuoter {\n /** Whether quotes can be asked for this site now: configured and switched on. */\n available(hostId: string): Promise<boolean>\n /**\n * The rates. Throws on a provider failure; a caller that cannot wait\n * aborts `signal` and falls back to its own rates.\n */\n quote(request: PluginShippingQuoteRequest): Promise<PluginShippingQuote[]>\n /** The services a seller can pick from for this site. */\n listServices(hostId: string): Promise<PluginShippingService[]>\n /** Whether an address is deliverable, and the carrier's correction. */\n validateAddress?(\n hostId: string,\n address: PluginShippingAddress,\n ): Promise<PluginShippingAddressCheck>\n}\n\nexport const PLUGIN_SHIPPING_RATE_QUOTER =\n definePluginServiceContract<PluginShippingRateQuoter>('core.shipping-rate-quoter', {\n multiple: false,\n })\n\n/** Registers the plugin that quotes carrier rates. A second plugin is refused. */\nexport function registerPluginShippingRateQuoter(\n quoter: PluginShippingRateQuoter,\n options?: { pluginId?: string },\n): void {\n registerPluginService(PLUGIN_SHIPPING_RATE_QUOTER, quoter, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\n/** The quoter, or `null` when no plugin registered one. */\nexport function pluginShippingRateQuoter(): PluginShippingRateQuoter | null {\n return resolvePluginServices(PLUGIN_SHIPPING_RATE_QUOTER)[0]?.impl ?? null\n}\n\n/**\n * Asks the quoter and gives up after `timeoutMs`: `null` when nobody is\n * registered, the site is not available, the provider failed, or the wait\n * ran out. Never throws. The caller's fallback is its own rates, so every\n * failure reads the same.\n */\nexport async function quotePluginShippingRates(\n request: Omit<PluginShippingQuoteRequest, 'signal'>,\n options: { timeoutMs: number },\n): Promise<PluginShippingQuote[] | null> {\n const quoter = pluginShippingRateQuoter()\n if (!quoter) return null\n const controller = new AbortController()\n let timer: ReturnType<typeof setTimeout> | undefined\n const deadline = new Promise<null>((resolve) => {\n timer = setTimeout(() => {\n controller.abort()\n resolve(null)\n }, Math.max(0, options.timeoutMs))\n })\n try {\n return await Promise.race([\n (async (): Promise<PluginShippingQuote[] | null> => {\n if (!(await quoter.available(request.hostId))) return null\n return quoter.quote({ ...request, signal: controller.signal })\n })().catch((): null => null),\n deadline,\n ])\n } finally {\n if (timer) clearTimeout(timer)\n }\n}\n"],"names":["definePluginServiceContract","registerPluginService","resolvePluginServices","PLUGIN_SHIPPING_RATE_QUOTER","multiple","registerPluginShippingRateQuoter","quoter","options","pluginId","pluginShippingRateQuoter","impl","quotePluginShippingRates","request","controller","AbortController","timer","deadline","Promise","resolve","setTimeout","abort","Math","max","timeoutMs","race","available","hostId","quote","signal","catch","clearTimeout"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AA2I1B,OAAO,MAAMC,8BACXH,4BAAsD,6BAA6B;IACjFI,UAAU;AACZ,GAAE;AAEJ,gFAAgF,GAChF,OAAO,SAASC,iCACdC,MAAgC,EAChCC,OAA+B;IAE/BN,sBAAsBE,6BAA6BG,QAAQ,aACrDC,CAAAA,2BAAAA,QAASC,QAAQ,IAAG;QAAEA,UAAUD,QAAQC,QAAQ;IAAC,IAAI,CAAC;AAE9D;AAEA,yDAAyD,GACzD,OAAO,SAASC;;QACPP;IAAP,gBAAOA,0BAAAA,sBAAsBC,4BAA4B,CAAC,EAAE,qBAArDD,wBAAuDQ,IAAI,mBAAI;AACxE;AAEA;;;;;CAKC,GACD,OAAO,eAAeC,yBACpBC,OAAmD,EACnDL,OAA8B;IAE9B,MAAMD,SAASG;IACf,IAAI,CAACH,QAAQ,OAAO;IACpB,MAAMO,aAAa,IAAIC;IACvB,IAAIC;IACJ,MAAMC,WAAW,IAAIC,QAAc,CAACC;QAClCH,QAAQI,WAAW;YACjBN,WAAWO,KAAK;YAChBF,QAAQ;QACV,GAAGG,KAAKC,GAAG,CAAC,GAAGf,QAAQgB,SAAS;IAClC;IACA,IAAI;QACF,OAAO,MAAMN,QAAQO,IAAI,CAAC;YACvB,CAAA;gBACC,IAAI,CAAE,MAAMlB,OAAOmB,SAAS,CAACb,QAAQc,MAAM,GAAI,OAAO;gBACtD,OAAOpB,OAAOqB,KAAK,CAAC,aAAKf;oBAASgB,QAAQf,WAAWe,MAAM;;YAC7D,CAAA,IAAKC,KAAK,CAAC,IAAY;YACvBb;SACD;IACH,SAAU;QACR,IAAID,OAAOe,aAAaf;IAC1B;AACF"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* STOCK PHOTOS (AGL-3660): a library of licensed photos outside this
|
|
19
|
+
* platform that a server process searches and copies from.
|
|
20
|
+
*
|
|
21
|
+
* Core defines the contract and never names a library. A plugin registers a
|
|
22
|
+
* provider from its server declarations, and a caller — the AI site build is
|
|
23
|
+
* the first — asks for {@link stockPhotoProvider} and gets the first one
|
|
24
|
+
* this deployment configured, or `null`. Nothing here stores a photo: a
|
|
25
|
+
* caller that keeps one copies its bytes into the site's own media library
|
|
26
|
+
* (`plugin-media-ingest.ts`), because a page that names a library's own
|
|
27
|
+
* address would hotlink it, and most libraries' terms refuse that.
|
|
28
|
+
*
|
|
29
|
+
* What a provider owes its library's terms — caching searches, its rate
|
|
30
|
+
* limit, the hosts it may fetch from — it keeps inside itself, so a caller
|
|
31
|
+
* cannot get them wrong. What it owes the caller is {@link
|
|
32
|
+
* StockPhotoProvider.credit}: the words and links the asset records about
|
|
33
|
+
* where it came from, and whether the library requires them shown.
|
|
34
|
+
*
|
|
35
|
+
* A provider that is registered and not configured (its key unset) answers
|
|
36
|
+
* as absent, so a deployment without the key behaves as one without the
|
|
37
|
+
* plugin.
|
|
38
|
+
*/
|
|
39
|
+
/** The shape a caller wants; a provider maps it onto its own filter. */
|
|
40
|
+
export type StockPhotoOrientation = 'horizontal' | 'vertical' | 'any';
|
|
41
|
+
export interface StockPhotoSearchRequest {
|
|
42
|
+
/** Plain search words, at most {@link STOCK_PHOTO_QUERY_MAX_CHARS}. */
|
|
43
|
+
query: string;
|
|
44
|
+
orientation?: StockPhotoOrientation;
|
|
45
|
+
/** The smallest original a hit may have, in pixels. */
|
|
46
|
+
minWidth?: number;
|
|
47
|
+
minHeight?: number;
|
|
48
|
+
/** A hint that the photo should show people, where the library can filter by it. */
|
|
49
|
+
people?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/** The longest query a caller sends; libraries refuse or truncate longer ones. */
|
|
52
|
+
export declare const STOCK_PHOTO_QUERY_MAX_CHARS = 100;
|
|
53
|
+
/** One photo a search found. */
|
|
54
|
+
export interface StockPhoto {
|
|
55
|
+
/** The registering provider's id. */
|
|
56
|
+
provider: string;
|
|
57
|
+
/** The library's own id for the photo, stable across searches. */
|
|
58
|
+
id: string;
|
|
59
|
+
/** The size of the copy {@link StockPhotoProvider.download} fetches. */
|
|
60
|
+
width: number;
|
|
61
|
+
height: number;
|
|
62
|
+
/** The photo's page at the library, for the credit. */
|
|
63
|
+
pageUrl: string;
|
|
64
|
+
/** The contributor's name as the library shows it. */
|
|
65
|
+
photographer: string;
|
|
66
|
+
/** The contributor's page at the library, when it has one. */
|
|
67
|
+
photographerUrl?: string;
|
|
68
|
+
/** The library's tags, lowercase. */
|
|
69
|
+
tags: string[];
|
|
70
|
+
}
|
|
71
|
+
/** What an asset copied from a library records about where it came from. */
|
|
72
|
+
export interface StockPhotoCredit {
|
|
73
|
+
/** The library's name, as its terms ask it written. */
|
|
74
|
+
providerLabel: string;
|
|
75
|
+
/** The license the photo is used under. */
|
|
76
|
+
license: string;
|
|
77
|
+
licenseUrl: string;
|
|
78
|
+
/** Whether the license requires the credit shown wherever the photo is. */
|
|
79
|
+
attributionRequired: boolean;
|
|
80
|
+
/** A sentence crediting the photo, for the asset's description. */
|
|
81
|
+
text: string;
|
|
82
|
+
}
|
|
83
|
+
export interface StockPhotoSearchResult {
|
|
84
|
+
photos: StockPhoto[];
|
|
85
|
+
/** Whether the answer came from the provider's own cache. */
|
|
86
|
+
cached: boolean;
|
|
87
|
+
}
|
|
88
|
+
export interface StockPhotoDownload {
|
|
89
|
+
bytes: Uint8Array;
|
|
90
|
+
/** `image/jpeg`, `image/png` or `image/webp`. */
|
|
91
|
+
contentType: string;
|
|
92
|
+
}
|
|
93
|
+
export interface StockPhotoProvider {
|
|
94
|
+
/** A stable id, the prefix of every source key: `pixabay`. */
|
|
95
|
+
id: string;
|
|
96
|
+
/** The library's name, in customer copy. */
|
|
97
|
+
label: string;
|
|
98
|
+
/** Whether this deployment holds what the provider needs to search. */
|
|
99
|
+
isConfigured(): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* The photos matching `request`, best first. `null` when the provider
|
|
102
|
+
* cannot ask right now — its rate limit is spent, or the library failed —
|
|
103
|
+
* which a caller treats as "no photo", never as an error to retry.
|
|
104
|
+
*/
|
|
105
|
+
search(request: StockPhotoSearchRequest, options?: {
|
|
106
|
+
signal?: AbortSignal;
|
|
107
|
+
}): Promise<StockPhotoSearchResult | null>;
|
|
108
|
+
/**
|
|
109
|
+
* The photo's bytes, fetched only from the library's own image hosts, or
|
|
110
|
+
* `null` when they cannot be had within `maxBytes` and the signal.
|
|
111
|
+
*/
|
|
112
|
+
download(photo: StockPhoto, options: {
|
|
113
|
+
maxBytes: number;
|
|
114
|
+
signal?: AbortSignal;
|
|
115
|
+
}): Promise<StockPhotoDownload | null>;
|
|
116
|
+
/** How an asset copied from `photo` credits it. */
|
|
117
|
+
credit(photo: StockPhoto): StockPhotoCredit;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Many plugins may each register a library; a caller is handed the first
|
|
121
|
+
* configured one, highest priority first.
|
|
122
|
+
*/
|
|
123
|
+
export declare const STOCK_PHOTO_PROVIDERS: import("./plugin-services").PluginServiceContract<StockPhotoProvider>;
|
|
124
|
+
/** The key an asset copied from a library is found again by: `{provider}:{id}`. */
|
|
125
|
+
export declare function stockPhotoSourceKey(photo: Pick<StockPhoto, 'provider' | 'id'>): string;
|
|
126
|
+
/**
|
|
127
|
+
* Registers a library. The owner is the loader's marker when a register fn
|
|
128
|
+
* is running, else `options.pluginId`; the provider's own id tells two
|
|
129
|
+
* libraries of one plugin apart.
|
|
130
|
+
*/
|
|
131
|
+
export declare function registerStockPhotoProvider(provider: StockPhotoProvider, options?: {
|
|
132
|
+
pluginId?: string;
|
|
133
|
+
priority?: number;
|
|
134
|
+
}): void;
|
|
135
|
+
/**
|
|
136
|
+
* The first registered library this deployment configured, or `null`.
|
|
137
|
+
* Synchronous and free of I/O. A provider whose configuration check throws
|
|
138
|
+
* answers as unconfigured: a stock photo is decoration, and its failure
|
|
139
|
+
* leaves the caller's own fallback standing.
|
|
140
|
+
*/
|
|
141
|
+
export declare function stockPhotoProvider(): StockPhotoProvider | null;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ import { definePluginServiceContract, registerPluginService, resolvePluginServices } from "./plugin-services.js";
|
|
18
|
+
/** The longest query a caller sends; libraries refuse or truncate longer ones. */ export const STOCK_PHOTO_QUERY_MAX_CHARS = 100;
|
|
19
|
+
/**
|
|
20
|
+
* Many plugins may each register a library; a caller is handed the first
|
|
21
|
+
* configured one, highest priority first.
|
|
22
|
+
*/ export const STOCK_PHOTO_PROVIDERS = definePluginServiceContract('core.stock-photos', {
|
|
23
|
+
multiple: true
|
|
24
|
+
});
|
|
25
|
+
/** The key an asset copied from a library is found again by: `{provider}:{id}`. */ export function stockPhotoSourceKey(photo) {
|
|
26
|
+
return `${photo.provider}:${photo.id}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Registers a library. The owner is the loader's marker when a register fn
|
|
30
|
+
* is running, else `options.pluginId`; the provider's own id tells two
|
|
31
|
+
* libraries of one plugin apart.
|
|
32
|
+
*/ export function registerStockPhotoProvider(provider, options) {
|
|
33
|
+
var _provider_id;
|
|
34
|
+
if (!(provider == null ? void 0 : (_provider_id = provider.id) == null ? void 0 : _provider_id.trim())) throw new Error('a stock photo provider needs an id');
|
|
35
|
+
registerPluginService(STOCK_PHOTO_PROVIDERS, provider, _extends({
|
|
36
|
+
key: provider.id
|
|
37
|
+
}, (options == null ? void 0 : options.pluginId) ? {
|
|
38
|
+
pluginId: options.pluginId
|
|
39
|
+
} : {}, (options == null ? void 0 : options.priority) !== undefined ? {
|
|
40
|
+
priority: options.priority
|
|
41
|
+
} : {}));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The first registered library this deployment configured, or `null`.
|
|
45
|
+
* Synchronous and free of I/O. A provider whose configuration check throws
|
|
46
|
+
* answers as unconfigured: a stock photo is decoration, and its failure
|
|
47
|
+
* leaves the caller's own fallback standing.
|
|
48
|
+
*/ export function stockPhotoProvider() {
|
|
49
|
+
for (const { impl } of resolvePluginServices(STOCK_PHOTO_PROVIDERS)){
|
|
50
|
+
try {
|
|
51
|
+
if (impl.isConfigured()) return impl;
|
|
52
|
+
} catch (unused) {
|
|
53
|
+
// Unconfigured, as the note says.
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=stock-photo-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/stock-photo-provider.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * STOCK PHOTOS (AGL-3660): a library of licensed photos outside this\n * platform that a server process searches and copies from.\n *\n * Core defines the contract and never names a library. A plugin registers a\n * provider from its server declarations, and a caller — the AI site build is\n * the first — asks for {@link stockPhotoProvider} and gets the first one\n * this deployment configured, or `null`. Nothing here stores a photo: a\n * caller that keeps one copies its bytes into the site's own media library\n * (`plugin-media-ingest.ts`), because a page that names a library's own\n * address would hotlink it, and most libraries' terms refuse that.\n *\n * What a provider owes its library's terms — caching searches, its rate\n * limit, the hosts it may fetch from — it keeps inside itself, so a caller\n * cannot get them wrong. What it owes the caller is {@link\n * StockPhotoProvider.credit}: the words and links the asset records about\n * where it came from, and whether the library requires them shown.\n *\n * A provider that is registered and not configured (its key unset) answers\n * as absent, so a deployment without the key behaves as one without the\n * plugin.\n */\n\n/** The shape a caller wants; a provider maps it onto its own filter. */\nexport type StockPhotoOrientation = 'horizontal' | 'vertical' | 'any'\n\nexport interface StockPhotoSearchRequest {\n /** Plain search words, at most {@link STOCK_PHOTO_QUERY_MAX_CHARS}. */\n query: string\n orientation?: StockPhotoOrientation\n /** The smallest original a hit may have, in pixels. */\n minWidth?: number\n minHeight?: number\n /** A hint that the photo should show people, where the library can filter by it. */\n people?: boolean\n}\n\n/** The longest query a caller sends; libraries refuse or truncate longer ones. */\nexport const STOCK_PHOTO_QUERY_MAX_CHARS = 100\n\n/** One photo a search found. */\nexport interface StockPhoto {\n /** The registering provider's id. */\n provider: string\n /** The library's own id for the photo, stable across searches. */\n id: string\n /** The size of the copy {@link StockPhotoProvider.download} fetches. */\n width: number\n height: number\n /** The photo's page at the library, for the credit. */\n pageUrl: string\n /** The contributor's name as the library shows it. */\n photographer: string\n /** The contributor's page at the library, when it has one. */\n photographerUrl?: string\n /** The library's tags, lowercase. */\n tags: string[]\n}\n\n/** What an asset copied from a library records about where it came from. */\nexport interface StockPhotoCredit {\n /** The library's name, as its terms ask it written. */\n providerLabel: string\n /** The license the photo is used under. */\n license: string\n licenseUrl: string\n /** Whether the license requires the credit shown wherever the photo is. */\n attributionRequired: boolean\n /** A sentence crediting the photo, for the asset's description. */\n text: string\n}\n\nexport interface StockPhotoSearchResult {\n photos: StockPhoto[]\n /** Whether the answer came from the provider's own cache. */\n cached: boolean\n}\n\nexport interface StockPhotoDownload {\n bytes: Uint8Array\n /** `image/jpeg`, `image/png` or `image/webp`. */\n contentType: string\n}\n\nexport interface StockPhotoProvider {\n /** A stable id, the prefix of every source key: `pixabay`. */\n id: string\n /** The library's name, in customer copy. */\n label: string\n /** Whether this deployment holds what the provider needs to search. */\n isConfigured(): boolean\n /**\n * The photos matching `request`, best first. `null` when the provider\n * cannot ask right now — its rate limit is spent, or the library failed —\n * which a caller treats as \"no photo\", never as an error to retry.\n */\n search(\n request: StockPhotoSearchRequest,\n options?: { signal?: AbortSignal },\n ): Promise<StockPhotoSearchResult | null>\n /**\n * The photo's bytes, fetched only from the library's own image hosts, or\n * `null` when they cannot be had within `maxBytes` and the signal.\n */\n download(\n photo: StockPhoto,\n options: { maxBytes: number; signal?: AbortSignal },\n ): Promise<StockPhotoDownload | null>\n /** How an asset copied from `photo` credits it. */\n credit(photo: StockPhoto): StockPhotoCredit\n}\n\n/**\n * Many plugins may each register a library; a caller is handed the first\n * configured one, highest priority first.\n */\nexport const STOCK_PHOTO_PROVIDERS = definePluginServiceContract<StockPhotoProvider>(\n 'core.stock-photos',\n { multiple: true },\n)\n\n/** The key an asset copied from a library is found again by: `{provider}:{id}`. */\nexport function stockPhotoSourceKey(photo: Pick<StockPhoto, 'provider' | 'id'>): string {\n return `${photo.provider}:${photo.id}`\n}\n\n/**\n * Registers a library. The owner is the loader's marker when a register fn\n * is running, else `options.pluginId`; the provider's own id tells two\n * libraries of one plugin apart.\n */\nexport function registerStockPhotoProvider(\n provider: StockPhotoProvider,\n options?: { pluginId?: string; priority?: number },\n): void {\n if (!provider?.id?.trim()) throw new Error('a stock photo provider needs an id')\n registerPluginService(STOCK_PHOTO_PROVIDERS, provider, {\n key: provider.id,\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n ...(options?.priority !== undefined ? { priority: options.priority } : {}),\n })\n}\n\n/**\n * The first registered library this deployment configured, or `null`.\n * Synchronous and free of I/O. A provider whose configuration check throws\n * answers as unconfigured: a stock photo is decoration, and its failure\n * leaves the caller's own fallback standing.\n */\nexport function stockPhotoProvider(): StockPhotoProvider | null {\n for (const { impl } of resolvePluginServices(STOCK_PHOTO_PROVIDERS)) {\n try {\n if (impl.isConfigured()) return impl\n } catch {\n // Unconfigured, as the note says.\n }\n }\n return null\n}\n"],"names":["definePluginServiceContract","registerPluginService","resolvePluginServices","STOCK_PHOTO_QUERY_MAX_CHARS","STOCK_PHOTO_PROVIDERS","multiple","stockPhotoSourceKey","photo","provider","id","registerStockPhotoProvider","options","trim","Error","key","pluginId","priority","undefined","stockPhotoProvider","impl","isConfigured"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AAuC1B,gFAAgF,GAChF,OAAO,MAAMC,8BAA8B,IAAG;AA0E9C;;;CAGC,GACD,OAAO,MAAMC,wBAAwBJ,4BACnC,qBACA;IAAEK,UAAU;AAAK,GAClB;AAED,iFAAiF,GACjF,OAAO,SAASC,oBAAoBC,KAA0C;IAC5E,OAAO,GAAGA,MAAMC,QAAQ,CAAC,CAAC,EAAED,MAAME,EAAE,EAAE;AACxC;AAEA;;;;CAIC,GACD,OAAO,SAASC,2BACdF,QAA4B,EAC5BG,OAAkD;QAE7CH;IAAL,IAAI,EAACA,6BAAAA,eAAAA,SAAUC,EAAE,qBAAZD,aAAcI,IAAI,KAAI,MAAM,IAAIC,MAAM;IAC3CZ,sBAAsBG,uBAAuBI,UAAU;QACrDM,KAAKN,SAASC,EAAE;OACZE,CAAAA,2BAAAA,QAASI,QAAQ,IAAG;QAAEA,UAAUJ,QAAQI,QAAQ;IAAC,IAAI,CAAC,GACtDJ,CAAAA,2BAAAA,QAASK,QAAQ,MAAKC,YAAY;QAAED,UAAUL,QAAQK,QAAQ;IAAC,IAAI,CAAC;AAE5E;AAEA;;;;;CAKC,GACD,OAAO,SAASE;IACd,KAAK,MAAM,EAAEC,IAAI,EAAE,IAAIjB,sBAAsBE,uBAAwB;QACnE,IAAI;YACF,IAAIe,KAAKC,YAAY,IAAI,OAAOD;QAClC,EAAE,eAAM;QACN,kCAAkC;QACpC;IACF;IACA,OAAO;AACT"}
|