@entifix/next-shell 0.4.1 → 0.5.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 (41) hide show
  1. package/dist/lib/command-palette/use-use-cases-source.d.ts +17 -4
  2. package/dist/lib/command-palette/use-use-cases-source.d.ts.map +1 -1
  3. package/dist/lib/command-palette/use-use-cases-source.js +5 -1
  4. package/dist/lib/command-palette/use-use-cases-source.js.map +1 -1
  5. package/dist/lib/config/config-route.d.ts +6 -19
  6. package/dist/lib/config/config-route.d.ts.map +1 -1
  7. package/dist/lib/config/config-route.js +6 -23
  8. package/dist/lib/config/config-route.js.map +1 -1
  9. package/dist/lib/config/configuration-source.d.ts +18 -0
  10. package/dist/lib/config/configuration-source.d.ts.map +1 -0
  11. package/dist/lib/config/configuration-source.js +15 -0
  12. package/dist/lib/config/configuration-source.js.map +1 -0
  13. package/dist/lib/crud/make-entity-crud.d.ts +7 -9
  14. package/dist/lib/crud/make-entity-crud.d.ts.map +1 -1
  15. package/dist/lib/crud/make-entity-crud.js +18 -12
  16. package/dist/lib/crud/make-entity-crud.js.map +1 -1
  17. package/dist/lib/crud/make-entity-crud.types.d.ts +12 -2
  18. package/dist/lib/crud/make-entity-crud.types.d.ts.map +1 -1
  19. package/dist/lib/crud/make-entity-crud.types.js.map +1 -1
  20. package/dist/lib/health/health-routes.d.ts +3 -4
  21. package/dist/lib/health/health-routes.d.ts.map +1 -1
  22. package/dist/lib/health/health-routes.js +7 -9
  23. package/dist/lib/health/health-routes.js.map +1 -1
  24. package/dist/lib/i18n/catalog/en.d.ts.map +1 -1
  25. package/dist/lib/i18n/catalog/en.js +0 -145
  26. package/dist/lib/i18n/catalog/en.js.map +1 -1
  27. package/dist/lib/i18n/catalog/es.d.ts +0 -159
  28. package/dist/lib/i18n/catalog/es.d.ts.map +1 -1
  29. package/dist/lib/i18n/catalog/es.js +0 -160
  30. package/dist/lib/i18n/catalog/es.js.map +1 -1
  31. package/dist/lib/i18n/catalog/index.d.ts +0 -282
  32. package/dist/lib/i18n/catalog/index.d.ts.map +1 -1
  33. package/dist/server.d.ts +1 -1
  34. package/dist/server.d.ts.map +1 -1
  35. package/dist/server.js +1 -1
  36. package/dist/server.js.map +1 -1
  37. package/package.json +9 -9
  38. package/dist/lib/config/service-token.d.ts +0 -5
  39. package/dist/lib/config/service-token.d.ts.map +0 -1
  40. package/dist/lib/config/service-token.js +0 -18
  41. package/dist/lib/config/service-token.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/crud/make-entity-crud.types.ts"],"sourcesContent":["import type {\n ConfigurationRepositoryTag,\n EntityRepositoryTag,\n} from '@entifix/business';\nimport type {\n BulkOutcome,\n Entity,\n EntityConstructor,\n EntityFieldDescriptor,\n EntityId,\n EntityMetadataSource,\n EntitySelection,\n} from '@entifix/core';\nimport type {\n EntityDraftStore,\n EntityLinkSourceConfig,\n} from '@entifix/react-integration';\nimport type { Context } from 'effect/Context';\nimport type { CustomTypeOptions } from 'i18next';\nimport type { ReactElement, ReactNode } from 'react';\n\n/**\n * The `entity` catalog keys that carry **both** form titles, a `label` and a\n * `plural`.\n *\n * Derived from the Spanish catalog rather than written out, so the union is the\n * catalog: an entity whose subtree has no `form.editTitle`/`form.newTitle`\n * cannot be handed to {@link makeEntityCrud} at all, and adding a reference\n * entity therefore starts by adding its copy to both locales. That is the whole\n * i18n gate for this factory — `@r10c/i18n-check` scans only\n * `packages/business/ts` for `@useCase()` decorators and never `.tsx`, so a\n * runtime key here would be checked by nothing.\n *\n * `label`/`plural` joined the condition when {@link EntityCrud} began carrying\n * them, so that a workspace tab and a nav entry derived from this descriptor\n * name the entity in the catalog's own words. They are part of the **type**\n * rather than a runtime assertion in the factory, because the catalog is\n * statically known here: a missing `plural` should fail at the call site that\n * generates the screens, not on the render that first tries to title a tab.\n *\n * Keeping the key typed is what lets the generated form call `useT('entity')`\n * with a template literal and still fail the build on a typo, instead of\n * reaching for the `useTranslateKey` escape hatch that authored copy must not\n * use. `AccountLabelKey` in `../session/account-links.ts` is the same trick\n * written out by hand; this one cannot drift because it is computed.\n */\nexport type EntityCatalogKey<\n TEntityCatalog = EntityCatalogOf<TypeOptionsResources>,\n> = [TEntityCatalog] extends [never]\n ? // No host augmentation in this compilation — this package's own specs, or\n // an adopter who has not declared one. The factory still works; the key is\n // simply unchecked, which is the same trade `useTranslateKey` makes.\n string\n : {\n [K in keyof TEntityCatalog]: TEntityCatalog[K] extends {\n form: { editTitle: string; newTitle: string };\n label: string;\n plural: string;\n }\n ? K\n : never;\n }[keyof TEntityCatalog] &\n string;\n\n/**\n * The host's `entity` namespace, read back out of its own `i18next`\n * augmentation.\n *\n * ⚠️ **The `entity` catalog is the host's, not entifix's.** It names *their*\n * entities — a parameter, an offering, a sales channel — so a framework that\n * shipped one would be shipping an application's product copy. Reading it back\n * through `CustomTypeOptions` keeps the key union computed rather than written\n * out, which is what stops it drifting, while leaving the catalog where it\n * belongs. A host that declares no augmentation gets `string`, and the factory\n * still works with the gate relaxed.\n */\ntype TypeOptionsResources = CustomTypeOptions extends { resources: infer R }\n ? R\n : never;\n\ntype EntityCatalogOf<TResources> = TResources extends { entity: infer E }\n ? E\n : never;\n\n/**\n * A relation the generated form edits with a picker.\n *\n * The target is named here rather than derived, because the common case is a\n * **plain foreign key**: when the target lives in another slice's store a typed\n * `EntityLink` is both an illegal import and a cross-store join, so the member\n * is a bare `string` (`ProductSpecification.brandId` into `catalog-reference`)\n * and its `@accessor()` has no vocabulary for \"the target's name\". Hence\n * `labelProperty`/`searchProperty` are stated at the call site instead of being\n * left to `describeEntityColumns`' `'name'` default, which happens to be right\n * today and states nothing.\n *\n * `searchProperty` must be `filterable` on the **target** or the service answers\n * `400`; `useEntityLinkSource` throws at render rather than letting that surface\n * as an empty suggestion list.\n */\nexport interface EntityCrudLink<TAdapters> {\n /** The owning entity's accessor name, e.g. `'brandId'`. */\n readonly field: string;\n readonly entityConstructor: EntityConstructor<Entity>;\n /**\n * Which adapter holds the **target's** repository. Often a different service\n * than the record's own: `catalog-reference` is another slice's store, so\n * resolving an id goes through that domain's own read path.\n */\n readonly repository: AdapterKey<TAdapters, Context<EntityRepositoryTag>>;\n /** Defaults to `'name'`. */\n readonly labelProperty?: string;\n /** Defaults to `'name'`. Must be `filterable` on the target. */\n readonly searchProperty?: string;\n}\n\n/** The keys of `TAdapters` whose value is assignable to `TValue`. */\nexport type AdapterKey<TAdapters, TValue> = {\n [K in keyof TAdapters]: TAdapters[K] extends TValue ? K : never;\n}[keyof TAdapters];\n\nexport interface EntityCrudOptions<TAdapters, TEntity extends Entity> {\n /** The domain shell's adapters hook, e.g. `useMarketplaceAdminAdapters`. */\n readonly useAdapters: () => TAdapters;\n /** Route prefix for both pages, e.g. `'/catalog/product-brand'`. */\n readonly basePath: string;\n /**\n * The entity's `entity` catalog key. Asserted against `@entity({ key })` at\n * factory time — the two are the same string by convention\n * (`entity:product-brand.label` mirrors `key: 'product-brand'`), and letting\n * them drift would title a form after a different entity.\n */\n readonly catalogKey: EntityCatalogKey;\n /** Which adapter holds this entity's own repository. */\n readonly repository: AdapterKey<TAdapters, Context<EntityRepositoryTag>>;\n readonly configuration: AdapterKey<\n TAdapters,\n Context<ConfigurationRepositoryTag>\n >;\n /**\n * Members the form keeps but does not show — `id` always, plus anything a\n * transaction assigns. A hidden member still round-trips: it is dropped from\n * the rendered fields, not from the draft, so `reconstructEntity` carries it\n * back out of the seeded values.\n */\n readonly hiddenFields?: readonly string[];\n /** `<EntityColumn>` overrides for the list, for presentation metadata cannot express. */\n readonly columns?: ReactNode;\n /**\n * Extra controls beside the table's own — an `<EntityTableToolbar>`.\n *\n * Its own option rather than more `columns`, though both end up as\n * `EntityTable` children and the slots are sorted by component identity: a\n * toolbar filed under a columns prop is a name that lies, and the first thing\n * to go here is a link into a wizard, which is not a column by any reading\n * ([ADR 0045](../../../../../../docs/adr/0045-the-wizard-a-step-graph-and-a-submit-that-hands-off.md)).\n */\n readonly toolbar?: ReactNode;\n /** Frozen at factory time — see `use-entity-link-sources.ts`. */\n readonly links?: readonly EntityCrudLink<TAdapters>[];\n /**\n * Where the entity's served affordances come from — `GET /api/<entity>/$metadata`.\n *\n * Supplying it is what turns on everything ADR 0026 and ADR 0035 describe:\n * Save and Delete filtered against the caller's real grants, the declared\n * verbs on the form, the row overflow menu, and the bulk bar. Omitting it\n * keeps the pre-0026 behaviour exactly, which is what every generated catalog\n * rendered before this option existed.\n *\n * A `EntityMetadataSource` rather than a URL because the two hosts reach\n * their service differently — one through the config-driven REST adapters,\n * one through a shell's own same-origin routes.\n */\n readonly metadataSource?: EntityMetadataSource;\n /**\n * Runs a `collection`-bound verb over a selection, and reports **per row**.\n *\n * Supplying it opts the list into the selection column and the bulk bar.\n * It is separate from `metadataSource` because the two are independent: an\n * entity can declare no collection verb and still want permission-filtered\n * Save, and the endpoint a verb posts to is the shell's knowledge, not\n * metadata's.\n */\n readonly runBulkUseCase?: (\n key: string,\n selection: EntitySelection<TEntity>,\n ) => Promise<readonly BulkOutcome[]>;\n /**\n * Runs an `entity`-bound verb on the record the single view is showing.\n *\n * The sibling of {@link runBulkUseCase}, and it had to exist for the same\n * reason: `EntityForm` has rendered these buttons since ADR 0035, and\n * `EntityCrudForm` has accepted an `onUseCase` for as long — but nothing ever\n * passed one, so a generated screen showed a declared, granted, served verb\n * that did nothing when clicked. Measured on `ProductOffering`'s `publish`,\n * which passed every `@r10c/slices` invariant and appeared nowhere.\n *\n * Resolving means the record changed, and the page reloads it: a verb that\n * moves a lifecycle leaves the form showing the old state otherwise, which\n * reads as \"the button did nothing\". Rejecting surfaces through the form's\n * own error slot, so a `409` from an illegal transition renders as the coded\n * message the catalog holds rather than a thrown promise nobody catches.\n */\n readonly runUseCase?: (key: string, id: EntityId) => Promise<void>;\n}\n\n/**\n * Props both hosts pass. A route host passes none — the slug comes from the URL\n * and a save returns to the list; the workspace tab host passes all of them.\n */\nexport interface EntityCrudSingleViewProps {\n /** Defaults to the `[slug]` route param. */\n readonly slug?: string;\n /** Defaults to navigating back to the list. */\n readonly onSaved?: () => void;\n readonly onDeleted?: () => void;\n /**\n * Where to autosave the edit. Supplying it is the whole opt-in: the form\n * seeds from the persisted draft, writes to it on every edit, and the page\n * clears it once a save or delete commits.\n *\n * A route host omits it and stays ephemeral, which is the rule stated as a\n * missing prop rather than as a flag — there is no value of \"absent\" that\n * accidentally starts persisting.\n */\n readonly draft?: EntityDraftStore;\n}\n\n/**\n * What the factory returns: a **named descriptor**, not four loose components.\n *\n * The identity fields are here so the workspace registry and the nav are derived\n * from a list of these rather than from the hand-written const maps they replace\n * (#141).\n */\nexport interface EntityCrud<TEntity extends Entity> {\n readonly entityConstructor: EntityConstructor<TEntity>;\n /** `@entity({ key })`, which is also `catalogKey` and the tab address payload. */\n readonly entityKey: EntityCatalogKey;\n /**\n * `@entity({ labelKey })` — how one record is named. A record tab's title.\n *\n * Read off the decorator rather than passed, so the tab strip, the nav and the\n * search results all name the entity from the one place it names itself.\n */\n readonly entityLabelKey: string;\n /** `@entity({ pluralKey })` — how the collection is named. A list tab's title. */\n readonly entityPluralKey: string;\n readonly basePath: string;\n readonly ListPage: () => ReactElement;\n readonly SingleViewPage: (props?: EntityCrudSingleViewProps) => ReactElement;\n}\n\n/**\n * A picker's transport with its context tags erased.\n *\n * The factory cannot preserve one type parameter per link — the pages that\n * build these know their adapters, the generated form only forwards them — and\n * `EntityForm.linkSources` is already `Record<string, EntityLinkSource<any>>`\n * for the same reason.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyEntityLinkSourceConfig = EntityLinkSourceConfig<Entity, any>;\n\n/**\n * One picker, resolved: the descriptor computed once at factory time, and the\n * use-cases plus adapter context the page builds per render.\n */\nexport interface EntityCrudLinkSource {\n readonly field: string;\n readonly descriptor: EntityFieldDescriptor;\n readonly config: AnyEntityLinkSourceConfig;\n}\n"],"names":[],"mappings":"AAwQA;;;CAGC,GACD,WAIC"}
1
+ {"version":3,"sources":["../../../src/lib/crud/make-entity-crud.types.ts"],"sourcesContent":["import type { EntityRepositoryTag } from '@entifix/business';\nimport type {\n BulkOutcome,\n Entity,\n EntityConstructor,\n EntityFieldDescriptor,\n EntityId,\n EntityMetadataSource,\n EntitySelection,\n} from '@entifix/core';\nimport type {\n EntityDraftStore,\n EntityLinkSourceConfig,\n} from '@entifix/react-integration';\nimport type { Context } from 'effect/Context';\nimport type { CustomTypeOptions } from 'i18next';\nimport type { ReactElement, ReactNode } from 'react';\n\n/**\n * The `entity` catalog keys that carry **both** form titles, a `label` and a\n * `plural`.\n *\n * Derived from the Spanish catalog rather than written out, so the union is the\n * catalog: an entity whose subtree has no `form.editTitle`/`form.newTitle`\n * cannot be handed to {@link makeEntityCrud} at all, and adding a reference\n * entity therefore starts by adding its copy to both locales. That is the whole\n * i18n gate for this factory — `@r10c/i18n-check` scans only\n * `packages/business/ts` for `@useCase()` decorators and never `.tsx`, so a\n * runtime key here would be checked by nothing.\n *\n * `label`/`plural` joined the condition when {@link EntityCrud} began carrying\n * them, so that a workspace tab and a nav entry derived from this descriptor\n * name the entity in the catalog's own words. They are part of the **type**\n * rather than a runtime assertion in the factory, because the catalog is\n * statically known here: a missing `plural` should fail at the call site that\n * generates the screens, not on the render that first tries to title a tab.\n *\n * Keeping the key typed is what lets the generated form call `useT('entity')`\n * with a template literal and still fail the build on a typo, instead of\n * reaching for the `useTranslateKey` escape hatch that authored copy must not\n * use. `AccountLabelKey` in `../session/account-links.ts` is the same trick\n * written out by hand; this one cannot drift because it is computed.\n */\nexport type EntityCatalogKey<\n TEntityCatalog = EntityCatalogOf<TypeOptionsResources>,\n> = [TEntityCatalog] extends [never]\n ? // No host augmentation in this compilation — this package's own specs, or\n // an adopter who has not declared one. The factory still works; the key is\n // simply unchecked, which is the same trade `useTranslateKey` makes.\n string\n : {\n [K in keyof TEntityCatalog]: TEntityCatalog[K] extends {\n form: { editTitle: string; newTitle: string };\n label: string;\n plural: string;\n }\n ? K\n : never;\n }[keyof TEntityCatalog] &\n string;\n\n/**\n * The host's `entity` namespace, read back out of its own `i18next`\n * augmentation.\n *\n * ⚠️ **The `entity` catalog is the host's, not entifix's.** It names *their*\n * entities — a parameter, an offering, a sales channel — so a framework that\n * shipped one would be shipping an application's product copy. Reading it back\n * through `CustomTypeOptions` keeps the key union computed rather than written\n * out, which is what stops it drifting, while leaving the catalog where it\n * belongs. A host that declares no augmentation gets `string`, and the factory\n * still works with the gate relaxed.\n */\ntype TypeOptionsResources = CustomTypeOptions extends { resources: infer R }\n ? R\n : never;\n\ntype EntityCatalogOf<TResources> = TResources extends { entity: infer E }\n ? E\n : never;\n\n/**\n * A relation the generated form edits with a picker.\n *\n * The target is named here rather than derived, because the common case is a\n * **plain foreign key**: when the target lives in another slice's store a typed\n * `EntityLink` is both an illegal import and a cross-store join, so the member\n * is a bare `string` (`ProductSpecification.brandId` into `catalog-reference`)\n * and its `@accessor()` has no vocabulary for \"the target's name\". Hence\n * `labelProperty`/`searchProperty` are stated at the call site instead of being\n * left to `describeEntityColumns`' `'name'` default, which happens to be right\n * today and states nothing.\n *\n * `searchProperty` must be `filterable` on the **target** or the service answers\n * `400`; `useEntityLinkSource` throws at render rather than letting that surface\n * as an empty suggestion list.\n */\nexport interface EntityCrudLink<TAdapters> {\n /** The owning entity's accessor name, e.g. `'brandId'`. */\n readonly field: string;\n readonly entityConstructor: EntityConstructor<Entity>;\n /**\n * Which adapter holds the **target's** repository. Often a different service\n * than the record's own: `catalog-reference` is another slice's store, so\n * resolving an id goes through that domain's own read path.\n */\n readonly repository: AdapterKey<TAdapters, Context<EntityRepositoryTag>>;\n /** Defaults to `'name'`. */\n readonly labelProperty?: string;\n /** Defaults to `'name'`. Must be `filterable` on the target. */\n readonly searchProperty?: string;\n}\n\n/** The keys of `TAdapters` whose value is assignable to `TValue`. */\nexport type AdapterKey<TAdapters, TValue> = {\n [K in keyof TAdapters]: TAdapters[K] extends TValue ? K : never;\n}[keyof TAdapters];\n\nexport interface EntityCrudOptions<TAdapters, TEntity extends Entity> {\n /** The domain shell's adapters hook, e.g. `useMarketplaceAdminAdapters`. */\n readonly useAdapters: () => TAdapters;\n /** Route prefix for both pages, e.g. `'/catalog/product-brand'`. */\n readonly basePath: string;\n /**\n * The entity's `entity` catalog key. Asserted against `@entity({ key })` at\n * factory time — the two are the same string by convention\n * (`entity:product-brand.label` mirrors `key: 'product-brand'`), and letting\n * them drift would title a form after a different entity.\n */\n readonly catalogKey: EntityCatalogKey;\n /** Which adapter holds this entity's own repository. */\n readonly repository: AdapterKey<TAdapters, Context<EntityRepositoryTag>>;\n /**\n * Members the form keeps but does not show — `id` always, plus anything a\n * transaction assigns. A hidden member still round-trips: it is dropped from\n * the rendered fields, not from the draft, so `reconstructEntity` carries it\n * back out of the seeded values.\n */\n readonly hiddenFields?: readonly string[];\n /** `<EntityColumn>` overrides for the list, for presentation metadata cannot express. */\n readonly columns?: ReactNode;\n /**\n * Extra controls beside the table's own — an `<EntityTableToolbar>`.\n *\n * Its own option rather than more `columns`, though both end up as\n * `EntityTable` children and the slots are sorted by component identity: a\n * toolbar filed under a columns prop is a name that lies, and the first thing\n * to go here is a link into a wizard, which is not a column by any reading\n * ([ADR 0045](../../../../../../docs/adr/0045-the-wizard-a-step-graph-and-a-submit-that-hands-off.md)).\n */\n readonly toolbar?: ReactNode;\n /** Frozen at factory time — see `use-entity-link-sources.ts`. */\n readonly links?: readonly EntityCrudLink<TAdapters>[];\n /**\n * Where the entity's served affordances come from — `GET /api/<entity>/$metadata`.\n *\n * Supplying it is what turns on everything ADR 0026 and ADR 0035 describe:\n * Save and Delete filtered against the caller's real grants, the declared\n * verbs on the form, the row overflow menu, and the bulk bar. Omitting it\n * keeps the pre-0026 behaviour exactly, which is what every generated catalog\n * rendered before this option existed.\n *\n * A `EntityMetadataSource` rather than a URL because the two hosts reach\n * their service differently — one through the config-driven REST adapters,\n * one through a shell's own same-origin routes.\n */\n readonly metadataSource?: EntityMetadataSource;\n /**\n * Which adapter holds this entity's {@link EntityMetadataSource} — the same\n * source as {@link metadataSource}, resolved from the host's composition\n * instead of built by the caller.\n *\n * Prefer it: a source is a transport, and naming it by key keeps the module\n * that generates the screens free of the adapter that fetches, exactly as\n * {@link repository} already does for records. Supplying both is a build\n * error — two answers to where the document comes from.\n */\n readonly metadata?: AdapterKey<TAdapters, EntityMetadataSource>;\n /**\n * Runs a `collection`-bound verb over a selection, and reports **per row**.\n *\n * Supplying it opts the list into the selection column and the bulk bar.\n * It is separate from `metadataSource` because the two are independent: an\n * entity can declare no collection verb and still want permission-filtered\n * Save, and the endpoint a verb posts to is the shell's knowledge, not\n * metadata's.\n */\n readonly runBulkUseCase?: (\n key: string,\n selection: EntitySelection<TEntity>,\n ) => Promise<readonly BulkOutcome[]>;\n /**\n * Runs an `entity`-bound verb on the record the single view is showing.\n *\n * The sibling of {@link runBulkUseCase}, and it had to exist for the same\n * reason: `EntityForm` has rendered these buttons since ADR 0035, and\n * `EntityCrudForm` has accepted an `onUseCase` for as long — but nothing ever\n * passed one, so a generated screen showed a declared, granted, served verb\n * that did nothing when clicked. Measured on `ProductOffering`'s `publish`,\n * which passed every `@r10c/slices` invariant and appeared nowhere.\n *\n * Resolving means the record changed, and the page reloads it: a verb that\n * moves a lifecycle leaves the form showing the old state otherwise, which\n * reads as \"the button did nothing\". Rejecting surfaces through the form's\n * own error slot, so a `409` from an illegal transition renders as the coded\n * message the catalog holds rather than a thrown promise nobody catches.\n */\n readonly runUseCase?: (key: string, id: EntityId) => Promise<void>;\n}\n\n/**\n * Props both hosts pass. A route host passes none — the slug comes from the URL\n * and a save returns to the list; the workspace tab host passes all of them.\n */\nexport interface EntityCrudSingleViewProps {\n /** Defaults to the `[slug]` route param. */\n readonly slug?: string;\n /** Defaults to navigating back to the list. */\n readonly onSaved?: () => void;\n readonly onDeleted?: () => void;\n /**\n * Where to autosave the edit. Supplying it is the whole opt-in: the form\n * seeds from the persisted draft, writes to it on every edit, and the page\n * clears it once a save or delete commits.\n *\n * A route host omits it and stays ephemeral, which is the rule stated as a\n * missing prop rather than as a flag — there is no value of \"absent\" that\n * accidentally starts persisting.\n */\n readonly draft?: EntityDraftStore;\n}\n\n/**\n * What the factory returns: a **named descriptor**, not four loose components.\n *\n * The identity fields are here so the workspace registry and the nav are derived\n * from a list of these rather than from the hand-written const maps they replace\n * (#141).\n */\nexport interface EntityCrud<TEntity extends Entity> {\n readonly entityConstructor: EntityConstructor<TEntity>;\n /** `@entity({ key })`, which is also `catalogKey` and the tab address payload. */\n readonly entityKey: EntityCatalogKey;\n /**\n * `@entity({ labelKey })` — how one record is named. A record tab's title.\n *\n * Read off the decorator rather than passed, so the tab strip, the nav and the\n * search results all name the entity from the one place it names itself.\n */\n readonly entityLabelKey: string;\n /** `@entity({ pluralKey })` — how the collection is named. A list tab's title. */\n readonly entityPluralKey: string;\n readonly basePath: string;\n readonly ListPage: () => ReactElement;\n readonly SingleViewPage: (props?: EntityCrudSingleViewProps) => ReactElement;\n}\n\n/**\n * A picker's transport with its context tags erased.\n *\n * The factory cannot preserve one type parameter per link — the pages that\n * build these know their adapters, the generated form only forwards them — and\n * `EntityForm.linkSources` is already `Record<string, EntityLinkSource<any>>`\n * for the same reason.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyEntityLinkSourceConfig = EntityLinkSourceConfig<Entity, any>;\n\n/**\n * One picker, resolved: the descriptor computed once at factory time, and the\n * use-cases plus adapter context the page builds per render.\n */\nexport interface EntityCrudLinkSource {\n readonly field: string;\n readonly descriptor: EntityFieldDescriptor;\n readonly config: AnyEntityLinkSourceConfig;\n}\n"],"names":[],"mappings":"AA4QA;;;CAGC,GACD,WAIC"}
@@ -5,13 +5,12 @@
5
5
  * They ship from `@entifix/next-shell/server` because a route handler must
6
6
  * not come from the `"use client"` bundle.
7
7
  */
8
+ import type { ConfigurationSource } from '../config/configuration-source.js';
8
9
  export interface HealthRouteOptions {
9
10
  /** The app's package name, echoed back so a probe says what it reached. */
10
11
  readonly app: string;
11
- /** Base URL of config-service, e.g. `http://localhost:3190`. */
12
- readonly configApiUrl: string;
13
- /** The app's config key, i.e. the `:service` in `GET /api/config/:service`. */
14
- readonly configKey: string;
12
+ /** The configuration readiness checks — the same source `/api/config` reads. */
13
+ readonly configuration: ConfigurationSource;
15
14
  }
16
15
  /**
17
16
  * Build the `GET` handlers for `/api/health`, `/api/health/live` and
@@ -1 +1 @@
1
- {"version":3,"file":"health-routes.d.ts","sourceRoot":"","sources":["../../../src/lib/health/health-routes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiCH,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,kBAAkB;IAuB1D,4DAA4D;;IAG5D,6BAA6B;;IAQ7B,8BAA8B;;CAejC,CAAC"}
1
+ {"version":3,"file":"health-routes.d.ts","sourceRoot":"","sources":["../../../src/lib/health/health-routes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AA+B7E,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,QAAQ,CAAC,aAAa,EAAE,mBAAmB,CAAC;CAC7C;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,kBAAkB;IAqB1D,4DAA4D;;IAG5D,6BAA6B;;IAQ7B,8BAA8B;;CAejC,CAAC"}
@@ -4,8 +4,7 @@
4
4
  *
5
5
  * They ship from `@entifix/next-shell/server` because a route handler must
6
6
  * not come from the `"use client"` bundle.
7
- */ import { SERVICE_TOKEN_HEADER, serviceToken } from '../config/service-token.js';
8
- /** How long a readiness result is reused, so probes cannot hammer config-service. */ const READY_CACHE_MS = 1000;
7
+ */ /** How long a readiness result is reused, so probes cannot hammer config-service. */ const READY_CACHE_MS = 1000;
9
8
  /** A readiness check that hangs is a readiness check that failed. */ const READY_TIMEOUT_MS = 2000;
10
9
  /**
11
10
  * Which build is answering: `next dev` or `next start`.
@@ -38,15 +37,14 @@
38
37
  let cached = null;
39
38
  const checkConfig = async ()=>{
40
39
  try {
41
- // The fleet token is not optional here: `GET /api/config/:service` serves
42
- // real credentials and answers `401` without it, which a readiness probe
43
- // reads as "degraded" — permanently, for an app that is in fact fine.
44
- const response = await fetch(`${options.configApiUrl}/api/config/${options.configKey}`, {
40
+ // The source's headers are not optional here: a configuration service
41
+ // that gates its lookup answers `401` without them, which a readiness
42
+ // probe reads as "degraded" — permanently, for an app that is in fact fine.
43
+ const { url, headers } = options.configuration();
44
+ const response = await fetch(url, {
45
45
  signal: AbortSignal.timeout(READY_TIMEOUT_MS),
46
46
  cache: 'no-store',
47
- headers: {
48
- [SERVICE_TOKEN_HEADER]: serviceToken()
49
- }
47
+ headers
50
48
  });
51
49
  return response.ok;
52
50
  } catch (unused) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/health/health-routes.ts"],"sourcesContent":["/**\n * Probe route handlers for the Next apps, mirroring what\n * `@entifix/service-shell` mounts on the backends.\n *\n * They ship from `@entifix/next-shell/server` because a route handler must\n * not come from the `\"use client\"` bundle.\n */\n\nimport { SERVICE_TOKEN_HEADER, serviceToken } from '../config/service-token.js';\n\n/** How long a readiness result is reused, so probes cannot hammer config-service. */\nconst READY_CACHE_MS = 1_000;\n\n/** A readiness check that hangs is a readiness check that failed. */\nconst READY_TIMEOUT_MS = 2_000;\n\n/**\n * Which build is answering: `next dev` or `next start`.\n *\n * Liveness carries it because an e2e run needs to know *which artifact* it\n * attached to. Playwright reuses whatever already listens on the app's port, so\n * a suite started while a dev server is up tests a different bundle against a\n * different backend than the one it claims to — see `assertExpectedServer` in\n * `@entifix/testing-e2e/playwright`.\n *\n * On liveness rather than readiness because liveness is the one endpoint that\n * answers from the process alone, before config-service or any backend is up.\n *\n * Not an information leak worth avoiding: a dev build already announces itself\n * in its asset paths long before anything asks this endpoint.\n */\nconst buildMode = (): 'development' | 'production' =>\n process.env.NODE_ENV === 'production' ? 'production' : 'development';\n\ninterface ReadyState {\n readonly at: number;\n readonly ready: boolean;\n}\n\nexport interface HealthRouteOptions {\n /** The app's package name, echoed back so a probe says what it reached. */\n readonly app: string;\n /** Base URL of config-service, e.g. `http://localhost:3190`. */\n readonly configApiUrl: string;\n /** The app's config key, i.e. the `:service` in `GET /api/config/:service`. */\n readonly configKey: string;\n}\n\n/**\n * Build the `GET` handlers for `/api/health`, `/api/health/live` and\n * `/api/health/ready`.\n *\n * **Liveness** answers from the process alone — no config-service, no backend,\n * no session. That is what makes it usable as Playwright's `readyPath` and what\n * keeps a dependency blip from getting the app killed by Kubernetes later.\n *\n * **Readiness** checks the one dependency the app cannot render without: its\n * configuration. It deliberately does *not* chain to the domain backend —\n * cascading readiness turns one degraded service into a fleet-wide outage, and\n * a page that renders with a degraded backend is still worth serving.\n */\nexport const createHealthRoutes = (options: HealthRouteOptions) => {\n let cached: ReadyState | null = null;\n\n const checkConfig = async (): Promise<boolean> => {\n try {\n // The fleet token is not optional here: `GET /api/config/:service` serves\n // real credentials and answers `401` without it, which a readiness probe\n // reads as \"degraded\" — permanently, for an app that is in fact fine.\n const response = await fetch(\n `${options.configApiUrl}/api/config/${options.configKey}`,\n {\n signal: AbortSignal.timeout(READY_TIMEOUT_MS),\n cache: 'no-store',\n headers: { [SERVICE_TOKEN_HEADER]: serviceToken() },\n },\n );\n return response.ok;\n } catch {\n return false;\n }\n };\n\n return {\n /** `GET /api/health` — the original endpoint, unchanged. */\n health: () => Response.json({ status: 'ok', app: options.app }),\n\n /** `GET /api/health/live` */\n live: () =>\n Response.json({\n status: 'live',\n app: options.app,\n mode: buildMode(),\n }),\n\n /** `GET /api/health/ready` */\n ready: async () => {\n const now = Date.now();\n if (cached === null || now - cached.at >= READY_CACHE_MS) {\n cached = { at: now, ready: await checkConfig() };\n }\n\n return cached.ready\n ? Response.json({ status: 'ready', app: options.app })\n : Response.json(\n { status: 'degraded', app: options.app, failing: ['config'] },\n { status: 503 },\n );\n },\n };\n};\n"],"names":["SERVICE_TOKEN_HEADER","serviceToken","READY_CACHE_MS","READY_TIMEOUT_MS","buildMode","process","env","NODE_ENV","createHealthRoutes","options","cached","checkConfig","response","fetch","configApiUrl","configKey","signal","AbortSignal","timeout","cache","headers","ok","health","Response","json","status","app","live","mode","ready","now","Date","at","failing"],"mappings":"AAAA;;;;;;CAMC,GAED,SAASA,oBAAoB,EAAEC,YAAY,QAAQ,6BAA6B;AAEhF,mFAAmF,GACnF,MAAMC,iBAAiB;AAEvB,mEAAmE,GACnE,MAAMC,mBAAmB;AAEzB;;;;;;;;;;;;;;CAcC,GACD,MAAMC,YAAY,IAChBC,QAAQC,GAAG,CAACC,QAAQ,KAAK,eAAe,eAAe;AAgBzD;;;;;;;;;;;;CAYC,GACD,OAAO,MAAMC,qBAAqB,CAACC;IACjC,IAAIC,SAA4B;IAEhC,MAAMC,cAAc;QAClB,IAAI;YACF,0EAA0E;YAC1E,yEAAyE;YACzE,sEAAsE;YACtE,MAAMC,WAAW,MAAMC,MACrB,GAAGJ,QAAQK,YAAY,CAAC,YAAY,EAAEL,QAAQM,SAAS,EAAE,EACzD;gBACEC,QAAQC,YAAYC,OAAO,CAACf;gBAC5BgB,OAAO;gBACPC,SAAS;oBAAE,CAACpB,qBAAqB,EAAEC;gBAAe;YACpD;YAEF,OAAOW,SAASS,EAAE;QACpB,EAAE,eAAM;YACN,OAAO;QACT;IACF;IAEA,OAAO;QACL,0DAA0D,GAC1DC,QAAQ,IAAMC,SAASC,IAAI,CAAC;gBAAEC,QAAQ;gBAAMC,KAAKjB,QAAQiB,GAAG;YAAC;QAE7D,2BAA2B,GAC3BC,MAAM,IACJJ,SAASC,IAAI,CAAC;gBACZC,QAAQ;gBACRC,KAAKjB,QAAQiB,GAAG;gBAChBE,MAAMxB;YACR;QAEF,4BAA4B,GAC5ByB,OAAO;YACL,MAAMC,MAAMC,KAAKD,GAAG;YACpB,IAAIpB,WAAW,QAAQoB,MAAMpB,OAAOsB,EAAE,IAAI9B,gBAAgB;gBACxDQ,SAAS;oBAAEsB,IAAIF;oBAAKD,OAAO,MAAMlB;gBAAc;YACjD;YAEA,OAAOD,OAAOmB,KAAK,GACfN,SAASC,IAAI,CAAC;gBAAEC,QAAQ;gBAASC,KAAKjB,QAAQiB,GAAG;YAAC,KAClDH,SAASC,IAAI,CACX;gBAAEC,QAAQ;gBAAYC,KAAKjB,QAAQiB,GAAG;gBAAEO,SAAS;oBAAC;iBAAS;YAAC,GAC5D;gBAAER,QAAQ;YAAI;QAEtB;IACF;AACF,EAAE"}
1
+ {"version":3,"sources":["../../../src/lib/health/health-routes.ts"],"sourcesContent":["/**\n * Probe route handlers for the Next apps, mirroring what\n * `@entifix/service-shell` mounts on the backends.\n *\n * They ship from `@entifix/next-shell/server` because a route handler must\n * not come from the `\"use client\"` bundle.\n */\n\nimport type { ConfigurationSource } from '../config/configuration-source.js';\n\n/** How long a readiness result is reused, so probes cannot hammer config-service. */\nconst READY_CACHE_MS = 1_000;\n\n/** A readiness check that hangs is a readiness check that failed. */\nconst READY_TIMEOUT_MS = 2_000;\n\n/**\n * Which build is answering: `next dev` or `next start`.\n *\n * Liveness carries it because an e2e run needs to know *which artifact* it\n * attached to. Playwright reuses whatever already listens on the app's port, so\n * a suite started while a dev server is up tests a different bundle against a\n * different backend than the one it claims to — see `assertExpectedServer` in\n * `@entifix/testing-e2e/playwright`.\n *\n * On liveness rather than readiness because liveness is the one endpoint that\n * answers from the process alone, before config-service or any backend is up.\n *\n * Not an information leak worth avoiding: a dev build already announces itself\n * in its asset paths long before anything asks this endpoint.\n */\nconst buildMode = (): 'development' | 'production' =>\n process.env.NODE_ENV === 'production' ? 'production' : 'development';\n\ninterface ReadyState {\n readonly at: number;\n readonly ready: boolean;\n}\n\nexport interface HealthRouteOptions {\n /** The app's package name, echoed back so a probe says what it reached. */\n readonly app: string;\n /** The configuration readiness checks — the same source `/api/config` reads. */\n readonly configuration: ConfigurationSource;\n}\n\n/**\n * Build the `GET` handlers for `/api/health`, `/api/health/live` and\n * `/api/health/ready`.\n *\n * **Liveness** answers from the process alone — no config-service, no backend,\n * no session. That is what makes it usable as Playwright's `readyPath` and what\n * keeps a dependency blip from getting the app killed by Kubernetes later.\n *\n * **Readiness** checks the one dependency the app cannot render without: its\n * configuration. It deliberately does *not* chain to the domain backend —\n * cascading readiness turns one degraded service into a fleet-wide outage, and\n * a page that renders with a degraded backend is still worth serving.\n */\nexport const createHealthRoutes = (options: HealthRouteOptions) => {\n let cached: ReadyState | null = null;\n\n const checkConfig = async (): Promise<boolean> => {\n try {\n // The source's headers are not optional here: a configuration service\n // that gates its lookup answers `401` without them, which a readiness\n // probe reads as \"degraded\" — permanently, for an app that is in fact fine.\n const { url, headers } = options.configuration();\n const response = await fetch(url, {\n signal: AbortSignal.timeout(READY_TIMEOUT_MS),\n cache: 'no-store',\n headers,\n });\n return response.ok;\n } catch {\n return false;\n }\n };\n\n return {\n /** `GET /api/health` — the original endpoint, unchanged. */\n health: () => Response.json({ status: 'ok', app: options.app }),\n\n /** `GET /api/health/live` */\n live: () =>\n Response.json({\n status: 'live',\n app: options.app,\n mode: buildMode(),\n }),\n\n /** `GET /api/health/ready` */\n ready: async () => {\n const now = Date.now();\n if (cached === null || now - cached.at >= READY_CACHE_MS) {\n cached = { at: now, ready: await checkConfig() };\n }\n\n return cached.ready\n ? Response.json({ status: 'ready', app: options.app })\n : Response.json(\n { status: 'degraded', app: options.app, failing: ['config'] },\n { status: 503 },\n );\n },\n };\n};\n"],"names":["READY_CACHE_MS","READY_TIMEOUT_MS","buildMode","process","env","NODE_ENV","createHealthRoutes","options","cached","checkConfig","url","headers","configuration","response","fetch","signal","AbortSignal","timeout","cache","ok","health","Response","json","status","app","live","mode","ready","now","Date","at","failing"],"mappings":"AAAA;;;;;;CAMC,GAID,mFAAmF,GACnF,MAAMA,iBAAiB;AAEvB,mEAAmE,GACnE,MAAMC,mBAAmB;AAEzB;;;;;;;;;;;;;;CAcC,GACD,MAAMC,YAAY,IAChBC,QAAQC,GAAG,CAACC,QAAQ,KAAK,eAAe,eAAe;AAczD;;;;;;;;;;;;CAYC,GACD,OAAO,MAAMC,qBAAqB,CAACC;IACjC,IAAIC,SAA4B;IAEhC,MAAMC,cAAc;QAClB,IAAI;YACF,sEAAsE;YACtE,sEAAsE;YACtE,4EAA4E;YAC5E,MAAM,EAAEC,GAAG,EAAEC,OAAO,EAAE,GAAGJ,QAAQK,aAAa;YAC9C,MAAMC,WAAW,MAAMC,MAAMJ,KAAK;gBAChCK,QAAQC,YAAYC,OAAO,CAAChB;gBAC5BiB,OAAO;gBACPP;YACF;YACA,OAAOE,SAASM,EAAE;QACpB,EAAE,eAAM;YACN,OAAO;QACT;IACF;IAEA,OAAO;QACL,0DAA0D,GAC1DC,QAAQ,IAAMC,SAASC,IAAI,CAAC;gBAAEC,QAAQ;gBAAMC,KAAKjB,QAAQiB,GAAG;YAAC;QAE7D,2BAA2B,GAC3BC,MAAM,IACJJ,SAASC,IAAI,CAAC;gBACZC,QAAQ;gBACRC,KAAKjB,QAAQiB,GAAG;gBAChBE,MAAMxB;YACR;QAEF,4BAA4B,GAC5ByB,OAAO;YACL,MAAMC,MAAMC,KAAKD,GAAG;YACpB,IAAIpB,WAAW,QAAQoB,MAAMpB,OAAOsB,EAAE,IAAI9B,gBAAgB;gBACxDQ,SAAS;oBAAEsB,IAAIF;oBAAKD,OAAO,MAAMlB;gBAAc;YACjD;YAEA,OAAOD,OAAOmB,KAAK,GACfN,SAASC,IAAI,CAAC;gBAAEC,QAAQ;gBAASC,KAAKjB,QAAQiB,GAAG;YAAC,KAClDH,SAASC,IAAI,CACX;gBAAEC,QAAQ;gBAAYC,KAAKjB,QAAQiB,GAAG;gBAAEO,SAAS;oBAAC;iBAAS;YAAC,GAC5D;gBAAER,QAAQ;YAAI;QAEtB;IACF;AACF,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../../../src/lib/i18n/catalog/en.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG,cAAc,SAAS,EAAE,KAAK,CAAC;AAE9C,eAAO,MAAM,KAAK,EAAE,OAsWnB,CAAC"}
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../../../src/lib/i18n/catalog/en.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG,cAAc,SAAS,EAAE,KAAK,CAAC;AAE9C,eAAO,MAAM,KAAK,EAAE,OA8MnB,CAAC"}
@@ -1,69 +1,4 @@
1
1
  export const shell = {
2
- auth: {
3
- nav: {
4
- identity: 'Identity',
5
- users: 'Users',
6
- accountSection: 'Account'
7
- },
8
- account: {
9
- overline: 'Account',
10
- title: 'My account',
11
- subtitle: 'Your identity and your access to the r10c fleet.',
12
- menu: 'Account',
13
- identifiers: 'Identifiers',
14
- noIdentifiers: 'No identifiers on record.',
15
- userId: 'User ID',
16
- subject: 'Subject',
17
- session: 'Session',
18
- roles: 'Roles',
19
- none: 'None',
20
- failed: 'We could not load your account.'
21
- },
22
- sessions: {
23
- overline: 'Security',
24
- title: 'Active sessions',
25
- subtitle: 'Where you are signed in. End anything you do not recognise.',
26
- current: 'This device',
27
- unknownDevice: 'Unknown device',
28
- startedAt: 'Started',
29
- expiresAt: 'Expires',
30
- lastIp: 'IP',
31
- revoke: 'End',
32
- revoking: 'Ending…',
33
- revokeOthers: 'End all others',
34
- empty: 'No other active sessions.',
35
- failed: 'We could not load your sessions.',
36
- loading: 'Loading sessions…'
37
- },
38
- security: {
39
- overline: 'Security',
40
- title: 'Password and access',
41
- subtitle: 'Your password, your second factor and your linked accounts live in r10c Identity.',
42
- explain: 'r10c does not store your password. Manage it, along with two-step verification and social sign-in, at the identity provider.',
43
- manage: 'Manage at r10c Identity'
44
- },
45
- fields: {
46
- displayName: 'Display name',
47
- email: 'Email',
48
- username: 'Username',
49
- role: 'Role'
50
- },
51
- submit: {
52
- wait: 'Please wait…',
53
- creating: 'Creating…',
54
- createUser: 'Create user'
55
- },
56
- users: {
57
- title: 'Users',
58
- newTitle: 'New user',
59
- fallbackName: 'User',
60
- sessionsTitle: 'This user’s sessions',
61
- sessionsEmpty: 'This user has no active sessions.',
62
- sessionsFailed: 'We could not load this user’s sessions.',
63
- kick: 'End all their sessions',
64
- kicking: 'Ending…'
65
- }
66
- },
67
2
  /**
68
3
  * The stock surface — the first Operaciones screens in the back office.
69
4
  *
@@ -261,86 +196,6 @@ export const shell = {
261
196
  savePending_other: 'Saving {{count}} records…',
262
197
  saveFailed: 'The record could not be saved.',
263
198
  saveFailedDismiss: 'Dismiss'
264
- },
265
- storefront: {
266
- nav: {
267
- catalog: 'Catalog'
268
- },
269
- home: {
270
- overline: 'Storefront',
271
- heading: 'r10c Marketplace',
272
- lead: 'Things for the house, chosen slowly.',
273
- featured: 'Featured'
274
- },
275
- category: {
276
- overline: 'Category',
277
- empty: 'Nothing in this category yet.',
278
- sort: 'Sort',
279
- sortByName: 'Name',
280
- sortByCode: 'Reference',
281
- results: '{{count}} products',
282
- previous: 'Previous',
283
- next: 'Next',
284
- pageOf: 'Page {{page}} of {{pages}}'
285
- },
286
- product: {
287
- addToCart: 'Add to cart',
288
- view: 'View product',
289
- brand: 'Brand',
290
- category: 'Category',
291
- reference: 'Reference',
292
- related: 'You might also like',
293
- available: 'Available',
294
- unavailable: 'Out of stock'
295
- },
296
- search: {
297
- heading: 'Search',
298
- label: 'Search products',
299
- placeholder: 'Lamp, mug, blanket…',
300
- submit: 'Search',
301
- resultsFor: 'Results for “{{term}}”',
302
- empty: 'Nothing matched “{{term}}”.',
303
- prompt: 'Type something to start searching.'
304
- },
305
- cart: {
306
- heading: 'Cart',
307
- empty: 'Your cart is empty.',
308
- remove: 'Remove',
309
- units: 'Qty {{count}}',
310
- total: 'Items in total',
311
- keepShopping: 'Keep shopping',
312
- checkout: 'Check out'
313
- },
314
- checkout: {
315
- placed: 'Your order is placed. The vendor has been notified.',
316
- unavailable: 'One of these is no longer available in the quantity you asked for. Nothing was charged, and every hold has been released.',
317
- empty: 'Nothing here is still on sale.',
318
- failed: 'Checkout could not be completed. Please try again.'
319
- },
320
- order: {
321
- heading: 'Thank you for your purchase',
322
- placed: 'Your order is placed, and the vendor has been notified.',
323
- reference: 'Order number',
324
- units: 'Qty {{count}}',
325
- total: 'Total',
326
- tooManyLines: 'This order has {{count}} items, too many to list here. The order number above identifies all of them.',
327
- keepShopping: 'Keep shopping',
328
- expiredHeading: 'There is no order to show',
329
- expired: 'The receipt for your last purchase is no longer available in this browser. If you have just bought something, check your confirmation email.',
330
- // The window is named rather than left for the button to stop working on
331
- // its own: the receipt carries the moment the server stamped, and the two
332
- // agree because `RECEIPT_TTL_SECONDS` and the service's own dial are one
333
- // number (ADR 0058 §5).
334
- cancel: 'Cancel order',
335
- cancelWindow: 'You can cancel this order until {{time}}.',
336
- cancelPending: 'Cancelling…',
337
- cancelledHeading: 'Order cancelled',
338
- cancelled: 'We have cancelled your order and the refund is on its way. It can take a few days to appear on your statement.',
339
- cancelFailed: 'The order could not be cancelled. The window may have closed, or it may already be on its way.'
340
- },
341
- footer: {
342
- note: 'Demo catalog. No order is real.'
343
- }
344
199
  }
345
200
  };
346
201
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/i18n/catalog/en.ts"],"sourcesContent":["type EsShell = typeof import('./es.js').shell;\n\nexport const shell: EsShell = {\n auth: {\n nav: {\n identity: 'Identity',\n users: 'Users',\n accountSection: 'Account',\n },\n account: {\n overline: 'Account',\n title: 'My account',\n subtitle: 'Your identity and your access to the r10c fleet.',\n menu: 'Account',\n identifiers: 'Identifiers',\n noIdentifiers: 'No identifiers on record.',\n userId: 'User ID',\n subject: 'Subject',\n session: 'Session',\n roles: 'Roles',\n none: 'None',\n failed: 'We could not load your account.',\n },\n sessions: {\n overline: 'Security',\n title: 'Active sessions',\n subtitle: 'Where you are signed in. End anything you do not recognise.',\n current: 'This device',\n unknownDevice: 'Unknown device',\n startedAt: 'Started',\n expiresAt: 'Expires',\n lastIp: 'IP',\n revoke: 'End',\n revoking: 'Ending…',\n revokeOthers: 'End all others',\n empty: 'No other active sessions.',\n failed: 'We could not load your sessions.',\n loading: 'Loading sessions…',\n },\n security: {\n overline: 'Security',\n title: 'Password and access',\n subtitle:\n 'Your password, your second factor and your linked accounts live in r10c Identity.',\n explain:\n 'r10c does not store your password. Manage it, along with two-step verification and social sign-in, at the identity provider.',\n manage: 'Manage at r10c Identity',\n },\n fields: {\n displayName: 'Display name',\n email: 'Email',\n username: 'Username',\n role: 'Role',\n },\n submit: {\n wait: 'Please wait…',\n creating: 'Creating…',\n createUser: 'Create user',\n },\n users: {\n title: 'Users',\n newTitle: 'New user',\n fallbackName: 'User',\n sessionsTitle: 'This user’s sessions',\n sessionsEmpty: 'This user has no active sessions.',\n sessionsFailed: 'We could not load this user’s sessions.',\n kick: 'End all their sessions',\n kicking: 'Ending…',\n },\n },\n /**\n * The stock surface — the first Operaciones screens in the back office.\n *\n * The *tier* name (\"Operaciones\") comes from `nav.screenType.operation`; this\n * names the group inside it.\n */\n stock: {\n nav: {\n stock: 'Stock',\n items: 'Stock on hand',\n movements: 'Movement ledger',\n reservations: 'Reservations',\n },\n },\n order: {\n nav: {\n orders: 'Orders',\n },\n },\n settlement: {\n nav: {\n settlement: 'Settlement',\n agreements: 'Agreements',\n entries: 'Commission entries',\n runs: 'Settlement runs',\n payouts: 'Vendor payouts',\n },\n agreement: {\n channelRatesHint:\n 'Leave blank to charge the default commission on that channel. A 0 means nothing is charged.',\n channelRateDefault: 'Default',\n noChannelRates: 'No per-channel rates',\n },\n },\n sales: {\n nav: {\n sales: 'Sales',\n channels: 'Sales channels',\n guided: 'Sales',\n counterSale: 'Sell at the counter',\n },\n counterSale: {\n title: 'Counter sale',\n steps: {\n channel: 'Channel',\n lines: 'Products',\n payment: 'Payment',\n summary: 'Summary',\n },\n channelHint: 'Pick the channel this sale goes through.',\n linesHint: 'Add the published products you are selling.',\n addLine: 'Add product',\n removeLine: 'Remove',\n quantity: 'Quantity',\n offering: 'Product',\n total: 'Total',\n paymentMethod: 'Payment method',\n charge: 'Charge',\n sold: 'Sale recorded',\n soldDetail: 'The stock is already drawn down and the order is written.',\n newSale: 'New sale',\n emptyLines: 'Add at least one product to charge for.',\n },\n },\n marketplaceAdmin: {\n nav: {\n catalog: 'Catalog',\n products: 'Products',\n brands: 'Brands',\n categories: 'Categories',\n offerings: 'Product offerings',\n offeringPrices: 'Offering prices',\n guided: 'Catalog',\n },\n wizard: {\n productSetup: {\n title: 'New product',\n launch: 'Guided new product',\n steps: {\n start: 'Source',\n source: 'Base product',\n identity: 'Identification',\n classification: 'Classification',\n summary: 'Summary',\n },\n start: {\n question: 'How do you want to start?',\n blank: 'From scratch',\n blankHint: 'Enter the details by hand.',\n duplicate: 'Duplicate an existing one',\n duplicateHint:\n 'Start from a product already on file. The code is not copied: it identifies the original.',\n },\n source: {\n prompt: 'Pick the product to start from.',\n chosen: 'Base product: {{name}}',\n required: 'Pick a product to continue.',\n },\n summary: {\n prompt: 'Check what you entered before creating it.',\n origin: 'Source',\n originBlank: 'From scratch',\n originDuplicate: 'Duplicated from {{name}}',\n empty: 'Not set',\n },\n recap: 'You had already answered:',\n },\n },\n },\n systemManagement: {\n nav: {\n section: 'System',\n configuration: 'Configuration',\n },\n configuration: {\n title: 'Platform configuration',\n description:\n 'Parameters every service resolves at boot. Editing a value affects that service on its next start.',\n secretPlaceholder: '•••••• (unchanged)',\n secretHint:\n 'Leaving this blank keeps the stored value. Typing a new one replaces it.',\n },\n },\n nav: {\n primary: 'Primary',\n openInWorkspace: 'Open {{label}} in workspace',\n openInWorkspaceShort: 'Open in workspace',\n openInNewTab: 'Open {{label}} in a new tab',\n openInNewTabShort: 'Open in a new tab',\n /**\n * The screen taxonomy (ADR 0033). Translated like every other string rather\n * than kept in Spanish: what that decision fixed was which *Spanish* word\n * ships to the default locale, not that the term is untranslatable.\n */\n screenType: {\n master: 'Definitions',\n operation: 'Operations',\n wizard: 'Wizards',\n report: 'Reports',\n },\n },\n commandPalette: {\n open: 'Search or run',\n title: 'Search or run',\n placeholder: 'Search a record, a screen or a command…',\n newPlaceholder: 'What would you like to create?',\n newLabel: 'New…',\n newTitle: 'New',\n back: 'Back',\n empty: 'No results',\n loading: 'Searching…',\n more_one: '{{count}} more',\n more_other: '{{count}} more',\n typeMore: 'Type at least {{count}} characters to search records.',\n groups: {\n actions: 'Actions',\n commands: 'Commands',\n navigation: 'Navigation',\n tabs: 'Open tabs',\n records: 'Records',\n },\n unavailableScope: 'Not available here: {{reason}}',\n unavailableReach: 'We could not reach this source: {{reason}}',\n openInWorkspaceHint: 'Tab',\n },\n sidebar: {\n expand: 'Expand sidebar',\n collapse: 'Collapse sidebar',\n openMenu: 'Open the menu',\n closeMenu: 'Close the menu',\n menu: 'Navigation menu',\n expandGroup: 'Expand {{group}}',\n collapseGroup: 'Collapse {{group}}',\n },\n session: {\n expiringSoon:\n 'Your session is about to expire. Save your work and sign in again to continue.',\n },\n breadcrumbs: {\n home: 'Home',\n // The `/new` segment, which every domain's create route shares. It was\n // an auth-specific string until one host started serving two domains,\n // at which point a catalog page's breadcrumb read \"New user\".\n new: 'New',\n },\n account: {\n profile: 'Profile',\n security: 'Security',\n sessions: 'Sessions',\n signOut: 'Sign out',\n },\n workspace: {\n copyLink: 'Copy link',\n empty: 'No open tabs. Pick a catalog from the sidebar to start.',\n unsupported: \"This tab can't be opened here.\",\n discardTitle: 'Discard changes',\n discard: 'This tab has unsaved changes. Closing it will lose them.',\n discardConfirm: 'Discard',\n // See the Spanish catalog for why a failure's reason is not a key here.\n pendingLabel: 'Save status',\n savePending_one: 'Saving 1 record…',\n savePending_other: 'Saving {{count}} records…',\n saveFailed: 'The record could not be saved.',\n saveFailedDismiss: 'Dismiss',\n },\n storefront: {\n nav: {\n catalog: 'Catalog',\n },\n home: {\n overline: 'Storefront',\n heading: 'r10c Marketplace',\n lead: 'Things for the house, chosen slowly.',\n featured: 'Featured',\n },\n category: {\n overline: 'Category',\n empty: 'Nothing in this category yet.',\n sort: 'Sort',\n sortByName: 'Name',\n sortByCode: 'Reference',\n results: '{{count}} products',\n previous: 'Previous',\n next: 'Next',\n pageOf: 'Page {{page}} of {{pages}}',\n },\n product: {\n addToCart: 'Add to cart',\n view: 'View product',\n brand: 'Brand',\n category: 'Category',\n reference: 'Reference',\n related: 'You might also like',\n available: 'Available',\n unavailable: 'Out of stock',\n },\n search: {\n heading: 'Search',\n label: 'Search products',\n placeholder: 'Lamp, mug, blanket…',\n submit: 'Search',\n resultsFor: 'Results for “{{term}}”',\n empty: 'Nothing matched “{{term}}”.',\n prompt: 'Type something to start searching.',\n },\n cart: {\n heading: 'Cart',\n empty: 'Your cart is empty.',\n remove: 'Remove',\n units: 'Qty {{count}}',\n total: 'Items in total',\n keepShopping: 'Keep shopping',\n checkout: 'Check out',\n },\n checkout: {\n placed: 'Your order is placed. The vendor has been notified.',\n unavailable:\n 'One of these is no longer available in the quantity you asked for. Nothing was charged, and every hold has been released.',\n empty: 'Nothing here is still on sale.',\n failed: 'Checkout could not be completed. Please try again.',\n },\n order: {\n heading: 'Thank you for your purchase',\n placed: 'Your order is placed, and the vendor has been notified.',\n reference: 'Order number',\n units: 'Qty {{count}}',\n total: 'Total',\n tooManyLines:\n 'This order has {{count}} items, too many to list here. The order number above identifies all of them.',\n keepShopping: 'Keep shopping',\n expiredHeading: 'There is no order to show',\n expired:\n 'The receipt for your last purchase is no longer available in this browser. If you have just bought something, check your confirmation email.',\n // The window is named rather than left for the button to stop working on\n // its own: the receipt carries the moment the server stamped, and the two\n // agree because `RECEIPT_TTL_SECONDS` and the service's own dial are one\n // number (ADR 0058 §5).\n cancel: 'Cancel order',\n cancelWindow: 'You can cancel this order until {{time}}.',\n cancelPending: 'Cancelling…',\n cancelledHeading: 'Order cancelled',\n cancelled:\n 'We have cancelled your order and the refund is on its way. It can take a few days to appear on your statement.',\n cancelFailed:\n 'The order could not be cancelled. The window may have closed, or it may already be on its way.',\n },\n footer: {\n note: 'Demo catalog. No order is real.',\n },\n },\n};\n"],"names":["shell","auth","nav","identity","users","accountSection","account","overline","title","subtitle","menu","identifiers","noIdentifiers","userId","subject","session","roles","none","failed","sessions","current","unknownDevice","startedAt","expiresAt","lastIp","revoke","revoking","revokeOthers","empty","loading","security","explain","manage","fields","displayName","email","username","role","submit","wait","creating","createUser","newTitle","fallbackName","sessionsTitle","sessionsEmpty","sessionsFailed","kick","kicking","stock","items","movements","reservations","order","orders","settlement","agreements","entries","runs","payouts","agreement","channelRatesHint","channelRateDefault","noChannelRates","sales","channels","guided","counterSale","steps","channel","lines","payment","summary","channelHint","linesHint","addLine","removeLine","quantity","offering","total","paymentMethod","charge","sold","soldDetail","newSale","emptyLines","marketplaceAdmin","catalog","products","brands","categories","offerings","offeringPrices","wizard","productSetup","launch","start","source","classification","question","blank","blankHint","duplicate","duplicateHint","prompt","chosen","required","origin","originBlank","originDuplicate","recap","systemManagement","section","configuration","description","secretPlaceholder","secretHint","primary","openInWorkspace","openInWorkspaceShort","openInNewTab","openInNewTabShort","screenType","master","operation","report","commandPalette","open","placeholder","newPlaceholder","newLabel","back","more_one","more_other","typeMore","groups","actions","commands","navigation","tabs","records","unavailableScope","unavailableReach","openInWorkspaceHint","sidebar","expand","collapse","openMenu","closeMenu","expandGroup","collapseGroup","expiringSoon","breadcrumbs","home","new","profile","signOut","workspace","copyLink","unsupported","discardTitle","discard","discardConfirm","pendingLabel","savePending_one","savePending_other","saveFailed","saveFailedDismiss","storefront","heading","lead","featured","category","sort","sortByName","sortByCode","results","previous","next","pageOf","product","addToCart","view","brand","reference","related","available","unavailable","search","label","resultsFor","cart","remove","units","keepShopping","checkout","placed","tooManyLines","expiredHeading","expired","cancel","cancelWindow","cancelPending","cancelledHeading","cancelled","cancelFailed","footer","note"],"mappings":"AAEA,OAAO,MAAMA,QAAiB;IAC5BC,MAAM;QACJC,KAAK;YACHC,UAAU;YACVC,OAAO;YACPC,gBAAgB;QAClB;QACAC,SAAS;YACPC,UAAU;YACVC,OAAO;YACPC,UAAU;YACVC,MAAM;YACNC,aAAa;YACbC,eAAe;YACfC,QAAQ;YACRC,SAAS;YACTC,SAAS;YACTC,OAAO;YACPC,MAAM;YACNC,QAAQ;QACV;QACAC,UAAU;YACRZ,UAAU;YACVC,OAAO;YACPC,UAAU;YACVW,SAAS;YACTC,eAAe;YACfC,WAAW;YACXC,WAAW;YACXC,QAAQ;YACRC,QAAQ;YACRC,UAAU;YACVC,cAAc;YACdC,OAAO;YACPV,QAAQ;YACRW,SAAS;QACX;QACAC,UAAU;YACRvB,UAAU;YACVC,OAAO;YACPC,UACE;YACFsB,SACE;YACFC,QAAQ;QACV;QACAC,QAAQ;YACNC,aAAa;YACbC,OAAO;YACPC,UAAU;YACVC,MAAM;QACR;QACAC,QAAQ;YACNC,MAAM;YACNC,UAAU;YACVC,YAAY;QACd;QACArC,OAAO;YACLI,OAAO;YACPkC,UAAU;YACVC,cAAc;YACdC,eAAe;YACfC,eAAe;YACfC,gBAAgB;YAChBC,MAAM;YACNC,SAAS;QACX;IACF;IACA;;;;;GAKC,GACDC,OAAO;QACL/C,KAAK;YACH+C,OAAO;YACPC,OAAO;YACPC,WAAW;YACXC,cAAc;QAChB;IACF;IACAC,OAAO;QACLnD,KAAK;YACHoD,QAAQ;QACV;IACF;IACAC,YAAY;QACVrD,KAAK;YACHqD,YAAY;YACZC,YAAY;YACZC,SAAS;YACTC,MAAM;YACNC,SAAS;QACX;QACAC,WAAW;YACTC,kBACE;YACFC,oBAAoB;YACpBC,gBAAgB;QAClB;IACF;IACAC,OAAO;QACL9D,KAAK;YACH8D,OAAO;YACPC,UAAU;YACVC,QAAQ;YACRC,aAAa;QACf;QACAA,aAAa;YACX3D,OAAO;YACP4D,OAAO;gBACLC,SAAS;gBACTC,OAAO;gBACPC,SAAS;gBACTC,SAAS;YACX;YACAC,aAAa;YACbC,WAAW;YACXC,SAAS;YACTC,YAAY;YACZC,UAAU;YACVC,UAAU;YACVC,OAAO;YACPC,eAAe;YACfC,QAAQ;YACRC,MAAM;YACNC,YAAY;YACZC,SAAS;YACTC,YAAY;QACd;IACF;IACAC,kBAAkB;QAChBpF,KAAK;YACHqF,SAAS;YACTC,UAAU;YACVC,QAAQ;YACRC,YAAY;YACZC,WAAW;YACXC,gBAAgB;YAChB1B,QAAQ;QACV;QACA2B,QAAQ;YACNC,cAAc;gBACZtF,OAAO;gBACPuF,QAAQ;gBACR3B,OAAO;oBACL4B,OAAO;oBACPC,QAAQ;oBACR9F,UAAU;oBACV+F,gBAAgB;oBAChB1B,SAAS;gBACX;gBACAwB,OAAO;oBACLG,UAAU;oBACVC,OAAO;oBACPC,WAAW;oBACXC,WAAW;oBACXC,eACE;gBACJ;gBACAN,QAAQ;oBACNO,QAAQ;oBACRC,QAAQ;oBACRC,UAAU;gBACZ;gBACAlC,SAAS;oBACPgC,QAAQ;oBACRG,QAAQ;oBACRC,aAAa;oBACbC,iBAAiB;oBACjBjF,OAAO;gBACT;gBACAkF,OAAO;YACT;QACF;IACF;IACAC,kBAAkB;QAChB7G,KAAK;YACH8G,SAAS;YACTC,eAAe;QACjB;QACAA,eAAe;YACbzG,OAAO;YACP0G,aACE;YACFC,mBAAmB;YACnBC,YACE;QACJ;IACF;IACAlH,KAAK;QACHmH,SAAS;QACTC,iBAAiB;QACjBC,sBAAsB;QACtBC,cAAc;QACdC,mBAAmB;QACnB;;;;KAIC,GACDC,YAAY;YACVC,QAAQ;YACRC,WAAW;YACX/B,QAAQ;YACRgC,QAAQ;QACV;IACF;IACAC,gBAAgB;QACdC,MAAM;QACNvH,OAAO;QACPwH,aAAa;QACbC,gBAAgB;QAChBC,UAAU;QACVxF,UAAU;QACVyF,MAAM;QACNvG,OAAO;QACPC,SAAS;QACTuG,UAAU;QACVC,YAAY;QACZC,UAAU;QACVC,QAAQ;YACNC,SAAS;YACTC,UAAU;YACVC,YAAY;YACZC,MAAM;YACNC,SAAS;QACX;QACAC,kBAAkB;QAClBC,kBAAkB;QAClBC,qBAAqB;IACvB;IACAC,SAAS;QACPC,QAAQ;QACRC,UAAU;QACVC,UAAU;QACVC,WAAW;QACX1I,MAAM;QACN2I,aAAa;QACbC,eAAe;IACjB;IACAvI,SAAS;QACPwI,cACE;IACJ;IACAC,aAAa;QACXC,MAAM;QACN,uEAAuE;QACvE,sEAAsE;QACtE,8DAA8D;QAC9DC,KAAK;IACP;IACApJ,SAAS;QACPqJ,SAAS;QACT7H,UAAU;QACVX,UAAU;QACVyI,SAAS;IACX;IACAC,WAAW;QACTC,UAAU;QACVlI,OAAO;QACPmI,aAAa;QACbC,cAAc;QACdC,SAAS;QACTC,gBAAgB;QAChB,wEAAwE;QACxEC,cAAc;QACdC,iBAAiB;QACjBC,mBAAmB;QACnBC,YAAY;QACZC,mBAAmB;IACrB;IACAC,YAAY;QACVtK,KAAK;YACHqF,SAAS;QACX;QACAkE,MAAM;YACJlJ,UAAU;YACVkK,SAAS;YACTC,MAAM;YACNC,UAAU;QACZ;QACAC,UAAU;YACRrK,UAAU;YACVqB,OAAO;YACPiJ,MAAM;YACNC,YAAY;YACZC,YAAY;YACZC,SAAS;YACTC,UAAU;YACVC,MAAM;YACNC,QAAQ;QACV;QACAC,SAAS;YACPC,WAAW;YACXC,MAAM;YACNC,OAAO;YACPX,UAAU;YACVY,WAAW;YACXC,SAAS;YACTC,WAAW;YACXC,aAAa;QACf;QACAC,QAAQ;YACNnB,SAAS;YACToB,OAAO;YACP7D,aAAa;YACb1F,QAAQ;YACRwJ,YAAY;YACZlK,OAAO;YACP4E,QAAQ;QACV;QACAuF,MAAM;YACJtB,SAAS;YACT7I,OAAO;YACPoK,QAAQ;YACRC,OAAO;YACPlH,OAAO;YACPmH,cAAc;YACdC,UAAU;QACZ;QACAA,UAAU;YACRC,QAAQ;YACRT,aACE;YACF/J,OAAO;YACPV,QAAQ;QACV;QACAmC,OAAO;YACLoH,SAAS;YACT2B,QAAQ;YACRZ,WAAW;YACXS,OAAO;YACPlH,OAAO;YACPsH,cACE;YACFH,cAAc;YACdI,gBAAgB;YAChBC,SACE;YACF,yEAAyE;YACzE,0EAA0E;YAC1E,yEAAyE;YACzE,wBAAwB;YACxBC,QAAQ;YACRC,cAAc;YACdC,eAAe;YACfC,kBAAkB;YAClBC,WACE;YACFC,cACE;QACJ;QACAC,QAAQ;YACNC,MAAM;QACR;IACF;AACF,EAAE"}
1
+ {"version":3,"sources":["../../../../src/lib/i18n/catalog/en.ts"],"sourcesContent":["type EsShell = typeof import('./es.js').shell;\n\nexport const shell: EsShell = {\n /**\n * The stock surface — the first Operaciones screens in the back office.\n *\n * The *tier* name (\"Operaciones\") comes from `nav.screenType.operation`; this\n * names the group inside it.\n */\n stock: {\n nav: {\n stock: 'Stock',\n items: 'Stock on hand',\n movements: 'Movement ledger',\n reservations: 'Reservations',\n },\n },\n order: {\n nav: {\n orders: 'Orders',\n },\n },\n settlement: {\n nav: {\n settlement: 'Settlement',\n agreements: 'Agreements',\n entries: 'Commission entries',\n runs: 'Settlement runs',\n payouts: 'Vendor payouts',\n },\n agreement: {\n channelRatesHint:\n 'Leave blank to charge the default commission on that channel. A 0 means nothing is charged.',\n channelRateDefault: 'Default',\n noChannelRates: 'No per-channel rates',\n },\n },\n sales: {\n nav: {\n sales: 'Sales',\n channels: 'Sales channels',\n guided: 'Sales',\n counterSale: 'Sell at the counter',\n },\n counterSale: {\n title: 'Counter sale',\n steps: {\n channel: 'Channel',\n lines: 'Products',\n payment: 'Payment',\n summary: 'Summary',\n },\n channelHint: 'Pick the channel this sale goes through.',\n linesHint: 'Add the published products you are selling.',\n addLine: 'Add product',\n removeLine: 'Remove',\n quantity: 'Quantity',\n offering: 'Product',\n total: 'Total',\n paymentMethod: 'Payment method',\n charge: 'Charge',\n sold: 'Sale recorded',\n soldDetail: 'The stock is already drawn down and the order is written.',\n newSale: 'New sale',\n emptyLines: 'Add at least one product to charge for.',\n },\n },\n marketplaceAdmin: {\n nav: {\n catalog: 'Catalog',\n products: 'Products',\n brands: 'Brands',\n categories: 'Categories',\n offerings: 'Product offerings',\n offeringPrices: 'Offering prices',\n guided: 'Catalog',\n },\n wizard: {\n productSetup: {\n title: 'New product',\n launch: 'Guided new product',\n steps: {\n start: 'Source',\n source: 'Base product',\n identity: 'Identification',\n classification: 'Classification',\n summary: 'Summary',\n },\n start: {\n question: 'How do you want to start?',\n blank: 'From scratch',\n blankHint: 'Enter the details by hand.',\n duplicate: 'Duplicate an existing one',\n duplicateHint:\n 'Start from a product already on file. The code is not copied: it identifies the original.',\n },\n source: {\n prompt: 'Pick the product to start from.',\n chosen: 'Base product: {{name}}',\n required: 'Pick a product to continue.',\n },\n summary: {\n prompt: 'Check what you entered before creating it.',\n origin: 'Source',\n originBlank: 'From scratch',\n originDuplicate: 'Duplicated from {{name}}',\n empty: 'Not set',\n },\n recap: 'You had already answered:',\n },\n },\n },\n systemManagement: {\n nav: {\n section: 'System',\n configuration: 'Configuration',\n },\n configuration: {\n title: 'Platform configuration',\n description:\n 'Parameters every service resolves at boot. Editing a value affects that service on its next start.',\n secretPlaceholder: '•••••• (unchanged)',\n secretHint:\n 'Leaving this blank keeps the stored value. Typing a new one replaces it.',\n },\n },\n nav: {\n primary: 'Primary',\n openInWorkspace: 'Open {{label}} in workspace',\n openInWorkspaceShort: 'Open in workspace',\n openInNewTab: 'Open {{label}} in a new tab',\n openInNewTabShort: 'Open in a new tab',\n /**\n * The screen taxonomy (ADR 0033). Translated like every other string rather\n * than kept in Spanish: what that decision fixed was which *Spanish* word\n * ships to the default locale, not that the term is untranslatable.\n */\n screenType: {\n master: 'Definitions',\n operation: 'Operations',\n wizard: 'Wizards',\n report: 'Reports',\n },\n },\n commandPalette: {\n open: 'Search or run',\n title: 'Search or run',\n placeholder: 'Search a record, a screen or a command…',\n newPlaceholder: 'What would you like to create?',\n newLabel: 'New…',\n newTitle: 'New',\n back: 'Back',\n empty: 'No results',\n loading: 'Searching…',\n more_one: '{{count}} more',\n more_other: '{{count}} more',\n typeMore: 'Type at least {{count}} characters to search records.',\n groups: {\n actions: 'Actions',\n commands: 'Commands',\n navigation: 'Navigation',\n tabs: 'Open tabs',\n records: 'Records',\n },\n unavailableScope: 'Not available here: {{reason}}',\n unavailableReach: 'We could not reach this source: {{reason}}',\n openInWorkspaceHint: 'Tab',\n },\n sidebar: {\n expand: 'Expand sidebar',\n collapse: 'Collapse sidebar',\n openMenu: 'Open the menu',\n closeMenu: 'Close the menu',\n menu: 'Navigation menu',\n expandGroup: 'Expand {{group}}',\n collapseGroup: 'Collapse {{group}}',\n },\n session: {\n expiringSoon:\n 'Your session is about to expire. Save your work and sign in again to continue.',\n },\n breadcrumbs: {\n home: 'Home',\n // The `/new` segment, which every domain's create route shares. It was\n // an auth-specific string until one host started serving two domains,\n // at which point a catalog page's breadcrumb read \"New user\".\n new: 'New',\n },\n account: {\n profile: 'Profile',\n security: 'Security',\n sessions: 'Sessions',\n signOut: 'Sign out',\n },\n workspace: {\n copyLink: 'Copy link',\n empty: 'No open tabs. Pick a catalog from the sidebar to start.',\n unsupported: \"This tab can't be opened here.\",\n discardTitle: 'Discard changes',\n discard: 'This tab has unsaved changes. Closing it will lose them.',\n discardConfirm: 'Discard',\n // See the Spanish catalog for why a failure's reason is not a key here.\n pendingLabel: 'Save status',\n savePending_one: 'Saving 1 record…',\n savePending_other: 'Saving {{count}} records…',\n saveFailed: 'The record could not be saved.',\n saveFailedDismiss: 'Dismiss',\n },\n};\n"],"names":["shell","stock","nav","items","movements","reservations","order","orders","settlement","agreements","entries","runs","payouts","agreement","channelRatesHint","channelRateDefault","noChannelRates","sales","channels","guided","counterSale","title","steps","channel","lines","payment","summary","channelHint","linesHint","addLine","removeLine","quantity","offering","total","paymentMethod","charge","sold","soldDetail","newSale","emptyLines","marketplaceAdmin","catalog","products","brands","categories","offerings","offeringPrices","wizard","productSetup","launch","start","source","identity","classification","question","blank","blankHint","duplicate","duplicateHint","prompt","chosen","required","origin","originBlank","originDuplicate","empty","recap","systemManagement","section","configuration","description","secretPlaceholder","secretHint","primary","openInWorkspace","openInWorkspaceShort","openInNewTab","openInNewTabShort","screenType","master","operation","report","commandPalette","open","placeholder","newPlaceholder","newLabel","newTitle","back","loading","more_one","more_other","typeMore","groups","actions","commands","navigation","tabs","records","unavailableScope","unavailableReach","openInWorkspaceHint","sidebar","expand","collapse","openMenu","closeMenu","menu","expandGroup","collapseGroup","session","expiringSoon","breadcrumbs","home","new","account","profile","security","sessions","signOut","workspace","copyLink","unsupported","discardTitle","discard","discardConfirm","pendingLabel","savePending_one","savePending_other","saveFailed","saveFailedDismiss"],"mappings":"AAEA,OAAO,MAAMA,QAAiB;IAC5B;;;;;GAKC,GACDC,OAAO;QACLC,KAAK;YACHD,OAAO;YACPE,OAAO;YACPC,WAAW;YACXC,cAAc;QAChB;IACF;IACAC,OAAO;QACLJ,KAAK;YACHK,QAAQ;QACV;IACF;IACAC,YAAY;QACVN,KAAK;YACHM,YAAY;YACZC,YAAY;YACZC,SAAS;YACTC,MAAM;YACNC,SAAS;QACX;QACAC,WAAW;YACTC,kBACE;YACFC,oBAAoB;YACpBC,gBAAgB;QAClB;IACF;IACAC,OAAO;QACLf,KAAK;YACHe,OAAO;YACPC,UAAU;YACVC,QAAQ;YACRC,aAAa;QACf;QACAA,aAAa;YACXC,OAAO;YACPC,OAAO;gBACLC,SAAS;gBACTC,OAAO;gBACPC,SAAS;gBACTC,SAAS;YACX;YACAC,aAAa;YACbC,WAAW;YACXC,SAAS;YACTC,YAAY;YACZC,UAAU;YACVC,UAAU;YACVC,OAAO;YACPC,eAAe;YACfC,QAAQ;YACRC,MAAM;YACNC,YAAY;YACZC,SAAS;YACTC,YAAY;QACd;IACF;IACAC,kBAAkB;QAChBtC,KAAK;YACHuC,SAAS;YACTC,UAAU;YACVC,QAAQ;YACRC,YAAY;YACZC,WAAW;YACXC,gBAAgB;YAChB3B,QAAQ;QACV;QACA4B,QAAQ;YACNC,cAAc;gBACZ3B,OAAO;gBACP4B,QAAQ;gBACR3B,OAAO;oBACL4B,OAAO;oBACPC,QAAQ;oBACRC,UAAU;oBACVC,gBAAgB;oBAChB3B,SAAS;gBACX;gBACAwB,OAAO;oBACLI,UAAU;oBACVC,OAAO;oBACPC,WAAW;oBACXC,WAAW;oBACXC,eACE;gBACJ;gBACAP,QAAQ;oBACNQ,QAAQ;oBACRC,QAAQ;oBACRC,UAAU;gBACZ;gBACAnC,SAAS;oBACPiC,QAAQ;oBACRG,QAAQ;oBACRC,aAAa;oBACbC,iBAAiB;oBACjBC,OAAO;gBACT;gBACAC,OAAO;YACT;QACF;IACF;IACAC,kBAAkB;QAChBjE,KAAK;YACHkE,SAAS;YACTC,eAAe;QACjB;QACAA,eAAe;YACbhD,OAAO;YACPiD,aACE;YACFC,mBAAmB;YACnBC,YACE;QACJ;IACF;IACAtE,KAAK;QACHuE,SAAS;QACTC,iBAAiB;QACjBC,sBAAsB;QACtBC,cAAc;QACdC,mBAAmB;QACnB;;;;KAIC,GACDC,YAAY;YACVC,QAAQ;YACRC,WAAW;YACXjC,QAAQ;YACRkC,QAAQ;QACV;IACF;IACAC,gBAAgB;QACdC,MAAM;QACN9D,OAAO;QACP+D,aAAa;QACbC,gBAAgB;QAChBC,UAAU;QACVC,UAAU;QACVC,MAAM;QACNvB,OAAO;QACPwB,SAAS;QACTC,UAAU;QACVC,YAAY;QACZC,UAAU;QACVC,QAAQ;YACNC,SAAS;YACTC,UAAU;YACVC,YAAY;YACZC,MAAM;YACNC,SAAS;QACX;QACAC,kBAAkB;QAClBC,kBAAkB;QAClBC,qBAAqB;IACvB;IACAC,SAAS;QACPC,QAAQ;QACRC,UAAU;QACVC,UAAU;QACVC,WAAW;QACXC,MAAM;QACNC,aAAa;QACbC,eAAe;IACjB;IACAC,SAAS;QACPC,cACE;IACJ;IACAC,aAAa;QACXC,MAAM;QACN,uEAAuE;QACvE,sEAAsE;QACtE,8DAA8D;QAC9DC,KAAK;IACP;IACAC,SAAS;QACPC,SAAS;QACTC,UAAU;QACVC,UAAU;QACVC,SAAS;IACX;IACAC,WAAW;QACTC,UAAU;QACVxD,OAAO;QACPyD,aAAa;QACbC,cAAc;QACdC,SAAS;QACTC,gBAAgB;QAChB,wEAAwE;QACxEC,cAAc;QACdC,iBAAiB;QACjBC,mBAAmB;QACnBC,YAAY;QACZC,mBAAmB;IACrB;AACF,EAAE"}
@@ -1,78 +1,5 @@
1
1
  /** Copy owned by the Next shells — back-office chrome and the tab workspace. */
2
2
  export declare const shell: {
3
- /**
4
- * The identity surface — user administration and the signed-in
5
- * account. The screens live in `@r10c/shells-next-auth` so a second
6
- * host can mount them, and copy follows the code: an `app:` key is
7
- * lint-restricted to `apps/`, so a shell binding one fails the build.
8
- * What stays in `app:auth` is the sign-in page itself, which is the
9
- * host's own front door rather than the domain's surface.
10
- */
11
- auth: {
12
- nav: {
13
- identity: string;
14
- users: string;
15
- accountSection: string;
16
- };
17
- account: {
18
- overline: string;
19
- title: string;
20
- subtitle: string;
21
- menu: string;
22
- identifiers: string;
23
- noIdentifiers: string;
24
- userId: string;
25
- subject: string;
26
- session: string;
27
- roles: string;
28
- none: string;
29
- failed: string;
30
- };
31
- sessions: {
32
- overline: string;
33
- title: string;
34
- subtitle: string;
35
- current: string;
36
- unknownDevice: string;
37
- startedAt: string;
38
- expiresAt: string;
39
- lastIp: string;
40
- revoke: string;
41
- revoking: string;
42
- revokeOthers: string;
43
- empty: string;
44
- failed: string;
45
- loading: string;
46
- };
47
- security: {
48
- overline: string;
49
- title: string;
50
- subtitle: string;
51
- explain: string;
52
- manage: string;
53
- };
54
- fields: {
55
- displayName: string;
56
- email: string;
57
- username: string;
58
- role: string;
59
- };
60
- submit: {
61
- wait: string;
62
- creating: string;
63
- createUser: string;
64
- };
65
- users: {
66
- title: string;
67
- newTitle: string;
68
- fallbackName: string;
69
- sessionsTitle: string;
70
- sessionsEmpty: string;
71
- sessionsFailed: string;
72
- kick: string;
73
- kicking: string;
74
- };
75
- };
76
3
  /**
77
4
  * System management — the operator surface. Lives in the framework shell so
78
5
  * a dedicated management app can mount the same screens later, which is why the
@@ -307,91 +234,5 @@ export declare const shell: {
307
234
  saveFailed: string;
308
235
  saveFailedDismiss: string;
309
236
  };
310
- /**
311
- * The storefront. Its pages live in `shells-next-marketplace`, so its copy
312
- * lives here and not in an app catalog — `app:` is reserved for `apps/`.
313
- */
314
- storefront: {
315
- nav: {
316
- catalog: string;
317
- };
318
- home: {
319
- overline: string;
320
- heading: string;
321
- lead: string;
322
- featured: string;
323
- };
324
- category: {
325
- overline: string;
326
- empty: string;
327
- sort: string;
328
- sortByName: string;
329
- sortByCode: string;
330
- results: string;
331
- previous: string;
332
- next: string;
333
- pageOf: string;
334
- };
335
- product: {
336
- addToCart: string;
337
- view: string;
338
- brand: string;
339
- category: string;
340
- reference: string;
341
- related: string;
342
- /**
343
- * `availableHint` es una **pista**, y el nombre lo dice: el catálogo
344
- * publicado es consistente en diferido a propósito y la verdad es la
345
- * reserva del checkout (ADR 0009). Por eso la copia no promete
346
- * existencias concretas.
347
- */
348
- available: string;
349
- unavailable: string;
350
- };
351
- search: {
352
- heading: string;
353
- label: string;
354
- placeholder: string;
355
- submit: string;
356
- resultsFor: string;
357
- empty: string;
358
- prompt: string;
359
- };
360
- cart: {
361
- heading: string;
362
- empty: string;
363
- remove: string;
364
- units: string;
365
- total: string;
366
- keepShopping: string;
367
- checkout: string;
368
- };
369
- checkout: {
370
- placed: string;
371
- unavailable: string;
372
- empty: string;
373
- failed: string;
374
- };
375
- order: {
376
- heading: string;
377
- placed: string;
378
- reference: string;
379
- units: string;
380
- total: string;
381
- tooManyLines: string;
382
- keepShopping: string;
383
- expiredHeading: string;
384
- expired: string;
385
- cancel: string;
386
- cancelWindow: string;
387
- cancelPending: string;
388
- cancelledHeading: string;
389
- cancelled: string;
390
- cancelFailed: string;
391
- };
392
- footer: {
393
- note: string;
394
- };
395
- };
396
237
  };
397
238
  //# sourceMappingURL=es.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../../../src/lib/i18n/catalog/es.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,eAAO,MAAM,KAAK;IAChB;;;;;;;OAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoEH;;;;OAIG;IACH;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6ED;;;WAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwDH;;;;;;WAMG;;;;;;;;IAQL;;;;OAIG;;QAED,4EAA4E;;QAE5E,qDAAqD;;;;;QAKrD,4EAA4E;;;;;;;QAO5E,2EAA2E;;;;;;;;;QAS3E;;;;WAIG;;;QAGH,uEAAuE;;;;;;;;;;;;IAezE;;;;;OAKG;;;;;;;;IAYH;;;;OAIG;;;;;;;;;;;;;;;;;;;;IA8BH;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YA6BC;;;;;eAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DR,CAAC"}
1
+ {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../../../src/lib/i18n/catalog/es.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,eAAO,MAAM,KAAK;IAChB;;;;OAIG;IACH;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6ED;;;WAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwDH;;;;;;WAMG;;;;;;;;IAQL;;;;OAIG;;QAED,4EAA4E;;QAE5E,qDAAqD;;;;;QAKrD,4EAA4E;;;;;;;QAO5E,2EAA2E;;;;;;;;;QAS3E;;;;WAIG;;;QAGH,uEAAuE;;;;;;;;;;;;IAezE;;;;;OAKG;;;;;;;;IAYH;;;;OAIG;;;;;;;;;;;;;;;;;;;;CAkCJ,CAAC"}