diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..2dea4d5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,197 @@ +# libmodulor - Agent Development Guide + +This guide provides essential information for agentic coding agents working with the libmodulor TypeScript library. + +## Project Overview + +**libmodulor** is a TypeScript library for creating platform-agnostic applications following a 4-layer architecture: +- **UseCase** - Business logic layer +- **App** - Application layer +- **Product** - Product layer +- **Target** - Platform-specific deployment targets + +This is a distribution repository containing compiled ESM modules in `dist/esm/`. + +## Build & Development Commands + +### Core Commands +```bash +# Lint and auto-fix code +pnpm lint + +# Lint without auto-fix (CI) +pnpm lint:ci + +# Type check and run tests +pnpm test + +# Type check only +tsc + +# Run tests only +vitest run +``` + +### Running Individual Tests +```bash +# Run specific test file +vitest run examples/apps/Trading/test/App.test.ts + +# Run tests with pattern +vitest run --reporter=verbose "**/test/**/*.test.ts" + +# Run tests in watch mode +vitest examples/apps/Trading/test/App.test.ts +``` + +### CLI Scaffolding Commands +```bash +# Create new project +npx libmodulor CreateProject --projectName my-project + +# Create app in existing project +pnpm libmodulor CreateApp --appName Banking + +# Create use case +pnpm libmodulor CreateUC --appName Banking --ucName CreateAccount + +# Create product +pnpm libmodulor CreateProduct --productName CustomerPortal + +# Create target +pnpm libmodulor CreateTarget --productName CustomerPortal --targetName node-express-server +``` + +## Code Style Guidelines + +### Formatting (Biome) +- **Indentation**: 4 spaces +- **Quotes**: Single quotes for strings +- **Semicolons**: Required +- **Trailing commas**: Enforced where appropriate + +### Import Organization +Imports are automatically organized in this specific order: +1. Node.js built-in modules (`fs`, `path`, etc.) +2. Blank line +3. Package imports (`lodash`, `express`, etc.) +4. Blank line +5. Path imports (`./utils`, `../types`, etc.) + +Example: +```typescript +import { join } from 'node:path'; +import { readFile } from 'node:fs'; + +import express from 'express'; +import { injectable } from 'inversify'; + +import { Configurator } from './Configurator.js'; +import { Logger } from '../types/Logger.js'; +``` + +### TypeScript Configuration +- **Strict mode**: Enabled +- **Target**: ESNext +- **Module**: NodeNext +- **Module Resolution**: NodeNext +- **Decorators**: Enabled with metadata +- **No implicit any**: Strict +- **No unused variables**: Error +- **Exact optional properties**: Enabled + +### Naming Conventions +- **Classes**: PascalCase (`UserManager`, `OrderService`) +- **Interfaces/Types**: PascalCase with descriptive prefixes (`TOrderStatus`, `UCInput`) +- **Functions/Methods**: camelCase (`getUserById`, `processOrder`) +- **Constants**: UPPER_SNAKE_CASE (`MAX_RETRY_COUNT`, `DEFAULT_TIMEOUT`) +- **Files**: PascalCase for classes (`UserManager.ts`), kebab-case for utilities (`file-utils.ts`) + +### Error Handling +- Use `CustomError` class from libmodulor for all business logic errors +- Never log or expose stack traces for `CustomError` instances +- Log unexpected errors before re-throwing +- Always handle errors in async functions with try/catch or proper error propagation + +### Decorators & Dependency Injection +- Use `@injectable()` for all service classes +- Use `@inject(TOKEN)` for constructor injection +- Enable `unsafeParameterDecoratorsEnabled` in Biome config +- Import from `inversify` for DI container setup + +### Testing Guidelines +- Tests are auto-generated - DO NOT EDIT test files directly +- Use Vitest as test runner +- Property testing with fast-check for monkey testing +- Test files located in `examples/*/test/` directories +- Use `describe`, `test`, `expect` from Vitest +- Snapshot testing for output verification + +### Architecture Patterns +- **Use Cases**: Implement business logic, extend `UCDef` +- **Apps**: Container for use cases, have `manifest.ts` +- **Products**: Collection of apps, have `manifest.ts` and `i18n.ts` +- **Targets**: Platform-specific deployment configurations + +### File Structure +``` +examples/ +├── apps/ +│ └── AppName/ +│ ├── src/ +│ │ ├── manifest.ts +│ │ ├── i18n.ts +│ │ ├── lib/ # Shared utilities +│ │ └── ucds/ # Use case definitions +│ ├── test/ +│ │ ├── App.test.ts # Auto-generated +│ │ └── Configurator.ts +│ └── index.ts +└── products/ + └── ProductName/ + ├── targets/ + │ └── PlatformName/ + ├── manifest.ts + └── i18n.ts +``` + +### Linting Rules (Key Biome Rules) +- `noInferrableTypes`: Error - Don't annotate obvious types +- `noParameterAssign`: Error - Don't reassign parameters +- `noConsole`: Error - Use proper logging instead +- `useAsConstAssertion`: Error - Use `as const` for literals +- `useSingleVarDeclarator`: Error - One variable per declaration +- `useSelfClosingElements`: Error - Use self-closing tags when possible + +### Internationalization +- All user-facing text must support i18n +- Use the i18n system with locale files in `i18n/locales/` +- Supported languages: de, en, es, fr +- Keys should be descriptive and namespaced + +### Platform Support +The library supports 25+ platform exports including: +- Node.js (Express, Hono, MCP, CLI, Test) +- React (Web, Native, Pure) +- Next.js +- Cloudflare Workers +- Vite +- Webpack +- Babel +- Web + +Import the appropriate platform-specific entry point: +```typescript +import { newNodeAppTester } from 'libmodulor/node-test'; +import { I18nEN } from 'libmodulor/locales/en'; +import { NodeAppTesterConfigurator } from 'libmodulor/node-test'; +``` + +## Important Notes + +- **DO NOT EDIT** auto-generated test files (marked with auto-generation comments) +- This is a research project (v0.26.0) - breaking changes expected until v1.0.0 +- Always run `pnpm lint` and `pnpm test` before committing changes +- Use property-based testing for comprehensive coverage +- Follow the 4-layer architecture strictly +- All business logic must be in Use Cases, not in Targets or Products \ No newline at end of file diff --git a/examples/apps/Auth/README.md b/examples/apps/Auth/README.md index 8d4c40c..447b17c 100644 --- a/examples/apps/Auth/README.md +++ b/examples/apps/Auth/README.md @@ -99,9 +99,57 @@ sequenceDiagram Client-->>-User: 👍 OK ``` +### SignUp + +- **Type** : `Client / Server` +- **Client Policy** : `Anonymous` +- **Server Policy** : `Anonymous` + +#### Input (I) + +|#|name|humanized|dataType| +|---|---|---|---| +|1|`email`|Email|`string`| +|2|`password`|Password|`string`| + +#### Output (O) + +##### Part 0 (OPI0) + +|#|name|humanized|dataType| +|---|---|---|---| +|1|`jwt`|Jwt|`JWT`| +|2|`id`|Id|`UUID`| + +##### Part 1 (OPI1) + +None + +#### Sequence Diagram + +```mermaid +sequenceDiagram + actor User + User->>+Client: ✏️ Fill
email: string
password: string + User->>Client: ↩️ Submit + Client->>Client: 🔐 Check policy "Anonymous" + break when any validation fails + Client-->User: show failure + end + Client->>+Server: 📤 Send
email: string
password: string + Server->>Server: 🔐 Check policy "Anonymous" + break when any validation fails + Server-->User: show failure + end + Server->>Server: Persist the use case first to get aggregateId + Server-->>-Client: 👍 OK
jwt: JWT
id: UUID + Client-->>-User: 👍 OK +``` + ## Technical Summary |#|filePath|constName|metadataName|metadataAction|metadataBeta|metadataIcon|metadataNew|metadataSensitive|externalImports|internalImports|ioI|ioIFields|ioOPI0|ioOPI0Fields|ioOPI1|ioOPI1Fields|lifecycleClientPolicy|lifecycleServerPolicy| |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| |1|/src/ucds/SignInUCD.ts|SignInUCD|SignIn|Create||right-to-bracket||||../../../../../dist/esm/index.js
../lib/TRole.js
../manifest.js
./SignInServerMain.js|SignInInput|role: UCInputFieldValue<Role>|SignInOPI0|jwt: JWT
id: UUID|||Anonymous|Anonymous| |2|/src/ucds/SignOutUCD.ts|SignOutUCD|SignOut|Delete||circle-xmark||true||../../../../../dist/esm/index.js
../manifest.js|||||||Authenticated|Authenticated| +|3|/src/ucds/SignUpUCD.ts|SignUpUCD|SignUp|Create||user-plus||||../../../../../dist/esm/index.js
../manifest.js
./SignUpServerMain.js|SignUpInput|email: UCInputFieldValue<string>
password: UCInputFieldValue<string>|SignUpOPI0|jwt: JWT
id: UUID|||Anonymous|Anonymous| diff --git a/examples/apps/Auth/src/i18n.ts b/examples/apps/Auth/src/i18n.ts index d738bf0..c3f2cd4 100644 --- a/examples/apps/Auth/src/i18n.ts +++ b/examples/apps/Auth/src/i18n.ts @@ -10,6 +10,12 @@ export const I18n = { uc_SignOut_i_submit_idle: 'Abmelden', uc_SignOut_i_submit_submitting: 'Abmeldung', uc_SignOut_label: 'Abmelden', + uc_SignUp_desc: 'Erstellen Sie ein neues Konto, um loszulegen', + uc_SignUp_i_submit_idle: 'Konto erstellen', + uc_SignUp_i_submit_submitting: 'Konto wird erstellt', + uc_SignUp_label: 'Konto erstellen', + ucif_email_label: 'E-Mail', + ucif_password_label: 'Passwort', ucif_role_label: 'Rolle', ucof_id_label: 'Kennung', ucof_jwt_label: 'JWT', @@ -22,6 +28,13 @@ export const I18n = { uc_SignOut_client_confirm_message: 'Are you sure?', uc_SignOut_i_submit_idle: 'Sign out', uc_SignOut_i_submit_submitting: 'Signing out', + uc_SignUp_desc: 'Create a new account to get started.', + uc_SignUp_i_submit_idle: 'Sign up', + uc_SignUp_i_submit_submitting: 'Signing up', + uc_SignUp_label: 'Sign up', + ucif_email_label: 'Email', + ucif_password_label: 'Password', + ucif_role_label: 'Role', }, es: { uc_SignIn_desc: 'Inicia sesión en tu cuenta para comenzar', @@ -32,6 +45,12 @@ export const I18n = { uc_SignOut_i_submit_idle: 'Cerrar sesión', uc_SignOut_i_submit_submitting: 'Cerrando sesión', uc_SignOut_label: 'Cerrar sesión', + uc_SignUp_desc: 'Crea una nueva cuenta para comenzar', + uc_SignUp_i_submit_idle: 'Crear cuenta', + uc_SignUp_i_submit_submitting: 'Creando cuenta', + uc_SignUp_label: 'Crear cuenta', + ucif_email_label: 'Correo electrónico', + ucif_password_label: 'Contraseña', ucif_role_label: 'Rol', ucof_id_label: 'Identificador', ucof_jwt_label: 'JWT', @@ -45,7 +64,13 @@ export const I18n = { uc_SignOut_i_submit_idle: 'Se déconnecter', uc_SignOut_i_submit_submitting: 'Déconnexion', uc_SignOut_label: 'Se déconnecter', - ucif_role_label: 'Role', + uc_SignUp_desc: 'Créez un nouveau compte pour commencer', + uc_SignUp_i_submit_idle: 'Créer un compte', + uc_SignUp_i_submit_submitting: 'Création du compte', + uc_SignUp_label: 'Créer un compte', + ucif_email_label: 'Adresse e-mail', + ucif_password_label: 'Mot de passe', + ucif_role_label: 'Rôle', ucof_id_label: 'Identifiant', ucof_jwt_label: 'JWT', }, diff --git a/examples/apps/Auth/src/manifest.ts b/examples/apps/Auth/src/manifest.ts index 567d8ed..5501058 100644 --- a/examples/apps/Auth/src/manifest.ts +++ b/examples/apps/Auth/src/manifest.ts @@ -15,5 +15,10 @@ export const Manifest = { name: 'SignOut', sensitive: true, }, + SignUp: { + action: 'Create', + icon: 'user-plus', + name: 'SignUp', + }, }, } satisfies AppManifest; diff --git a/examples/apps/Auth/src/ucds/SignUpServerMain.ts b/examples/apps/Auth/src/ucds/SignUpServerMain.ts new file mode 100644 index 0000000..c615f7f --- /dev/null +++ b/examples/apps/Auth/src/ucds/SignUpServerMain.ts @@ -0,0 +1,78 @@ +import { inject, injectable } from 'inversify'; + +import { + type CryptoManager, + type UCAuth, + type UCMain, + type UCMainInput, + type UCManager, + type UCOutput, + UCOutputBuilder, +} from '../../../../../dist/esm/index.js'; +import type { SignUpInput, SignUpOPI0 } from './SignUpUCD.js'; +import { UCAuth } from '../uc/auth/consts.js'; + +@injectable() +export class SignUpServerMain implements UCMain { + constructor( + @inject('JWTManager') + private jwtManager: JWTManager, + @inject('UCManager') + private ucManager: UCManager, + @inject('CryptoManager') + private cryptoManager: CryptoManager, + ) {} + + public async exec({ + uc, + }: UCMainInput): Promise> { + const email = uc.reqVal0('email'); + const password = uc.reqVal0('password'); + + // DO NOT USE THIS IN PRODUCTION !!! + // TODO: In production, validate email format and password strength + // TODO: Check if email already exists in database + // TODO: Hash password before storing + + /// Persist the use case first to get aggregateId + const { aggregateId } = await this.ucManager.persist(uc); + + // Always create a regular user for signup (no role selection) + const auth = FAKE_USER_REGULAR; + + const jwt = await this.jwtManager.encode(auth); + + return new UCOutputBuilder() + .add({ + id: aggregateId, + jwt + }) + .get(); + } +} + + // Hash password using CryptoManager + const hashedPassword = await this.cryptoManager.hash( + password, + 'sha256', + ); + + // Create auth object with proper structure + const auth: UCAuth = { + organizationId, + user: { + id: aggregateId, + name, + }, + }; + + const jwt = await this.jwtManager.encode(auth); + + return new UCOutputBuilder() + .add({ + id: aggregateId, + jwt, + }) + .get(); + } +} diff --git a/examples/apps/Auth/src/ucds/SignUpUCD.ts b/examples/apps/Auth/src/ucds/SignUpUCD.ts new file mode 100644 index 0000000..0c4aeed --- /dev/null +++ b/examples/apps/Auth/src/ucds/SignUpUCD.ts @@ -0,0 +1,62 @@ +import { + AnonymousUCPolicy, + type JWT, + SendClientMain, + TEmail, + TJWT, + TPassword, + type UCDef, + type UCInput, + type UCInputFieldValue, + type UCOPIBase, + UCOutputSideEffectType, +} from '../../../../../dist/esm/index.js'; +import { Manifest } from '../manifest.js'; +import { SignUpServerMain } from './SignUpServerMain.js'; + +export interface SignUpInput extends UCInput { + email: UCInputFieldValue; + password: UCInputFieldValue; +} + +export interface SignUpOPI0 extends UCOPIBase { + jwt: JWT; +} + +export const SignUpUCD: UCDef = { + io: { + i: { + fields: { + email: { + type: new TEmail(), + }, + password: { + type: new TPassword(), + }, + }, + }, + o: { + parts: { + _0: { + fields: { + jwt: { + type: new TJWT(), + }, + }, + }, + }, + sideEffects: [{ type: UCOutputSideEffectType.SET_AUTH }], + }, + }, + lifecycle: { + client: { + main: SendClientMain, + policy: AnonymousUCPolicy, + }, + server: { + main: SignUpServerMain, + policy: AnonymousUCPolicy, + }, + }, + metadata: Manifest.ucReg.SignUp, +}; diff --git a/examples/apps/Auth/test/__snapshots__/App.test.ts.snap b/examples/apps/Auth/test/__snapshots__/App.test.ts.snap index 2365466..6a02a56 100644 --- a/examples/apps/Auth/test/__snapshots__/App.test.ts.snap +++ b/examples/apps/Auth/test/__snapshots__/App.test.ts.snap @@ -453,3 +453,294 @@ exports[`Run > Use Cases > 'SignOut' > should execute with auth 'REGULAR' and in "sideEffects": undefined, } `; + +exports[`Run > Use Cases > 'SignUp' > should execute with auth 'ADMIN' and input 'ALL_WITH_EXAMPLES' > hash = 5dbf39a3f94274b5cc62c26fc405c32cb434cfc3abcea2794c663aee33b45d7c 1`] = ` +{ + "out": { + "args": { + "auth": { + "organization": { + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + }, + "role": "admin", + "user": { + "firstname": "Dexter", + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + "initials": "DM", + }, + }, + "authName": "ADMIN", + "inputFiller": [Function], + "inputFillerName": "ALL_WITH_EXAMPLES", + }, + "err": [ForbiddenError: Forbidden], + "hash": "5dbf39a3f94274b5cc62c26fc405c32cb434cfc3abcea2794c663aee33b45d7c", + "io": { + "i": { + "email": "dexter@caramail.com", + "password": "fmUUNWXazWH4", + }, + "o": null, + }, + }, + "sideEffects": undefined, +} +`; + +exports[`Run > Use Cases > 'SignUp' > should execute with auth 'ADMIN' and input 'ONLY_MANDATORY_WITH_EXAMPLES' > hash = 90d904a51f4c0248cd4a28f91fdd571756ee60719aacefc3223c3b8df86b4a77 1`] = ` +{ + "out": { + "args": { + "auth": { + "organization": { + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + }, + "role": "admin", + "user": { + "firstname": "Dexter", + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + "initials": "DM", + }, + }, + "authName": "ADMIN", + "inputFiller": [Function], + "inputFillerName": "ONLY_MANDATORY_WITH_EXAMPLES", + }, + "err": [ForbiddenError: Forbidden], + "hash": "90d904a51f4c0248cd4a28f91fdd571756ee60719aacefc3223c3b8df86b4a77", + "io": { + "i": { + "email": "dexter@caramail.com", + "password": "fmUUNWXazWH4", + }, + "o": null, + }, + }, + "sideEffects": undefined, +} +`; + +exports[`Run > Use Cases > 'SignUp' > should execute with auth 'ADMIN' and input 'ONLY_SET_PROGRAMMATICALLY_WITH_EXAMPL…' > hash = eeb998439877d31e8e0fec2dd8d34d710c93424a153245743d722fcb0047ee19 1`] = ` +{ + "out": { + "args": { + "auth": { + "organization": { + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + }, + "role": "admin", + "user": { + "firstname": "Dexter", + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + "initials": "DM", + }, + }, + "authName": "ADMIN", + "inputFiller": [Function], + "inputFillerName": "ONLY_SET_PROGRAMMATICALLY_WITH_EXAMPLES", + }, + "err": [ForbiddenError: Forbidden], + "hash": "eeb998439877d31e8e0fec2dd8d34d710c93424a153245743d722fcb0047ee19", + "io": { + "i": { + "email": undefined, + "password": undefined, + }, + "o": null, + }, + }, + "sideEffects": undefined, +} +`; + +exports[`Run > Use Cases > 'SignUp' > should execute with auth 'ANONYMOUS' and input 'ALL_WITH_EXAMPLES' > hash = a9b91b0adfc04784ac4a628471106e5759b8a7bef8e2dbb888f3027b6a7697ef 1`] = ` +{ + "out": { + "args": { + "auth": null, + "authName": "ANONYMOUS", + "inputFiller": [Function], + "inputFillerName": "ALL_WITH_EXAMPLES", + }, + "err": null, + "hash": "a9b91b0adfc04784ac4a628471106e5759b8a7bef8e2dbb888f3027b6a7697ef", + "io": { + "i": { + "email": "dexter@caramail.com", + "password": "fmUUNWXazWH4", + }, + "o": { + "parts": { + "_0": { + "items": [ + { + "id": "356a192b-7913-404c-9457-4d18c28d46e6", + "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdhbml6YXRpb24iOnsiaWQiOiJkZDk2NzBlNy0xZGQ1LTQxNTUtODVjMi0zMzU3MTQ3OTlmZjcifSwicm9sZSI6InJlZ3VsYXIiLCJ1c2VyIjp7ImZpcnN0bmFtZSI6IkRleHRlciIsImlkIjoiMzU2YTE5MmItNzkxMy00MDRjLTk0NTctNGQxOGMyOGQ0NmU2IiwiaW5pdGlhbHMiOiJETSJ9LCJhdWQiOiJsaWJtb2R1bG9yIiwiZXhwIjoxNzY4MDY2NDczLCJpc3MiOiJsaWJtb2R1bG9yIiwiaWF0IjoxNzY4MDYyODczfQ.uJ8iOsCR14GN0vyH-GgG3nR2X98NTwSkwq5UnqdtLi0", + }, + ], + "total": 1, + }, + }, + }, + }, + }, + "sideEffects": undefined, +} +`; + +exports[`Run > Use Cases > 'SignUp' > should execute with auth 'ANONYMOUS' and input 'ONLY_MANDATORY_WITH_EXAMPLES' > hash = 4dfe9a0d4d3ace21d98c3edb45830564554aac3ecc9f808102a4fe6b0d0d498b 1`] = ` +{ + "out": { + "args": { + "auth": null, + "authName": "ANONYMOUS", + "inputFiller": [Function], + "inputFillerName": "ONLY_MANDATORY_WITH_EXAMPLES", + }, + "err": null, + "hash": "4dfe9a0d4d3ace21d98c3edb45830564554aac3ecc9f808102a4fe6b0d0d498b", + "io": { + "i": { + "email": "dexter@caramail.com", + "password": "fmUUNWXazWH4", + }, + "o": { + "parts": { + "_0": { + "items": [ + { + "id": "356a192b-7913-404c-9457-4d18c28d46e6", + "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdhbml6YXRpb24iOnsiaWQiOiJkZDk2NzBlNy0xZGQ1LTQxNTUtODVjMi0zMzU3MTQ3OTlmZjcifSwicm9sZSI6InJlZ3VsYXIiLCJ1c2VyIjp7ImZpcnN0bmFtZSI6IkRleHRlciIsImlkIjoiMzU2YTE5MmItNzkxMy00MDRjLTk0NTctNGQxOGMyOGQ0NmU2IiwiaW5pdGlhbHMiOiJETSJ9LCJhdWQiOiJsaWJtb2R1bG9yIiwiZXhwIjoxNzY4MDY2NDczLCJpc3MiOiJsaWJtb2R1bG9yIiwiaWF0IjoxNzY4MDYyODczfQ.uJ8iOsCR14GN0vyH-GgG3nR2X98NTwSkwq5UnqdtLi0", + }, + ], + "total": 1, + }, + }, + }, + }, + }, + "sideEffects": undefined, +} +`; + +exports[`Run > Use Cases > 'SignUp' > should execute with auth 'ANONYMOUS' and input 'ONLY_SET_PROGRAMMATICALLY_WITH_EXAMPL…' > hash = 6835cd897388aceb9a52651a220bf9b0e028b2435b7b6b666ce312ee36d1ffd9 1`] = ` +{ + "out": { + "args": { + "auth": null, + "authName": "ANONYMOUS", + "inputFiller": [Function], + "inputFillerName": "ONLY_SET_PROGRAMMATICALLY_WITH_EXAMPLES", + }, + "err": [IllegalArgumentError: Email must be filled], + "hash": "6835cd897388aceb9a52651a220bf9b0e028b2435b7b6b666ce312ee36d1ffd9", + "io": { + "i": { + "email": undefined, + "password": undefined, + }, + "o": null, + }, + }, + "sideEffects": undefined, +} +`; + +exports[`Run > Use Cases > 'SignUp' > should execute with auth 'REGULAR' and input 'ALL_WITH_EXAMPLES' > hash = 765330b1703e4a1b1b53f308b592e21970ca086c905dc37aef8664a599b7f307 1`] = ` +{ + "out": { + "args": { + "auth": { + "organization": { + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + }, + "role": "regular", + "user": { + "firstname": "Dexter", + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + "initials": "DM", + }, + }, + "authName": "REGULAR", + "inputFiller": [Function], + "inputFillerName": "ALL_WITH_EXAMPLES", + }, + "err": [ForbiddenError: Forbidden], + "hash": "765330b1703e4a1b1b53f308b592e21970ca086c905dc37aef8664a599b7f307", + "io": { + "i": { + "email": "dexter@caramail.com", + "password": "fmUUNWXazWH4", + }, + "o": null, + }, + }, + "sideEffects": undefined, +} +`; + +exports[`Run > Use Cases > 'SignUp' > should execute with auth 'REGULAR' and input 'ONLY_MANDATORY_WITH_EXAMPLES' > hash = aed9326e12337387670c4886d1fe6e375a8c5997f24cea7fff5d47713cbbf56e 1`] = ` +{ + "out": { + "args": { + "auth": { + "organization": { + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + }, + "role": "regular", + "user": { + "firstname": "Dexter", + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + "initials": "DM", + }, + }, + "authName": "REGULAR", + "inputFiller": [Function], + "inputFillerName": "ONLY_MANDATORY_WITH_EXAMPLES", + }, + "err": [ForbiddenError: Forbidden], + "hash": "aed9326e12337387670c4886d1fe6e375a8c5997f24cea7fff5d47713cbbf56e", + "io": { + "i": { + "email": "dexter@caramail.com", + "password": "fmUUNWXazWH4", + }, + "o": null, + }, + }, + "sideEffects": undefined, +} +`; + +exports[`Run > Use Cases > 'SignUp' > should execute with auth 'REGULAR' and input 'ONLY_SET_PROGRAMMATICALLY_WITH_EXAMPL…' > hash = 60dd77bbc1b44ba6a92203a8c7d8745329f954102d578562d77d914abd842d46 1`] = ` +{ + "out": { + "args": { + "auth": { + "organization": { + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + }, + "role": "regular", + "user": { + "firstname": "Dexter", + "id": "dd9670e7-1dd5-4155-85c2-335714799ff7", + "initials": "DM", + }, + }, + "authName": "REGULAR", + "inputFiller": [Function], + "inputFillerName": "ONLY_SET_PROGRAMMATICALLY_WITH_EXAMPLES", + }, + "err": [ForbiddenError: Forbidden], + "hash": "60dd77bbc1b44ba6a92203a8c7d8745329f954102d578562d77d914abd842d46", + "io": { + "i": { + "email": undefined, + "password": undefined, + }, + "o": null, + }, + }, + "sideEffects": undefined, +} +`;