@famgia/omnify-react-sso 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +418 -12
- package/dist/@omnify-base/package.json +16 -0
- package/dist/@omnify-base/schemas/Branch.ts +131 -0
- package/dist/@omnify-base/schemas/Permission.ts +114 -0
- package/dist/@omnify-base/schemas/Role.ts +121 -0
- package/dist/@omnify-base/schemas/RolePermission.ts +97 -0
- package/dist/@omnify-base/schemas/Team.ts +110 -0
- package/dist/@omnify-base/schemas/TeamPermission.ts +109 -0
- package/dist/@omnify-base/schemas/User.ts +135 -0
- package/dist/@omnify-base/schemas/common.ts +47 -0
- package/dist/@omnify-base/schemas/i18n.ts +118 -0
- package/dist/index.cjs +2143 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1204 -1
- package/dist/index.d.ts +1204 -1
- package/dist/index.js +2059 -72
- package/dist/index.js.map +1 -1
- package/dist/schemas/index.cjs +449 -63
- package/dist/schemas/index.cjs.map +1 -1
- package/dist/schemas/index.d.cts +1 -1
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +393 -72
- package/dist/schemas/index.js.map +1 -1
- package/dist/testing/index.cjs +120 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +97 -0
- package/dist/testing/index.d.ts +97 -0
- package/dist/testing/index.js +87 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-BCBSfJJr.d.cts +136 -0
- package/dist/types-BCBSfJJr.d.ts +136 -0
- package/package.json +109 -79
- package/scripts/build-schemas.ts +112 -13
- package/scripts/postinstall.cjs +43 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @famgia/omnify-react-sso
|
|
2
2
|
|
|
3
|
-
SSO (Single Sign-On) schemas, types, and utilities for Omnify Console integration.
|
|
3
|
+
SSO (Single Sign-On) schemas, types, React hooks, components, and utilities for Omnify Console integration.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -12,11 +12,234 @@ pnpm add @famgia/omnify-react-sso
|
|
|
12
12
|
|
|
13
13
|
## Features
|
|
14
14
|
|
|
15
|
+
- **React Hooks**: `useSso()`, `useAuth()`, `useOrganization()` for SSO state management
|
|
16
|
+
- **React Components**: `SsoProvider`, `SsoCallback`, `OrganizationSwitcher`, `ProtectedRoute`
|
|
17
|
+
- **SSO Service**: `createSsoService()` for API communication
|
|
15
18
|
- **User Management**: User schema with Zod validation and i18n support
|
|
16
19
|
- **Role-Based Access Control (RBAC)**: Role, Permission, and RolePermission schemas
|
|
17
20
|
- **Team Management**: Team and TeamPermission schemas
|
|
18
21
|
- **Multi-locale Support**: Japanese and English labels/messages
|
|
19
|
-
- **
|
|
22
|
+
- **Query Keys**: Pre-defined TanStack Query keys for SSO data
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
// 1. Wrap your app with SsoProvider
|
|
28
|
+
import { SsoProvider } from '@famgia/omnify-react-sso';
|
|
29
|
+
|
|
30
|
+
function App() {
|
|
31
|
+
return (
|
|
32
|
+
<SsoProvider config={{
|
|
33
|
+
apiUrl: process.env.NEXT_PUBLIC_API_URL,
|
|
34
|
+
consoleUrl: process.env.NEXT_PUBLIC_SSO_URL,
|
|
35
|
+
loginPath: '/login',
|
|
36
|
+
callbackPath: '/sso/callback',
|
|
37
|
+
}}>
|
|
38
|
+
<YourApp />
|
|
39
|
+
</SsoProvider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 2. Use hooks in your components
|
|
44
|
+
import { useSso } from '@famgia/omnify-react-sso';
|
|
45
|
+
|
|
46
|
+
function Dashboard() {
|
|
47
|
+
const { user, isAuthenticated, currentOrg, logout } = useSso();
|
|
48
|
+
|
|
49
|
+
if (!isAuthenticated) return <Login />;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div>
|
|
53
|
+
Welcome, {user.name}!
|
|
54
|
+
Current org: {currentOrg?.name}
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 🔧 Development & Build Workflow
|
|
63
|
+
|
|
64
|
+
### Prerequisites
|
|
65
|
+
|
|
66
|
+
This package depends on schemas from `omnifyjp/omnify-client-laravel-sso`. The build process will:
|
|
67
|
+
|
|
68
|
+
1. **Try local**: Copy from `../omnify-client-laravel-sso/database/schemas/Sso`
|
|
69
|
+
2. **Fallback to git**: Clone via SSH from GitHub (requires access to omnifyjp org)
|
|
70
|
+
|
|
71
|
+
**SSH Access Required**: Developers must have SSH access to `git@github.com:omnifyjp/omnify-client-laravel-sso.git`
|
|
72
|
+
|
|
73
|
+
### Build Commands
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Full build (schemas + library)
|
|
77
|
+
pnpm build
|
|
78
|
+
|
|
79
|
+
# Build only schemas (fetch + generate types)
|
|
80
|
+
pnpm build:schemas
|
|
81
|
+
|
|
82
|
+
# Build only library (requires schemas to exist)
|
|
83
|
+
pnpm build:lib
|
|
84
|
+
|
|
85
|
+
# Run tests
|
|
86
|
+
pnpm test
|
|
87
|
+
|
|
88
|
+
# Type check
|
|
89
|
+
pnpm typecheck
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Build Process Detail
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
96
|
+
│ pnpm build │
|
|
97
|
+
└───────────────────────────┬─────────────────────────────────────┘
|
|
98
|
+
│
|
|
99
|
+
▼
|
|
100
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
101
|
+
│ Step 1: pnpm build:schemas │
|
|
102
|
+
│ │
|
|
103
|
+
│ 1. Clean previous builds (schemas/, src/schemas/, src/enum/) │
|
|
104
|
+
│ 2. Obtain SSO schemas: │
|
|
105
|
+
│ - Try: ../omnify-client-laravel-sso/database/schemas/Sso │
|
|
106
|
+
│ - Fallback: git clone from GitHub (sparse checkout) │
|
|
107
|
+
│ 3. Run: npx omnify generate --types-only │
|
|
108
|
+
│ → Creates @omnify-base in node_modules │
|
|
109
|
+
│ → Generates src/schemas/*.ts │
|
|
110
|
+
└───────────────────────────┬─────────────────────────────────────┘
|
|
111
|
+
│
|
|
112
|
+
▼
|
|
113
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
114
|
+
│ Step 2: pnpm build:lib (tsup) │
|
|
115
|
+
│ │
|
|
116
|
+
│ - Bundle src/index.ts → dist/index.js │
|
|
117
|
+
│ - Bundle src/schemas/index.ts → dist/schemas/index.js │
|
|
118
|
+
│ - Generate .d.ts type definitions │
|
|
119
|
+
│ - External: zod, @omnify-base/* │
|
|
120
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### First Time Setup
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Option A: Just run build (auto-fetches via SSH)
|
|
127
|
+
pnpm install
|
|
128
|
+
pnpm build # Will clone schemas from git automatically
|
|
129
|
+
|
|
130
|
+
# Option B: Clone laravel-sso as sibling (for frequent schema changes)
|
|
131
|
+
cd packages
|
|
132
|
+
git clone git@github.com:omnifyjp/omnify-client-laravel-sso.git
|
|
133
|
+
cd omnify-client-react-sso
|
|
134
|
+
pnpm install
|
|
135
|
+
pnpm build
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
> **Note**: Build script uses SSH (`git@github.com:omnifyjp/...`). Ensure your SSH key is added to GitHub.
|
|
139
|
+
|
|
140
|
+
### When to Rebuild
|
|
141
|
+
|
|
142
|
+
You need to run `pnpm build` when:
|
|
143
|
+
|
|
144
|
+
- ✅ First time setup
|
|
145
|
+
- ✅ Schema changes in `omnify-client-laravel-sso`
|
|
146
|
+
- ✅ After pulling updates from laravel-sso
|
|
147
|
+
- ✅ Before publishing to npm
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Local Development with Boilerplate
|
|
152
|
+
|
|
153
|
+
### Linking Package to Boilerplate
|
|
154
|
+
|
|
155
|
+
Instead of using npm registry or tarballs, link the package directly:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# In boilerplate/frontend
|
|
159
|
+
pnpm add /path/to/omnify/packages/omnify-client-react-sso
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
This creates a symlink in `package.json`:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
"@famgia/omnify-react-sso": "link:/path/to/omnify/packages/omnify-client-react-sso"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Development Workflow
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
172
|
+
│ omnify-client-laravel-sso (Laravel Package) │
|
|
173
|
+
│ - SSO schema YAML files (source of truth) │
|
|
174
|
+
│ - Backend models, migrations, controllers │
|
|
175
|
+
└───────────────────────────┬─────────────────────────────────────┘
|
|
176
|
+
│ schemas copied during build
|
|
177
|
+
▼
|
|
178
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
179
|
+
│ @famgia/omnify-react-sso (This Package) │
|
|
180
|
+
│ │
|
|
181
|
+
│ pnpm build │
|
|
182
|
+
│ ├── 1. Copy schemas from laravel-sso │
|
|
183
|
+
│ ├── 2. omnify generate --types-only │
|
|
184
|
+
│ └── 3. tsup bundle → dist/ │
|
|
185
|
+
│ │
|
|
186
|
+
│ Exports: │
|
|
187
|
+
│ - React hooks (useSso, useAuth, useOrganization) │
|
|
188
|
+
│ - React components (SsoProvider, ProtectedRoute, etc.) │
|
|
189
|
+
│ - Services (createAuthService, createRoleService, etc.) │
|
|
190
|
+
│ - SSO Schemas (Role, Permission, Branch, Team, User) │
|
|
191
|
+
│ - Query Keys (ssoQueryKeys) │
|
|
192
|
+
└───────────────────────────┬─────────────────────────────────────┘
|
|
193
|
+
│ linked via pnpm
|
|
194
|
+
▼
|
|
195
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
196
|
+
│ Boilerplate / Your App │
|
|
197
|
+
│ │
|
|
198
|
+
│ package.json: │
|
|
199
|
+
│ "@famgia/omnify-react-sso": "link:/path/to/package" │
|
|
200
|
+
│ │
|
|
201
|
+
│ omnify.config.ts: │
|
|
202
|
+
│ typescriptPlugin({ │
|
|
203
|
+
│ exclude: ["Branch", "Role", "Permission", ...] // SSO types │
|
|
204
|
+
│ }) │
|
|
205
|
+
│ │
|
|
206
|
+
│ Imports: │
|
|
207
|
+
│ - SSO types → from "@famgia/omnify-react-sso" │
|
|
208
|
+
│ - App types → from "@/omnify/schemas" (local generate) │
|
|
209
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### After Changing SSO Schemas
|
|
213
|
+
|
|
214
|
+
1. **Update Laravel package** (if schema YAML changed)
|
|
215
|
+
2. **Rebuild this package:**
|
|
216
|
+
```bash
|
|
217
|
+
cd packages/omnify-client-react-sso
|
|
218
|
+
pnpm build
|
|
219
|
+
```
|
|
220
|
+
3. **Boilerplate automatically uses new dist** (linked)
|
|
221
|
+
|
|
222
|
+
### Boilerplate Configuration
|
|
223
|
+
|
|
224
|
+
In the boilerplate's `omnify.config.ts`, exclude SSO schemas:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
typescriptPlugin({
|
|
228
|
+
modelsPath: "./frontend/src/omnify/schemas",
|
|
229
|
+
exclude: [
|
|
230
|
+
"Branch",
|
|
231
|
+
"Permission",
|
|
232
|
+
"Role",
|
|
233
|
+
"RolePermission",
|
|
234
|
+
"Team",
|
|
235
|
+
"TeamPermission",
|
|
236
|
+
],
|
|
237
|
+
})
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
This prevents duplicate schema generation - SSO types come from this package.
|
|
241
|
+
|
|
242
|
+
---
|
|
20
243
|
|
|
21
244
|
## Architecture Note
|
|
22
245
|
|
|
@@ -35,7 +258,123 @@ Console (SSO Provider) Your React App (SSO Client)
|
|
|
35
258
|
|
|
36
259
|
> **Note:** Your app only needs the `service_slug`. Console manages credentials per-organization through ServiceInstance.
|
|
37
260
|
|
|
38
|
-
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## API Reference
|
|
264
|
+
|
|
265
|
+
### Hooks
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { useSso, useAuth, useOrganization } from '@famgia/omnify-react-sso';
|
|
269
|
+
|
|
270
|
+
// Main hook - all SSO functionality
|
|
271
|
+
const {
|
|
272
|
+
user, // Current user
|
|
273
|
+
isAuthenticated, // Auth status
|
|
274
|
+
isLoading, // Loading state
|
|
275
|
+
organizations, // User's organizations
|
|
276
|
+
currentOrg, // Current organization
|
|
277
|
+
hasMultipleOrgs, // Has more than one org?
|
|
278
|
+
login, // Redirect to login
|
|
279
|
+
logout, // Logout current session
|
|
280
|
+
globalLogout, // Logout from all sessions
|
|
281
|
+
switchOrg, // Switch organization
|
|
282
|
+
getHeaders, // Get auth headers
|
|
283
|
+
config, // SSO config
|
|
284
|
+
} = useSso();
|
|
285
|
+
|
|
286
|
+
// Auth-focused hook
|
|
287
|
+
const { user, isAuthenticated, login, logout } = useAuth();
|
|
288
|
+
|
|
289
|
+
// Organization-focused hook
|
|
290
|
+
const { organizations, currentOrg, switchOrg, hasMultipleOrgs } = useOrganization();
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Components
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
import {
|
|
297
|
+
SsoProvider,
|
|
298
|
+
SsoCallback,
|
|
299
|
+
OrganizationSwitcher,
|
|
300
|
+
ProtectedRoute,
|
|
301
|
+
} from '@famgia/omnify-react-sso';
|
|
302
|
+
|
|
303
|
+
// Provider - wrap your app
|
|
304
|
+
<SsoProvider config={ssoConfig}>
|
|
305
|
+
<App />
|
|
306
|
+
</SsoProvider>
|
|
307
|
+
|
|
308
|
+
// Callback page - handle OAuth redirect
|
|
309
|
+
<SsoCallback
|
|
310
|
+
onSuccess={(user) => router.push('/dashboard')}
|
|
311
|
+
onError={(error) => console.error(error)}
|
|
312
|
+
/>
|
|
313
|
+
|
|
314
|
+
// Organization switcher dropdown
|
|
315
|
+
<OrganizationSwitcher />
|
|
316
|
+
|
|
317
|
+
// Protected route wrapper
|
|
318
|
+
<ProtectedRoute fallback={<Login />}>
|
|
319
|
+
<Dashboard />
|
|
320
|
+
</ProtectedRoute>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Services (Recommended)
|
|
324
|
+
|
|
325
|
+
Use individual services for better tree-shaking and type safety:
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import {
|
|
329
|
+
createAuthService,
|
|
330
|
+
createRoleService,
|
|
331
|
+
createPermissionService,
|
|
332
|
+
createBranchService,
|
|
333
|
+
createUserRoleService,
|
|
334
|
+
} from '@famgia/omnify-react-sso';
|
|
335
|
+
|
|
336
|
+
const config = { apiUrl: 'https://api.example.com' };
|
|
337
|
+
|
|
338
|
+
// Auth Service
|
|
339
|
+
const authService = createAuthService(config);
|
|
340
|
+
await authService.callback({ code: 'oauth-code' });
|
|
341
|
+
await authService.getUser();
|
|
342
|
+
await authService.logout();
|
|
343
|
+
|
|
344
|
+
// Role Service
|
|
345
|
+
const roleService = createRoleService(config);
|
|
346
|
+
await roleService.list();
|
|
347
|
+
await roleService.get(roleId);
|
|
348
|
+
await roleService.create({ name: 'Editor', slug: 'editor' });
|
|
349
|
+
await roleService.syncPermissions(roleId, { permissions: ['read', 'write'] });
|
|
350
|
+
|
|
351
|
+
// Permission Service
|
|
352
|
+
const permissionService = createPermissionService(config);
|
|
353
|
+
await permissionService.list();
|
|
354
|
+
await permissionService.getMatrix();
|
|
355
|
+
|
|
356
|
+
// Branch Service
|
|
357
|
+
const branchService = createBranchService(config);
|
|
358
|
+
await branchService.list();
|
|
359
|
+
await branchService.getPrimary();
|
|
360
|
+
|
|
361
|
+
// User Role Service (Scoped Assignments)
|
|
362
|
+
const userRoleService = createUserRoleService(config);
|
|
363
|
+
await userRoleService.listForUser(userId);
|
|
364
|
+
await userRoleService.assign({ user_id, role_id, scope: 'branch', branch_id });
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Legacy Service (Deprecated)
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
// @deprecated - Use individual services instead
|
|
371
|
+
import { createSsoService } from '@famgia/omnify-react-sso';
|
|
372
|
+
|
|
373
|
+
const ssoService = createSsoService({ apiUrl: 'https://api.example.com' });
|
|
374
|
+
await ssoService.getRoles(); // Use roleService.list() instead
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Schemas
|
|
39
378
|
|
|
40
379
|
```typescript
|
|
41
380
|
import {
|
|
@@ -64,16 +403,24 @@ import {
|
|
|
64
403
|
} from '@famgia/omnify-react-sso';
|
|
65
404
|
```
|
|
66
405
|
|
|
67
|
-
|
|
406
|
+
### Query Keys
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import { ssoQueryKeys } from '@famgia/omnify-react-sso';
|
|
68
410
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
411
|
+
// Use with TanStack Query
|
|
412
|
+
useQuery({
|
|
413
|
+
queryKey: ssoQueryKeys.auth.user(),
|
|
414
|
+
queryFn: () => ssoService.getUser(),
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
useQuery({
|
|
418
|
+
queryKey: ssoQueryKeys.roles.list(),
|
|
419
|
+
queryFn: () => ssoService.getRoles(),
|
|
420
|
+
});
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
77
424
|
|
|
78
425
|
## i18n Support
|
|
79
426
|
|
|
@@ -89,6 +436,65 @@ const label = getUserLabel('ja'); // 'ユーザー'
|
|
|
89
436
|
const emailLabel = getUserFieldLabel('email', 'ja'); // 'メールアドレス'
|
|
90
437
|
```
|
|
91
438
|
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## Testing
|
|
442
|
+
|
|
443
|
+
### Run Tests
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
pnpm test # Run once
|
|
447
|
+
pnpm test:watch # Watch mode
|
|
448
|
+
pnpm typecheck # Type check
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Test Utilities (for App Tests)
|
|
452
|
+
|
|
453
|
+
The package provides official test mocks:
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
import {
|
|
457
|
+
createMockUser,
|
|
458
|
+
createMockOrganization,
|
|
459
|
+
setMockSsoData,
|
|
460
|
+
resetMockSsoData,
|
|
461
|
+
mockUseSso,
|
|
462
|
+
} from '@famgia/omnify-react-sso/testing';
|
|
463
|
+
|
|
464
|
+
// Create mock data
|
|
465
|
+
const user = createMockUser({ name: 'Custom User' });
|
|
466
|
+
const org = createMockOrganization({ slug: 'my-org' });
|
|
467
|
+
|
|
468
|
+
// Setup mock for tests
|
|
469
|
+
beforeEach(() => {
|
|
470
|
+
setMockSsoData({
|
|
471
|
+
user,
|
|
472
|
+
organizations: [org],
|
|
473
|
+
currentOrg: org,
|
|
474
|
+
isAuthenticated: true,
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
afterEach(() => {
|
|
479
|
+
resetMockSsoData();
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
// Mock the hooks in vitest
|
|
483
|
+
vi.mock('@famgia/omnify-react-sso', async () => {
|
|
484
|
+
const testing = await import('@famgia/omnify-react-sso/testing');
|
|
485
|
+
return {
|
|
486
|
+
useSso: testing.mockUseSso,
|
|
487
|
+
useAuth: testing.mockUseAuth,
|
|
488
|
+
useOrganization: testing.mockUseOrganization,
|
|
489
|
+
SsoProvider: ({ children }) => children,
|
|
490
|
+
};
|
|
491
|
+
});
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
> **Note**: Subpath exports (`/testing`) require the package to be installed from npm, not linked locally.
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
92
498
|
## License
|
|
93
499
|
|
|
94
500
|
MIT
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@omnify-base",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
"./enum/*": {
|
|
8
|
+
"types": "./enum/*.ts",
|
|
9
|
+
"default": "./enum/*.ts"
|
|
10
|
+
},
|
|
11
|
+
"./schemas/*": {
|
|
12
|
+
"types": "./schemas/*.ts",
|
|
13
|
+
"default": "./schemas/*.ts"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⚠️ DO NOT EDIT THIS FILE! ⚠️
|
|
3
|
+
* このファイルを編集しないでください!
|
|
4
|
+
* KHÔNG ĐƯỢC SỬA FILE NÀY!
|
|
5
|
+
*
|
|
6
|
+
* Auto-generated TypeScript types from Omnify schemas.
|
|
7
|
+
* Any manual changes will be OVERWRITTEN on next generation.
|
|
8
|
+
*
|
|
9
|
+
* To modify: Edit the schema YAML file and run: npx omnify generate
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import type { DateTimeString } from './common';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Branch
|
|
17
|
+
*/
|
|
18
|
+
export interface Branch {
|
|
19
|
+
/** Primary key */
|
|
20
|
+
id: string;
|
|
21
|
+
/** Console Branch ID */
|
|
22
|
+
console_branch_id: unknown;
|
|
23
|
+
/** Console Organization ID */
|
|
24
|
+
console_org_id: unknown;
|
|
25
|
+
/** Branch Code */
|
|
26
|
+
code: string;
|
|
27
|
+
/** Branch Name */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Is Headquarters */
|
|
30
|
+
is_headquarters: boolean;
|
|
31
|
+
/** Active */
|
|
32
|
+
is_active: boolean;
|
|
33
|
+
/** Creation timestamp */
|
|
34
|
+
created_at?: DateTimeString;
|
|
35
|
+
/** Last update timestamp */
|
|
36
|
+
updated_at?: DateTimeString;
|
|
37
|
+
/** Soft delete timestamp */
|
|
38
|
+
deleted_at?: DateTimeString;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// I18n (Internationalization)
|
|
43
|
+
// ============================================================================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Unified i18n object for Branch
|
|
47
|
+
* Contains model label and all field labels/placeholders
|
|
48
|
+
*/
|
|
49
|
+
export const branchI18n = {
|
|
50
|
+
/** Model display name */
|
|
51
|
+
label: {"en":"Branch"},
|
|
52
|
+
/** Field labels and placeholders */
|
|
53
|
+
fields: {
|
|
54
|
+
console_branch_id: {
|
|
55
|
+
label: {"en":"Console Branch ID"},
|
|
56
|
+
},
|
|
57
|
+
console_org_id: {
|
|
58
|
+
label: {"en":"Console Organization ID"},
|
|
59
|
+
},
|
|
60
|
+
code: {
|
|
61
|
+
label: {"en":"Branch Code"},
|
|
62
|
+
},
|
|
63
|
+
name: {
|
|
64
|
+
label: {"en":"Branch Name"},
|
|
65
|
+
},
|
|
66
|
+
is_headquarters: {
|
|
67
|
+
label: {"en":"Is Headquarters"},
|
|
68
|
+
},
|
|
69
|
+
is_active: {
|
|
70
|
+
label: {"en":"Active"},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
} as const;
|
|
74
|
+
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// Zod Schemas
|
|
77
|
+
// ============================================================================
|
|
78
|
+
|
|
79
|
+
/** Field schemas for Branch */
|
|
80
|
+
export const baseBranchSchemas = {
|
|
81
|
+
console_branch_id: z.string(),
|
|
82
|
+
console_org_id: z.string(),
|
|
83
|
+
code: z.string().min(1).max(20),
|
|
84
|
+
name: z.string().min(1).max(100),
|
|
85
|
+
is_headquarters: z.boolean(),
|
|
86
|
+
is_active: z.boolean(),
|
|
87
|
+
} as const;
|
|
88
|
+
|
|
89
|
+
/** Create schema for Branch (POST requests) */
|
|
90
|
+
export const baseBranchCreateSchema = z.object({
|
|
91
|
+
console_branch_id: baseBranchSchemas.console_branch_id,
|
|
92
|
+
console_org_id: baseBranchSchemas.console_org_id,
|
|
93
|
+
code: baseBranchSchemas.code,
|
|
94
|
+
name: baseBranchSchemas.name,
|
|
95
|
+
is_headquarters: baseBranchSchemas.is_headquarters,
|
|
96
|
+
is_active: baseBranchSchemas.is_active,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
/** Update schema for Branch (PUT/PATCH requests) */
|
|
100
|
+
export const baseBranchUpdateSchema = baseBranchCreateSchema.partial();
|
|
101
|
+
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Inferred Types
|
|
104
|
+
// ============================================================================
|
|
105
|
+
|
|
106
|
+
export type BaseBranchCreate = z.infer<typeof baseBranchCreateSchema>;
|
|
107
|
+
export type BaseBranchUpdate = z.infer<typeof baseBranchUpdateSchema>;
|
|
108
|
+
|
|
109
|
+
// ============================================================================
|
|
110
|
+
// I18n Helper Functions
|
|
111
|
+
// ============================================================================
|
|
112
|
+
|
|
113
|
+
/** Get model label for a specific locale */
|
|
114
|
+
export function getBranchLabel(locale: string): string {
|
|
115
|
+
return branchI18n.label[locale as keyof typeof branchI18n.label] ?? branchI18n.label['en'] ?? 'Branch';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Get field label for a specific locale */
|
|
119
|
+
export function getBranchFieldLabel(field: string, locale: string): string {
|
|
120
|
+
const fieldI18n = branchI18n.fields[field as keyof typeof branchI18n.fields];
|
|
121
|
+
if (!fieldI18n) return field;
|
|
122
|
+
return fieldI18n.label[locale as keyof typeof fieldI18n.label] ?? fieldI18n.label['en'] ?? field;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Get field placeholder for a specific locale */
|
|
126
|
+
export function getBranchFieldPlaceholder(field: string, locale: string): string {
|
|
127
|
+
const fieldI18n = branchI18n.fields[field as keyof typeof branchI18n.fields];
|
|
128
|
+
if (!fieldI18n || !('placeholder' in fieldI18n)) return '';
|
|
129
|
+
const placeholder = fieldI18n.placeholder as Record<string, string>;
|
|
130
|
+
return placeholder[locale] ?? placeholder['en'] ?? '';
|
|
131
|
+
}
|