@classytic/arc 1.1.0 → 2.1.3

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 (200) hide show
  1. package/README.md +247 -794
  2. package/bin/arc.js +91 -52
  3. package/dist/EventTransport-BkUDYZEb.d.mts +99 -0
  4. package/dist/HookSystem-BsGV-j2l.mjs +404 -0
  5. package/dist/ResourceRegistry-7Ic20ZMw.mjs +249 -0
  6. package/dist/adapters/index.d.mts +5 -0
  7. package/dist/adapters/index.mjs +3 -0
  8. package/dist/audit/index.d.mts +81 -0
  9. package/dist/audit/index.mjs +275 -0
  10. package/dist/audit/mongodb.d.mts +5 -0
  11. package/dist/audit/mongodb.mjs +3 -0
  12. package/dist/audited-CGdLiSlE.mjs +140 -0
  13. package/dist/auth/index.d.mts +188 -0
  14. package/dist/auth/index.mjs +1096 -0
  15. package/dist/auth/redis-session.d.mts +43 -0
  16. package/dist/auth/redis-session.mjs +75 -0
  17. package/dist/betterAuthOpenApi-DjWDddNc.mjs +249 -0
  18. package/dist/cache/index.d.mts +145 -0
  19. package/dist/cache/index.mjs +91 -0
  20. package/dist/caching-GSDJcA6-.mjs +93 -0
  21. package/dist/chunk-C7Uep-_p.mjs +20 -0
  22. package/dist/circuitBreaker-DYhWBW_D.mjs +1096 -0
  23. package/dist/cli/commands/describe.d.mts +18 -0
  24. package/dist/cli/commands/describe.mjs +238 -0
  25. package/dist/cli/commands/docs.d.mts +13 -0
  26. package/dist/cli/commands/docs.mjs +52 -0
  27. package/dist/cli/commands/{generate.d.ts → generate.d.mts} +3 -2
  28. package/dist/cli/commands/generate.mjs +357 -0
  29. package/dist/cli/commands/{init.d.ts → init.d.mts} +11 -8
  30. package/dist/cli/commands/{init.js → init.mjs} +807 -617
  31. package/dist/cli/commands/introspect.d.mts +10 -0
  32. package/dist/cli/commands/introspect.mjs +75 -0
  33. package/dist/cli/index.d.mts +16 -0
  34. package/dist/cli/index.mjs +156 -0
  35. package/dist/constants-DdXFXQtN.mjs +84 -0
  36. package/dist/core/index.d.mts +5 -0
  37. package/dist/core/index.mjs +4 -0
  38. package/dist/createApp-D2D5XXaV.mjs +559 -0
  39. package/dist/defineResource-PXzSJ15_.mjs +2197 -0
  40. package/dist/discovery/index.d.mts +46 -0
  41. package/dist/discovery/index.mjs +109 -0
  42. package/dist/docs/index.d.mts +162 -0
  43. package/dist/docs/index.mjs +74 -0
  44. package/dist/elevation-DGo5shaX.d.mts +87 -0
  45. package/dist/elevation-DSTbVvYj.mjs +113 -0
  46. package/dist/errorHandler-C3GY3_ow.mjs +108 -0
  47. package/dist/errorHandler-CW3OOeYq.d.mts +72 -0
  48. package/dist/errors-DAWRdiYP.d.mts +124 -0
  49. package/dist/errors-DBANPbGr.mjs +211 -0
  50. package/dist/eventPlugin-BEOvaDqo.mjs +229 -0
  51. package/dist/eventPlugin-H6wDDjGO.d.mts +124 -0
  52. package/dist/events/index.d.mts +53 -0
  53. package/dist/events/index.mjs +51 -0
  54. package/dist/events/transports/redis-stream-entry.d.mts +2 -0
  55. package/dist/events/transports/redis-stream-entry.mjs +177 -0
  56. package/dist/events/transports/redis.d.mts +76 -0
  57. package/dist/events/transports/redis.mjs +124 -0
  58. package/dist/externalPaths-SyPF2tgK.d.mts +50 -0
  59. package/dist/factory/index.d.mts +63 -0
  60. package/dist/factory/index.mjs +3 -0
  61. package/dist/fastifyAdapter-C8DlE0YH.d.mts +216 -0
  62. package/dist/fields-Bi_AVKSo.d.mts +109 -0
  63. package/dist/fields-CTd_CrKr.mjs +114 -0
  64. package/dist/hooks/index.d.mts +4 -0
  65. package/dist/hooks/index.mjs +3 -0
  66. package/dist/idempotency/index.d.mts +96 -0
  67. package/dist/idempotency/index.mjs +319 -0
  68. package/dist/idempotency/mongodb.d.mts +2 -0
  69. package/dist/idempotency/mongodb.mjs +114 -0
  70. package/dist/idempotency/redis.d.mts +2 -0
  71. package/dist/idempotency/redis.mjs +103 -0
  72. package/dist/index.d.mts +260 -0
  73. package/dist/index.mjs +104 -0
  74. package/dist/integrations/event-gateway.d.mts +46 -0
  75. package/dist/integrations/event-gateway.mjs +43 -0
  76. package/dist/integrations/index.d.mts +5 -0
  77. package/dist/integrations/index.mjs +1 -0
  78. package/dist/integrations/jobs.d.mts +103 -0
  79. package/dist/integrations/jobs.mjs +123 -0
  80. package/dist/integrations/streamline.d.mts +60 -0
  81. package/dist/integrations/streamline.mjs +125 -0
  82. package/dist/integrations/websocket.d.mts +82 -0
  83. package/dist/integrations/websocket.mjs +288 -0
  84. package/dist/interface-CSNjltAc.d.mts +77 -0
  85. package/dist/interface-DTbsvIWe.d.mts +54 -0
  86. package/dist/interface-e9XfSsUV.d.mts +1097 -0
  87. package/dist/introspectionPlugin-B3JkrjwU.mjs +53 -0
  88. package/dist/keys-DhqDRxv3.mjs +42 -0
  89. package/dist/logger-ByrvQWZO.mjs +78 -0
  90. package/dist/memory-B2v7KrCB.mjs +143 -0
  91. package/dist/migrations/index.d.mts +156 -0
  92. package/dist/migrations/index.mjs +260 -0
  93. package/dist/mongodb-ClykrfGo.d.mts +118 -0
  94. package/dist/mongodb-DNKEExbf.mjs +93 -0
  95. package/dist/mongodb-Dg8O_gvd.d.mts +71 -0
  96. package/dist/openapi-9nB_kiuR.mjs +525 -0
  97. package/dist/org/index.d.mts +68 -0
  98. package/dist/org/index.mjs +513 -0
  99. package/dist/org/types.d.mts +82 -0
  100. package/dist/org/types.mjs +1 -0
  101. package/dist/permissions/index.d.mts +278 -0
  102. package/dist/permissions/index.mjs +579 -0
  103. package/dist/plugins/index.d.mts +172 -0
  104. package/dist/plugins/index.mjs +522 -0
  105. package/dist/plugins/response-cache.d.mts +87 -0
  106. package/dist/plugins/response-cache.mjs +283 -0
  107. package/dist/plugins/tracing-entry.d.mts +2 -0
  108. package/dist/plugins/tracing-entry.mjs +185 -0
  109. package/dist/pluralize-CM-jZg7p.mjs +86 -0
  110. package/dist/policies/{index.d.ts → index.d.mts} +204 -170
  111. package/dist/policies/index.mjs +321 -0
  112. package/dist/presets/{index.d.ts → index.d.mts} +62 -131
  113. package/dist/presets/index.mjs +143 -0
  114. package/dist/presets/multiTenant.d.mts +24 -0
  115. package/dist/presets/multiTenant.mjs +113 -0
  116. package/dist/presets-BTeYbw7h.d.mts +57 -0
  117. package/dist/presets-CeFtfDR8.mjs +119 -0
  118. package/dist/prisma-C3iornoK.d.mts +274 -0
  119. package/dist/prisma-DJbMt3yf.mjs +627 -0
  120. package/dist/queryCachePlugin-B6R0d4av.mjs +138 -0
  121. package/dist/queryCachePlugin-Q6SYuHZ6.d.mts +71 -0
  122. package/dist/redis-UwjEp8Ea.d.mts +49 -0
  123. package/dist/redis-stream-CBg0upHI.d.mts +103 -0
  124. package/dist/registry/index.d.mts +11 -0
  125. package/dist/registry/index.mjs +4 -0
  126. package/dist/requestContext-xi6OKBL-.mjs +55 -0
  127. package/dist/schemaConverter-Dtg0Kt9T.mjs +98 -0
  128. package/dist/schemas/index.d.mts +63 -0
  129. package/dist/schemas/index.mjs +82 -0
  130. package/dist/scope/index.d.mts +21 -0
  131. package/dist/scope/index.mjs +65 -0
  132. package/dist/sessionManager-D_iEHjQl.d.mts +186 -0
  133. package/dist/sse-DkqQ1uxb.mjs +123 -0
  134. package/dist/testing/index.d.mts +907 -0
  135. package/dist/testing/index.mjs +1976 -0
  136. package/dist/tracing-8CEbhF0w.d.mts +70 -0
  137. package/dist/typeGuards-DwxA1t_L.mjs +9 -0
  138. package/dist/types/index.d.mts +946 -0
  139. package/dist/types/index.mjs +14 -0
  140. package/dist/types-B0dhNrnd.d.mts +445 -0
  141. package/dist/types-Beqn1Un7.mjs +38 -0
  142. package/dist/types-DelU6kln.mjs +25 -0
  143. package/dist/types-RLkFVgaw.d.mts +101 -0
  144. package/dist/utils/index.d.mts +747 -0
  145. package/dist/utils/index.mjs +6 -0
  146. package/package.json +194 -68
  147. package/dist/BaseController-DVAiHxEQ.d.ts +0 -233
  148. package/dist/adapters/index.d.ts +0 -237
  149. package/dist/adapters/index.js +0 -668
  150. package/dist/arcCorePlugin-CsShQdyP.d.ts +0 -273
  151. package/dist/audit/index.d.ts +0 -195
  152. package/dist/audit/index.js +0 -319
  153. package/dist/auth/index.d.ts +0 -47
  154. package/dist/auth/index.js +0 -174
  155. package/dist/cli/commands/docs.d.ts +0 -11
  156. package/dist/cli/commands/docs.js +0 -474
  157. package/dist/cli/commands/generate.js +0 -334
  158. package/dist/cli/commands/introspect.d.ts +0 -8
  159. package/dist/cli/commands/introspect.js +0 -338
  160. package/dist/cli/index.d.ts +0 -4
  161. package/dist/cli/index.js +0 -3269
  162. package/dist/core/index.d.ts +0 -220
  163. package/dist/core/index.js +0 -2786
  164. package/dist/createApp-Ce9wl8W9.d.ts +0 -77
  165. package/dist/docs/index.d.ts +0 -166
  166. package/dist/docs/index.js +0 -658
  167. package/dist/errors-8WIxGS_6.d.ts +0 -122
  168. package/dist/events/index.d.ts +0 -117
  169. package/dist/events/index.js +0 -89
  170. package/dist/factory/index.d.ts +0 -38
  171. package/dist/factory/index.js +0 -1652
  172. package/dist/hooks/index.d.ts +0 -4
  173. package/dist/hooks/index.js +0 -199
  174. package/dist/idempotency/index.d.ts +0 -323
  175. package/dist/idempotency/index.js +0 -500
  176. package/dist/index-B4t03KQ0.d.ts +0 -1366
  177. package/dist/index.d.ts +0 -135
  178. package/dist/index.js +0 -4756
  179. package/dist/migrations/index.d.ts +0 -185
  180. package/dist/migrations/index.js +0 -274
  181. package/dist/org/index.d.ts +0 -129
  182. package/dist/org/index.js +0 -220
  183. package/dist/permissions/index.d.ts +0 -144
  184. package/dist/permissions/index.js +0 -103
  185. package/dist/plugins/index.d.ts +0 -46
  186. package/dist/plugins/index.js +0 -1069
  187. package/dist/policies/index.js +0 -196
  188. package/dist/presets/index.js +0 -384
  189. package/dist/presets/multiTenant.d.ts +0 -39
  190. package/dist/presets/multiTenant.js +0 -112
  191. package/dist/registry/index.d.ts +0 -16
  192. package/dist/registry/index.js +0 -253
  193. package/dist/testing/index.d.ts +0 -618
  194. package/dist/testing/index.js +0 -48020
  195. package/dist/types/index.d.ts +0 -4
  196. package/dist/types/index.js +0 -8
  197. package/dist/types-B99TBmFV.d.ts +0 -76
  198. package/dist/types-BvckRbs2.d.ts +0 -143
  199. package/dist/utils/index.d.ts +0 -679
  200. package/dist/utils/index.js +0 -931
@@ -0,0 +1,143 @@
1
+ import { a as softDeletePreset, i as slugLookupPreset, n as treePreset, r as ownedByUserPreset, t as auditedPreset } from "../audited-CGdLiSlE.mjs";
2
+ import multiTenantPreset from "./multiTenant.mjs";
3
+
4
+ //#region src/presets/index.ts
5
+ /**
6
+ * Convenience alias for multiTenantPreset with public list/get routes
7
+ * Equivalent to: multiTenantPreset({ allowPublic: ['list', 'get'] })
8
+ */
9
+ const flexibleMultiTenantPreset = (options = {}) => multiTenantPreset({
10
+ ...options,
11
+ allowPublic: ["list", "get"]
12
+ });
13
+ const presetRegistry = {
14
+ softDelete: softDeletePreset,
15
+ slugLookup: slugLookupPreset,
16
+ ownedByUser: ownedByUserPreset,
17
+ multiTenant: multiTenantPreset,
18
+ tree: treePreset,
19
+ audited: auditedPreset
20
+ };
21
+ /**
22
+ * Get preset by name with options
23
+ */
24
+ function getPreset(nameOrConfig) {
25
+ if (typeof nameOrConfig === "object" && nameOrConfig.name) {
26
+ const { name, ...options } = nameOrConfig;
27
+ return resolvePreset(name, options);
28
+ }
29
+ return resolvePreset(nameOrConfig);
30
+ }
31
+ /**
32
+ * Resolve preset by name
33
+ */
34
+ function resolvePreset(name, options = {}) {
35
+ const factory = presetRegistry[name];
36
+ if (!factory) {
37
+ const available = Object.keys(presetRegistry).join(", ");
38
+ throw new Error(`Unknown preset: '${name}'\nAvailable presets: ${available}\nDocs: https://github.com/classytic/arc#presets`);
39
+ }
40
+ return factory(options);
41
+ }
42
+ /**
43
+ * Register a custom preset
44
+ */
45
+ function registerPreset(name, factory, options) {
46
+ if (presetRegistry[name] && !options?.override) throw new Error(`Preset '${name}' already exists. Pass { override: true } to replace.`);
47
+ presetRegistry[name] = factory;
48
+ }
49
+ /**
50
+ * Get all available preset names
51
+ */
52
+ function getAvailablePresets() {
53
+ return Object.keys(presetRegistry);
54
+ }
55
+ /**
56
+ * Validate that preset combinations don't conflict.
57
+ * Detects route collisions (same method + path from different presets).
58
+ */
59
+ function validatePresetCombination(presets) {
60
+ const conflicts = [];
61
+ const routeMap = /* @__PURE__ */ new Map();
62
+ for (const preset of presets) {
63
+ const name = preset.name ?? "unknown";
64
+ const routes = typeof preset.additionalRoutes === "function" ? preset.additionalRoutes({}) : preset.additionalRoutes ?? [];
65
+ for (const route of routes) {
66
+ const key = `${route.method} ${route.path}`;
67
+ const existing = routeMap.get(key);
68
+ if (existing) conflicts.push({
69
+ presets: [existing, name],
70
+ message: `Both '${existing}' and '${name}' define route ${key}`,
71
+ severity: "error"
72
+ });
73
+ routeMap.set(key, name);
74
+ }
75
+ }
76
+ return conflicts;
77
+ }
78
+ /**
79
+ * Apply presets to resource config.
80
+ * Validates preset combinations for conflicts before merging.
81
+ */
82
+ function applyPresets(config, presets = []) {
83
+ let result = { ...config };
84
+ const resolved = presets.map(resolvePresetInput);
85
+ const errors = validatePresetCombination(resolved).filter((c) => c.severity === "error");
86
+ if (errors.length > 0) throw new Error(`[Arc] Resource '${config.name}' preset conflicts:\n` + errors.map((c) => ` - ${c.message}`).join("\n"));
87
+ for (const preset of resolved) result = mergePreset(result, preset);
88
+ return result;
89
+ }
90
+ /**
91
+ * Resolve preset input to PresetResult
92
+ */
93
+ function resolvePresetInput(preset) {
94
+ if (typeof preset === "object" && ("middlewares" in preset || "additionalRoutes" in preset)) return preset;
95
+ if (typeof preset === "object" && "name" in preset) {
96
+ const { name, ...options } = preset;
97
+ return resolvePreset(name, options);
98
+ }
99
+ return resolvePreset(preset);
100
+ }
101
+ /**
102
+ * Merge preset into config
103
+ */
104
+ function mergePreset(config, preset) {
105
+ const result = { ...config };
106
+ if (preset.additionalRoutes) {
107
+ const routes = typeof preset.additionalRoutes === "function" ? preset.additionalRoutes(config.permissions ?? {}) : preset.additionalRoutes;
108
+ result.additionalRoutes = [...result.additionalRoutes ?? [], ...routes];
109
+ }
110
+ if (preset.middlewares) {
111
+ result.middlewares = result.middlewares ?? {};
112
+ for (const [op, mws] of Object.entries(preset.middlewares)) {
113
+ const key = op;
114
+ result.middlewares[key] = [...result.middlewares[key] ?? [], ...mws ?? []];
115
+ }
116
+ }
117
+ if (preset.schemaOptions) result.schemaOptions = {
118
+ ...result.schemaOptions,
119
+ ...preset.schemaOptions,
120
+ fieldRules: {
121
+ ...result.schemaOptions?.fieldRules,
122
+ ...preset.schemaOptions?.fieldRules
123
+ }
124
+ };
125
+ if (preset.controllerOptions) result._controllerOptions = {
126
+ ...result._controllerOptions,
127
+ ...preset.controllerOptions
128
+ };
129
+ if (preset.hooks && preset.hooks.length > 0) {
130
+ result._hooks = result._hooks ?? [];
131
+ for (const hook of preset.hooks) result._hooks.push({
132
+ presetName: preset.name,
133
+ operation: hook.operation,
134
+ phase: hook.phase,
135
+ handler: hook.handler,
136
+ priority: hook.priority
137
+ });
138
+ }
139
+ return result;
140
+ }
141
+
142
+ //#endregion
143
+ export { applyPresets, auditedPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, slugLookupPreset, softDeletePreset, treePreset };
@@ -0,0 +1,24 @@
1
+ import "../elevation-DGo5shaX.mjs";
2
+ import "../interface-e9XfSsUV.mjs";
3
+ import "../types-RLkFVgaw.mjs";
4
+ import { CrudRouteKey, PresetResult } from "../types/index.mjs";
5
+
6
+ //#region src/presets/multiTenant.d.ts
7
+ interface MultiTenantOptions {
8
+ /** Field name in database (default: 'organizationId') */
9
+ tenantField?: string;
10
+ /**
11
+ * Routes that allow public access (no auth required)
12
+ * When a route is in this array:
13
+ * - If no org context: allow through without filtering (public data)
14
+ * - If org context present: require auth and apply filter
15
+ *
16
+ * @default [] (strict mode - all routes require auth)
17
+ * @example
18
+ * multiTenantPreset({ allowPublic: ['list', 'get'] })
19
+ */
20
+ allowPublic?: CrudRouteKey[];
21
+ }
22
+ declare function multiTenantPreset(options?: MultiTenantOptions): PresetResult;
23
+ //#endregion
24
+ export { MultiTenantOptions, multiTenantPreset as default, multiTenantPreset };
@@ -0,0 +1,113 @@
1
+ import { o as DEFAULT_TENANT_FIELD } from "../constants-DdXFXQtN.mjs";
2
+ import { c as isElevated, l as isMember, n as PUBLIC_SCOPE, r as getOrgId } from "../types-Beqn1Un7.mjs";
3
+
4
+ //#region src/presets/multiTenant.ts
5
+ /** Read request.scope safely */
6
+ function getScope(request) {
7
+ return request.scope ?? PUBLIC_SCOPE;
8
+ }
9
+ /**
10
+ * Create tenant filter middleware
11
+ * Adds tenant filter to query for list/get operations.
12
+ * Reads `request.scope` for org context and elevation bypass.
13
+ */
14
+ function createTenantFilter(tenantField) {
15
+ return async (request, reply) => {
16
+ const scope = getScope(request);
17
+ if (isElevated(scope)) {
18
+ const orgId = getOrgId(scope);
19
+ if (orgId) request._policyFilters = {
20
+ ...request._policyFilters ?? {},
21
+ [tenantField]: orgId
22
+ };
23
+ return;
24
+ }
25
+ if (isMember(scope)) {
26
+ request._policyFilters = {
27
+ ...request._policyFilters ?? {},
28
+ [tenantField]: scope.organizationId
29
+ };
30
+ return;
31
+ }
32
+ if (scope.kind === "public") {
33
+ reply.code(401).send({
34
+ success: false,
35
+ error: "Unauthorized",
36
+ message: "Authentication required for multi-tenant resources"
37
+ });
38
+ return;
39
+ }
40
+ reply.code(403).send({
41
+ success: false,
42
+ error: "Forbidden",
43
+ message: "Organization context required for this operation"
44
+ });
45
+ };
46
+ }
47
+ /**
48
+ * Create flexible tenant filter middleware
49
+ * For routes in allowPublic: only filter when org context is present
50
+ * No org context = allow through (public data)
51
+ * Org context present = require auth and apply filter
52
+ */
53
+ function createFlexibleTenantFilter(tenantField) {
54
+ return async (request, reply) => {
55
+ const scope = getScope(request);
56
+ if (isElevated(scope)) {
57
+ const orgId = getOrgId(scope);
58
+ if (orgId) request._policyFilters = {
59
+ ...request._policyFilters ?? {},
60
+ [tenantField]: orgId
61
+ };
62
+ return;
63
+ }
64
+ if (isMember(scope)) {
65
+ request._policyFilters = {
66
+ ...request._policyFilters ?? {},
67
+ [tenantField]: scope.organizationId
68
+ };
69
+ return;
70
+ }
71
+ };
72
+ }
73
+ /**
74
+ * Create tenant injection middleware
75
+ * Injects tenant ID into request body on create.
76
+ * Reads `request.scope` for org context.
77
+ */
78
+ function createTenantInjection(tenantField) {
79
+ return async (request, reply) => {
80
+ const scope = getScope(request);
81
+ const orgId = getOrgId(scope);
82
+ if (isElevated(scope) && !orgId) return;
83
+ if (!orgId) {
84
+ reply.code(403).send({
85
+ success: false,
86
+ error: "Forbidden",
87
+ message: "Organization context required to create resources"
88
+ });
89
+ return;
90
+ }
91
+ if (request.body) request.body[tenantField] = orgId;
92
+ };
93
+ }
94
+ function multiTenantPreset(options = {}) {
95
+ const { tenantField = DEFAULT_TENANT_FIELD, allowPublic = [] } = options;
96
+ const strictTenantFilter = createTenantFilter(tenantField);
97
+ const flexibleTenantFilter = createFlexibleTenantFilter(tenantField);
98
+ const tenantInjection = createTenantInjection(tenantField);
99
+ const getFilter = (route) => allowPublic.includes(route) ? flexibleTenantFilter : strictTenantFilter;
100
+ return {
101
+ name: "multiTenant",
102
+ middlewares: {
103
+ list: [getFilter("list")],
104
+ get: [getFilter("get")],
105
+ create: [tenantInjection],
106
+ update: [getFilter("update")],
107
+ delete: [getFilter("delete")]
108
+ }
109
+ };
110
+ }
111
+
112
+ //#endregion
113
+ export { multiTenantPreset as default, multiTenantPreset };
@@ -0,0 +1,57 @@
1
+ import { t as PermissionCheck } from "./types-RLkFVgaw.mjs";
2
+
3
+ //#region src/permissions/presets.d.ts
4
+ declare namespace presets_d_exports {
5
+ export { adminOnly, authenticated, fullPublic, ownerWithAdminBypass, publicRead, publicReadAdminWrite, readOnly };
6
+ }
7
+ /**
8
+ * ResourcePermissions shape — matches the type in types/index.ts
9
+ */
10
+ interface ResourcePermissions<TDoc = any> {
11
+ list?: PermissionCheck<TDoc>;
12
+ get?: PermissionCheck<TDoc>;
13
+ create?: PermissionCheck<TDoc>;
14
+ update?: PermissionCheck<TDoc>;
15
+ delete?: PermissionCheck<TDoc>;
16
+ }
17
+ type PermissionOverrides<TDoc = any> = Partial<ResourcePermissions<TDoc>>;
18
+ /**
19
+ * Public read, authenticated write.
20
+ * list + get = allowPublic(), create + update + delete = requireAuth()
21
+ */
22
+ declare function publicRead<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
23
+ /**
24
+ * Public read, admin write.
25
+ * list + get = allowPublic(), create + update + delete = requireRoles(['admin'])
26
+ */
27
+ declare function publicReadAdminWrite<TDoc = any>(roles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
28
+ /**
29
+ * All operations require authentication.
30
+ */
31
+ declare function authenticated<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
32
+ /**
33
+ * All operations require specific roles.
34
+ * @param roles - Required roles (user needs at least one). Default: ['admin']
35
+ */
36
+ declare function adminOnly<TDoc = any>(roles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
37
+ /**
38
+ * Owner-scoped with admin bypass.
39
+ * list = auth (scoped to owner), get = auth, create = auth,
40
+ * update + delete = ownership check with admin bypass.
41
+ *
42
+ * @param ownerField - Field containing owner ID (default: 'userId')
43
+ * @param bypassRoles - Roles that bypass ownership check (default: ['admin'])
44
+ */
45
+ declare function ownerWithAdminBypass<TDoc = any>(ownerField?: Extract<keyof TDoc, string> | string, bypassRoles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
46
+ /**
47
+ * Full public access — no auth required for any operation.
48
+ * Use sparingly (dev/testing, truly public APIs).
49
+ */
50
+ declare function fullPublic<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
51
+ /**
52
+ * Read-only: list + get authenticated, write operations denied.
53
+ * Useful for computed/derived resources.
54
+ */
55
+ declare function readOnly<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
56
+ //#endregion
57
+ export { presets_d_exports as a, readOnly as c, ownerWithAdminBypass as i, authenticated as n, publicRead as o, fullPublic as r, publicReadAdminWrite as s, adminOnly as t };
@@ -0,0 +1,119 @@
1
+ import { t as __exportAll } from "./chunk-C7Uep-_p.mjs";
2
+ import { allowPublic, anyOf, requireAuth, requireOwnership, requireRoles } from "./permissions/index.mjs";
3
+
4
+ //#region src/permissions/presets.ts
5
+ var presets_exports = /* @__PURE__ */ __exportAll({
6
+ adminOnly: () => adminOnly,
7
+ authenticated: () => authenticated,
8
+ fullPublic: () => fullPublic,
9
+ ownerWithAdminBypass: () => ownerWithAdminBypass,
10
+ publicRead: () => publicRead,
11
+ publicReadAdminWrite: () => publicReadAdminWrite,
12
+ readOnly: () => readOnly
13
+ });
14
+ /**
15
+ * Merge a base preset with user overrides.
16
+ * Overrides replace individual operations — undefined values don't clear them.
17
+ */
18
+ function withOverrides(base, overrides) {
19
+ if (!overrides) return base;
20
+ const filtered = Object.fromEntries(Object.entries(overrides).filter(([, v]) => v !== void 0));
21
+ return {
22
+ ...base,
23
+ ...filtered
24
+ };
25
+ }
26
+ /**
27
+ * Public read, authenticated write.
28
+ * list + get = allowPublic(), create + update + delete = requireAuth()
29
+ */
30
+ function publicRead(overrides) {
31
+ return withOverrides({
32
+ list: allowPublic(),
33
+ get: allowPublic(),
34
+ create: requireAuth(),
35
+ update: requireAuth(),
36
+ delete: requireAuth()
37
+ }, overrides);
38
+ }
39
+ /**
40
+ * Public read, admin write.
41
+ * list + get = allowPublic(), create + update + delete = requireRoles(['admin'])
42
+ */
43
+ function publicReadAdminWrite(roles = ["admin"], overrides) {
44
+ return withOverrides({
45
+ list: allowPublic(),
46
+ get: allowPublic(),
47
+ create: requireRoles(roles),
48
+ update: requireRoles(roles),
49
+ delete: requireRoles(roles)
50
+ }, overrides);
51
+ }
52
+ /**
53
+ * All operations require authentication.
54
+ */
55
+ function authenticated(overrides) {
56
+ return withOverrides({
57
+ list: requireAuth(),
58
+ get: requireAuth(),
59
+ create: requireAuth(),
60
+ update: requireAuth(),
61
+ delete: requireAuth()
62
+ }, overrides);
63
+ }
64
+ /**
65
+ * All operations require specific roles.
66
+ * @param roles - Required roles (user needs at least one). Default: ['admin']
67
+ */
68
+ function adminOnly(roles = ["admin"], overrides) {
69
+ return withOverrides({
70
+ list: requireRoles(roles),
71
+ get: requireRoles(roles),
72
+ create: requireRoles(roles),
73
+ update: requireRoles(roles),
74
+ delete: requireRoles(roles)
75
+ }, overrides);
76
+ }
77
+ /**
78
+ * Owner-scoped with admin bypass.
79
+ * list = auth (scoped to owner), get = auth, create = auth,
80
+ * update + delete = ownership check with admin bypass.
81
+ *
82
+ * @param ownerField - Field containing owner ID (default: 'userId')
83
+ * @param bypassRoles - Roles that bypass ownership check (default: ['admin'])
84
+ */
85
+ function ownerWithAdminBypass(ownerField = "userId", bypassRoles = ["admin"], overrides) {
86
+ return withOverrides({
87
+ list: requireAuth(),
88
+ get: requireAuth(),
89
+ create: requireAuth(),
90
+ update: anyOf(requireRoles(bypassRoles), requireOwnership(ownerField)),
91
+ delete: anyOf(requireRoles(bypassRoles), requireOwnership(ownerField))
92
+ }, overrides);
93
+ }
94
+ /**
95
+ * Full public access — no auth required for any operation.
96
+ * Use sparingly (dev/testing, truly public APIs).
97
+ */
98
+ function fullPublic(overrides) {
99
+ return withOverrides({
100
+ list: allowPublic(),
101
+ get: allowPublic(),
102
+ create: allowPublic(),
103
+ update: allowPublic(),
104
+ delete: allowPublic()
105
+ }, overrides);
106
+ }
107
+ /**
108
+ * Read-only: list + get authenticated, write operations denied.
109
+ * Useful for computed/derived resources.
110
+ */
111
+ function readOnly(overrides) {
112
+ return withOverrides({
113
+ list: requireAuth(),
114
+ get: requireAuth()
115
+ }, overrides);
116
+ }
117
+
118
+ //#endregion
119
+ export { presets_exports as a, readOnly as c, ownerWithAdminBypass as i, authenticated as n, publicRead as o, fullPublic as r, publicReadAdminWrite as s, adminOnly as t };