@classytic/arc 1.0.0 → 1.0.8

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 (36) hide show
  1. package/README.md +65 -35
  2. package/bin/arc.js +118 -103
  3. package/dist/BaseController-nNRS3vpA.d.ts +233 -0
  4. package/dist/adapters/index.d.ts +2 -2
  5. package/dist/{arcCorePlugin-DTPWXcZN.d.ts → arcCorePlugin-CAjBQtZB.d.ts} +1 -1
  6. package/dist/auth/index.d.ts +1 -1
  7. package/dist/cli/commands/generate.d.ts +16 -0
  8. package/dist/cli/commands/generate.js +334 -0
  9. package/dist/cli/commands/init.d.ts +24 -0
  10. package/dist/cli/commands/init.js +2425 -0
  11. package/dist/cli/index.d.ts +4 -43
  12. package/dist/cli/index.js +3160 -411
  13. package/dist/core/index.d.ts +220 -0
  14. package/dist/core/index.js +2764 -0
  15. package/dist/{createApp-pzUAkzbz.d.ts → createApp-CjN9zZSL.d.ts} +1 -1
  16. package/dist/docs/index.js +19 -11
  17. package/dist/factory/index.d.ts +4 -4
  18. package/dist/factory/index.js +6 -23
  19. package/dist/hooks/index.d.ts +1 -1
  20. package/dist/{index-DkAW8BXh.d.ts → index-D5QTob1X.d.ts} +32 -12
  21. package/dist/index.d.ts +7 -203
  22. package/dist/index.js +108 -113
  23. package/dist/org/index.d.ts +1 -1
  24. package/dist/permissions/index.js +5 -2
  25. package/dist/plugins/index.d.ts +2 -2
  26. package/dist/presets/index.d.ts +6 -6
  27. package/dist/presets/index.js +3 -1
  28. package/dist/presets/multiTenant.d.ts +1 -1
  29. package/dist/registry/index.d.ts +2 -2
  30. package/dist/testing/index.d.ts +2 -2
  31. package/dist/testing/index.js +6 -23
  32. package/dist/types/index.d.ts +1 -1
  33. package/dist/{types-0IPhH_NR.d.ts → types-zpN48n6B.d.ts} +1 -1
  34. package/dist/utils/index.d.ts +28 -4
  35. package/dist/utils/index.js +17 -8
  36. package/package.json +8 -14
@@ -0,0 +1,220 @@
1
+ export { B as BaseController, a as BaseControllerOptions } from '../BaseController-nNRS3vpA.js';
2
+ import { RouteHandlerMethod, FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
3
+ import { w as FastifyWithDecorators, B as CrudController, _ as CrudRouterOptions, d as RequestWithExtras, a as IRequestContext, c as IControllerResponse, I as IController } from '../index-D5QTob1X.js';
4
+ export { q as ResourceDefinition, p as defineResource } from '../index-D5QTob1X.js';
5
+ import { P as PermissionCheck } from '../types-B99TBmFV.js';
6
+ import 'mongoose';
7
+
8
+ /**
9
+ * CRUD Router Factory
10
+ *
11
+ * Creates standard REST routes with permission-based access control.
12
+ * Full TypeScript support with proper Fastify types.
13
+ *
14
+ * Features:
15
+ * - Permission-based access control via PermissionCheck functions
16
+ * - Organization scoping for multi-tenant routes
17
+ * - Consistent route patterns
18
+ * - Framework-agnostic controllers via adapter pattern
19
+ */
20
+
21
+ /**
22
+ * Create CRUD routes for a controller
23
+ *
24
+ * @param fastify - Fastify instance with Arc decorators
25
+ * @param controller - CRUD controller with handler methods
26
+ * @param options - Router configuration
27
+ */
28
+ declare function createCrudRouter<TDoc = unknown>(fastify: FastifyWithDecorators, controller: CrudController<TDoc> | undefined, options?: CrudRouterOptions): void;
29
+ /**
30
+ * Helper to create org scoped middleware
31
+ */
32
+ declare function createOrgScopedMiddleware(instance: FastifyWithDecorators): RouteHandlerMethod[];
33
+ /**
34
+ * Create permission middleware from PermissionCheck
35
+ * Useful for custom route registration
36
+ */
37
+ declare function createPermissionMiddleware(permission: PermissionCheck, resourceName: string, action: string): RouteHandlerMethod | null;
38
+
39
+ /**
40
+ * Action Router Factory (Stripe Pattern)
41
+ *
42
+ * Consolidates multiple state-transition endpoints into a single unified action endpoint.
43
+ * Instead of separate endpoints for each action (approve, dispatch, receive, cancel),
44
+ * this creates one endpoint: POST /:id/action
45
+ *
46
+ * Benefits:
47
+ * - 40% fewer endpoints
48
+ * - Consistent permission checking
49
+ * - Self-documenting via action enum
50
+ * - Type-safe action validation
51
+ * - Single audit point for all state transitions
52
+ *
53
+ * @example
54
+ * import { createActionRouter } from '@classytic/arc';
55
+ * import { requireRoles } from '@classytic/arc/permissions';
56
+ *
57
+ * createActionRouter(fastify, {
58
+ * tag: 'Inventory - Transfers',
59
+ * actions: {
60
+ * approve: async (id, data, req) => transferService.approve(id, req.user),
61
+ * dispatch: async (id, data, req) => transferService.dispatch(id, data.transport, req.user),
62
+ * receive: async (id, data, req) => transferService.receive(id, data, req.user),
63
+ * cancel: async (id, data, req) => transferService.cancel(id, data.reason, req.user),
64
+ * },
65
+ * actionPermissions: {
66
+ * approve: requireRoles(['admin', 'warehouse-manager']),
67
+ * dispatch: requireRoles(['admin', 'warehouse-staff']),
68
+ * receive: requireRoles(['admin', 'store-manager']),
69
+ * cancel: requireRoles(['admin']),
70
+ * },
71
+ * actionSchemas: {
72
+ * dispatch: {
73
+ * transport: { type: 'object', properties: { driver: { type: 'string' } } }
74
+ * },
75
+ * cancel: {
76
+ * reason: { type: 'string', minLength: 10 }
77
+ * },
78
+ * }
79
+ * });
80
+ */
81
+
82
+ /**
83
+ * Action handler function
84
+ * @param id - Resource ID
85
+ * @param data - Action-specific data from request body
86
+ * @param req - Full Fastify request object
87
+ * @returns Action result (will be wrapped in success response)
88
+ */
89
+ type ActionHandler<TData = any, TResult = any> = (id: string, data: TData, req: RequestWithExtras) => Promise<TResult>;
90
+ /**
91
+ * Action router configuration
92
+ */
93
+ interface ActionRouterConfig {
94
+ /**
95
+ * OpenAPI tag for grouping routes
96
+ */
97
+ tag?: string;
98
+ /**
99
+ * Action handlers map
100
+ * @example { approve: (id, data, req) => service.approve(id), ... }
101
+ */
102
+ actions: Record<string, ActionHandler>;
103
+ /**
104
+ * Per-action permission checks (PermissionCheck functions)
105
+ * @example { approve: requireRoles(['admin', 'manager']), cancel: requireRoles(['admin']) }
106
+ */
107
+ actionPermissions?: Record<string, PermissionCheck>;
108
+ /**
109
+ * Per-action JSON schema for body validation
110
+ * @example { dispatch: { transport: { type: 'object' } } }
111
+ */
112
+ actionSchemas?: Record<string, Record<string, any>>;
113
+ /**
114
+ * Global permission check applied to all actions (if action-specific not defined)
115
+ */
116
+ globalAuth?: PermissionCheck;
117
+ /**
118
+ * Optional idempotency service
119
+ * If provided, will handle idempotency-key header
120
+ */
121
+ idempotencyService?: IdempotencyService;
122
+ /**
123
+ * Custom error handler for action execution failures
124
+ * @param error - The error thrown by action handler
125
+ * @param action - The action that failed
126
+ * @param id - The resource ID
127
+ * @returns Status code and error response
128
+ */
129
+ onError?: (error: Error, action: string, id: string) => {
130
+ statusCode: number;
131
+ error: string;
132
+ code?: string;
133
+ };
134
+ }
135
+ /**
136
+ * Idempotency service interface
137
+ * Apps can provide their own implementation
138
+ */
139
+ interface IdempotencyService {
140
+ check(key: string, payload: any): Promise<{
141
+ isNew: boolean;
142
+ existingResult?: any;
143
+ }>;
144
+ complete(key: string | undefined, result: any): Promise<void>;
145
+ fail(key: string | undefined, error: Error): Promise<void>;
146
+ }
147
+ /**
148
+ * Create action-based state transition endpoint
149
+ *
150
+ * Registers: POST /:id/action
151
+ * Body: { action: string, ...actionData }
152
+ *
153
+ * @param fastify - Fastify instance
154
+ * @param config - Action router configuration
155
+ */
156
+ declare function createActionRouter(fastify: FastifyInstance, config: ActionRouterConfig): void;
157
+
158
+ /**
159
+ * Fastify Adapter for IController
160
+ *
161
+ * Converts between Fastify's request/reply and framework-agnostic IRequestContext/IControllerResponse.
162
+ * This allows controllers implementing IController to work seamlessly with Fastify.
163
+ */
164
+
165
+ /**
166
+ * Create IRequestContext from Fastify request
167
+ *
168
+ * Extracts framework-agnostic context from Fastify-specific request object
169
+ */
170
+ declare function createRequestContext(req: FastifyRequest): IRequestContext;
171
+ /**
172
+ * Send IControllerResponse via Fastify reply
173
+ *
174
+ * Converts framework-agnostic response to Fastify response
175
+ * Applies field masking if specified in request
176
+ */
177
+ declare function sendControllerResponse<T>(reply: FastifyReply, response: IControllerResponse<T>, request?: FastifyRequest): void;
178
+ /**
179
+ * Create Fastify route handler from IController method
180
+ *
181
+ * Wraps framework-agnostic controller method in Fastify-specific handler
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * const controller = new BaseController(repository);
186
+ *
187
+ * // Create Fastify handler
188
+ * const listHandler = createFastifyHandler(controller.list.bind(controller));
189
+ *
190
+ * // Register route
191
+ * fastify.get('/products', listHandler);
192
+ * ```
193
+ */
194
+ declare function createFastifyHandler<T>(controllerMethod: (req: IRequestContext) => Promise<IControllerResponse<T>>): (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
195
+ /**
196
+ * Create Fastify adapters for all CRUD methods of an IController
197
+ *
198
+ * Returns Fastify-compatible handlers for each CRUD operation
199
+ *
200
+ * @example
201
+ * ```typescript
202
+ * const controller = new BaseController(repository);
203
+ * const handlers = createCrudHandlers(controller);
204
+ *
205
+ * fastify.get('/', handlers.list);
206
+ * fastify.get('/:id', handlers.get);
207
+ * fastify.post('/', handlers.create);
208
+ * fastify.patch('/:id', handlers.update);
209
+ * fastify.delete('/:id', handlers.delete);
210
+ * ```
211
+ */
212
+ declare function createCrudHandlers<TDoc>(controller: IController<TDoc>): {
213
+ list: (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
214
+ get: (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
215
+ create: (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
216
+ update: (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
217
+ delete: (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
218
+ };
219
+
220
+ export { type ActionHandler, type ActionRouterConfig, type IdempotencyService, createActionRouter, createCrudHandlers, createCrudRouter, createFastifyHandler, createOrgScopedMiddleware, createPermissionMiddleware, createRequestContext, sendControllerResponse };