@ankhorage/contracts 5.0.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/dist/index.d.ts +0 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +0 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/types.d.ts +2 -2
  8. package/dist/types.js.map +1 -1
  9. package/package.json +1 -5
  10. package/src/bindings.test.ts +1 -1
  11. package/src/contracts.test.ts +40 -2
  12. package/src/index.ts +0 -1
  13. package/src/secrets.test.ts +1 -1
  14. package/src/types.ts +2 -2
  15. package/dist/nutrition/capture.d.ts +0 -54
  16. package/dist/nutrition/capture.d.ts.map +0 -1
  17. package/dist/nutrition/capture.js +0 -8
  18. package/dist/nutrition/capture.js.map +0 -1
  19. package/dist/nutrition/common.d.ts +0 -22
  20. package/dist/nutrition/common.d.ts.map +0 -1
  21. package/dist/nutrition/common.js +0 -25
  22. package/dist/nutrition/common.js.map +0 -1
  23. package/dist/nutrition/index.d.ts +0 -5
  24. package/dist/nutrition/index.d.ts.map +0 -1
  25. package/dist/nutrition/index.js +0 -5
  26. package/dist/nutrition/index.js.map +0 -1
  27. package/dist/nutrition/products.d.ts +0 -93
  28. package/dist/nutrition/products.d.ts.map +0 -1
  29. package/dist/nutrition/products.js +0 -9
  30. package/dist/nutrition/products.js.map +0 -1
  31. package/dist/nutrition/review.d.ts +0 -47
  32. package/dist/nutrition/review.d.ts.map +0 -1
  33. package/dist/nutrition/review.js +0 -8
  34. package/dist/nutrition/review.js.map +0 -1
  35. package/src/nutrition/capture.ts +0 -80
  36. package/src/nutrition/common.ts +0 -51
  37. package/src/nutrition/index.ts +0 -4
  38. package/src/nutrition/nutrition.test.ts +0 -137
  39. package/src/nutrition/products.ts +0 -134
  40. package/src/nutrition/review.ts +0 -65
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ankhorage/contracts
2
2
 
3
+ ## 7.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 24d3c97: Remove the unused nutrition contracts and the public `@ankhorage/contracts/nutrition` subpath export.
8
+
9
+ ## 6.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - 6dd3d50: Replace the Ankhorage module registry fields on `InfraManifest` with the canonical `modules` and `modulesConfig` names. The obsolete `plugins` and `pluginsConfig` fields are removed without compatibility aliases.
14
+
3
15
  ## 5.0.0
4
16
 
5
17
  ### Major Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # CONTRACTS
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v4.0.2](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v6.0.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Serializable app, action, theme, auth, and secret-store contracts for Ankhorage.
9
9
 
package/dist/index.d.ts CHANGED
@@ -3,7 +3,6 @@ export * from './bindings';
3
3
  export * from './cli';
4
4
  export * from './data';
5
5
  export * from './db';
6
- export * from './nutrition';
7
6
  export * from './requirements';
8
7
  export * from './runtimeCallbacks';
9
8
  export * from './secretManifest';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,MAAM,CAAC;AACrB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,MAAM,CAAC;AACrB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,MAAM,CAAC"}
package/dist/index.js CHANGED
@@ -3,7 +3,6 @@ export * from './bindings';
3
3
  export * from './cli';
4
4
  export * from './data';
5
5
  export * from './db';
6
- export * from './nutrition';
7
6
  export * from './requirements';
8
7
  export * from './runtimeCallbacks';
9
8
  export * from './secretManifest';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,MAAM,CAAC;AACrB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,MAAM,CAAC","sourcesContent":["export * from './auth';\nexport * from './bindings';\nexport * from './cli';\nexport * from './data';\nexport * from './db';\nexport * from './nutrition';\nexport * from './requirements';\nexport * from './runtimeCallbacks';\nexport * from './secretManifest';\nexport * from './secrets';\nexport * from './state';\nexport * from './storage';\nexport * from './types';\nexport * from './ui';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,MAAM,CAAC;AACrB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,MAAM,CAAC","sourcesContent":["export * from './auth';\nexport * from './bindings';\nexport * from './cli';\nexport * from './data';\nexport * from './db';\nexport * from './requirements';\nexport * from './runtimeCallbacks';\nexport * from './secretManifest';\nexport * from './secrets';\nexport * from './state';\nexport * from './storage';\nexport * from './types';\nexport * from './ui';\n"]}
package/dist/types.d.ts CHANGED
@@ -239,8 +239,8 @@ export interface InfraManifest {
239
239
  storage?: StorageSpec;
240
240
  state?: StateSpec;
241
241
  networking?: NetworkingSpec;
242
- plugins: string[];
243
- pluginsConfig?: Record<string, unknown>;
242
+ modules: string[];
243
+ modulesConfig?: Record<string, unknown>;
244
244
  }
245
245
  export interface AppSettings {
246
246
  apiBaseUrl?: string;
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2IA,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAGpE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,eAAe;IACf,uBAAuB;IACvB,iBAAiB;IACjB,oBAAoB;IACpB,qBAAqB;IACrB,eAAe;IACf,YAAY;IACZ,OAAO;IACP,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,SAAS;IACT,aAAa;IACb,mBAAmB;IACnB,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,mBAAmB;IACnB,kBAAkB;IAClB,QAAQ;IACR,iBAAiB;IACjB,SAAS;CACD,CAAC;AAGX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,CAAU,CAAC;AAIxD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,CAAU,CAAC;AAIxD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,MAAM,CAAU,CAAC;AAGvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAG/D,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAAQ,CAAU,CAAC;AAInD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAU,CAAC;AAGxF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAU,CAAC;AAGrD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAG3D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAU,CAAC;AAGrE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAU,CAAU,CAAC;AAIpD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAU,CAAC;AAGhF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,YAAY,EAAE,qBAAqB,CAAU,CAAC;AAGpF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,wBAAwB;IAC3B,WAAW;IACX,UAAU;IACV,aAAa;IACb,WAAW;CACH,CAAC;AAIX,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,YAAY,CAAU,CAAC;AAG3E,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAGjF,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,KAAK,EAAE,KAAK,CAAU,CAAC","sourcesContent":["import type { ColorHarmony } from '@ankhorage/color-theory';\n\nimport type { AuthFlowConfig, AuthIdentifierKind, AuthOAuthConfig, AuthSignUpField } from './auth';\nimport type {\n BindingValueSource,\n ComponentDataBindingRegistry,\n ScreenDataLoaderDefinition,\n} from './bindings';\nimport type { DataSourceRegistry, GeneratedApiRegistry } from './data';\nimport type { ScreenRequirements } from './requirements';\n\nexport interface ThemeModeConfig {\n primaryColor: string;\n harmony: ColorHarmony;\n}\n\nexport interface ThemeConfig {\n id: string;\n name: string;\n light: ThemeModeConfig;\n dark: ThemeModeConfig;\n}\n\nexport type ActionType =\n | 'navigate'\n | 'alert'\n | 'console'\n | 'toggleDarkMode'\n | 'setLanguage'\n | 'search'\n | 'filter';\n\nexport interface NavigateAction {\n type: 'navigate';\n payload: {\n route: string;\n params?: Record<string, number | string>;\n };\n}\n\nexport interface AlertAction {\n type: 'alert';\n payload?: {\n message?: string;\n };\n}\n\nexport interface ConsoleAction {\n type: 'console';\n payload?: Record<string, unknown>;\n}\n\nexport interface ToggleDarkModeAction {\n type: 'toggleDarkMode';\n payload?: never;\n}\n\nexport interface SetLanguageAction {\n type: 'setLanguage';\n payload: {\n locale: string;\n };\n}\n\nexport interface SearchAction {\n type: 'search';\n payload: {\n query: string;\n scope?: string;\n };\n}\n\nexport interface FilterAction {\n type: 'filter';\n payload: {\n filterKey: string;\n filterValue: string;\n };\n}\n\nexport type Action =\n | AlertAction\n | ConsoleAction\n | FilterAction\n | NavigateAction\n | SearchAction\n | SetLanguageAction\n | ToggleDarkModeAction;\n\nexport type ManifestValue =\n | string\n | number\n | boolean\n | null\n | readonly ManifestValue[]\n | { readonly [key: string]: ManifestValue };\n\nexport type ComponentEventPayloadValue = ManifestValue;\n\nexport interface ComponentEventDto<\n TType extends string = string,\n TPayload extends object = Record<string, ComponentEventPayloadValue>,\n> {\n readonly type: TType;\n readonly sourceNodeId: string;\n readonly payload: TPayload;\n}\n\nexport type FormSubmitValues = Record<string, ComponentEventPayloadValue>;\n\nexport type FormSubmitEventDto = ComponentEventDto<\n 'form.submit',\n {\n readonly values: FormSubmitValues;\n }\n>;\n\nexport type ButtonPressEventDto = ComponentEventDto<'button.press', Record<string, never>>;\n\nexport interface CollectionItemPressPayload {\n readonly itemId: string | number;\n readonly item: Record<string, ComponentEventPayloadValue>;\n}\n\nexport type CollectionItemPressEventDto = ComponentEventDto<\n 'collection.itemPress',\n CollectionItemPressPayload\n>;\n\nexport type ComponentEventDtoKind =\n | ButtonPressEventDto['type']\n | CollectionItemPressEventDto['type']\n | FormSubmitEventDto['type'];\n\nexport type KnownComponentEventDto =\n | ButtonPressEventDto\n | CollectionItemPressEventDto\n | FormSubmitEventDto;\n\nexport const NAVIGATOR_TYPES = ['stack', 'tabs', 'drawer'] as const;\nexport type NavigatorType = (typeof NAVIGATOR_TYPES)[number];\n\nexport const APP_CATEGORIES = [\n 'books_reading',\n 'business_productivity',\n 'developer_tools',\n 'education_learning',\n 'entertainment_media',\n 'finance_money',\n 'food_drink',\n 'games',\n 'graphics_design',\n 'health_fitness',\n 'kids_family',\n 'lifestyle',\n 'medical',\n 'music_audio',\n 'navigation_travel',\n 'news_magazines',\n 'photo_video',\n 'reference',\n 'shopping_commerce',\n 'social_community',\n 'sports',\n 'utilities_tools',\n 'weather',\n] as const;\nexport type AppCategory = (typeof APP_CATEGORIES)[number];\n\nexport const DEPLOYMENT_TARGETS = ['minikube'] as const;\nexport type KnownDeploymentTarget = (typeof DEPLOYMENT_TARGETS)[number];\nexport type DeploymentTarget = KnownDeploymentTarget | (string & {});\n\nexport const DATABASE_PROVIDERS = ['supabase'] as const;\nexport type KnownDatabaseProvider = (typeof DATABASE_PROVIDERS)[number];\nexport type DatabaseProvider = KnownDatabaseProvider | (string & {});\n\nexport const DATABASE_TIERS = ['dev', 'prod'] as const;\nexport type DatabaseTier = (typeof DATABASE_TIERS)[number];\n\nexport const STORAGE_PROVIDERS = ['auto', 's3', 'r2'] as const;\nexport type StorageProvider = (typeof STORAGE_PROVIDERS)[number];\n\nexport const STATE_PROVIDERS = ['legend'] as const;\nexport type KnownStateProvider = (typeof STATE_PROVIDERS)[number];\nexport type StateProvider = KnownStateProvider | (string & {});\n\nexport const STATE_PERSISTENCE_MODES = ['none', 'local', 'secure', 'database'] as const;\nexport type StatePersistenceMode = (typeof STATE_PERSISTENCE_MODES)[number];\n\nexport const AUTHZ_KINDS = ['RBAC', 'ABAC'] as const;\nexport type AuthzKind = (typeof AUTHZ_KINDS)[number];\n\nexport const AUTHZ_ENGINES = ['cerbos', 'native'] as const;\nexport type AuthzEngine = (typeof AUTHZ_ENGINES)[number];\n\nexport const AUTH_SCOPES = ['global', 'none', 'integrated'] as const;\nexport type AuthScope = (typeof AUTH_SCOPES)[number];\n\nexport const AUTH_PROVIDERS = ['supabase'] as const;\nexport type KnownAuthProvider = (typeof AUTH_PROVIDERS)[number];\nexport type AuthProvider = KnownAuthProvider | (string & {});\n\nexport const AUTH_SIGN_IN_IDENTIFIERS = ['email', 'username', 'phone'] as const;\nexport type AuthSignInIdentifier = AuthIdentifierKind;\n\nexport const AUTH_SIGN_UP_POLICIES = ['autoSignIn', 'requireVerification'] as const;\nexport type AuthSignUpPolicy = (typeof AUTH_SIGN_UP_POLICIES)[number];\n\nexport const AUTH_PROFILE_FIELDS = [\n ...AUTH_SIGN_IN_IDENTIFIERS,\n 'firstName',\n 'lastName',\n 'displayName',\n 'avatarUrl',\n] as const;\nexport type KnownAuthProfileField = (typeof AUTH_PROFILE_FIELDS)[number];\nexport type AuthProfileField = KnownAuthProfileField | (string & {});\n\nexport const AUTH_PROFILE_PRIMARY_KEY_STRATEGIES = ['authUserId'] as const;\nexport type AuthProfilePrimaryKeyStrategy = (typeof AUTH_PROFILE_PRIMARY_KEY_STRATEGIES)[number];\n\nexport const AUTH_PROFILE_CREATE_STRATEGIES = ['trigger', 'api', 'app'] as const;\nexport type AuthProfileCreateStrategy = (typeof AUTH_PROFILE_CREATE_STRATEGIES)[number];\n\nexport const AUTH_PROFILE_UPDATE_STRATEGIES = ['api', 'app'] as const;\nexport type AuthProfileUpdateStrategy = (typeof AUTH_PROFILE_UPDATE_STRATEGIES)[number];\n\nexport interface IconSpec {\n name: string;\n provider?: string;\n size?: number | string;\n color?: string;\n}\n\nexport interface UiNodeRepeatSpec {\n source: BindingValueSource;\n itemAlias?: string;\n keyPath?: string;\n empty?: readonly UiNode[];\n}\n\nexport interface UiNode {\n id: string;\n type: string;\n alias?: string;\n props?: Record<string, unknown>;\n children?: UiNode[];\n style?: Record<string, number | string>;\n repeat?: UiNodeRepeatSpec;\n}\n\nexport interface ScreenSpec {\n id: string;\n name: string;\n title?: string;\n description?: string;\n root: UiNode;\n dataLoaders?: readonly ScreenDataLoaderDefinition[];\n requires?: ScreenRequirements;\n}\n\nexport interface NavigatorSpec {\n type: NavigatorType;\n initialRouteName?: string;\n routes: RouteDefinition[];\n options?: Record<string, unknown>;\n}\n\nexport interface RouteDefinition {\n name: string;\n path?: string;\n label?: string;\n icon?: IconSpec;\n /**\n * Whether this route appears in Tabs and Drawer primary navigation.\n *\n * Omitted routes are visible by default. Setting this to `false` hides the\n * route from primary navigation without making it unnavigable. Stack\n * navigators preserve the value but do not present primary navigation.\n */\n showInPrimaryNavigation?: boolean;\n guards?: string[];\n screenId?: string;\n navigator?: NavigatorSpec;\n}\n\nexport type SplashScreenResizeMode = 'contain' | 'cover' | 'native';\n\nexport interface SplashScreenAssetSpec {\n readonly image?: string;\n readonly imageWidth?: number;\n readonly resizeMode?: SplashScreenResizeMode;\n}\n\nexport interface SplashScreenModeSpec extends SplashScreenAssetSpec {\n readonly backgroundColor?: string;\n}\n\nexport interface SplashScreenSpec extends SplashScreenModeSpec {\n readonly dark?: SplashScreenModeSpec;\n}\n\nexport interface DeploymentSpec {\n target: DeploymentTarget;\n monitoring: boolean;\n}\n\nexport interface DatabaseSpec {\n provider: DatabaseProvider;\n tier: DatabaseTier;\n}\n\nexport interface StorageSpec {\n provider: StorageProvider;\n buckets: string[];\n}\n\nexport interface StateSpec {\n readonly provider: StateProvider;\n readonly persistence?: StatePersistenceMode;\n}\n\nexport interface AuthzSpec {\n kind: AuthzKind;\n engine: AuthzEngine;\n}\n\nexport interface AuthSignInSpec {\n identifiers: AuthSignInIdentifier[];\n}\n\nexport interface AuthSignUpSpec {\n requiredFields: AuthSignUpField[];\n optionalFields?: AuthSignUpField[];\n signUpPolicy?: AuthSignUpPolicy;\n}\n\nexport interface AuthProfileSpec {\n fields: AuthProfileField[];\n table?: string;\n primaryKey?: AuthProfilePrimaryKeyStrategy;\n createStrategy?: AuthProfileCreateStrategy;\n updateStrategy?: AuthProfileUpdateStrategy;\n}\n\nexport interface AuthSpec {\n scope: AuthScope;\n provider: AuthProvider;\n authorization?: AuthzSpec;\n flow?: AuthFlowConfig;\n signIn?: AuthSignInSpec;\n signUp?: AuthSignUpSpec;\n oauth?: AuthOAuthConfig;\n profile?: AuthProfileSpec;\n}\n\nexport interface NetworkingSpec {\n domain?: string;\n cdn: boolean;\n}\n\nexport interface InfraManifest {\n deployment?: DeploymentSpec;\n auth?: AuthSpec;\n database?: DatabaseSpec;\n storage?: StorageSpec;\n state?: StateSpec;\n networking?: NetworkingSpec;\n plugins: string[];\n pluginsConfig?: Record<string, unknown>;\n}\n\nexport interface AppSettings {\n apiBaseUrl?: string;\n localization: {\n defaultLocale: string;\n locales: string[];\n };\n}\n\nexport interface AppManifest {\n metadata: {\n name: string;\n slug: string;\n version: string;\n category: AppCategory;\n themeId: string;\n created?: string;\n updated?: string;\n };\n themes: ThemeConfig[];\n activeThemeId: string;\n activeThemeMode?: 'dark' | 'light';\n splashScreen?: SplashScreenSpec;\n infra: InfraManifest;\n navigator: NavigatorSpec;\n screens: Record<string, ScreenSpec>;\n generatedApis?: GeneratedApiRegistry;\n dataSources?: DataSourceRegistry;\n dataBindings?: ComponentDataBindingRegistry;\n settings: AppSettings;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2IA,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAGpE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,eAAe;IACf,uBAAuB;IACvB,iBAAiB;IACjB,oBAAoB;IACpB,qBAAqB;IACrB,eAAe;IACf,YAAY;IACZ,OAAO;IACP,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,SAAS;IACT,aAAa;IACb,mBAAmB;IACnB,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,mBAAmB;IACnB,kBAAkB;IAClB,QAAQ;IACR,iBAAiB;IACjB,SAAS;CACD,CAAC;AAGX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,CAAU,CAAC;AAIxD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,CAAU,CAAC;AAIxD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,MAAM,CAAU,CAAC;AAGvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAG/D,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAAQ,CAAU,CAAC;AAInD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAU,CAAC;AAGxF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAU,CAAC;AAGrD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAG3D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAU,CAAC;AAGrE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,UAAU,CAAU,CAAC;AAIpD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAU,CAAC;AAGhF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,YAAY,EAAE,qBAAqB,CAAU,CAAC;AAGpF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,wBAAwB;IAC3B,WAAW;IACX,UAAU;IACV,aAAa;IACb,WAAW;CACH,CAAC;AAIX,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,YAAY,CAAU,CAAC;AAG3E,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAGjF,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,KAAK,EAAE,KAAK,CAAU,CAAC","sourcesContent":["import type { ColorHarmony } from '@ankhorage/color-theory';\n\nimport type { AuthFlowConfig, AuthIdentifierKind, AuthOAuthConfig, AuthSignUpField } from './auth';\nimport type {\n BindingValueSource,\n ComponentDataBindingRegistry,\n ScreenDataLoaderDefinition,\n} from './bindings';\nimport type { DataSourceRegistry, GeneratedApiRegistry } from './data';\nimport type { ScreenRequirements } from './requirements';\n\nexport interface ThemeModeConfig {\n primaryColor: string;\n harmony: ColorHarmony;\n}\n\nexport interface ThemeConfig {\n id: string;\n name: string;\n light: ThemeModeConfig;\n dark: ThemeModeConfig;\n}\n\nexport type ActionType =\n | 'navigate'\n | 'alert'\n | 'console'\n | 'toggleDarkMode'\n | 'setLanguage'\n | 'search'\n | 'filter';\n\nexport interface NavigateAction {\n type: 'navigate';\n payload: {\n route: string;\n params?: Record<string, number | string>;\n };\n}\n\nexport interface AlertAction {\n type: 'alert';\n payload?: {\n message?: string;\n };\n}\n\nexport interface ConsoleAction {\n type: 'console';\n payload?: Record<string, unknown>;\n}\n\nexport interface ToggleDarkModeAction {\n type: 'toggleDarkMode';\n payload?: never;\n}\n\nexport interface SetLanguageAction {\n type: 'setLanguage';\n payload: {\n locale: string;\n };\n}\n\nexport interface SearchAction {\n type: 'search';\n payload: {\n query: string;\n scope?: string;\n };\n}\n\nexport interface FilterAction {\n type: 'filter';\n payload: {\n filterKey: string;\n filterValue: string;\n };\n}\n\nexport type Action =\n | AlertAction\n | ConsoleAction\n | FilterAction\n | NavigateAction\n | SearchAction\n | SetLanguageAction\n | ToggleDarkModeAction;\n\nexport type ManifestValue =\n | string\n | number\n | boolean\n | null\n | readonly ManifestValue[]\n | { readonly [key: string]: ManifestValue };\n\nexport type ComponentEventPayloadValue = ManifestValue;\n\nexport interface ComponentEventDto<\n TType extends string = string,\n TPayload extends object = Record<string, ComponentEventPayloadValue>,\n> {\n readonly type: TType;\n readonly sourceNodeId: string;\n readonly payload: TPayload;\n}\n\nexport type FormSubmitValues = Record<string, ComponentEventPayloadValue>;\n\nexport type FormSubmitEventDto = ComponentEventDto<\n 'form.submit',\n {\n readonly values: FormSubmitValues;\n }\n>;\n\nexport type ButtonPressEventDto = ComponentEventDto<'button.press', Record<string, never>>;\n\nexport interface CollectionItemPressPayload {\n readonly itemId: string | number;\n readonly item: Record<string, ComponentEventPayloadValue>;\n}\n\nexport type CollectionItemPressEventDto = ComponentEventDto<\n 'collection.itemPress',\n CollectionItemPressPayload\n>;\n\nexport type ComponentEventDtoKind =\n | ButtonPressEventDto['type']\n | CollectionItemPressEventDto['type']\n | FormSubmitEventDto['type'];\n\nexport type KnownComponentEventDto =\n | ButtonPressEventDto\n | CollectionItemPressEventDto\n | FormSubmitEventDto;\n\nexport const NAVIGATOR_TYPES = ['stack', 'tabs', 'drawer'] as const;\nexport type NavigatorType = (typeof NAVIGATOR_TYPES)[number];\n\nexport const APP_CATEGORIES = [\n 'books_reading',\n 'business_productivity',\n 'developer_tools',\n 'education_learning',\n 'entertainment_media',\n 'finance_money',\n 'food_drink',\n 'games',\n 'graphics_design',\n 'health_fitness',\n 'kids_family',\n 'lifestyle',\n 'medical',\n 'music_audio',\n 'navigation_travel',\n 'news_magazines',\n 'photo_video',\n 'reference',\n 'shopping_commerce',\n 'social_community',\n 'sports',\n 'utilities_tools',\n 'weather',\n] as const;\nexport type AppCategory = (typeof APP_CATEGORIES)[number];\n\nexport const DEPLOYMENT_TARGETS = ['minikube'] as const;\nexport type KnownDeploymentTarget = (typeof DEPLOYMENT_TARGETS)[number];\nexport type DeploymentTarget = KnownDeploymentTarget | (string & {});\n\nexport const DATABASE_PROVIDERS = ['supabase'] as const;\nexport type KnownDatabaseProvider = (typeof DATABASE_PROVIDERS)[number];\nexport type DatabaseProvider = KnownDatabaseProvider | (string & {});\n\nexport const DATABASE_TIERS = ['dev', 'prod'] as const;\nexport type DatabaseTier = (typeof DATABASE_TIERS)[number];\n\nexport const STORAGE_PROVIDERS = ['auto', 's3', 'r2'] as const;\nexport type StorageProvider = (typeof STORAGE_PROVIDERS)[number];\n\nexport const STATE_PROVIDERS = ['legend'] as const;\nexport type KnownStateProvider = (typeof STATE_PROVIDERS)[number];\nexport type StateProvider = KnownStateProvider | (string & {});\n\nexport const STATE_PERSISTENCE_MODES = ['none', 'local', 'secure', 'database'] as const;\nexport type StatePersistenceMode = (typeof STATE_PERSISTENCE_MODES)[number];\n\nexport const AUTHZ_KINDS = ['RBAC', 'ABAC'] as const;\nexport type AuthzKind = (typeof AUTHZ_KINDS)[number];\n\nexport const AUTHZ_ENGINES = ['cerbos', 'native'] as const;\nexport type AuthzEngine = (typeof AUTHZ_ENGINES)[number];\n\nexport const AUTH_SCOPES = ['global', 'none', 'integrated'] as const;\nexport type AuthScope = (typeof AUTH_SCOPES)[number];\n\nexport const AUTH_PROVIDERS = ['supabase'] as const;\nexport type KnownAuthProvider = (typeof AUTH_PROVIDERS)[number];\nexport type AuthProvider = KnownAuthProvider | (string & {});\n\nexport const AUTH_SIGN_IN_IDENTIFIERS = ['email', 'username', 'phone'] as const;\nexport type AuthSignInIdentifier = AuthIdentifierKind;\n\nexport const AUTH_SIGN_UP_POLICIES = ['autoSignIn', 'requireVerification'] as const;\nexport type AuthSignUpPolicy = (typeof AUTH_SIGN_UP_POLICIES)[number];\n\nexport const AUTH_PROFILE_FIELDS = [\n ...AUTH_SIGN_IN_IDENTIFIERS,\n 'firstName',\n 'lastName',\n 'displayName',\n 'avatarUrl',\n] as const;\nexport type KnownAuthProfileField = (typeof AUTH_PROFILE_FIELDS)[number];\nexport type AuthProfileField = KnownAuthProfileField | (string & {});\n\nexport const AUTH_PROFILE_PRIMARY_KEY_STRATEGIES = ['authUserId'] as const;\nexport type AuthProfilePrimaryKeyStrategy = (typeof AUTH_PROFILE_PRIMARY_KEY_STRATEGIES)[number];\n\nexport const AUTH_PROFILE_CREATE_STRATEGIES = ['trigger', 'api', 'app'] as const;\nexport type AuthProfileCreateStrategy = (typeof AUTH_PROFILE_CREATE_STRATEGIES)[number];\n\nexport const AUTH_PROFILE_UPDATE_STRATEGIES = ['api', 'app'] as const;\nexport type AuthProfileUpdateStrategy = (typeof AUTH_PROFILE_UPDATE_STRATEGIES)[number];\n\nexport interface IconSpec {\n name: string;\n provider?: string;\n size?: number | string;\n color?: string;\n}\n\nexport interface UiNodeRepeatSpec {\n source: BindingValueSource;\n itemAlias?: string;\n keyPath?: string;\n empty?: readonly UiNode[];\n}\n\nexport interface UiNode {\n id: string;\n type: string;\n alias?: string;\n props?: Record<string, unknown>;\n children?: UiNode[];\n style?: Record<string, number | string>;\n repeat?: UiNodeRepeatSpec;\n}\n\nexport interface ScreenSpec {\n id: string;\n name: string;\n title?: string;\n description?: string;\n root: UiNode;\n dataLoaders?: readonly ScreenDataLoaderDefinition[];\n requires?: ScreenRequirements;\n}\n\nexport interface NavigatorSpec {\n type: NavigatorType;\n initialRouteName?: string;\n routes: RouteDefinition[];\n options?: Record<string, unknown>;\n}\n\nexport interface RouteDefinition {\n name: string;\n path?: string;\n label?: string;\n icon?: IconSpec;\n /**\n * Whether this route appears in Tabs and Drawer primary navigation.\n *\n * Omitted routes are visible by default. Setting this to `false` hides the\n * route from primary navigation without making it unnavigable. Stack\n * navigators preserve the value but do not present primary navigation.\n */\n showInPrimaryNavigation?: boolean;\n guards?: string[];\n screenId?: string;\n navigator?: NavigatorSpec;\n}\n\nexport type SplashScreenResizeMode = 'contain' | 'cover' | 'native';\n\nexport interface SplashScreenAssetSpec {\n readonly image?: string;\n readonly imageWidth?: number;\n readonly resizeMode?: SplashScreenResizeMode;\n}\n\nexport interface SplashScreenModeSpec extends SplashScreenAssetSpec {\n readonly backgroundColor?: string;\n}\n\nexport interface SplashScreenSpec extends SplashScreenModeSpec {\n readonly dark?: SplashScreenModeSpec;\n}\n\nexport interface DeploymentSpec {\n target: DeploymentTarget;\n monitoring: boolean;\n}\n\nexport interface DatabaseSpec {\n provider: DatabaseProvider;\n tier: DatabaseTier;\n}\n\nexport interface StorageSpec {\n provider: StorageProvider;\n buckets: string[];\n}\n\nexport interface StateSpec {\n readonly provider: StateProvider;\n readonly persistence?: StatePersistenceMode;\n}\n\nexport interface AuthzSpec {\n kind: AuthzKind;\n engine: AuthzEngine;\n}\n\nexport interface AuthSignInSpec {\n identifiers: AuthSignInIdentifier[];\n}\n\nexport interface AuthSignUpSpec {\n requiredFields: AuthSignUpField[];\n optionalFields?: AuthSignUpField[];\n signUpPolicy?: AuthSignUpPolicy;\n}\n\nexport interface AuthProfileSpec {\n fields: AuthProfileField[];\n table?: string;\n primaryKey?: AuthProfilePrimaryKeyStrategy;\n createStrategy?: AuthProfileCreateStrategy;\n updateStrategy?: AuthProfileUpdateStrategy;\n}\n\nexport interface AuthSpec {\n scope: AuthScope;\n provider: AuthProvider;\n authorization?: AuthzSpec;\n flow?: AuthFlowConfig;\n signIn?: AuthSignInSpec;\n signUp?: AuthSignUpSpec;\n oauth?: AuthOAuthConfig;\n profile?: AuthProfileSpec;\n}\n\nexport interface NetworkingSpec {\n domain?: string;\n cdn: boolean;\n}\n\nexport interface InfraManifest {\n deployment?: DeploymentSpec;\n auth?: AuthSpec;\n database?: DatabaseSpec;\n storage?: StorageSpec;\n state?: StateSpec;\n networking?: NetworkingSpec;\n modules: string[];\n modulesConfig?: Record<string, unknown>;\n}\n\nexport interface AppSettings {\n apiBaseUrl?: string;\n localization: {\n defaultLocale: string;\n locales: string[];\n };\n}\n\nexport interface AppManifest {\n metadata: {\n name: string;\n slug: string;\n version: string;\n category: AppCategory;\n themeId: string;\n created?: string;\n updated?: string;\n };\n themes: ThemeConfig[];\n activeThemeId: string;\n activeThemeMode?: 'dark' | 'light';\n splashScreen?: SplashScreenSpec;\n infra: InfraManifest;\n navigator: NavigatorSpec;\n screens: Record<string, ScreenSpec>;\n generatedApis?: GeneratedApiRegistry;\n dataSources?: DataSourceRegistry;\n dataBindings?: ComponentDataBindingRegistry;\n settings: AppSettings;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/contracts",
3
- "version": "5.0.0",
3
+ "version": "7.0.0",
4
4
  "main": "./dist/index.js",
5
5
  "ankh": {
6
6
  "category": "contracts",
@@ -45,10 +45,6 @@
45
45
  "types": "./dist/db.d.ts",
46
46
  "default": "./dist/db.js"
47
47
  },
48
- "./nutrition": {
49
- "types": "./dist/nutrition/index.d.ts",
50
- "default": "./dist/nutrition/index.js"
51
- },
52
48
  "./runtime": {
53
49
  "types": "./dist/runtimeCallbacks.d.ts",
54
50
  "default": "./dist/runtimeCallbacks.js"
@@ -490,7 +490,7 @@ describe('component data-binding contracts', () => {
490
490
  ],
491
491
  activeThemeId: 'default',
492
492
  infra: {
493
- plugins: [],
493
+ modules: [],
494
494
  },
495
495
  navigator: {
496
496
  type: 'stack',
@@ -25,6 +25,7 @@ import {
25
25
  DEPLOYMENT_TARGETS,
26
26
  type FormSubmitEventDto,
27
27
  type ImageAssetSource,
28
+ type InfraManifest,
28
29
  NAVIGATOR_TYPES,
29
30
  type RouteDefinition,
30
31
  type SplashScreenSpec,
@@ -242,18 +243,55 @@ describe('contracts', () => {
242
243
  const manifest: Pick<AppManifest, 'infra'> = {
243
244
  infra: {
244
245
  state,
245
- plugins: [],
246
+ modules: [],
247
+ modulesConfig: {
248
+ localization: {
249
+ defaultLocale: 'en',
250
+ },
251
+ },
246
252
  },
247
253
  };
248
254
 
249
255
  expect(JSON.parse(JSON.stringify(manifest))).toEqual({
250
256
  infra: {
251
257
  state,
252
- plugins: [],
258
+ modules: [],
259
+ modulesConfig: {
260
+ localization: {
261
+ defaultLocale: 'en',
262
+ },
263
+ },
253
264
  },
254
265
  });
255
266
  });
256
267
 
268
+ it('exposes only canonical module fields without reserving external plugin terminology', () => {
269
+ type HasLegacyModules = 'plugins' extends keyof InfraManifest ? true : false;
270
+ type HasLegacyModulesConfig = 'pluginsConfig' extends keyof InfraManifest ? true : false;
271
+
272
+ const hasLegacyModules: HasLegacyModules = false;
273
+ const hasLegacyModulesConfig: HasLegacyModulesConfig = false;
274
+ const infra: InfraManifest = {
275
+ modules: ['expo-localization'],
276
+ modulesConfig: {
277
+ 'expo-localization': {
278
+ defaultLocale: 'en',
279
+ locales: ['en', 'de'],
280
+ },
281
+ },
282
+ };
283
+ // `plugins` remains valid when it names an unrelated external ecosystem concept,
284
+ // such as Expo configuration plugins rather than Ankhorage Orchestrator modules.
285
+ const expoConfig: { plugins: string[] } = {
286
+ plugins: ['expo-router'],
287
+ };
288
+
289
+ expect(hasLegacyModules).toBe(false);
290
+ expect(hasLegacyModulesConfig).toBe(false);
291
+ expect(Object.keys(infra).sort()).toEqual(['modules', 'modulesConfig']);
292
+ expect(expoConfig.plugins).toEqual(['expo-router']);
293
+ });
294
+
257
295
  it('ThemeModeConfig.harmony accepts all ColorHarmony values', () => {
258
296
  for (const harmony of COLOR_HARMONIES) {
259
297
  const config = { primaryColor: '#ff0000', harmony } satisfies ThemeModeConfig;
package/src/index.ts CHANGED
@@ -3,7 +3,6 @@ export * from './bindings';
3
3
  export * from './cli';
4
4
  export * from './data';
5
5
  export * from './db';
6
- export * from './nutrition';
7
6
  export * from './requirements';
8
7
  export * from './runtimeCallbacks';
9
8
  export * from './secretManifest';
@@ -69,7 +69,7 @@ describe('secret-store contracts', () => {
69
69
  };
70
70
 
71
71
  const infra: InfraManifest = {
72
- plugins: [],
72
+ modules: [],
73
73
  secretStore: { provider: 'supabase-vault' },
74
74
  auth: {
75
75
  scope: 'global',
package/src/types.ts CHANGED
@@ -367,8 +367,8 @@ export interface InfraManifest {
367
367
  storage?: StorageSpec;
368
368
  state?: StateSpec;
369
369
  networking?: NetworkingSpec;
370
- plugins: string[];
371
- pluginsConfig?: Record<string, unknown>;
370
+ modules: string[];
371
+ modulesConfig?: Record<string, unknown>;
372
372
  }
373
373
 
374
374
  export interface AppSettings {
@@ -1,54 +0,0 @@
1
- import type { NutritionBarcode, NutritionCaptureSubmissionId, NutritionIsoDateTime, NutritionJsonValue, NutritionProductId, NutritionUserId } from './common';
2
- import type { NutritionFactsPer100g, NutritionImageEvidence, NutritionIngredientStatement, NutritionServing, NutritionStoreObservation } from './products';
3
- export declare const NUTRITION_CAPTURE_SUBMISSION_STATUSES: readonly ["queued", "needs_more_data", "accepted", "rejected", "merged"];
4
- export type NutritionCaptureSubmissionStatus = (typeof NUTRITION_CAPTURE_SUBMISSION_STATUSES)[number];
5
- export interface NutritionCaptureClientContext {
6
- readonly userId?: NutritionUserId;
7
- readonly anonymousDeviceId?: string;
8
- readonly platform?: 'android' | 'ios' | 'web' | (string & {});
9
- readonly appVersion?: string;
10
- readonly locale?: string;
11
- readonly clientCapturedAt?: NutritionIsoDateTime;
12
- }
13
- export interface NutritionProductCaptureDraft {
14
- readonly barcode: NutritionBarcode;
15
- readonly name?: string;
16
- readonly brand?: string;
17
- readonly quantity?: string;
18
- readonly packageSizeG?: number;
19
- readonly packageSizeMl?: number;
20
- readonly serving?: NutritionServing;
21
- readonly nutrientsPer100g?: NutritionFactsPer100g;
22
- readonly ingredients?: NutritionIngredientStatement;
23
- readonly storeObservation?: NutritionStoreObservation;
24
- readonly images?: readonly NutritionImageEvidence[];
25
- readonly rawPayload?: NutritionJsonValue;
26
- }
27
- export interface NutritionProductCaptureRequest {
28
- readonly draft: NutritionProductCaptureDraft;
29
- readonly client?: NutritionCaptureClientContext;
30
- }
31
- export interface NutritionProductCaptureResponse {
32
- readonly submissionId: NutritionCaptureSubmissionId;
33
- readonly status: NutritionCaptureSubmissionStatus;
34
- readonly productId?: NutritionProductId;
35
- readonly message?: string;
36
- }
37
- export interface NutritionProductCorrectionRequest {
38
- readonly productId: NutritionProductId;
39
- readonly patch: Partial<NutritionProductCaptureDraft>;
40
- readonly client?: NutritionCaptureClientContext;
41
- readonly note?: string;
42
- }
43
- export interface NutritionCaptureSubmission {
44
- readonly id: NutritionCaptureSubmissionId;
45
- readonly status: NutritionCaptureSubmissionStatus;
46
- readonly draft: NutritionProductCaptureDraft;
47
- readonly client?: NutritionCaptureClientContext;
48
- readonly matchedProductId?: NutritionProductId | null;
49
- readonly reviewerNote?: string;
50
- readonly createdAt: NutritionIsoDateTime;
51
- readonly updatedAt: NutritionIsoDateTime;
52
- readonly decidedAt?: NutritionIsoDateTime | null;
53
- }
54
- //# sourceMappingURL=capture.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/nutrition/capture.ts"],"names":[],"mappings":"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"}
@@ -1,8 +0,0 @@
1
- export const NUTRITION_CAPTURE_SUBMISSION_STATUSES = [
2
- 'queued',
3
- 'needs_more_data',
4
- 'accepted',
5
- 'rejected',
6
- 'merged',
7
- ];
8
- //# sourceMappingURL=capture.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/nutrition/capture.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,qCAAqC,GAAG;IACnD,QAAQ;IACR,iBAAiB;IACjB,UAAU;IACV,UAAU;IACV,QAAQ;CACA,CAAC","sourcesContent":["import type {\n NutritionBarcode,\n NutritionCaptureSubmissionId,\n NutritionIsoDateTime,\n NutritionJsonValue,\n NutritionProductId,\n NutritionUserId,\n} from './common';\nimport type {\n NutritionFactsPer100g,\n NutritionImageEvidence,\n NutritionIngredientStatement,\n NutritionServing,\n NutritionStoreObservation,\n} from './products';\n\nexport const NUTRITION_CAPTURE_SUBMISSION_STATUSES = [\n 'queued',\n 'needs_more_data',\n 'accepted',\n 'rejected',\n 'merged',\n] as const;\nexport type NutritionCaptureSubmissionStatus =\n (typeof NUTRITION_CAPTURE_SUBMISSION_STATUSES)[number];\n\nexport interface NutritionCaptureClientContext {\n readonly userId?: NutritionUserId;\n readonly anonymousDeviceId?: string;\n readonly platform?: 'android' | 'ios' | 'web' | (string & {});\n readonly appVersion?: string;\n readonly locale?: string;\n readonly clientCapturedAt?: NutritionIsoDateTime;\n}\n\nexport interface NutritionProductCaptureDraft {\n readonly barcode: NutritionBarcode;\n readonly name?: string;\n readonly brand?: string;\n readonly quantity?: string;\n readonly packageSizeG?: number;\n readonly packageSizeMl?: number;\n readonly serving?: NutritionServing;\n readonly nutrientsPer100g?: NutritionFactsPer100g;\n readonly ingredients?: NutritionIngredientStatement;\n readonly storeObservation?: NutritionStoreObservation;\n readonly images?: readonly NutritionImageEvidence[];\n readonly rawPayload?: NutritionJsonValue;\n}\n\nexport interface NutritionProductCaptureRequest {\n readonly draft: NutritionProductCaptureDraft;\n readonly client?: NutritionCaptureClientContext;\n}\n\nexport interface NutritionProductCaptureResponse {\n readonly submissionId: NutritionCaptureSubmissionId;\n readonly status: NutritionCaptureSubmissionStatus;\n readonly productId?: NutritionProductId;\n readonly message?: string;\n}\n\nexport interface NutritionProductCorrectionRequest {\n readonly productId: NutritionProductId;\n readonly patch: Partial<NutritionProductCaptureDraft>;\n readonly client?: NutritionCaptureClientContext;\n readonly note?: string;\n}\n\nexport interface NutritionCaptureSubmission {\n readonly id: NutritionCaptureSubmissionId;\n readonly status: NutritionCaptureSubmissionStatus;\n readonly draft: NutritionProductCaptureDraft;\n readonly client?: NutritionCaptureClientContext;\n readonly matchedProductId?: NutritionProductId | null;\n readonly reviewerNote?: string;\n readonly createdAt: NutritionIsoDateTime;\n readonly updatedAt: NutritionIsoDateTime;\n readonly decidedAt?: NutritionIsoDateTime | null;\n}\n"]}
@@ -1,22 +0,0 @@
1
- export type NutritionIsoDateTime = string;
2
- export type NutritionProductId = string;
3
- export type NutritionCaptureSubmissionId = string;
4
- export type NutritionReviewId = string;
5
- export type NutritionUserId = string;
6
- export type NutritionJsonValue = boolean | number | string | null | readonly NutritionJsonValue[] | {
7
- readonly [key: string]: NutritionJsonValue;
8
- };
9
- export declare const NUTRITION_BARCODE_TYPES: readonly ["ean_8", "ean_13", "upc_a", "upc_e", "gtin_14", "unknown"];
10
- export type NutritionBarcodeType = (typeof NUTRITION_BARCODE_TYPES)[number];
11
- export interface NutritionBarcode {
12
- readonly value: string;
13
- readonly type: NutritionBarcodeType;
14
- readonly normalizedValue?: string;
15
- }
16
- export declare const NUTRITION_PRODUCT_STATUSES: readonly ["draft", "pending_review", "published", "rejected", "archived"];
17
- export type NutritionProductStatus = (typeof NUTRITION_PRODUCT_STATUSES)[number];
18
- export declare const NUTRITION_DATA_SOURCES: readonly ["manual_scan", "user_correction", "open_food_facts", "foodrepo_legacy", "retailer_import", "admin_import"];
19
- export type NutritionDataSource = (typeof NUTRITION_DATA_SOURCES)[number];
20
- export declare const NUTRITION_SOURCE_CONFIDENCE_LEVELS: readonly ["unknown", "low", "medium", "high"];
21
- export type NutritionSourceConfidence = (typeof NUTRITION_SOURCE_CONFIDENCE_LEVELS)[number];
22
- //# sourceMappingURL=common.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/nutrition/common.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAC1C,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AACxC,MAAM,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAClD,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACvC,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC,MAAM,MAAM,kBAAkB,GAC1B,OAAO,GACP,MAAM,GACN,MAAM,GACN,IAAI,GACJ,SAAS,kBAAkB,EAAE,GAC7B;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;CAAE,CAAC;AAEnD,eAAO,MAAM,uBAAuB,sEAO1B,CAAC;AACX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,eAAO,MAAM,0BAA0B,2EAM7B,CAAC;AACX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF,eAAO,MAAM,sBAAsB,sHAOzB,CAAC;AACX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,eAAO,MAAM,kCAAkC,+CAAgD,CAAC;AAChG,MAAM,MAAM,yBAAyB,GAAG,CAAC,OAAO,kCAAkC,CAAC,CAAC,MAAM,CAAC,CAAC"}
@@ -1,25 +0,0 @@
1
- export const NUTRITION_BARCODE_TYPES = [
2
- 'ean_8',
3
- 'ean_13',
4
- 'upc_a',
5
- 'upc_e',
6
- 'gtin_14',
7
- 'unknown',
8
- ];
9
- export const NUTRITION_PRODUCT_STATUSES = [
10
- 'draft',
11
- 'pending_review',
12
- 'published',
13
- 'rejected',
14
- 'archived',
15
- ];
16
- export const NUTRITION_DATA_SOURCES = [
17
- 'manual_scan',
18
- 'user_correction',
19
- 'open_food_facts',
20
- 'foodrepo_legacy',
21
- 'retailer_import',
22
- 'admin_import',
23
- ];
24
- export const NUTRITION_SOURCE_CONFIDENCE_LEVELS = ['unknown', 'low', 'medium', 'high'];
25
- //# sourceMappingURL=common.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/nutrition/common.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,SAAS;IACT,SAAS;CACD,CAAC;AASX,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,OAAO;IACP,gBAAgB;IAChB,WAAW;IACX,UAAU;IACV,UAAU;CACF,CAAC;AAGX,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,aAAa;IACb,iBAAiB;IACjB,iBAAiB;IACjB,iBAAiB;IACjB,iBAAiB;IACjB,cAAc;CACN,CAAC;AAGX,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAC","sourcesContent":["export type NutritionIsoDateTime = string;\nexport type NutritionProductId = string;\nexport type NutritionCaptureSubmissionId = string;\nexport type NutritionReviewId = string;\nexport type NutritionUserId = string;\n\nexport type NutritionJsonValue =\n | boolean\n | number\n | string\n | null\n | readonly NutritionJsonValue[]\n | { readonly [key: string]: NutritionJsonValue };\n\nexport const NUTRITION_BARCODE_TYPES = [\n 'ean_8',\n 'ean_13',\n 'upc_a',\n 'upc_e',\n 'gtin_14',\n 'unknown',\n] as const;\nexport type NutritionBarcodeType = (typeof NUTRITION_BARCODE_TYPES)[number];\n\nexport interface NutritionBarcode {\n readonly value: string;\n readonly type: NutritionBarcodeType;\n readonly normalizedValue?: string;\n}\n\nexport const NUTRITION_PRODUCT_STATUSES = [\n 'draft',\n 'pending_review',\n 'published',\n 'rejected',\n 'archived',\n] as const;\nexport type NutritionProductStatus = (typeof NUTRITION_PRODUCT_STATUSES)[number];\n\nexport const NUTRITION_DATA_SOURCES = [\n 'manual_scan',\n 'user_correction',\n 'open_food_facts',\n 'foodrepo_legacy',\n 'retailer_import',\n 'admin_import',\n] as const;\nexport type NutritionDataSource = (typeof NUTRITION_DATA_SOURCES)[number];\n\nexport const NUTRITION_SOURCE_CONFIDENCE_LEVELS = ['unknown', 'low', 'medium', 'high'] as const;\nexport type NutritionSourceConfidence = (typeof NUTRITION_SOURCE_CONFIDENCE_LEVELS)[number];\n"]}
@@ -1,5 +0,0 @@
1
- export * from './capture';
2
- export * from './common';
3
- export * from './products';
4
- export * from './review';
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nutrition/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC"}
@@ -1,5 +0,0 @@
1
- export * from './capture';
2
- export * from './common';
3
- export * from './products';
4
- export * from './review';
5
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nutrition/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC","sourcesContent":["export * from './capture';\nexport * from './common';\nexport * from './products';\nexport * from './review';\n"]}
@@ -1,93 +0,0 @@
1
- import type { NutritionBarcode, NutritionDataSource, NutritionIsoDateTime, NutritionJsonValue, NutritionProductId, NutritionProductStatus, NutritionSourceConfidence } from './common';
2
- export type NutritionMeasurementBasis = 'per_100g' | 'per_100ml';
3
- export interface NutritionFactsPer100g {
4
- readonly basis?: NutritionMeasurementBasis;
5
- readonly energyKcal?: number;
6
- readonly energyKj?: number;
7
- readonly proteinG?: number;
8
- readonly carbohydratesG?: number;
9
- readonly sugarsG?: number;
10
- readonly fatG?: number;
11
- readonly saturatedFatG?: number;
12
- readonly fiberG?: number;
13
- readonly saltG?: number;
14
- readonly sodiumG?: number;
15
- }
16
- export interface NutritionServing {
17
- readonly label?: string;
18
- readonly sizeG?: number;
19
- readonly sizeMl?: number;
20
- readonly servingsPerPackage?: number;
21
- }
22
- export interface NutritionIngredientStatement {
23
- readonly text?: string;
24
- readonly locale?: string;
25
- readonly rawText?: string;
26
- }
27
- export type NutritionAllergenTag = 'celery' | 'cereals_containing_gluten' | 'crustaceans' | 'eggs' | 'fish' | 'lupin' | 'milk' | 'molluscs' | 'mustard' | 'nuts' | 'peanuts' | 'sesame' | 'soybeans' | 'sulphur_dioxide_and_sulphites' | (string & {});
28
- export interface NutritionStoreObservation {
29
- readonly countryCode?: string;
30
- readonly storeChain?: string;
31
- readonly storeName?: string;
32
- readonly storeLocationLabel?: string;
33
- readonly observedAt?: NutritionIsoDateTime;
34
- }
35
- export declare const NUTRITION_IMAGE_KINDS: readonly ["front", "nutrition_label", "ingredients", "barcode", "package_back", "other"];
36
- export type NutritionImageKind = (typeof NUTRITION_IMAGE_KINDS)[number];
37
- export interface NutritionImageEvidence {
38
- readonly id?: string;
39
- readonly kind: NutritionImageKind;
40
- readonly storageId?: string;
41
- readonly bucket?: string;
42
- readonly path?: string;
43
- readonly publicUrl?: string;
44
- readonly contentType?: string;
45
- readonly width?: number;
46
- readonly height?: number;
47
- readonly capturedAt?: NutritionIsoDateTime;
48
- readonly metadata?: Record<string, NutritionJsonValue>;
49
- }
50
- export interface NutritionProductSummary {
51
- readonly id: NutritionProductId;
52
- readonly primaryBarcode: NutritionBarcode;
53
- readonly name: string;
54
- readonly brand?: string;
55
- readonly quantity?: string;
56
- readonly status: NutritionProductStatus;
57
- readonly source: NutritionDataSource;
58
- readonly sourceConfidence: NutritionSourceConfidence;
59
- readonly imageUrl?: string;
60
- readonly updatedAt: NutritionIsoDateTime;
61
- }
62
- export interface NutritionProduct {
63
- readonly id: NutritionProductId;
64
- readonly primaryBarcode: NutritionBarcode;
65
- readonly barcodes?: readonly NutritionBarcode[];
66
- readonly name: string;
67
- readonly brand?: string;
68
- readonly quantity?: string;
69
- readonly packageSizeG?: number;
70
- readonly packageSizeMl?: number;
71
- readonly serving?: NutritionServing;
72
- readonly nutrientsPer100g?: NutritionFactsPer100g;
73
- readonly ingredients?: NutritionIngredientStatement;
74
- readonly allergens?: readonly NutritionAllergenTag[];
75
- readonly traces?: readonly NutritionAllergenTag[];
76
- readonly stores?: readonly NutritionStoreObservation[];
77
- readonly images?: readonly NutritionImageEvidence[];
78
- readonly status: NutritionProductStatus;
79
- readonly source: NutritionDataSource;
80
- readonly sourceConfidence: NutritionSourceConfidence;
81
- readonly sourcePayload?: NutritionJsonValue;
82
- readonly verifiedByUser?: boolean;
83
- readonly createdAt: NutritionIsoDateTime;
84
- readonly updatedAt: NutritionIsoDateTime;
85
- readonly publishedAt?: NutritionIsoDateTime | null;
86
- }
87
- export interface NutritionProductDetail {
88
- readonly product: NutritionProduct;
89
- }
90
- export interface NutritionProductLookupByBarcodeResponse {
91
- readonly product: NutritionProduct;
92
- }
93
- //# sourceMappingURL=products.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../src/nutrition/products.ts"],"names":[],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- export const NUTRITION_IMAGE_KINDS = [
2
- 'front',
3
- 'nutrition_label',
4
- 'ingredients',
5
- 'barcode',
6
- 'package_back',
7
- 'other',
8
- ];
9
- //# sourceMappingURL=products.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"products.js","sourceRoot":"","sources":["../../src/nutrition/products.ts"],"names":[],"mappings":"AAgEA,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,OAAO;IACP,iBAAiB;IACjB,aAAa;IACb,SAAS;IACT,cAAc;IACd,OAAO;CACC,CAAC","sourcesContent":["import type {\n NutritionBarcode,\n NutritionDataSource,\n NutritionIsoDateTime,\n NutritionJsonValue,\n NutritionProductId,\n NutritionProductStatus,\n NutritionSourceConfidence,\n} from './common';\n\nexport type NutritionMeasurementBasis = 'per_100g' | 'per_100ml';\n\nexport interface NutritionFactsPer100g {\n readonly basis?: NutritionMeasurementBasis;\n readonly energyKcal?: number;\n readonly energyKj?: number;\n readonly proteinG?: number;\n readonly carbohydratesG?: number;\n readonly sugarsG?: number;\n readonly fatG?: number;\n readonly saturatedFatG?: number;\n readonly fiberG?: number;\n readonly saltG?: number;\n readonly sodiumG?: number;\n}\n\nexport interface NutritionServing {\n readonly label?: string;\n readonly sizeG?: number;\n readonly sizeMl?: number;\n readonly servingsPerPackage?: number;\n}\n\nexport interface NutritionIngredientStatement {\n readonly text?: string;\n readonly locale?: string;\n readonly rawText?: string;\n}\n\nexport type NutritionAllergenTag =\n | 'celery'\n | 'cereals_containing_gluten'\n | 'crustaceans'\n | 'eggs'\n | 'fish'\n | 'lupin'\n | 'milk'\n | 'molluscs'\n | 'mustard'\n | 'nuts'\n | 'peanuts'\n | 'sesame'\n | 'soybeans'\n | 'sulphur_dioxide_and_sulphites'\n | (string & {});\n\nexport interface NutritionStoreObservation {\n readonly countryCode?: string;\n readonly storeChain?: string;\n readonly storeName?: string;\n readonly storeLocationLabel?: string;\n readonly observedAt?: NutritionIsoDateTime;\n}\n\nexport const NUTRITION_IMAGE_KINDS = [\n 'front',\n 'nutrition_label',\n 'ingredients',\n 'barcode',\n 'package_back',\n 'other',\n] as const;\nexport type NutritionImageKind = (typeof NUTRITION_IMAGE_KINDS)[number];\n\nexport interface NutritionImageEvidence {\n readonly id?: string;\n readonly kind: NutritionImageKind;\n readonly storageId?: string;\n readonly bucket?: string;\n readonly path?: string;\n readonly publicUrl?: string;\n readonly contentType?: string;\n readonly width?: number;\n readonly height?: number;\n readonly capturedAt?: NutritionIsoDateTime;\n readonly metadata?: Record<string, NutritionJsonValue>;\n}\n\nexport interface NutritionProductSummary {\n readonly id: NutritionProductId;\n readonly primaryBarcode: NutritionBarcode;\n readonly name: string;\n readonly brand?: string;\n readonly quantity?: string;\n readonly status: NutritionProductStatus;\n readonly source: NutritionDataSource;\n readonly sourceConfidence: NutritionSourceConfidence;\n readonly imageUrl?: string;\n readonly updatedAt: NutritionIsoDateTime;\n}\n\nexport interface NutritionProduct {\n readonly id: NutritionProductId;\n readonly primaryBarcode: NutritionBarcode;\n readonly barcodes?: readonly NutritionBarcode[];\n readonly name: string;\n readonly brand?: string;\n readonly quantity?: string;\n readonly packageSizeG?: number;\n readonly packageSizeMl?: number;\n readonly serving?: NutritionServing;\n readonly nutrientsPer100g?: NutritionFactsPer100g;\n readonly ingredients?: NutritionIngredientStatement;\n readonly allergens?: readonly NutritionAllergenTag[];\n readonly traces?: readonly NutritionAllergenTag[];\n readonly stores?: readonly NutritionStoreObservation[];\n readonly images?: readonly NutritionImageEvidence[];\n readonly status: NutritionProductStatus;\n readonly source: NutritionDataSource;\n readonly sourceConfidence: NutritionSourceConfidence;\n readonly sourcePayload?: NutritionJsonValue;\n readonly verifiedByUser?: boolean;\n readonly createdAt: NutritionIsoDateTime;\n readonly updatedAt: NutritionIsoDateTime;\n readonly publishedAt?: NutritionIsoDateTime | null;\n}\n\nexport interface NutritionProductDetail {\n readonly product: NutritionProduct;\n}\n\nexport interface NutritionProductLookupByBarcodeResponse {\n readonly product: NutritionProduct;\n}\n"]}
@@ -1,47 +0,0 @@
1
- import type { NutritionCaptureSubmission, NutritionCaptureSubmissionStatus } from './capture';
2
- import type { NutritionCaptureSubmissionId, NutritionIsoDateTime, NutritionJsonValue, NutritionProductId, NutritionReviewId, NutritionUserId } from './common';
3
- import type { NutritionProduct } from './products';
4
- export declare const NUTRITION_REVIEW_DECISIONS: readonly ["accept", "reject", "merge", "request_changes", "publish"];
5
- export type NutritionReviewDecision = (typeof NUTRITION_REVIEW_DECISIONS)[number];
6
- export interface NutritionReviewDecisionRequest {
7
- readonly decision: NutritionReviewDecision;
8
- readonly submissionId: NutritionCaptureSubmissionId;
9
- readonly reviewerId?: NutritionUserId;
10
- readonly targetProductId?: NutritionProductId;
11
- readonly productOverride?: Partial<NutritionProduct>;
12
- readonly note?: string;
13
- readonly metadata?: Record<string, NutritionJsonValue>;
14
- }
15
- export interface NutritionReviewDecisionResponse {
16
- readonly reviewId: NutritionReviewId;
17
- readonly submissionId: NutritionCaptureSubmissionId;
18
- readonly decision: NutritionReviewDecision;
19
- readonly status: NutritionCaptureSubmissionStatus;
20
- readonly productId?: NutritionProductId;
21
- readonly decidedAt: NutritionIsoDateTime;
22
- }
23
- export interface NutritionReviewRecord {
24
- readonly id: NutritionReviewId;
25
- readonly submissionId: NutritionCaptureSubmissionId;
26
- readonly reviewerId?: NutritionUserId;
27
- readonly decision: NutritionReviewDecision;
28
- readonly previousStatus: NutritionCaptureSubmissionStatus;
29
- readonly nextStatus: NutritionCaptureSubmissionStatus;
30
- readonly targetProductId?: NutritionProductId | null;
31
- readonly note?: string;
32
- readonly metadata?: Record<string, NutritionJsonValue>;
33
- readonly createdAt: NutritionIsoDateTime;
34
- }
35
- export interface NutritionReviewSubmissionListRequest {
36
- readonly status?: NutritionCaptureSubmissionStatus;
37
- readonly barcode?: string;
38
- readonly store?: string;
39
- readonly limit?: number;
40
- readonly offset?: number;
41
- }
42
- export interface NutritionReviewSubmissionListResponse {
43
- readonly submissions: readonly NutritionCaptureSubmission[];
44
- readonly limit?: number;
45
- readonly offset?: number;
46
- }
47
- //# sourceMappingURL=review.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/nutrition/review.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,gCAAgC,EAAE,MAAM,WAAW,CAAC;AAC9F,OAAO,KAAK,EACV,4BAA4B,EAC5B,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EAChB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,eAAO,MAAM,0BAA0B,sEAM7B,CAAC;AACX,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAElF,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,YAAY,EAAE,4BAA4B,CAAC;IACpD,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,eAAe,CAAC,EAAE,kBAAkB,CAAC;IAC9C,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,4BAA4B,CAAC;IACpD,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,gCAAgC,CAAC;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAC;CAC1C;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,iBAAiB,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,4BAA4B,CAAC;IACpD,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,gCAAgC,CAAC;IAC1D,QAAQ,CAAC,UAAU,EAAE,gCAAgC,CAAC;IACtD,QAAQ,CAAC,eAAe,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACrD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACvD,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAC;CAC1C;AAED,MAAM,WAAW,oCAAoC;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,gCAAgC,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,qCAAqC;IACpD,QAAQ,CAAC,WAAW,EAAE,SAAS,0BAA0B,EAAE,CAAC;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B"}
@@ -1,8 +0,0 @@
1
- export const NUTRITION_REVIEW_DECISIONS = [
2
- 'accept',
3
- 'reject',
4
- 'merge',
5
- 'request_changes',
6
- 'publish',
7
- ];
8
- //# sourceMappingURL=review.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/nutrition/review.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,iBAAiB;IACjB,SAAS;CACD,CAAC","sourcesContent":["import type { NutritionCaptureSubmission, NutritionCaptureSubmissionStatus } from './capture';\nimport type {\n NutritionCaptureSubmissionId,\n NutritionIsoDateTime,\n NutritionJsonValue,\n NutritionProductId,\n NutritionReviewId,\n NutritionUserId,\n} from './common';\nimport type { NutritionProduct } from './products';\n\nexport const NUTRITION_REVIEW_DECISIONS = [\n 'accept',\n 'reject',\n 'merge',\n 'request_changes',\n 'publish',\n] as const;\nexport type NutritionReviewDecision = (typeof NUTRITION_REVIEW_DECISIONS)[number];\n\nexport interface NutritionReviewDecisionRequest {\n readonly decision: NutritionReviewDecision;\n readonly submissionId: NutritionCaptureSubmissionId;\n readonly reviewerId?: NutritionUserId;\n readonly targetProductId?: NutritionProductId;\n readonly productOverride?: Partial<NutritionProduct>;\n readonly note?: string;\n readonly metadata?: Record<string, NutritionJsonValue>;\n}\n\nexport interface NutritionReviewDecisionResponse {\n readonly reviewId: NutritionReviewId;\n readonly submissionId: NutritionCaptureSubmissionId;\n readonly decision: NutritionReviewDecision;\n readonly status: NutritionCaptureSubmissionStatus;\n readonly productId?: NutritionProductId;\n readonly decidedAt: NutritionIsoDateTime;\n}\n\nexport interface NutritionReviewRecord {\n readonly id: NutritionReviewId;\n readonly submissionId: NutritionCaptureSubmissionId;\n readonly reviewerId?: NutritionUserId;\n readonly decision: NutritionReviewDecision;\n readonly previousStatus: NutritionCaptureSubmissionStatus;\n readonly nextStatus: NutritionCaptureSubmissionStatus;\n readonly targetProductId?: NutritionProductId | null;\n readonly note?: string;\n readonly metadata?: Record<string, NutritionJsonValue>;\n readonly createdAt: NutritionIsoDateTime;\n}\n\nexport interface NutritionReviewSubmissionListRequest {\n readonly status?: NutritionCaptureSubmissionStatus;\n readonly barcode?: string;\n readonly store?: string;\n readonly limit?: number;\n readonly offset?: number;\n}\n\nexport interface NutritionReviewSubmissionListResponse {\n readonly submissions: readonly NutritionCaptureSubmission[];\n readonly limit?: number;\n readonly offset?: number;\n}\n"]}
@@ -1,80 +0,0 @@
1
- import type {
2
- NutritionBarcode,
3
- NutritionCaptureSubmissionId,
4
- NutritionIsoDateTime,
5
- NutritionJsonValue,
6
- NutritionProductId,
7
- NutritionUserId,
8
- } from './common';
9
- import type {
10
- NutritionFactsPer100g,
11
- NutritionImageEvidence,
12
- NutritionIngredientStatement,
13
- NutritionServing,
14
- NutritionStoreObservation,
15
- } from './products';
16
-
17
- export const NUTRITION_CAPTURE_SUBMISSION_STATUSES = [
18
- 'queued',
19
- 'needs_more_data',
20
- 'accepted',
21
- 'rejected',
22
- 'merged',
23
- ] as const;
24
- export type NutritionCaptureSubmissionStatus =
25
- (typeof NUTRITION_CAPTURE_SUBMISSION_STATUSES)[number];
26
-
27
- export interface NutritionCaptureClientContext {
28
- readonly userId?: NutritionUserId;
29
- readonly anonymousDeviceId?: string;
30
- readonly platform?: 'android' | 'ios' | 'web' | (string & {});
31
- readonly appVersion?: string;
32
- readonly locale?: string;
33
- readonly clientCapturedAt?: NutritionIsoDateTime;
34
- }
35
-
36
- export interface NutritionProductCaptureDraft {
37
- readonly barcode: NutritionBarcode;
38
- readonly name?: string;
39
- readonly brand?: string;
40
- readonly quantity?: string;
41
- readonly packageSizeG?: number;
42
- readonly packageSizeMl?: number;
43
- readonly serving?: NutritionServing;
44
- readonly nutrientsPer100g?: NutritionFactsPer100g;
45
- readonly ingredients?: NutritionIngredientStatement;
46
- readonly storeObservation?: NutritionStoreObservation;
47
- readonly images?: readonly NutritionImageEvidence[];
48
- readonly rawPayload?: NutritionJsonValue;
49
- }
50
-
51
- export interface NutritionProductCaptureRequest {
52
- readonly draft: NutritionProductCaptureDraft;
53
- readonly client?: NutritionCaptureClientContext;
54
- }
55
-
56
- export interface NutritionProductCaptureResponse {
57
- readonly submissionId: NutritionCaptureSubmissionId;
58
- readonly status: NutritionCaptureSubmissionStatus;
59
- readonly productId?: NutritionProductId;
60
- readonly message?: string;
61
- }
62
-
63
- export interface NutritionProductCorrectionRequest {
64
- readonly productId: NutritionProductId;
65
- readonly patch: Partial<NutritionProductCaptureDraft>;
66
- readonly client?: NutritionCaptureClientContext;
67
- readonly note?: string;
68
- }
69
-
70
- export interface NutritionCaptureSubmission {
71
- readonly id: NutritionCaptureSubmissionId;
72
- readonly status: NutritionCaptureSubmissionStatus;
73
- readonly draft: NutritionProductCaptureDraft;
74
- readonly client?: NutritionCaptureClientContext;
75
- readonly matchedProductId?: NutritionProductId | null;
76
- readonly reviewerNote?: string;
77
- readonly createdAt: NutritionIsoDateTime;
78
- readonly updatedAt: NutritionIsoDateTime;
79
- readonly decidedAt?: NutritionIsoDateTime | null;
80
- }
@@ -1,51 +0,0 @@
1
- export type NutritionIsoDateTime = string;
2
- export type NutritionProductId = string;
3
- export type NutritionCaptureSubmissionId = string;
4
- export type NutritionReviewId = string;
5
- export type NutritionUserId = string;
6
-
7
- export type NutritionJsonValue =
8
- | boolean
9
- | number
10
- | string
11
- | null
12
- | readonly NutritionJsonValue[]
13
- | { readonly [key: string]: NutritionJsonValue };
14
-
15
- export const NUTRITION_BARCODE_TYPES = [
16
- 'ean_8',
17
- 'ean_13',
18
- 'upc_a',
19
- 'upc_e',
20
- 'gtin_14',
21
- 'unknown',
22
- ] as const;
23
- export type NutritionBarcodeType = (typeof NUTRITION_BARCODE_TYPES)[number];
24
-
25
- export interface NutritionBarcode {
26
- readonly value: string;
27
- readonly type: NutritionBarcodeType;
28
- readonly normalizedValue?: string;
29
- }
30
-
31
- export const NUTRITION_PRODUCT_STATUSES = [
32
- 'draft',
33
- 'pending_review',
34
- 'published',
35
- 'rejected',
36
- 'archived',
37
- ] as const;
38
- export type NutritionProductStatus = (typeof NUTRITION_PRODUCT_STATUSES)[number];
39
-
40
- export const NUTRITION_DATA_SOURCES = [
41
- 'manual_scan',
42
- 'user_correction',
43
- 'open_food_facts',
44
- 'foodrepo_legacy',
45
- 'retailer_import',
46
- 'admin_import',
47
- ] as const;
48
- export type NutritionDataSource = (typeof NUTRITION_DATA_SOURCES)[number];
49
-
50
- export const NUTRITION_SOURCE_CONFIDENCE_LEVELS = ['unknown', 'low', 'medium', 'high'] as const;
51
- export type NutritionSourceConfidence = (typeof NUTRITION_SOURCE_CONFIDENCE_LEVELS)[number];
@@ -1,4 +0,0 @@
1
- export * from './capture';
2
- export * from './common';
3
- export * from './products';
4
- export * from './review';
@@ -1,137 +0,0 @@
1
- import { describe, expect, it } from 'bun:test';
2
-
3
- import {
4
- NUTRITION_BARCODE_TYPES,
5
- NUTRITION_CAPTURE_SUBMISSION_STATUSES,
6
- NUTRITION_DATA_SOURCES,
7
- NUTRITION_PRODUCT_STATUSES,
8
- NUTRITION_REVIEW_DECISIONS,
9
- type NutritionCaptureSubmission,
10
- type NutritionProduct,
11
- type NutritionProductCaptureRequest,
12
- type NutritionReviewDecisionRequest,
13
- } from './index';
14
-
15
- describe('nutrition contracts', () => {
16
- it('exports stable literal unions for nutrition workflows', () => {
17
- expect(NUTRITION_BARCODE_TYPES).toEqual([
18
- 'ean_8',
19
- 'ean_13',
20
- 'upc_a',
21
- 'upc_e',
22
- 'gtin_14',
23
- 'unknown',
24
- ]);
25
- expect(NUTRITION_PRODUCT_STATUSES).toEqual([
26
- 'draft',
27
- 'pending_review',
28
- 'published',
29
- 'rejected',
30
- 'archived',
31
- ]);
32
- expect(NUTRITION_DATA_SOURCES).toEqual([
33
- 'manual_scan',
34
- 'user_correction',
35
- 'open_food_facts',
36
- 'foodrepo_legacy',
37
- 'retailer_import',
38
- 'admin_import',
39
- ]);
40
- expect(NUTRITION_CAPTURE_SUBMISSION_STATUSES).toEqual([
41
- 'queued',
42
- 'needs_more_data',
43
- 'accepted',
44
- 'rejected',
45
- 'merged',
46
- ]);
47
- expect(NUTRITION_REVIEW_DECISIONS).toEqual([
48
- 'accept',
49
- 'reject',
50
- 'merge',
51
- 'request_changes',
52
- 'publish',
53
- ]);
54
- });
55
-
56
- it('serializes a published barcode product', () => {
57
- const product: NutritionProduct = {
58
- id: 'product_01',
59
- primaryBarcode: {
60
- value: '7612345678901',
61
- type: 'ean_13',
62
- normalizedValue: '7612345678901',
63
- },
64
- name: 'Example Yogurt Nature',
65
- brand: 'Example Brand',
66
- quantity: '250 g',
67
- packageSizeG: 250,
68
- serving: { label: '1 cup', sizeG: 250, servingsPerPackage: 1 },
69
- nutrientsPer100g: {
70
- basis: 'per_100g',
71
- energyKcal: 62,
72
- energyKj: 260,
73
- proteinG: 11,
74
- carbohydratesG: 3.8,
75
- sugarsG: 3.8,
76
- fatG: 0.2,
77
- saturatedFatG: 0.1,
78
- fiberG: 0,
79
- saltG: 0.1,
80
- sodiumG: 0.04,
81
- },
82
- ingredients: { locale: 'de-CH', text: 'Milk, cultures.' },
83
- allergens: ['milk'],
84
- stores: [{ countryCode: 'CH', storeChain: 'Example Store' }],
85
- images: [{ kind: 'nutrition_label', path: 'labels/7612345678901.jpg' }],
86
- status: 'published',
87
- source: 'manual_scan',
88
- sourceConfidence: 'high',
89
- verifiedByUser: true,
90
- createdAt: '2026-06-01T12:00:00.000Z',
91
- updatedAt: '2026-06-01T12:05:00.000Z',
92
- publishedAt: '2026-06-01T12:10:00.000Z',
93
- };
94
-
95
- expect(JSON.parse(JSON.stringify(product))).toEqual(product);
96
- expect(product.nutrientsPer100g?.proteinG).toBe(11);
97
- });
98
-
99
- it('serializes capture submissions and review decisions', () => {
100
- const capture: NutritionProductCaptureRequest = {
101
- draft: {
102
- barcode: { value: '7612345678901', type: 'ean_13' },
103
- name: 'Example Yogurt Nature',
104
- nutrientsPer100g: { energyKcal: 62, proteinG: 11 },
105
- storeObservation: { countryCode: 'CH', storeChain: 'Example Store' },
106
- rawPayload: { source: 'manual' },
107
- },
108
- client: {
109
- anonymousDeviceId: 'device-1',
110
- platform: 'ios',
111
- appVersion: '0.1.0',
112
- clientCapturedAt: '2026-06-01T12:00:00.000Z',
113
- },
114
- };
115
-
116
- const submission: NutritionCaptureSubmission = {
117
- id: 'submission_01',
118
- status: 'queued',
119
- draft: capture.draft,
120
- client: capture.client,
121
- matchedProductId: null,
122
- createdAt: '2026-06-01T12:00:00.000Z',
123
- updatedAt: '2026-06-01T12:00:00.000Z',
124
- };
125
-
126
- const decision: NutritionReviewDecisionRequest = {
127
- submissionId: submission.id,
128
- decision: 'accept',
129
- reviewerId: 'reviewer-1',
130
- note: 'Readable label.',
131
- };
132
-
133
- expect(JSON.parse(JSON.stringify(capture))).toEqual(capture);
134
- expect(JSON.parse(JSON.stringify(submission))).toEqual(submission);
135
- expect(decision.decision).toBe('accept');
136
- });
137
- });
@@ -1,134 +0,0 @@
1
- import type {
2
- NutritionBarcode,
3
- NutritionDataSource,
4
- NutritionIsoDateTime,
5
- NutritionJsonValue,
6
- NutritionProductId,
7
- NutritionProductStatus,
8
- NutritionSourceConfidence,
9
- } from './common';
10
-
11
- export type NutritionMeasurementBasis = 'per_100g' | 'per_100ml';
12
-
13
- export interface NutritionFactsPer100g {
14
- readonly basis?: NutritionMeasurementBasis;
15
- readonly energyKcal?: number;
16
- readonly energyKj?: number;
17
- readonly proteinG?: number;
18
- readonly carbohydratesG?: number;
19
- readonly sugarsG?: number;
20
- readonly fatG?: number;
21
- readonly saturatedFatG?: number;
22
- readonly fiberG?: number;
23
- readonly saltG?: number;
24
- readonly sodiumG?: number;
25
- }
26
-
27
- export interface NutritionServing {
28
- readonly label?: string;
29
- readonly sizeG?: number;
30
- readonly sizeMl?: number;
31
- readonly servingsPerPackage?: number;
32
- }
33
-
34
- export interface NutritionIngredientStatement {
35
- readonly text?: string;
36
- readonly locale?: string;
37
- readonly rawText?: string;
38
- }
39
-
40
- export type NutritionAllergenTag =
41
- | 'celery'
42
- | 'cereals_containing_gluten'
43
- | 'crustaceans'
44
- | 'eggs'
45
- | 'fish'
46
- | 'lupin'
47
- | 'milk'
48
- | 'molluscs'
49
- | 'mustard'
50
- | 'nuts'
51
- | 'peanuts'
52
- | 'sesame'
53
- | 'soybeans'
54
- | 'sulphur_dioxide_and_sulphites'
55
- | (string & {});
56
-
57
- export interface NutritionStoreObservation {
58
- readonly countryCode?: string;
59
- readonly storeChain?: string;
60
- readonly storeName?: string;
61
- readonly storeLocationLabel?: string;
62
- readonly observedAt?: NutritionIsoDateTime;
63
- }
64
-
65
- export const NUTRITION_IMAGE_KINDS = [
66
- 'front',
67
- 'nutrition_label',
68
- 'ingredients',
69
- 'barcode',
70
- 'package_back',
71
- 'other',
72
- ] as const;
73
- export type NutritionImageKind = (typeof NUTRITION_IMAGE_KINDS)[number];
74
-
75
- export interface NutritionImageEvidence {
76
- readonly id?: string;
77
- readonly kind: NutritionImageKind;
78
- readonly storageId?: string;
79
- readonly bucket?: string;
80
- readonly path?: string;
81
- readonly publicUrl?: string;
82
- readonly contentType?: string;
83
- readonly width?: number;
84
- readonly height?: number;
85
- readonly capturedAt?: NutritionIsoDateTime;
86
- readonly metadata?: Record<string, NutritionJsonValue>;
87
- }
88
-
89
- export interface NutritionProductSummary {
90
- readonly id: NutritionProductId;
91
- readonly primaryBarcode: NutritionBarcode;
92
- readonly name: string;
93
- readonly brand?: string;
94
- readonly quantity?: string;
95
- readonly status: NutritionProductStatus;
96
- readonly source: NutritionDataSource;
97
- readonly sourceConfidence: NutritionSourceConfidence;
98
- readonly imageUrl?: string;
99
- readonly updatedAt: NutritionIsoDateTime;
100
- }
101
-
102
- export interface NutritionProduct {
103
- readonly id: NutritionProductId;
104
- readonly primaryBarcode: NutritionBarcode;
105
- readonly barcodes?: readonly NutritionBarcode[];
106
- readonly name: string;
107
- readonly brand?: string;
108
- readonly quantity?: string;
109
- readonly packageSizeG?: number;
110
- readonly packageSizeMl?: number;
111
- readonly serving?: NutritionServing;
112
- readonly nutrientsPer100g?: NutritionFactsPer100g;
113
- readonly ingredients?: NutritionIngredientStatement;
114
- readonly allergens?: readonly NutritionAllergenTag[];
115
- readonly traces?: readonly NutritionAllergenTag[];
116
- readonly stores?: readonly NutritionStoreObservation[];
117
- readonly images?: readonly NutritionImageEvidence[];
118
- readonly status: NutritionProductStatus;
119
- readonly source: NutritionDataSource;
120
- readonly sourceConfidence: NutritionSourceConfidence;
121
- readonly sourcePayload?: NutritionJsonValue;
122
- readonly verifiedByUser?: boolean;
123
- readonly createdAt: NutritionIsoDateTime;
124
- readonly updatedAt: NutritionIsoDateTime;
125
- readonly publishedAt?: NutritionIsoDateTime | null;
126
- }
127
-
128
- export interface NutritionProductDetail {
129
- readonly product: NutritionProduct;
130
- }
131
-
132
- export interface NutritionProductLookupByBarcodeResponse {
133
- readonly product: NutritionProduct;
134
- }
@@ -1,65 +0,0 @@
1
- import type { NutritionCaptureSubmission, NutritionCaptureSubmissionStatus } from './capture';
2
- import type {
3
- NutritionCaptureSubmissionId,
4
- NutritionIsoDateTime,
5
- NutritionJsonValue,
6
- NutritionProductId,
7
- NutritionReviewId,
8
- NutritionUserId,
9
- } from './common';
10
- import type { NutritionProduct } from './products';
11
-
12
- export const NUTRITION_REVIEW_DECISIONS = [
13
- 'accept',
14
- 'reject',
15
- 'merge',
16
- 'request_changes',
17
- 'publish',
18
- ] as const;
19
- export type NutritionReviewDecision = (typeof NUTRITION_REVIEW_DECISIONS)[number];
20
-
21
- export interface NutritionReviewDecisionRequest {
22
- readonly decision: NutritionReviewDecision;
23
- readonly submissionId: NutritionCaptureSubmissionId;
24
- readonly reviewerId?: NutritionUserId;
25
- readonly targetProductId?: NutritionProductId;
26
- readonly productOverride?: Partial<NutritionProduct>;
27
- readonly note?: string;
28
- readonly metadata?: Record<string, NutritionJsonValue>;
29
- }
30
-
31
- export interface NutritionReviewDecisionResponse {
32
- readonly reviewId: NutritionReviewId;
33
- readonly submissionId: NutritionCaptureSubmissionId;
34
- readonly decision: NutritionReviewDecision;
35
- readonly status: NutritionCaptureSubmissionStatus;
36
- readonly productId?: NutritionProductId;
37
- readonly decidedAt: NutritionIsoDateTime;
38
- }
39
-
40
- export interface NutritionReviewRecord {
41
- readonly id: NutritionReviewId;
42
- readonly submissionId: NutritionCaptureSubmissionId;
43
- readonly reviewerId?: NutritionUserId;
44
- readonly decision: NutritionReviewDecision;
45
- readonly previousStatus: NutritionCaptureSubmissionStatus;
46
- readonly nextStatus: NutritionCaptureSubmissionStatus;
47
- readonly targetProductId?: NutritionProductId | null;
48
- readonly note?: string;
49
- readonly metadata?: Record<string, NutritionJsonValue>;
50
- readonly createdAt: NutritionIsoDateTime;
51
- }
52
-
53
- export interface NutritionReviewSubmissionListRequest {
54
- readonly status?: NutritionCaptureSubmissionStatus;
55
- readonly barcode?: string;
56
- readonly store?: string;
57
- readonly limit?: number;
58
- readonly offset?: number;
59
- }
60
-
61
- export interface NutritionReviewSubmissionListResponse {
62
- readonly submissions: readonly NutritionCaptureSubmission[];
63
- readonly limit?: number;
64
- readonly offset?: number;
65
- }