hono-crud 0.3.2 → 0.4.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.
- package/CHANGELOG.md +2 -0
- package/dist/adapters/drizzle/index.d.ts +18 -30
- package/dist/adapters/drizzle/index.js +12 -39
- package/dist/adapters/memory/index.d.ts +2 -2
- package/dist/adapters/memory/index.js +2 -2
- package/dist/adapters/prisma/index.d.ts +1 -1
- package/dist/adapters/prisma/index.js +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/{bulk-patch-B6j0q_p_.d.ts → bulk-patch-f4TR8L-q.d.ts} +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/{chunk-KP4HGONO.js → chunk-57J3NJYN.js} +5 -13
- package/dist/{chunk-G7OXZ24G.js → chunk-G7IQ5DWC.js} +1 -1
- package/dist/{chunk-IPGNLIJV.js → chunk-I36Y45QN.js} +1 -1
- package/dist/{chunk-LCRNKT65.js → chunk-T6J4NSMC.js} +48 -5
- package/dist/{chunk-WOFE46VS.js → chunk-Y74QJH7Y.js} +25 -19
- package/dist/{import-B7KS4Wvh.d.ts → import-BZ05PJMa.d.ts} +11 -0
- package/dist/{index-Dm8-ODYA.d.ts → index-431Ovi2o.d.ts} +2 -2
- package/dist/{index-5BEg0ty5.d.ts → index-bSnRLgcs.d.ts} +1 -1
- package/dist/index.d.ts +25 -10
- package/dist/index.js +109 -32
- package/dist/logging/index.d.ts +4 -4
- package/dist/logging/index.js +2 -2
- package/dist/rate-limit/index.d.ts +2 -2
- package/dist/rate-limit/index.js +1 -1
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.js +1 -1
- package/dist/{types-Bc7ebF5x.d.ts → types-BO3G_MZk.d.ts} +2 -2
- package/dist/{types-B8CWg4nO.d.ts → types-DnQWCfXp.d.ts} +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
13
13
|
%b
|
|
14
14
|
%b
|
|
15
15
|
%b
|
|
16
|
+
%b
|
|
16
17
|
## [0.1.0] - 2025-01-29
|
|
17
18
|
|
|
18
19
|
### Added
|
|
@@ -42,3 +43,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
42
43
|
[0.3.0]: https://github.com/kshdotdev/hono-crud/compare/v0.2.0...v0.3.0
|
|
43
44
|
[0.3.1]: https://github.com/kshdotdev/hono-crud/compare/v0.3.0...v0.3.1
|
|
44
45
|
[0.3.2]: https://github.com/kshdotdev/hono-crud/compare/v0.3.1...v0.3.2
|
|
46
|
+
[0.4.0]: https://github.com/kshdotdev/hono-crud/compare/v0.3.2...v0.4.0
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Table, SQL, Column } from 'drizzle-orm';
|
|
2
2
|
import { M as MetaInput, I as IncludeOptions, F as FilterCondition, g as RelationConfig, h as NestedUpdateInput, i as NestedWriteResult, L as ListFilters, P as PaginatedResult, j as AggregateOptions, k as AggregateResult, S as SearchOptions, l as SearchResult } from '../../types-CA784ZtV.js';
|
|
3
3
|
import { Env } from 'hono';
|
|
4
|
-
import { C as CreateEndpoint, M as ModelObject, R as ReadEndpoint, U as UpdateEndpoint, D as DeleteEndpoint, L as ListEndpoint, a as RestoreEndpoint, B as BatchCreateEndpoint, b as BatchDeleteEndpoint, c as BatchRestoreEndpoint, d as BatchUpdateEndpoint, e as BatchUpdateItem, A as AggregateEndpoint, f as BatchUpsertEndpoint, g as UpsertEndpoint, E as ExportEndpoint, I as ImportEndpoint, S as SearchEndpoint, V as VersionCompareEndpoint, h as VersionHistoryEndpoint, i as VersionReadEndpoint, j as VersionRollbackEndpoint } from '../../import-
|
|
5
|
-
import { A as AdapterBundle } from '../../index-
|
|
4
|
+
import { C as CreateEndpoint, M as ModelObject, R as ReadEndpoint, U as UpdateEndpoint, D as DeleteEndpoint, L as ListEndpoint, a as RestoreEndpoint, B as BatchCreateEndpoint, b as BatchDeleteEndpoint, c as BatchRestoreEndpoint, d as BatchUpdateEndpoint, e as BatchUpdateItem, A as AggregateEndpoint, f as BatchUpsertEndpoint, g as UpsertEndpoint, E as ExportEndpoint, I as ImportEndpoint, S as SearchEndpoint, V as VersionCompareEndpoint, h as VersionHistoryEndpoint, i as VersionReadEndpoint, j as VersionRollbackEndpoint } from '../../import-BZ05PJMa.js';
|
|
5
|
+
import { A as AdapterBundle } from '../../index-bSnRLgcs.js';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import '@hono/zod-openapi';
|
|
8
8
|
import '../../route-DwSID3du.js';
|
|
@@ -731,7 +731,7 @@ declare const DrizzleAdapters: AdapterBundle;
|
|
|
731
731
|
* createdAt: timestamp('created_at').defaultNow(),
|
|
732
732
|
* });
|
|
733
733
|
*
|
|
734
|
-
* const { select: UserSchema, insert: CreateUserSchema } = createDrizzleSchemas(users);
|
|
734
|
+
* const { select: UserSchema, insert: CreateUserSchema } = await createDrizzleSchemas(users);
|
|
735
735
|
* ```
|
|
736
736
|
*/
|
|
737
737
|
|
|
@@ -751,36 +751,36 @@ type DrizzleTable = {
|
|
|
751
751
|
*
|
|
752
752
|
* @param table - Drizzle table definition
|
|
753
753
|
* @param refine - Optional refinements for specific columns
|
|
754
|
-
* @returns Zod schema for the table's select type
|
|
754
|
+
* @returns Promise resolving to a Zod schema for the table's select type
|
|
755
755
|
*
|
|
756
756
|
* @example
|
|
757
757
|
* ```ts
|
|
758
758
|
* import { users } from './schema';
|
|
759
759
|
* import { createSelectSchema } from 'hono-crud/adapters/drizzle';
|
|
760
760
|
*
|
|
761
|
-
* const UserSchema = createSelectSchema(users);
|
|
761
|
+
* const UserSchema = await createSelectSchema(users);
|
|
762
762
|
* type User = z.infer<typeof UserSchema>;
|
|
763
763
|
* ```
|
|
764
764
|
*/
|
|
765
|
-
declare function createSelectSchema<T extends DrizzleTable>(table: T, refine?: Record<string, z.ZodTypeAny>): z.ZodObject<Record<string, z.ZodTypeAny
|
|
765
|
+
declare function createSelectSchema<T extends DrizzleTable>(table: T, refine?: Record<string, z.ZodTypeAny>): Promise<z.ZodObject<Record<string, z.ZodTypeAny>>>;
|
|
766
766
|
/**
|
|
767
767
|
* Re-export createInsertSchema from drizzle-zod.
|
|
768
768
|
* Creates a Zod schema for INSERT queries (columns with defaults become optional).
|
|
769
769
|
*
|
|
770
770
|
* @param table - Drizzle table definition
|
|
771
771
|
* @param refine - Optional refinements for specific columns
|
|
772
|
-
* @returns Zod schema for the table's insert type
|
|
772
|
+
* @returns Promise resolving to a Zod schema for the table's insert type
|
|
773
773
|
*
|
|
774
774
|
* @example
|
|
775
775
|
* ```ts
|
|
776
776
|
* import { users } from './schema';
|
|
777
777
|
* import { createInsertSchema } from 'hono-crud/adapters/drizzle';
|
|
778
778
|
*
|
|
779
|
-
* const CreateUserSchema = createInsertSchema(users);
|
|
779
|
+
* const CreateUserSchema = await createInsertSchema(users);
|
|
780
780
|
* type CreateUser = z.infer<typeof CreateUserSchema>;
|
|
781
781
|
* ```
|
|
782
782
|
*/
|
|
783
|
-
declare function createInsertSchema<T extends DrizzleTable>(table: T, refine?: Record<string, z.ZodTypeAny>): z.ZodObject<Record<string, z.ZodTypeAny
|
|
783
|
+
declare function createInsertSchema<T extends DrizzleTable>(table: T, refine?: Record<string, z.ZodTypeAny>): Promise<z.ZodObject<Record<string, z.ZodTypeAny>>>;
|
|
784
784
|
/**
|
|
785
785
|
* Re-export createUpdateSchema from drizzle-zod (if available).
|
|
786
786
|
* Creates a Zod schema for UPDATE queries (all columns become optional).
|
|
@@ -790,18 +790,18 @@ declare function createInsertSchema<T extends DrizzleTable>(table: T, refine?: R
|
|
|
790
790
|
*
|
|
791
791
|
* @param table - Drizzle table definition
|
|
792
792
|
* @param refine - Optional refinements for specific columns
|
|
793
|
-
* @returns Zod schema for the table's update type
|
|
793
|
+
* @returns Promise resolving to a Zod schema for the table's update type
|
|
794
794
|
*
|
|
795
795
|
* @example
|
|
796
796
|
* ```ts
|
|
797
797
|
* import { users } from './schema';
|
|
798
798
|
* import { createUpdateSchema } from 'hono-crud/adapters/drizzle';
|
|
799
799
|
*
|
|
800
|
-
* const UpdateUserSchema = createUpdateSchema(users);
|
|
800
|
+
* const UpdateUserSchema = await createUpdateSchema(users);
|
|
801
801
|
* type UpdateUser = z.infer<typeof UpdateUserSchema>;
|
|
802
802
|
* ```
|
|
803
803
|
*/
|
|
804
|
-
declare function createUpdateSchema<T extends DrizzleTable>(table: T, refine?: Record<string, z.ZodTypeAny>): z.ZodObject<Record<string, z.ZodTypeAny
|
|
804
|
+
declare function createUpdateSchema<T extends DrizzleTable>(table: T, refine?: Record<string, z.ZodTypeAny>): Promise<z.ZodObject<Record<string, z.ZodTypeAny>>>;
|
|
805
805
|
/**
|
|
806
806
|
* Result of createDrizzleSchemas helper.
|
|
807
807
|
*/
|
|
@@ -830,7 +830,7 @@ interface DrizzleSchemas {
|
|
|
830
830
|
* @param options.selectRefine - Refinements for select schema
|
|
831
831
|
* @param options.updateRefine - Refinements for update schema
|
|
832
832
|
* @param options.coerceDates - Whether to coerce date strings to Date objects (default: true)
|
|
833
|
-
* @returns
|
|
833
|
+
* @returns Promise resolving to object containing select, insert, and update schemas
|
|
834
834
|
*
|
|
835
835
|
* @example
|
|
836
836
|
* ```ts
|
|
@@ -845,7 +845,7 @@ interface DrizzleSchemas {
|
|
|
845
845
|
* });
|
|
846
846
|
*
|
|
847
847
|
* // Generate schemas from table
|
|
848
|
-
* const schemas = createDrizzleSchemas(users, {
|
|
848
|
+
* const schemas = await createDrizzleSchemas(users, {
|
|
849
849
|
* insertRefine: {
|
|
850
850
|
* email: z.string().email(), // Add email validation
|
|
851
851
|
* },
|
|
@@ -866,24 +866,12 @@ declare function createDrizzleSchemas<T extends DrizzleTable>(table: T, options?
|
|
|
866
866
|
updateRefine?: Record<string, z.ZodTypeAny>;
|
|
867
867
|
/** Whether to coerce date strings to Date objects. Default: true */
|
|
868
868
|
coerceDates?: boolean;
|
|
869
|
-
}): DrizzleSchemas;
|
|
870
|
-
/**
|
|
871
|
-
* Async version of createDrizzleSchemas that handles lazy loading.
|
|
872
|
-
* Use this if you're not sure drizzle-zod is already loaded.
|
|
873
|
-
*
|
|
874
|
-
* @param table - Drizzle table definition
|
|
875
|
-
* @param options - Optional configuration
|
|
876
|
-
* @returns Promise resolving to schemas object
|
|
877
|
-
*/
|
|
878
|
-
declare function createDrizzleSchemasAsync<T extends DrizzleTable>(table: T, options?: {
|
|
879
|
-
insertRefine?: Record<string, z.ZodTypeAny>;
|
|
880
|
-
selectRefine?: Record<string, z.ZodTypeAny>;
|
|
881
|
-
updateRefine?: Record<string, z.ZodTypeAny>;
|
|
882
869
|
}): Promise<DrizzleSchemas>;
|
|
883
870
|
/**
|
|
884
|
-
* Checks if drizzle-zod is available.
|
|
885
|
-
*
|
|
871
|
+
* Checks if drizzle-zod is available (from cache only).
|
|
872
|
+
* Returns true only if drizzle-zod has been successfully loaded before.
|
|
873
|
+
* @returns true if drizzle-zod has been loaded
|
|
886
874
|
*/
|
|
887
875
|
declare function isDrizzleZodAvailable(): boolean;
|
|
888
876
|
|
|
889
|
-
export { type Database, DrizzleAdapters, DrizzleAggregateEndpoint, DrizzleBatchCreateEndpoint, DrizzleBatchDeleteEndpoint, DrizzleBatchRestoreEndpoint, DrizzleBatchUpdateEndpoint, DrizzleBatchUpsertEndpoint, DrizzleCreateEndpoint, type DrizzleCrudClasses, type DrizzleDB, type DrizzleDatabase, type DrizzleDatabaseConstraint, DrizzleDeleteEndpoint, type DrizzleEnv, DrizzleExportEndpoint, DrizzleImportEndpoint, DrizzleListEndpoint, DrizzleReadEndpoint, DrizzleRestoreEndpoint, type DrizzleSchemas, DrizzleSearchEndpoint, DrizzleUpdateEndpoint, DrizzleUpsertEndpoint, DrizzleVersionCompareEndpoint, DrizzleVersionHistoryEndpoint, DrizzleVersionReadEndpoint, DrizzleVersionRollbackEndpoint, type QueryBuilder, batchLoadDrizzleRelations, buildWhereCondition, cast, createDrizzleCrud, createDrizzleSchemas,
|
|
877
|
+
export { type Database, DrizzleAdapters, DrizzleAggregateEndpoint, DrizzleBatchCreateEndpoint, DrizzleBatchDeleteEndpoint, DrizzleBatchRestoreEndpoint, DrizzleBatchUpdateEndpoint, DrizzleBatchUpsertEndpoint, DrizzleCreateEndpoint, type DrizzleCrudClasses, type DrizzleDB, type DrizzleDatabase, type DrizzleDatabaseConstraint, DrizzleDeleteEndpoint, type DrizzleEnv, DrizzleExportEndpoint, DrizzleImportEndpoint, DrizzleListEndpoint, DrizzleReadEndpoint, DrizzleRestoreEndpoint, type DrizzleSchemas, DrizzleSearchEndpoint, DrizzleUpdateEndpoint, DrizzleUpsertEndpoint, DrizzleVersionCompareEndpoint, DrizzleVersionHistoryEndpoint, DrizzleVersionReadEndpoint, DrizzleVersionRollbackEndpoint, type QueryBuilder, batchLoadDrizzleRelations, buildWhereCondition, cast, createDrizzleCrud, createDrizzleSchemas, createInsertSchema, createSelectSchema, createUpdateSchema, getColumn, getTable, isDrizzleZodAvailable, loadDrizzleRelation, loadDrizzleRelations };
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { CreateEndpoint, ReadEndpoint, UpdateEndpoint, DeleteEndpoint, ListEndpoint, RestoreEndpoint, BatchCreateEndpoint, BatchUpdateEndpoint, BatchDeleteEndpoint, BatchRestoreEndpoint, UpsertEndpoint, BatchUpsertEndpoint, VersionHistoryEndpoint, VersionReadEndpoint, VersionCompareEndpoint, VersionRollbackEndpoint, AggregateEndpoint, computeAggregations, SearchEndpoint, searchInMemory, ExportEndpoint, ImportEndpoint } from '../../chunk-
|
|
1
|
+
import { CreateEndpoint, ReadEndpoint, UpdateEndpoint, DeleteEndpoint, ListEndpoint, RestoreEndpoint, BatchCreateEndpoint, BatchUpdateEndpoint, BatchDeleteEndpoint, BatchRestoreEndpoint, UpsertEndpoint, BatchUpsertEndpoint, VersionHistoryEndpoint, VersionReadEndpoint, VersionCompareEndpoint, VersionRollbackEndpoint, AggregateEndpoint, computeAggregations, SearchEndpoint, searchInMemory, ExportEndpoint, ImportEndpoint } from '../../chunk-T6J4NSMC.js';
|
|
2
2
|
import '../../chunk-CDCGYMC6.js';
|
|
3
3
|
import '../../chunk-U3SUUXJK.js';
|
|
4
4
|
import { getLogger } from '../../chunk-FST5S5UY.js';
|
|
5
5
|
import { getTableColumns, eq, inArray, between, isNull, isNotNull, ilike, like, notInArray, lte, lt, gte, gt, ne, and, sql, or, desc, asc } from 'drizzle-orm';
|
|
6
6
|
import { z } from 'zod';
|
|
7
|
-
import { createRequire } from 'module';
|
|
8
7
|
|
|
9
8
|
function cast(instance) {
|
|
10
9
|
return instance;
|
|
@@ -1520,27 +1519,10 @@ var DrizzleAdapters = {
|
|
|
1520
1519
|
UpdateEndpoint: DrizzleUpdateEndpoint,
|
|
1521
1520
|
DeleteEndpoint: DrizzleDeleteEndpoint
|
|
1522
1521
|
};
|
|
1523
|
-
var require2 = createRequire(import.meta.url);
|
|
1524
1522
|
var _drizzleZod = null;
|
|
1525
1523
|
var _loadAttempted = false;
|
|
1526
1524
|
var _loadError = null;
|
|
1527
|
-
function
|
|
1528
|
-
if (_loadAttempted) {
|
|
1529
|
-
if (_loadError) throw _loadError;
|
|
1530
|
-
return _drizzleZod;
|
|
1531
|
-
}
|
|
1532
|
-
_loadAttempted = true;
|
|
1533
|
-
try {
|
|
1534
|
-
_drizzleZod = require2("drizzle-zod");
|
|
1535
|
-
return _drizzleZod;
|
|
1536
|
-
} catch {
|
|
1537
|
-
_loadError = new Error(
|
|
1538
|
-
"drizzle-zod is not installed. Please install it: npm install drizzle-zod"
|
|
1539
|
-
);
|
|
1540
|
-
throw _loadError;
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
async function loadDrizzleZodAsync() {
|
|
1525
|
+
async function ensureDrizzleZod() {
|
|
1544
1526
|
if (_loadAttempted) {
|
|
1545
1527
|
if (_loadError) throw _loadError;
|
|
1546
1528
|
return _drizzleZod;
|
|
@@ -1556,24 +1538,24 @@ async function loadDrizzleZodAsync() {
|
|
|
1556
1538
|
throw _loadError;
|
|
1557
1539
|
}
|
|
1558
1540
|
}
|
|
1559
|
-
function createSelectSchema(table, refine) {
|
|
1560
|
-
const drizzleZod =
|
|
1541
|
+
async function createSelectSchema(table, refine) {
|
|
1542
|
+
const drizzleZod = await ensureDrizzleZod();
|
|
1561
1543
|
return drizzleZod.createSelectSchema(table, refine);
|
|
1562
1544
|
}
|
|
1563
|
-
function createInsertSchema(table, refine) {
|
|
1564
|
-
const drizzleZod =
|
|
1545
|
+
async function createInsertSchema(table, refine) {
|
|
1546
|
+
const drizzleZod = await ensureDrizzleZod();
|
|
1565
1547
|
return drizzleZod.createInsertSchema(table, refine);
|
|
1566
1548
|
}
|
|
1567
|
-
function createUpdateSchema(table, refine) {
|
|
1568
|
-
const drizzleZod =
|
|
1549
|
+
async function createUpdateSchema(table, refine) {
|
|
1550
|
+
const drizzleZod = await ensureDrizzleZod();
|
|
1569
1551
|
if (drizzleZod.createUpdateSchema) {
|
|
1570
1552
|
return drizzleZod.createUpdateSchema(table, refine);
|
|
1571
1553
|
}
|
|
1572
1554
|
const insertSchema = drizzleZod.createInsertSchema(table, refine);
|
|
1573
1555
|
return insertSchema.partial();
|
|
1574
1556
|
}
|
|
1575
|
-
function createDrizzleSchemas(table, options) {
|
|
1576
|
-
const drizzleZod =
|
|
1557
|
+
async function createDrizzleSchemas(table, options) {
|
|
1558
|
+
const drizzleZod = await ensureDrizzleZod();
|
|
1577
1559
|
const shouldCoerceDates = options?.coerceDates !== false;
|
|
1578
1560
|
const dateColumns = shouldCoerceDates ? getDateColumns(table) : /* @__PURE__ */ new Set();
|
|
1579
1561
|
const select = drizzleZod.createSelectSchema(table, options?.selectRefine);
|
|
@@ -1590,17 +1572,8 @@ function createDrizzleSchemas(table, options) {
|
|
|
1590
1572
|
}
|
|
1591
1573
|
return { select, insert, update };
|
|
1592
1574
|
}
|
|
1593
|
-
async function createDrizzleSchemasAsync(table, options) {
|
|
1594
|
-
await loadDrizzleZodAsync();
|
|
1595
|
-
return createDrizzleSchemas(table, options);
|
|
1596
|
-
}
|
|
1597
1575
|
function isDrizzleZodAvailable() {
|
|
1598
|
-
|
|
1599
|
-
tryLoadDrizzleZod();
|
|
1600
|
-
return true;
|
|
1601
|
-
} catch {
|
|
1602
|
-
return false;
|
|
1603
|
-
}
|
|
1576
|
+
return _drizzleZod !== null;
|
|
1604
1577
|
}
|
|
1605
1578
|
var coercedDate = z.preprocess(
|
|
1606
1579
|
(val) => {
|
|
@@ -1665,4 +1638,4 @@ function applyDateCoercion(schema, dateColumns) {
|
|
|
1665
1638
|
return z.object(newShape);
|
|
1666
1639
|
}
|
|
1667
1640
|
|
|
1668
|
-
export { DrizzleAdapters, DrizzleAggregateEndpoint, DrizzleBatchCreateEndpoint, DrizzleBatchDeleteEndpoint, DrizzleBatchRestoreEndpoint, DrizzleBatchUpdateEndpoint, DrizzleBatchUpsertEndpoint, DrizzleCreateEndpoint, DrizzleDeleteEndpoint, DrizzleExportEndpoint, DrizzleImportEndpoint, DrizzleListEndpoint, DrizzleReadEndpoint, DrizzleRestoreEndpoint, DrizzleSearchEndpoint, DrizzleUpdateEndpoint, DrizzleUpsertEndpoint, DrizzleVersionCompareEndpoint, DrizzleVersionHistoryEndpoint, DrizzleVersionReadEndpoint, DrizzleVersionRollbackEndpoint, batchLoadDrizzleRelations, buildWhereCondition, cast, createDrizzleCrud, createDrizzleSchemas,
|
|
1641
|
+
export { DrizzleAdapters, DrizzleAggregateEndpoint, DrizzleBatchCreateEndpoint, DrizzleBatchDeleteEndpoint, DrizzleBatchRestoreEndpoint, DrizzleBatchUpdateEndpoint, DrizzleBatchUpsertEndpoint, DrizzleCreateEndpoint, DrizzleDeleteEndpoint, DrizzleExportEndpoint, DrizzleImportEndpoint, DrizzleListEndpoint, DrizzleReadEndpoint, DrizzleRestoreEndpoint, DrizzleSearchEndpoint, DrizzleUpdateEndpoint, DrizzleUpsertEndpoint, DrizzleVersionCompareEndpoint, DrizzleVersionHistoryEndpoint, DrizzleVersionReadEndpoint, DrizzleVersionRollbackEndpoint, batchLoadDrizzleRelations, buildWhereCondition, cast, createDrizzleCrud, createDrizzleSchemas, createInsertSchema, createSelectSchema, createUpdateSchema, getColumn, getTable, isDrizzleZodAvailable, loadDrizzleRelation, loadDrizzleRelations };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Env } from 'hono';
|
|
2
|
-
import { C as CreateEndpoint, M as ModelObject, D as DeleteEndpoint, L as ListEndpoint, R as ReadEndpoint, a as RestoreEndpoint, U as UpdateEndpoint, B as BatchCreateEndpoint, b as BatchDeleteEndpoint, c as BatchRestoreEndpoint, d as BatchUpdateEndpoint, e as BatchUpdateItem, f as BatchUpsertEndpoint, A as AggregateEndpoint, E as ExportEndpoint, I as ImportEndpoint, S as SearchEndpoint, g as UpsertEndpoint, V as VersionCompareEndpoint, h as VersionHistoryEndpoint, i as VersionReadEndpoint, j as VersionRollbackEndpoint } from '../../import-
|
|
2
|
+
import { C as CreateEndpoint, M as ModelObject, D as DeleteEndpoint, L as ListEndpoint, R as ReadEndpoint, a as RestoreEndpoint, U as UpdateEndpoint, B as BatchCreateEndpoint, b as BatchDeleteEndpoint, c as BatchRestoreEndpoint, d as BatchUpdateEndpoint, e as BatchUpdateItem, f as BatchUpsertEndpoint, A as AggregateEndpoint, E as ExportEndpoint, I as ImportEndpoint, S as SearchEndpoint, g as UpsertEndpoint, V as VersionCompareEndpoint, h as VersionHistoryEndpoint, i as VersionReadEndpoint, j as VersionRollbackEndpoint } from '../../import-BZ05PJMa.js';
|
|
3
3
|
import { M as MetaInput, g as RelationConfig, L as ListFilters, P as PaginatedResult, I as IncludeOptions, h as NestedUpdateInput, i as NestedWriteResult, j as AggregateOptions, k as AggregateResult, S as SearchOptions, l as SearchResult } from '../../types-CA784ZtV.js';
|
|
4
|
-
import { B as BulkPatchEndpoint, C as CloneEndpoint } from '../../bulk-patch-
|
|
4
|
+
import { B as BulkPatchEndpoint, C as CloneEndpoint } from '../../bulk-patch-f4TR8L-q.js';
|
|
5
5
|
import 'zod';
|
|
6
6
|
import '../../route-DwSID3du.js';
|
|
7
7
|
import 'hono/utils/http-status';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { MemoryAggregateEndpoint, MemoryBatchCreateEndpoint, MemoryBatchDeleteEndpoint, MemoryBatchRestoreEndpoint, MemoryBatchUpdateEndpoint, MemoryBatchUpsertEndpoint, MemoryBulkPatchEndpoint, MemoryCloneEndpoint, MemoryCreateEndpoint, MemoryDeleteEndpoint, MemoryExportEndpoint, MemoryImportEndpoint, MemoryListEndpoint, MemoryReadEndpoint, MemoryRestoreEndpoint, MemorySearchEndpoint, MemoryUpdateEndpoint, MemoryUpsertEndpoint, MemoryVersionCompareEndpoint, MemoryVersionHistoryEndpoint, MemoryVersionReadEndpoint, MemoryVersionRollbackEndpoint, clearStorage, getStorage, getStore, storage } from '../../chunk-
|
|
2
|
-
import '../../chunk-
|
|
1
|
+
export { MemoryAggregateEndpoint, MemoryBatchCreateEndpoint, MemoryBatchDeleteEndpoint, MemoryBatchRestoreEndpoint, MemoryBatchUpdateEndpoint, MemoryBatchUpsertEndpoint, MemoryBulkPatchEndpoint, MemoryCloneEndpoint, MemoryCreateEndpoint, MemoryDeleteEndpoint, MemoryExportEndpoint, MemoryImportEndpoint, MemoryListEndpoint, MemoryReadEndpoint, MemoryRestoreEndpoint, MemorySearchEndpoint, MemoryUpdateEndpoint, MemoryUpsertEndpoint, MemoryVersionCompareEndpoint, MemoryVersionHistoryEndpoint, MemoryVersionReadEndpoint, MemoryVersionRollbackEndpoint, clearStorage, getStorage, getStore, storage } from '../../chunk-G7IQ5DWC.js';
|
|
2
|
+
import '../../chunk-T6J4NSMC.js';
|
|
3
3
|
import '../../chunk-CDCGYMC6.js';
|
|
4
4
|
import '../../chunk-U3SUUXJK.js';
|
|
5
5
|
import '../../chunk-FST5S5UY.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Env } from 'hono';
|
|
2
|
-
import { C as CreateEndpoint, M as ModelObject, D as DeleteEndpoint, L as ListEndpoint, R as ReadEndpoint, U as UpdateEndpoint, B as BatchCreateEndpoint, b as BatchDeleteEndpoint, c as BatchRestoreEndpoint, d as BatchUpdateEndpoint, e as BatchUpdateItem, f as BatchUpsertEndpoint, a as RestoreEndpoint, A as AggregateEndpoint, E as ExportEndpoint, I as ImportEndpoint, S as SearchEndpoint, g as UpsertEndpoint, V as VersionCompareEndpoint, h as VersionHistoryEndpoint, i as VersionReadEndpoint, j as VersionRollbackEndpoint } from '../../import-
|
|
2
|
+
import { C as CreateEndpoint, M as ModelObject, D as DeleteEndpoint, L as ListEndpoint, R as ReadEndpoint, U as UpdateEndpoint, B as BatchCreateEndpoint, b as BatchDeleteEndpoint, c as BatchRestoreEndpoint, d as BatchUpdateEndpoint, e as BatchUpdateItem, f as BatchUpsertEndpoint, a as RestoreEndpoint, A as AggregateEndpoint, E as ExportEndpoint, I as ImportEndpoint, S as SearchEndpoint, g as UpsertEndpoint, V as VersionCompareEndpoint, h as VersionHistoryEndpoint, i as VersionReadEndpoint, j as VersionRollbackEndpoint } from '../../import-BZ05PJMa.js';
|
|
3
3
|
import { M as MetaInput, L as ListFilters, P as PaginatedResult, I as IncludeOptions, j as AggregateOptions, k as AggregateResult, m as AggregateField, S as SearchOptions, l as SearchResult } from '../../types-CA784ZtV.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import '../../route-DwSID3du.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreateEndpoint, ReadEndpoint, UpdateEndpoint, DeleteEndpoint, ListEndpoint, RestoreEndpoint, BatchCreateEndpoint, BatchUpdateEndpoint, BatchDeleteEndpoint, BatchRestoreEndpoint, BatchUpsertEndpoint, SearchEndpoint, searchInMemory, ExportEndpoint, ImportEndpoint, UpsertEndpoint, VersionHistoryEndpoint, VersionReadEndpoint, VersionCompareEndpoint, VersionRollbackEndpoint, AggregateEndpoint, computeAggregations } from '../../chunk-
|
|
1
|
+
import { CreateEndpoint, ReadEndpoint, UpdateEndpoint, DeleteEndpoint, ListEndpoint, RestoreEndpoint, BatchCreateEndpoint, BatchUpdateEndpoint, BatchDeleteEndpoint, BatchRestoreEndpoint, BatchUpsertEndpoint, SearchEndpoint, searchInMemory, ExportEndpoint, ImportEndpoint, UpsertEndpoint, VersionHistoryEndpoint, VersionReadEndpoint, VersionCompareEndpoint, VersionRollbackEndpoint, AggregateEndpoint, computeAggregations } from '../../chunk-T6J4NSMC.js';
|
|
2
2
|
import '../../chunk-CDCGYMC6.js';
|
|
3
3
|
import '../../chunk-U3SUUXJK.js';
|
|
4
4
|
import '../../chunk-FST5S5UY.js';
|
package/dist/auth/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AuthenticatedEndpoint, JWTClaimsSchema, allOf, allowAll, anyOf, createAPIKeyMiddleware, createAuthMiddleware, createJWTMiddleware, decodeJWT, defaultHashAPIKey, denyAll, optionalAuth, parseJWTClaims, requireAllRoles, requireAnyPermission, requireAuth, requireAuthenticated, requireAuthentication, requireOwnership, requireOwnershipOrRole, requirePermissions, requireRoles, safeParseJWTClaims, validateAPIKey, validateAPIKeyEntry, validateJWTClaims, verifyJWT, withAuth } from '../chunk-
|
|
1
|
+
export { AuthenticatedEndpoint, JWTClaimsSchema, allOf, allowAll, anyOf, createAPIKeyMiddleware, createAuthMiddleware, createJWTMiddleware, decodeJWT, defaultHashAPIKey, denyAll, optionalAuth, parseJWTClaims, requireAllRoles, requireAnyPermission, requireAuth, requireAuthenticated, requireAuthentication, requireOwnership, requireOwnershipOrRole, requirePermissions, requireRoles, safeParseJWTClaims, validateAPIKey, validateAPIKeyEntry, validateJWTClaims, verifyJWT, withAuth } from '../chunk-57J3NJYN.js';
|
|
2
2
|
export { MemoryAPIKeyStorage, generateAPIKey, getAPIKeyStorage, hashAPIKey, isValidAPIKeyFormat, setAPIKeyStorage } from '../chunk-6LS3LNIH.js';
|
|
3
3
|
import '../chunk-CDCGYMC6.js';
|
|
4
4
|
import '../chunk-FST5S5UY.js';
|
|
@@ -2,7 +2,7 @@ import { ZodObject, ZodRawShape } from 'zod';
|
|
|
2
2
|
import { Env } from 'hono';
|
|
3
3
|
import { O as OpenAPIRoute } from './route-DwSID3du.js';
|
|
4
4
|
import { M as MetaInput, N as NormalizedSoftDeleteConfig, a as NormalizedMultiTenantConfig, O as OpenAPIRouteSchema, H as HookMode, L as ListFilters } from './types-CA784ZtV.js';
|
|
5
|
-
import { M as ModelObject } from './import-
|
|
5
|
+
import { M as ModelObject } from './import-BZ05PJMa.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Base endpoint for cloning/duplicating a resource.
|
package/dist/cache/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { RedisCacheStorage } from '../chunk-YJMGFVHZ.js';
|
|
2
|
-
export { MemoryCacheStorage, createInvalidationPattern, createRelatedPatterns, generateCacheKey, getCacheStorage, matchesPattern, parseCacheKey, setCacheStorage, withCache, withCacheInvalidation } from '../chunk-
|
|
2
|
+
export { MemoryCacheStorage, createInvalidationPattern, createRelatedPatterns, generateCacheKey, getCacheStorage, matchesPattern, parseCacheKey, setCacheStorage, withCache, withCacheInvalidation } from '../chunk-Y74QJH7Y.js';
|
|
3
3
|
import '../chunk-6LS3LNIH.js';
|
|
4
4
|
import '../chunk-U3SUUXJK.js';
|
|
5
5
|
import '../chunk-FST5S5UY.js';
|
|
@@ -355,9 +355,7 @@ function requireRoles(...roles) {
|
|
|
355
355
|
const userRoles = user.roles || [];
|
|
356
356
|
const hasRole = roles.some((role) => userRoles.includes(role));
|
|
357
357
|
if (!hasRole) {
|
|
358
|
-
throw new ForbiddenException(
|
|
359
|
-
`Required role: ${roles.join(" or ")}`
|
|
360
|
-
);
|
|
358
|
+
throw new ForbiddenException("Insufficient permissions");
|
|
361
359
|
}
|
|
362
360
|
await next();
|
|
363
361
|
};
|
|
@@ -371,9 +369,7 @@ function requireAllRoles(...roles) {
|
|
|
371
369
|
const userRoles = user.roles || [];
|
|
372
370
|
const hasAllRoles = roles.every((role) => userRoles.includes(role));
|
|
373
371
|
if (!hasAllRoles) {
|
|
374
|
-
throw new ForbiddenException(
|
|
375
|
-
`Required roles: ${roles.join(" and ")}`
|
|
376
|
-
);
|
|
372
|
+
throw new ForbiddenException("Insufficient permissions");
|
|
377
373
|
}
|
|
378
374
|
await next();
|
|
379
375
|
};
|
|
@@ -387,9 +383,7 @@ function requirePermissions(...permissions) {
|
|
|
387
383
|
const userPermissions = user.permissions || [];
|
|
388
384
|
const hasAllPermissions = permissions.every((perm) => userPermissions.includes(perm));
|
|
389
385
|
if (!hasAllPermissions) {
|
|
390
|
-
throw new ForbiddenException(
|
|
391
|
-
`Required permissions: ${permissions.join(", ")}`
|
|
392
|
-
);
|
|
386
|
+
throw new ForbiddenException("Insufficient permissions");
|
|
393
387
|
}
|
|
394
388
|
await next();
|
|
395
389
|
};
|
|
@@ -403,9 +397,7 @@ function requireAnyPermission(...permissions) {
|
|
|
403
397
|
const userPermissions = user.permissions || [];
|
|
404
398
|
const hasAnyPermission = permissions.some((perm) => userPermissions.includes(perm));
|
|
405
399
|
if (!hasAnyPermission) {
|
|
406
|
-
throw new ForbiddenException(
|
|
407
|
-
`Required permission: ${permissions.join(" or ")}`
|
|
408
|
-
);
|
|
400
|
+
throw new ForbiddenException("Insufficient permissions");
|
|
409
401
|
}
|
|
410
402
|
await next();
|
|
411
403
|
};
|
|
@@ -453,7 +445,7 @@ function requireOwnershipOrRole(getOwnerId, ...roles) {
|
|
|
453
445
|
await next();
|
|
454
446
|
return;
|
|
455
447
|
}
|
|
456
|
-
throw new ForbiddenException("Access denied
|
|
448
|
+
throw new ForbiddenException("Access denied");
|
|
457
449
|
};
|
|
458
450
|
}
|
|
459
451
|
function allOf(...guards) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreateEndpoint, ReadEndpoint, UpdateEndpoint, DeleteEndpoint, ListEndpoint, RestoreEndpoint, BatchCreateEndpoint, BatchUpdateEndpoint, BatchDeleteEndpoint, BatchRestoreEndpoint, BatchUpsertEndpoint, getSchemaFields, parseListFilters, UpsertEndpoint, VersionHistoryEndpoint, VersionReadEndpoint, VersionCompareEndpoint, VersionRollbackEndpoint, AggregateEndpoint, computeAggregations, SearchEndpoint, searchInMemory, ExportEndpoint, ImportEndpoint } from './chunk-
|
|
1
|
+
import { CreateEndpoint, ReadEndpoint, UpdateEndpoint, DeleteEndpoint, ListEndpoint, RestoreEndpoint, BatchCreateEndpoint, BatchUpdateEndpoint, BatchDeleteEndpoint, BatchRestoreEndpoint, BatchUpsertEndpoint, getSchemaFields, parseListFilters, UpsertEndpoint, VersionHistoryEndpoint, VersionReadEndpoint, VersionCompareEndpoint, VersionRollbackEndpoint, AggregateEndpoint, computeAggregations, SearchEndpoint, searchInMemory, ExportEndpoint, ImportEndpoint } from './chunk-T6J4NSMC.js';
|
|
2
2
|
import { OpenAPIRoute } from './chunk-CDCGYMC6.js';
|
|
3
3
|
import { decodeCursor, encodeCursor, getSoftDeleteConfig, getMultiTenantConfig, extractTenantId, applyComputedFields } from './chunk-U3SUUXJK.js';
|
|
4
4
|
import { NotFoundException } from './chunk-FST5S5UY.js';
|
|
@@ -4552,6 +4552,11 @@ var AggregateEndpoint = class extends OpenAPIRoute {
|
|
|
4552
4552
|
* Override to restrict which fields can be aggregated.
|
|
4553
4553
|
*/
|
|
4554
4554
|
aggregateConfig = {};
|
|
4555
|
+
/**
|
|
4556
|
+
* Maximum number of GROUP BY fields allowed per query.
|
|
4557
|
+
* Prevents cardinality explosion from too many grouping dimensions.
|
|
4558
|
+
*/
|
|
4559
|
+
maxGroupByFields = 5;
|
|
4555
4560
|
/**
|
|
4556
4561
|
* Fields that can be used for filtering.
|
|
4557
4562
|
* Empty array means all fields are allowed.
|
|
@@ -4690,6 +4695,11 @@ var AggregateEndpoint = class extends OpenAPIRoute {
|
|
|
4690
4695
|
}
|
|
4691
4696
|
}
|
|
4692
4697
|
if (options.groupBy) {
|
|
4698
|
+
if (options.groupBy.length > this.maxGroupByFields) {
|
|
4699
|
+
throw new InputValidationException(
|
|
4700
|
+
`Maximum ${this.maxGroupByFields} GROUP BY fields allowed`
|
|
4701
|
+
);
|
|
4702
|
+
}
|
|
4693
4703
|
for (const field of options.groupBy) {
|
|
4694
4704
|
if (config.groupByFields.length > 0 && !config.groupByFields.includes(field)) {
|
|
4695
4705
|
throw new Error(`Field '${field}' is not allowed for GROUP BY`);
|
|
@@ -5146,6 +5156,10 @@ var SearchEndpoint = class extends OpenAPIRoute {
|
|
|
5146
5156
|
* Minimum query length required to perform search.
|
|
5147
5157
|
*/
|
|
5148
5158
|
minQueryLength = 2;
|
|
5159
|
+
/**
|
|
5160
|
+
* Maximum query length allowed to prevent CPU exhaustion from long search strings.
|
|
5161
|
+
*/
|
|
5162
|
+
maxQueryLength = 500;
|
|
5149
5163
|
/**
|
|
5150
5164
|
* HTML tag used to wrap highlighted matches.
|
|
5151
5165
|
*/
|
|
@@ -5242,7 +5256,7 @@ var SearchEndpoint = class extends OpenAPIRoute {
|
|
|
5242
5256
|
getQuerySchema() {
|
|
5243
5257
|
const shape = {
|
|
5244
5258
|
// Search parameters
|
|
5245
|
-
q: z.string().min(this.minQueryLength).describe("Search query"),
|
|
5259
|
+
q: z.string().min(this.minQueryLength).max(this.maxQueryLength).describe("Search query"),
|
|
5246
5260
|
fields: z.string().optional().describe(
|
|
5247
5261
|
`Comma-separated fields to search. Available: ${Object.keys(this.getSearchableFields()).join(", ")}`
|
|
5248
5262
|
),
|
|
@@ -5564,6 +5578,11 @@ function escapeCsvValue(value, options = {}) {
|
|
|
5564
5578
|
return value ? "true" : "false";
|
|
5565
5579
|
}
|
|
5566
5580
|
const str = String(value);
|
|
5581
|
+
const firstChar = str.charAt(0);
|
|
5582
|
+
if (firstChar === "=" || firstChar === "+" || firstChar === "-" || firstChar === "@" || firstChar === " " || firstChar === "\r") {
|
|
5583
|
+
const escaped = str.replace(/"/g, '""');
|
|
5584
|
+
return `" ${escaped}"`;
|
|
5585
|
+
}
|
|
5567
5586
|
const needsQuoting = str.includes(delimiter) || str.includes('"') || str.includes("\n") || str.includes("\r");
|
|
5568
5587
|
if (needsQuoting) {
|
|
5569
5588
|
const escaped = str.replace(/"/g, '""');
|
|
@@ -5936,7 +5955,8 @@ var ExportEndpoint = class extends ListEndpoint {
|
|
|
5936
5955
|
* Gets the filename for the export.
|
|
5937
5956
|
*/
|
|
5938
5957
|
getExportFilename(format) {
|
|
5939
|
-
const
|
|
5958
|
+
const rawName = this.exportFilename || this._meta.model.tableName;
|
|
5959
|
+
const baseName = rawName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5940
5960
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
5941
5961
|
return `${baseName}-export-${timestamp}.${format}`;
|
|
5942
5962
|
}
|
|
@@ -6030,6 +6050,10 @@ var ExportEndpoint = class extends ListEndpoint {
|
|
|
6030
6050
|
* Escapes a CSV field value for safe output.
|
|
6031
6051
|
*/
|
|
6032
6052
|
escapeCsvField(value) {
|
|
6053
|
+
const firstChar = value.charAt(0);
|
|
6054
|
+
if (firstChar === "=" || firstChar === "+" || firstChar === "-" || firstChar === "@" || firstChar === " " || firstChar === "\r") {
|
|
6055
|
+
return `" ${value.replace(/"/g, '""')}"`;
|
|
6056
|
+
}
|
|
6033
6057
|
if (value.includes(",") || value.includes('"') || value.includes("\n") || value.includes("\r")) {
|
|
6034
6058
|
return `"${value.replace(/"/g, '""')}"`;
|
|
6035
6059
|
}
|
|
@@ -6080,12 +6104,13 @@ var ExportEndpoint = class extends ListEndpoint {
|
|
|
6080
6104
|
* Overrides pagination to fetch up to maxExportRecords.
|
|
6081
6105
|
*/
|
|
6082
6106
|
async fetchAllForExport(filters) {
|
|
6107
|
+
const effectiveLimit = Math.min(this.maxExportRecords, 1e5);
|
|
6083
6108
|
const exportFilters = {
|
|
6084
6109
|
...filters,
|
|
6085
6110
|
options: {
|
|
6086
6111
|
...filters.options,
|
|
6087
6112
|
page: 1,
|
|
6088
|
-
per_page:
|
|
6113
|
+
per_page: effectiveLimit
|
|
6089
6114
|
}
|
|
6090
6115
|
};
|
|
6091
6116
|
const result = await this.list(exportFilters);
|
|
@@ -6125,6 +6150,8 @@ var ImportEndpoint = class extends OpenAPIRoute {
|
|
|
6125
6150
|
immutableFields = [];
|
|
6126
6151
|
/** CSV parsing options. */
|
|
6127
6152
|
csvOptions = {};
|
|
6153
|
+
/** Maximum body size in bytes for import requests (default: 10MB). */
|
|
6154
|
+
maxBodySize = 10 * 1024 * 1024;
|
|
6128
6155
|
/** Fields that are optional during import (won't cause validation errors if missing). */
|
|
6129
6156
|
optionalImportFields = [];
|
|
6130
6157
|
// Audit logging
|
|
@@ -6322,6 +6349,9 @@ var ImportEndpoint = class extends OpenAPIRoute {
|
|
|
6322
6349
|
}
|
|
6323
6350
|
if (contentType.includes("text/csv")) {
|
|
6324
6351
|
const csvContent = await ctx.req.text();
|
|
6352
|
+
if (csvContent.length > this.maxBodySize) {
|
|
6353
|
+
throw new InputValidationException(`Request body exceeds maximum size of ${this.maxBodySize} bytes`);
|
|
6354
|
+
}
|
|
6325
6355
|
return this.parseCsvData(csvContent);
|
|
6326
6356
|
}
|
|
6327
6357
|
if (contentType.includes("multipart/form-data")) {
|
|
@@ -6331,9 +6361,17 @@ var ImportEndpoint = class extends OpenAPIRoute {
|
|
|
6331
6361
|
throw new InputValidationException("No file provided in form data");
|
|
6332
6362
|
}
|
|
6333
6363
|
const content = await file.text();
|
|
6364
|
+
if (content.length > this.maxBodySize) {
|
|
6365
|
+
throw new InputValidationException(`Uploaded file exceeds maximum size of ${this.maxBodySize} bytes`);
|
|
6366
|
+
}
|
|
6334
6367
|
const filename = file.name.toLowerCase();
|
|
6335
6368
|
if (filename.endsWith(".json")) {
|
|
6336
|
-
|
|
6369
|
+
let body;
|
|
6370
|
+
try {
|
|
6371
|
+
body = JSON.parse(content);
|
|
6372
|
+
} catch {
|
|
6373
|
+
throw new InputValidationException("Invalid JSON content in uploaded file");
|
|
6374
|
+
}
|
|
6337
6375
|
const items = Array.isArray(body) ? body : body.items;
|
|
6338
6376
|
if (!items || !Array.isArray(items)) {
|
|
6339
6377
|
throw new InputValidationException('JSON file must contain an array or an object with "items" array');
|
|
@@ -6348,7 +6386,12 @@ var ImportEndpoint = class extends OpenAPIRoute {
|
|
|
6348
6386
|
}
|
|
6349
6387
|
const trimmed = content.trim();
|
|
6350
6388
|
if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
|
|
6351
|
-
|
|
6389
|
+
let body;
|
|
6390
|
+
try {
|
|
6391
|
+
body = JSON.parse(content);
|
|
6392
|
+
} catch {
|
|
6393
|
+
throw new InputValidationException("Invalid JSON content in uploaded file");
|
|
6394
|
+
}
|
|
6352
6395
|
const items = Array.isArray(body) ? body : body.items;
|
|
6353
6396
|
if (!items || !Array.isArray(items)) {
|
|
6354
6397
|
throw new InputValidationException('JSON file must contain an array or an object with "items" array');
|
|
@@ -85,24 +85,22 @@ function shouldExcludePath(path, includePaths, excludePaths) {
|
|
|
85
85
|
}
|
|
86
86
|
return true;
|
|
87
87
|
}
|
|
88
|
-
function extractClientIp(ctx, ipHeader = "X-Forwarded-For",
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return firstIP;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
const realIP = ctx.req.header("X-Real-IP");
|
|
98
|
-
if (realIP) {
|
|
99
|
-
return realIP.trim();
|
|
100
|
-
}
|
|
101
|
-
const cfIP = ctx.req.header("CF-Connecting-IP");
|
|
102
|
-
if (cfIP) {
|
|
103
|
-
return cfIP.trim();
|
|
88
|
+
function extractClientIp(ctx, ipHeader = "X-Forwarded-For", _trustProxy = false) {
|
|
89
|
+
const proxyHeader = ctx.req.header(ipHeader);
|
|
90
|
+
if (proxyHeader) {
|
|
91
|
+
const firstIP = proxyHeader.split(",")[0].trim();
|
|
92
|
+
if (firstIP) {
|
|
93
|
+
return firstIP;
|
|
104
94
|
}
|
|
105
95
|
}
|
|
96
|
+
const realIP = ctx.req.header("X-Real-IP");
|
|
97
|
+
if (realIP) {
|
|
98
|
+
return realIP.trim();
|
|
99
|
+
}
|
|
100
|
+
const cfIP = ctx.req.header("CF-Connecting-IP");
|
|
101
|
+
if (cfIP) {
|
|
102
|
+
return cfIP.trim();
|
|
103
|
+
}
|
|
106
104
|
const raw = ctx.req.raw;
|
|
107
105
|
if (raw && "socket" in raw && raw.socket && typeof raw.socket === "object") {
|
|
108
106
|
const socket = raw.socket;
|
|
@@ -166,6 +164,14 @@ function generateRequestId() {
|
|
|
166
164
|
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
167
165
|
return crypto.randomUUID();
|
|
168
166
|
}
|
|
167
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
168
|
+
const bytes = new Uint8Array(16);
|
|
169
|
+
crypto.getRandomValues(bytes);
|
|
170
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
171
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
172
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
173
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
174
|
+
}
|
|
169
175
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
170
176
|
const r = Math.random() * 16 | 0;
|
|
171
177
|
const v = c === "x" ? r : r & 3 | 8;
|
|
@@ -182,7 +188,7 @@ var RateLimitExceededException = class extends ApiException {
|
|
|
182
188
|
};
|
|
183
189
|
|
|
184
190
|
// src/rate-limit/utils.ts
|
|
185
|
-
function extractIP(ctx, ipHeader = "X-Forwarded-For", trustProxy =
|
|
191
|
+
function extractIP(ctx, ipHeader = "X-Forwarded-For", trustProxy = false) {
|
|
186
192
|
if (trustProxy) {
|
|
187
193
|
const proxyHeader = ctx.req.header(ipHeader);
|
|
188
194
|
if (proxyHeader) {
|
|
@@ -317,7 +323,7 @@ function createLoggingMiddleware(config = {}) {
|
|
|
317
323
|
const includeQuery = config.includeQuery ?? true;
|
|
318
324
|
const includeClientIp = config.includeClientIp ?? true;
|
|
319
325
|
const ipHeader = config.ipHeader ?? "X-Forwarded-For";
|
|
320
|
-
const trustProxy = config.trustProxy ??
|
|
326
|
+
const trustProxy = config.trustProxy ?? false;
|
|
321
327
|
const minResponseTimeMs = config.minResponseTimeMs ?? 0;
|
|
322
328
|
const generateRequestId2 = config.generateRequestId ?? generateRequestId;
|
|
323
329
|
return async (ctx, next) => {
|
|
@@ -609,7 +615,7 @@ var MemoryCacheStorage = class {
|
|
|
609
615
|
maxEntries;
|
|
610
616
|
constructor(options) {
|
|
611
617
|
this.defaultTtl = options?.defaultTtl ?? 300;
|
|
612
|
-
this.maxEntries = options?.maxEntries ??
|
|
618
|
+
this.maxEntries = options?.maxEntries ?? 1e4;
|
|
613
619
|
}
|
|
614
620
|
/**
|
|
615
621
|
* Get a cached entry by key.
|
|
@@ -2057,6 +2057,11 @@ declare abstract class AggregateEndpoint<E extends Env = Env, M extends MetaInpu
|
|
|
2057
2057
|
* Override to restrict which fields can be aggregated.
|
|
2058
2058
|
*/
|
|
2059
2059
|
protected aggregateConfig: AggregateConfig;
|
|
2060
|
+
/**
|
|
2061
|
+
* Maximum number of GROUP BY fields allowed per query.
|
|
2062
|
+
* Prevents cardinality explosion from too many grouping dimensions.
|
|
2063
|
+
*/
|
|
2064
|
+
protected maxGroupByFields: number;
|
|
2060
2065
|
/**
|
|
2061
2066
|
* Fields that can be used for filtering.
|
|
2062
2067
|
* Empty array means all fields are allowed.
|
|
@@ -2162,6 +2167,10 @@ declare abstract class SearchEndpoint<E extends Env = Env, M extends MetaInput =
|
|
|
2162
2167
|
* Minimum query length required to perform search.
|
|
2163
2168
|
*/
|
|
2164
2169
|
protected minQueryLength: number;
|
|
2170
|
+
/**
|
|
2171
|
+
* Maximum query length allowed to prevent CPU exhaustion from long search strings.
|
|
2172
|
+
*/
|
|
2173
|
+
protected maxQueryLength: number;
|
|
2165
2174
|
/**
|
|
2166
2175
|
* HTML tag used to wrap highlighted matches.
|
|
2167
2176
|
*/
|
|
@@ -2701,6 +2710,8 @@ declare abstract class ImportEndpoint<E extends Env = Env, M extends MetaInput =
|
|
|
2701
2710
|
protected immutableFields: string[];
|
|
2702
2711
|
/** CSV parsing options. */
|
|
2703
2712
|
protected csvOptions: Partial<CsvParseOptions>;
|
|
2713
|
+
/** Maximum body size in bytes for import requests (default: 10MB). */
|
|
2714
|
+
protected maxBodySize: number;
|
|
2704
2715
|
/** Fields that are optional during import (won't cause validation errors if missing). */
|
|
2705
2716
|
protected optionalImportFields: string[];
|
|
2706
2717
|
private _auditLogger?;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PathPattern, c as RateLimitConfig, f as RateLimitStorage, F as FixedWindowEntry, S as SlidingWindowEntry, d as RateLimitEntry } from './types-
|
|
1
|
+
import { P as PathPattern, c as RateLimitConfig, f as RateLimitStorage, F as FixedWindowEntry, S as SlidingWindowEntry, d as RateLimitEntry } from './types-BO3G_MZk.js';
|
|
2
2
|
import { HTTPException } from 'hono/http-exception';
|
|
3
3
|
import { ZodError } from 'zod';
|
|
4
4
|
import { ContentfulStatusCode } from 'hono/utils/http-status';
|
|
@@ -85,7 +85,7 @@ declare class RateLimitExceededException extends ApiException {
|
|
|
85
85
|
*
|
|
86
86
|
* @param ctx - Hono context
|
|
87
87
|
* @param ipHeader - Header name for proxy IP (default: 'X-Forwarded-For')
|
|
88
|
-
* @param trustProxy - Whether to trust proxy headers (default:
|
|
88
|
+
* @param trustProxy - Whether to trust proxy headers (default: false)
|
|
89
89
|
* @returns The client IP address or 'unknown'
|
|
90
90
|
*/
|
|
91
91
|
declare function extractIP<E extends Env>(ctx: Context<E>, ipHeader?: string, trustProxy?: boolean): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { A as AuthEnv } from './memory-B_NZbOQP.js';
|
|
2
2
|
export { a as APIKeyConfig, b as APIKeyEntry, c as APIKeyLookupResult, d as AuthConfig, e as AuthType, f as AuthUser, g as AuthorizationCheck, E as EndpointAuthConfig, G as Guard, J as JWTAlgorithm, h as JWTClaims, i as JWTClaimsSchema, j as JWTConfig, M as MemoryAPIKeyStorage, O as OwnershipExtractor, P as PathPattern, V as ValidatedJWTClaims, k as generateAPIKey, l as getAPIKeyStorage, m as hashAPIKey, n as isValidAPIKeyFormat, p as parseJWTClaims, s as safeParseJWTClaims, o as setAPIKeyStorage } from './memory-B_NZbOQP.js';
|
|
3
|
-
import { L as LoggingEnv } from './types-
|
|
4
|
-
export { a as LogEntry, b as LogLevel, c as LogQueryOptions, d as LoggingConfig, P as LoggingPathPattern, e as LoggingStorage, R as RedactField, f as RequestBodyConfig, g as RequestLogEntry, h as ResponseBodyConfig, i as ResponseLogEntry } from './types-
|
|
5
|
-
import { R as RateLimitEnv } from './types-
|
|
6
|
-
export { F as FixedWindowEntry, K as KeyExtractor, a as KeyStrategy, O as OnRateLimitExceeded, b as RateLimitAlgorithm, c as RateLimitConfig, d as RateLimitEntry, P as RateLimitPathPattern, e as RateLimitResult, f as RateLimitStorage, g as RateLimitTier, S as SlidingWindowEntry, T as TierFunction } from './types-
|
|
3
|
+
import { L as LoggingEnv } from './types-DnQWCfXp.js';
|
|
4
|
+
export { a as LogEntry, b as LogLevel, c as LogQueryOptions, d as LoggingConfig, P as LoggingPathPattern, e as LoggingStorage, R as RedactField, f as RequestBodyConfig, g as RequestLogEntry, h as ResponseBodyConfig, i as ResponseLogEntry } from './types-DnQWCfXp.js';
|
|
5
|
+
import { R as RateLimitEnv } from './types-BO3G_MZk.js';
|
|
6
|
+
export { F as FixedWindowEntry, K as KeyExtractor, a as KeyStrategy, O as OnRateLimitExceeded, b as RateLimitAlgorithm, c as RateLimitConfig, d as RateLimitEntry, P as RateLimitPathPattern, e as RateLimitResult, f as RateLimitStorage, g as RateLimitTier, S as SlidingWindowEntry, T as TierFunction } from './types-BO3G_MZk.js';
|
|
7
7
|
import { StorageEnv } from './storage/index.js';
|
|
8
8
|
export { StorageMiddlewareConfig, StorageRegistry, createAPIKeyStorageMiddleware, createAuditStorageMiddleware, createCacheStorageMiddleware, createLoggingStorageMiddleware, createNullableRegistry, createRateLimitStorageMiddleware, createRegistryWithDefault, createStorageMiddleware, createVersioningStorageMiddleware, resolveAPIKeyStorage, resolveAuditStorage, resolveCacheStorage, resolveLoggingStorage, resolveRateLimitStorage, resolveVersioningStorage } from './storage/index.js';
|
|
9
9
|
import { O as OpenAPIRoute } from './route-DwSID3du.js';
|
|
@@ -12,12 +12,12 @@ import { Env, MiddlewareHandler, Hono, Context, ErrorHandler } from 'hono';
|
|
|
12
12
|
import { OpenAPIHono, Hook } from '@hono/zod-openapi';
|
|
13
13
|
import { O as OpenAPIRouteSchema, t as SearchFieldConfig, u as SearchMode, M as MetaInput, H as HookMode } from './types-CA784ZtV.js';
|
|
14
14
|
export { s as AggregateConfig, m as AggregateField, w as AggregateOperation, j as AggregateOptions, k as AggregateResult, b as AuditAction, c as AuditConfig, f as AuditFieldChange, A as AuditLogEntry, C as CascadeAction, x as CascadeConfig, y as ComputedFieldConfig, z as ComputedFieldFn, B as ComputedFieldsConfig, E as ErrorResponse, F as FilterCondition, o as FilterConfig, p as FilterOperator, D as HandleArgs, G as HookConfig, J as HookFn, I as IncludeOptions, K as InferMeta, Q as InferModel, T as InferSchema, L as ListFilters, U as ListOptions, n as Model, W as ModelTable, X as MultiTenantConfig, Y as NestedCreateManyInput, Z as NestedCreateOneInput, h as NestedUpdateInput, _ as NestedWriteConfig, i as NestedWriteResult, $ as NestedWritesConfig, q as NormalizedAuditConfig, a as NormalizedMultiTenantConfig, N as NormalizedSoftDeleteConfig, r as NormalizedVersioningConfig, P as PaginatedResult, a0 as PartialBy, g as RelationConfig, a1 as RelationType, a2 as RelationsConfig, a3 as RequiredBy, R as RouteOptions, a4 as SchemaKeys, a5 as SearchConfig, S as SearchOptions, l as SearchResult, v as SearchResultItem, a6 as SoftDeleteConfig, a7 as SuccessResponse, V as ValidatedData, d as VersionHistoryEntry, e as VersioningConfig, a8 as applyComputedFields, a9 as applyComputedFieldsToArray, aa as calculateChanges, ab as decodeCursor, ac as defineMeta, ad as defineModel, ae as encodeCursor, af as extractNestedData, ag as extractTenantId, ah as getAuditConfig, ai as getMultiTenantConfig, aj as getSoftDeleteConfig, ak as getVersioningConfig, al as isDirectNestedData, am as parseAggregateField, an as parseAggregateQuery, ao as parseSearchMode } from './types-CA784ZtV.js';
|
|
15
|
-
import { A as ApiException } from './index-
|
|
16
|
-
export { a as AggregationException, C as CacheException, b as ConfigurationException, c as ConflictException, F as ForbiddenException, I as InputValidationException, M as MemoryRateLimitStorage, d as MemoryRateLimitStorageOptions, N as NotFoundException, R as RateLimitExceededException, e as RedisRateLimitClient, f as RedisRateLimitStorage, g as RedisRateLimitStorageOptions, U as UnauthorizedException, h as createRateLimitMiddleware, i as extractAPIKey, j as extractIP, k as extractUserId, l as generateKey, m as getRateLimitStorage, n as matchPath, r as resetRateLimit, s as setRateLimitStorage, o as shouldSkipPath } from './index-
|
|
15
|
+
import { A as ApiException } from './index-431Ovi2o.js';
|
|
16
|
+
export { a as AggregationException, C as CacheException, b as ConfigurationException, c as ConflictException, F as ForbiddenException, I as InputValidationException, M as MemoryRateLimitStorage, d as MemoryRateLimitStorageOptions, N as NotFoundException, R as RateLimitExceededException, e as RedisRateLimitClient, f as RedisRateLimitStorage, g as RedisRateLimitStorageOptions, U as UnauthorizedException, h as createRateLimitMiddleware, i as extractAPIKey, j as extractIP, k as extractUserId, l as generateKey, m as getRateLimitStorage, n as matchPath, r as resetRateLimit, s as setRateLimitStorage, o as shouldSkipPath } from './index-431Ovi2o.js';
|
|
17
17
|
export { a as AuditLogStorage, A as AuditLogger, M as MemoryAuditLogStorage, b as MemoryVersioningStorage, V as VersionManager, c as VersioningStorage, d as createAuditLogger, e as createVersionManager, g as getAuditStorage, f as getVersioningStorage, s as setAuditStorage, h as setVersioningStorage } from './versioning-BG8-R7C0.js';
|
|
18
|
-
import { M as ModelObject } from './import-
|
|
19
|
-
export { A as AggregateEndpoint, B as BatchCreateEndpoint, b as BatchDeleteEndpoint, k as BatchDeleteResult, c as BatchRestoreEndpoint, l as BatchRestoreResult, d as BatchUpdateEndpoint, e as BatchUpdateItem, m as BatchUpdateResult, f as BatchUpsertEndpoint, n as BatchUpsertItemResult, o as BatchUpsertResult, p as CascadeResult, C as CreateEndpoint, q as CsvGenerateOptions, r as CsvParseError, s as CsvParseOptions, t as CsvParseResult, u as CsvValidationResult, D as DeleteEndpoint, E as ExportEndpoint, v as ExportFormat, w as ExportOptions, x as ExportResult, F as FieldSelection, y as FieldSelectionConfig, I as ImportEndpoint, z as ImportMode, G as ImportOptions, H as ImportResult, J as ImportRowResult, K as ImportRowStatus, N as ImportSummary, L as ListEndpoint, O as ListEndpointConfig, R as ReadEndpoint, a as RestoreEndpoint, S as SearchEndpoint, P as SingleEndpointConfig, U as UpdateEndpoint, Q as UpdateEndpointConfig, g as UpsertEndpoint, T as UpsertResult, V as VersionCompareEndpoint, h as VersionHistoryEndpoint, i as VersionReadEndpoint, j as VersionRollbackEndpoint, W as applyFieldSelection, X as applyFieldSelectionToArray, Y as computeAggregations, Z as createCsvStream, _ as csvToJson, $ as escapeCsvValue, a0 as generateCsv, a1 as getSchemaFields, a2 as inferCsvContentType, a3 as jsonToCsv, a4 as parseCsv, a5 as parseFieldSelection, a6 as parseFilterValue, a7 as parseListFilters, a8 as searchInMemory, a9 as validateCsvHeaders } from './import-
|
|
20
|
-
export { B as BulkPatchEndpoint, a as BulkPatchResult, C as CloneEndpoint } from './bulk-patch-
|
|
18
|
+
import { M as ModelObject } from './import-BZ05PJMa.js';
|
|
19
|
+
export { A as AggregateEndpoint, B as BatchCreateEndpoint, b as BatchDeleteEndpoint, k as BatchDeleteResult, c as BatchRestoreEndpoint, l as BatchRestoreResult, d as BatchUpdateEndpoint, e as BatchUpdateItem, m as BatchUpdateResult, f as BatchUpsertEndpoint, n as BatchUpsertItemResult, o as BatchUpsertResult, p as CascadeResult, C as CreateEndpoint, q as CsvGenerateOptions, r as CsvParseError, s as CsvParseOptions, t as CsvParseResult, u as CsvValidationResult, D as DeleteEndpoint, E as ExportEndpoint, v as ExportFormat, w as ExportOptions, x as ExportResult, F as FieldSelection, y as FieldSelectionConfig, I as ImportEndpoint, z as ImportMode, G as ImportOptions, H as ImportResult, J as ImportRowResult, K as ImportRowStatus, N as ImportSummary, L as ListEndpoint, O as ListEndpointConfig, R as ReadEndpoint, a as RestoreEndpoint, S as SearchEndpoint, P as SingleEndpointConfig, U as UpdateEndpoint, Q as UpdateEndpointConfig, g as UpsertEndpoint, T as UpsertResult, V as VersionCompareEndpoint, h as VersionHistoryEndpoint, i as VersionReadEndpoint, j as VersionRollbackEndpoint, W as applyFieldSelection, X as applyFieldSelectionToArray, Y as computeAggregations, Z as createCsvStream, _ as csvToJson, $ as escapeCsvValue, a0 as generateCsv, a1 as getSchemaFields, a2 as inferCsvContentType, a3 as jsonToCsv, a4 as parseCsv, a5 as parseFieldSelection, a6 as parseFilterValue, a7 as parseListFilters, a8 as searchInMemory, a9 as validateCsvHeaders } from './import-BZ05PJMa.js';
|
|
20
|
+
export { B as BulkPatchEndpoint, a as BulkPatchResult, C as CloneEndpoint } from './bulk-patch-f4TR8L-q.js';
|
|
21
21
|
export { S as ScalarConfig, a as ScalarTheme, U as UIOptions, s as scalarUI, b as setupDocs, c as setupDocsIndex, d as setupReDoc, e as setupScalar, f as setupSwaggerUI } from './ui-CNJUoCg1.js';
|
|
22
22
|
import { z } from 'zod';
|
|
23
23
|
export { AuthEndpointMethods, AuthenticatedEndpoint, JWTClaimsValidationOptions, allOf, allowAll, anyOf, createAPIKeyMiddleware, createAuthMiddleware, createJWTMiddleware, decodeJWT, defaultHashAPIKey, denyAll, optionalAuth, requireAllRoles, requireAnyPermission, requireAuth, requireAuthenticated, requireAuthentication, requireOwnership, requireOwnershipOrRole, requirePermissions, requireRoles, validateAPIKey, validateAPIKeyEntry, validateJWTClaims, verifyJWT, withAuth } from './auth/index.js';
|
|
@@ -25,7 +25,7 @@ export { C as CacheConfig, a as CacheEntry, b as CacheInvalidationConfig, c as C
|
|
|
25
25
|
export { CacheEndpointMethods, CacheInvalidationMethods, MemoryCacheStorage, RedisCacheStorage, RedisCacheStorageOptions, RedisClient, createInvalidationPattern, createRelatedPatterns, generateCacheKey, getCacheStorage, matchesPattern, parseCacheKey, setCacheStorage, withCache, withCacheInvalidation } from './cache/index.js';
|
|
26
26
|
export { MemoryLoggingStorage, MemoryLoggingStorageOptions, createLoggingMiddleware, extractClientIp, extractHeaders, extractUserId as extractLoggingUserId, extractQuery, generateRequestId, getLoggingStorage, getRequestId, getRequestStartTime, isAllowedContentType, matchPath as matchLoggingPath, redactHeaders, redactObject, setLoggingStorage, shouldExcludePath, shouldRedact, truncateBody } from './logging/index.js';
|
|
27
27
|
import * as hono_types from 'hono/types';
|
|
28
|
-
export { A as AdapterBundle, C as ConfigCreateEndpoint, D as ConfigDeleteEndpoint, L as ConfigListEndpoint, R as ConfigReadEndpoint, U as ConfigUpdateEndpoint, E as EndpointsConfig, G as GeneratedEndpoints, M as MemoryAdapters, d as defineEndpoints } from './index-
|
|
28
|
+
export { A as AdapterBundle, C as ConfigCreateEndpoint, D as ConfigDeleteEndpoint, L as ConfigListEndpoint, R as ConfigReadEndpoint, U as ConfigUpdateEndpoint, E as EndpointsConfig, G as GeneratedEndpoints, M as MemoryAdapters, d as defineEndpoints } from './index-bSnRLgcs.js';
|
|
29
29
|
import 'hono/utils/http-status';
|
|
30
30
|
import 'hono/http-exception';
|
|
31
31
|
|
|
@@ -484,6 +484,11 @@ declare class CrudEventEmitter {
|
|
|
484
484
|
private tableListeners;
|
|
485
485
|
/** Listeners for all events on all tables */
|
|
486
486
|
private globalListeners;
|
|
487
|
+
/** Maximum listeners per event key. 0 = unlimited. */
|
|
488
|
+
private maxListeners;
|
|
489
|
+
constructor(options?: {
|
|
490
|
+
maxListeners?: number;
|
|
491
|
+
});
|
|
487
492
|
/**
|
|
488
493
|
* Subscribe to a specific event type on a specific table.
|
|
489
494
|
*/
|
|
@@ -546,10 +551,17 @@ interface SubscribeEndpointConfig {
|
|
|
546
551
|
filter?: (event: CrudEventPayload, ctx: Context) => boolean;
|
|
547
552
|
/** Heartbeat interval in milliseconds. @default 30000 */
|
|
548
553
|
heartbeatInterval?: number;
|
|
554
|
+
/** Maximum concurrent SSE connections per table. @default 1000 */
|
|
555
|
+
maxConnections?: number;
|
|
556
|
+
/** Connection timeout in milliseconds. @default 300000 (5 min) */
|
|
557
|
+
connectionTimeout?: number;
|
|
558
|
+
/** Fields to strip from event payloads before streaming. @default ['password', 'token', 'secret', 'apiKey', 'creditCard', 'ssn'] */
|
|
559
|
+
excludeFields?: string[];
|
|
549
560
|
}
|
|
550
561
|
/**
|
|
551
562
|
* Create an SSE subscription handler for real-time CRUD events.
|
|
552
563
|
* Uses Hono's built-in `streamSSE()` which works on Cloudflare Workers.
|
|
564
|
+
* Edge-compatible: uses stream.sleep() instead of setInterval/setTimeout.
|
|
553
565
|
*
|
|
554
566
|
* @example
|
|
555
567
|
* ```ts
|
|
@@ -1535,8 +1547,11 @@ declare class MemoryIdempotencyStorage implements IdempotencyStorage {
|
|
|
1535
1547
|
private cleanupInterval;
|
|
1536
1548
|
/** Timestamp of last cleanup run */
|
|
1537
1549
|
private lastCleanup;
|
|
1550
|
+
/** Maximum number of entries before evicting oldest */
|
|
1551
|
+
private maxEntries;
|
|
1538
1552
|
constructor(options?: {
|
|
1539
1553
|
cleanupInterval?: number;
|
|
1554
|
+
maxEntries?: number;
|
|
1540
1555
|
});
|
|
1541
1556
|
private maybeCleanup;
|
|
1542
1557
|
private cleanupExpired;
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { MemoryDeleteEndpoint, MemoryUpdateEndpoint, MemoryReadEndpoint, MemoryListEndpoint, MemoryCreateEndpoint } from './chunk-
|
|
2
|
-
export { BulkPatchEndpoint, CloneEndpoint } from './chunk-
|
|
1
|
+
import { MemoryDeleteEndpoint, MemoryUpdateEndpoint, MemoryReadEndpoint, MemoryListEndpoint, MemoryCreateEndpoint } from './chunk-G7IQ5DWC.js';
|
|
2
|
+
export { BulkPatchEndpoint, CloneEndpoint } from './chunk-G7IQ5DWC.js';
|
|
3
3
|
export { scalarUI, setupDocs, setupDocsIndex, setupReDoc, setupScalar, setupSwaggerUI } from './chunk-CNE7UR5E.js';
|
|
4
|
-
export { AuthenticatedEndpoint, JWTClaimsSchema, allOf, allowAll, anyOf, createAPIKeyMiddleware, createAuthMiddleware, createJWTMiddleware, decodeJWT, defaultHashAPIKey, denyAll, optionalAuth, parseJWTClaims, requireAllRoles, requireAnyPermission, requireAuth, requireAuthenticated, requireAuthentication, requireOwnership, requireOwnershipOrRole, requirePermissions, requireRoles, safeParseJWTClaims, validateAPIKey, validateAPIKeyEntry, validateJWTClaims, verifyJWT, withAuth } from './chunk-
|
|
4
|
+
export { AuthenticatedEndpoint, JWTClaimsSchema, allOf, allowAll, anyOf, createAPIKeyMiddleware, createAuthMiddleware, createJWTMiddleware, decodeJWT, defaultHashAPIKey, denyAll, optionalAuth, parseJWTClaims, requireAllRoles, requireAnyPermission, requireAuth, requireAuthenticated, requireAuthentication, requireOwnership, requireOwnershipOrRole, requirePermissions, requireRoles, safeParseJWTClaims, validateAPIKey, validateAPIKeyEntry, validateJWTClaims, verifyJWT, withAuth } from './chunk-57J3NJYN.js';
|
|
5
5
|
export { RedisCacheStorage } from './chunk-YJMGFVHZ.js';
|
|
6
|
-
export { MemoryLoggingStorage } from './chunk-
|
|
6
|
+
export { MemoryLoggingStorage } from './chunk-I36Y45QN.js';
|
|
7
7
|
export { MemoryRateLimitStorage, RedisRateLimitStorage } from './chunk-MANRQHEB.js';
|
|
8
8
|
export { createAPIKeyStorageMiddleware, createAuditStorageMiddleware, createCacheStorageMiddleware, createLoggingStorageMiddleware, createRateLimitStorageMiddleware, createStorageMiddleware, createVersioningStorageMiddleware } from './chunk-ZCHXXN7T.js';
|
|
9
|
-
import { getRequestId } from './chunk-
|
|
10
|
-
export { MemoryCacheStorage, RateLimitExceededException, createInvalidationPattern, createLoggingMiddleware, createRateLimitMiddleware, createRelatedPatterns, extractAPIKey, extractClientIp, extractHeaders, extractIP, extractUserId as extractLoggingUserId, extractQuery, extractUserId2 as extractUserId, generateCacheKey, generateKey, generateRequestId, getCacheStorage, getErrorMessage, getLoggingStorage, getRateLimitStorage, getRequestId, getRequestStartTime, isAllowedContentType, matchPath as matchLoggingPath, matchPath2 as matchPath, matchesPattern, parseCacheKey, redactHeaders, redactObject, resetRateLimit, resolveAPIKeyStorage, resolveAuditStorage, resolveCacheStorage, resolveLoggingStorage, resolveRateLimitStorage, resolveVersioningStorage, setCacheStorage, setLoggingStorage, setRateLimitStorage, shouldExcludePath, shouldRedact, shouldSkipPath, toError, truncateBody, withCache, withCacheInvalidation, wrapError } from './chunk-
|
|
9
|
+
import { getRequestId } from './chunk-Y74QJH7Y.js';
|
|
10
|
+
export { MemoryCacheStorage, RateLimitExceededException, createInvalidationPattern, createLoggingMiddleware, createRateLimitMiddleware, createRelatedPatterns, extractAPIKey, extractClientIp, extractHeaders, extractIP, extractUserId as extractLoggingUserId, extractQuery, extractUserId2 as extractUserId, generateCacheKey, generateKey, generateRequestId, getCacheStorage, getErrorMessage, getLoggingStorage, getRateLimitStorage, getRequestId, getRequestStartTime, isAllowedContentType, matchPath as matchLoggingPath, matchPath2 as matchPath, matchesPattern, parseCacheKey, redactHeaders, redactObject, resetRateLimit, resolveAPIKeyStorage, resolveAuditStorage, resolveCacheStorage, resolveLoggingStorage, resolveRateLimitStorage, resolveVersioningStorage, setCacheStorage, setLoggingStorage, setRateLimitStorage, shouldExcludePath, shouldRedact, shouldSkipPath, toError, truncateBody, withCache, withCacheInvalidation, wrapError } from './chunk-Y74QJH7Y.js';
|
|
11
11
|
export { MemoryAPIKeyStorage, generateAPIKey, getAPIKeyStorage, hashAPIKey, isValidAPIKeyFormat, setAPIKeyStorage } from './chunk-6LS3LNIH.js';
|
|
12
|
-
export { AggregateEndpoint, BatchCreateEndpoint, BatchDeleteEndpoint, BatchRestoreEndpoint, BatchUpdateEndpoint, BatchUpsertEndpoint, CreateEndpoint, DeleteEndpoint, ExportEndpoint, ImportEndpoint, ListEndpoint, ReadEndpoint, RestoreEndpoint, SearchEndpoint, UpdateEndpoint, UpsertEndpoint, VersionCompareEndpoint, VersionHistoryEndpoint, VersionReadEndpoint, VersionRollbackEndpoint, applyFieldSelection, applyFieldSelectionToArray, buildSearchConfig, calculateScore, computeAggregations, createCsvStream, csvToJson, escapeCsvValue, generateCsv, generateETag, generateHighlights, getSchemaFields, inferCsvContentType, jsonToCsv, matchesIfMatch, matchesIfNoneMatch, parseCsv, parseFieldSelection, parseFilterValue, parseListFilters, parseSearchFields, searchInMemory, termFrequency, tokenize, tokenizeQuery, validateCsvHeaders } from './chunk-
|
|
12
|
+
export { AggregateEndpoint, BatchCreateEndpoint, BatchDeleteEndpoint, BatchRestoreEndpoint, BatchUpdateEndpoint, BatchUpsertEndpoint, CreateEndpoint, DeleteEndpoint, ExportEndpoint, ImportEndpoint, ListEndpoint, ReadEndpoint, RestoreEndpoint, SearchEndpoint, UpdateEndpoint, UpsertEndpoint, VersionCompareEndpoint, VersionHistoryEndpoint, VersionReadEndpoint, VersionRollbackEndpoint, applyFieldSelection, applyFieldSelectionToArray, buildSearchConfig, calculateScore, computeAggregations, createCsvStream, csvToJson, escapeCsvValue, generateCsv, generateETag, generateHighlights, getSchemaFields, inferCsvContentType, jsonToCsv, matchesIfMatch, matchesIfNoneMatch, parseCsv, parseFieldSelection, parseFilterValue, parseListFilters, parseSearchFields, searchInMemory, termFrequency, tokenize, tokenizeQuery, validateCsvHeaders } from './chunk-T6J4NSMC.js';
|
|
13
13
|
import { isRouteClass } from './chunk-CDCGYMC6.js';
|
|
14
14
|
export { OpenAPIRoute, isRouteClass } from './chunk-CDCGYMC6.js';
|
|
15
15
|
export { AuditLogger, MemoryAuditLogStorage, MemoryVersioningStorage, VersionManager, applyComputedFields, applyComputedFieldsToArray, calculateChanges, createAuditLogger, createVersionManager, decodeCursor, defineMeta, defineModel, encodeCursor, extractNestedData, extractTenantId, getAuditConfig, getAuditStorage, getMultiTenantConfig, getSoftDeleteConfig, getVersioningConfig, getVersioningStorage, isDirectNestedData, parseAggregateField, parseAggregateQuery, parseSearchMode, setAuditStorage, setVersioningStorage } from './chunk-U3SUUXJK.js';
|
|
16
|
-
import { createRegistryWithDefault, ApiException, InputValidationException, getLogger } from './chunk-FST5S5UY.js';
|
|
16
|
+
import { createRegistryWithDefault, ApiException, InputValidationException, getLogger, getContextVar } from './chunk-FST5S5UY.js';
|
|
17
17
|
export { AggregationException, ApiException, CacheException, ConfigurationException, ConflictException, ForbiddenException, InputValidationException, NotFoundException, StorageRegistry, UnauthorizedException, createNullableRegistry, createRegistryWithDefault, getAuthType, getRequestId as getContextRequestId, getContextVar, getLogger, getTenantId, getUser, getUserId, getUserPermissions, getUserRoles, hasAllPermissions, hasAllRoles, hasAnyRole, hasPermission, hasRole, setContextVar, setLogger } from './chunk-FST5S5UY.js';
|
|
18
18
|
import { OpenAPIHono, createRoute } from '@hono/zod-openapi';
|
|
19
19
|
import { HTTPException } from 'hono/http-exception';
|
|
@@ -290,6 +290,11 @@ var CrudEventEmitter = class {
|
|
|
290
290
|
tableListeners = /* @__PURE__ */ new Map();
|
|
291
291
|
/** Listeners for all events on all tables */
|
|
292
292
|
globalListeners = /* @__PURE__ */ new Set();
|
|
293
|
+
/** Maximum listeners per event key. 0 = unlimited. */
|
|
294
|
+
maxListeners;
|
|
295
|
+
constructor(options) {
|
|
296
|
+
this.maxListeners = options?.maxListeners ?? 100;
|
|
297
|
+
}
|
|
293
298
|
/**
|
|
294
299
|
* Subscribe to a specific event type on a specific table.
|
|
295
300
|
*/
|
|
@@ -298,7 +303,13 @@ var CrudEventEmitter = class {
|
|
|
298
303
|
if (!this.listeners.has(key)) {
|
|
299
304
|
this.listeners.set(key, /* @__PURE__ */ new Set());
|
|
300
305
|
}
|
|
301
|
-
this.listeners.get(key)
|
|
306
|
+
const set = this.listeners.get(key);
|
|
307
|
+
if (this.maxListeners > 0 && set.size >= this.maxListeners) {
|
|
308
|
+
getLogger().warn(`Max listeners (${this.maxListeners}) reached for event "${key}". Listener not added.`);
|
|
309
|
+
return { unsubscribe: () => {
|
|
310
|
+
} };
|
|
311
|
+
}
|
|
312
|
+
set.add(listener);
|
|
302
313
|
return {
|
|
303
314
|
unsubscribe: () => {
|
|
304
315
|
this.listeners.get(key)?.delete(listener);
|
|
@@ -312,7 +323,13 @@ var CrudEventEmitter = class {
|
|
|
312
323
|
if (!this.tableListeners.has(table)) {
|
|
313
324
|
this.tableListeners.set(table, /* @__PURE__ */ new Set());
|
|
314
325
|
}
|
|
315
|
-
this.tableListeners.get(table)
|
|
326
|
+
const set = this.tableListeners.get(table);
|
|
327
|
+
if (this.maxListeners > 0 && set.size >= this.maxListeners) {
|
|
328
|
+
getLogger().warn(`Max listeners (${this.maxListeners}) reached for table "${table}". Listener not added.`);
|
|
329
|
+
return { unsubscribe: () => {
|
|
330
|
+
} };
|
|
331
|
+
}
|
|
332
|
+
set.add(listener);
|
|
316
333
|
return {
|
|
317
334
|
unsubscribe: () => {
|
|
318
335
|
this.tableListeners.get(table)?.delete(listener);
|
|
@@ -323,6 +340,11 @@ var CrudEventEmitter = class {
|
|
|
323
340
|
* Subscribe to all events on all tables.
|
|
324
341
|
*/
|
|
325
342
|
onAny(listener) {
|
|
343
|
+
if (this.maxListeners > 0 && this.globalListeners.size >= this.maxListeners) {
|
|
344
|
+
getLogger().warn(`Max global listeners (${this.maxListeners}) reached. Listener not added.`);
|
|
345
|
+
return { unsubscribe: () => {
|
|
346
|
+
} };
|
|
347
|
+
}
|
|
326
348
|
this.globalListeners.add(listener);
|
|
327
349
|
return {
|
|
328
350
|
unsubscribe: () => {
|
|
@@ -413,19 +435,46 @@ function setEventEmitter(emitter) {
|
|
|
413
435
|
}
|
|
414
436
|
|
|
415
437
|
// src/endpoints/subscribe.ts
|
|
438
|
+
var connectionCounts = /* @__PURE__ */ new Map();
|
|
439
|
+
var DEFAULT_EXCLUDE_FIELDS = ["password", "token", "secret", "apiKey", "creditCard", "ssn"];
|
|
440
|
+
function stripSensitiveFields(data, excludeFields) {
|
|
441
|
+
if (data === null || data === void 0 || typeof data !== "object") {
|
|
442
|
+
return data;
|
|
443
|
+
}
|
|
444
|
+
if (Array.isArray(data)) {
|
|
445
|
+
return data.map((item) => stripSensitiveFields(item, excludeFields));
|
|
446
|
+
}
|
|
447
|
+
const result = {};
|
|
448
|
+
for (const [key, value] of Object.entries(data)) {
|
|
449
|
+
if (!excludeFields.includes(key)) {
|
|
450
|
+
result[key] = typeof value === "object" && value !== null ? stripSensitiveFields(value, excludeFields) : value;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return result;
|
|
454
|
+
}
|
|
416
455
|
function createSubscribeHandler(config) {
|
|
417
456
|
const {
|
|
418
457
|
table,
|
|
419
458
|
events: eventFilter,
|
|
420
459
|
emitter: customEmitter,
|
|
421
460
|
filter,
|
|
422
|
-
heartbeatInterval = 3e4
|
|
461
|
+
heartbeatInterval = 3e4,
|
|
462
|
+
maxConnections = 1e3,
|
|
463
|
+
connectionTimeout = 3e5,
|
|
464
|
+
excludeFields = DEFAULT_EXCLUDE_FIELDS
|
|
423
465
|
} = config;
|
|
424
466
|
return (ctx) => {
|
|
467
|
+
const currentCount = connectionCounts.get(table) || 0;
|
|
468
|
+
if (currentCount >= maxConnections) {
|
|
469
|
+
return ctx.json(
|
|
470
|
+
{ success: false, error: { code: "TOO_MANY_CONNECTIONS", message: "Too many SSE connections" } },
|
|
471
|
+
503
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
connectionCounts.set(table, currentCount + 1);
|
|
425
475
|
return streamSSE(ctx, async (stream) => {
|
|
426
476
|
const emitter = customEmitter ?? getEventEmitter();
|
|
427
477
|
let subscription;
|
|
428
|
-
let heartbeatTimer = null;
|
|
429
478
|
const listener = async (event) => {
|
|
430
479
|
if (eventFilter && eventFilter.length > 0 && !eventFilter.includes(event.type)) {
|
|
431
480
|
return;
|
|
@@ -433,6 +482,8 @@ function createSubscribeHandler(config) {
|
|
|
433
482
|
if (filter && !filter(event, ctx)) {
|
|
434
483
|
return;
|
|
435
484
|
}
|
|
485
|
+
const sanitizedData = excludeFields.length > 0 ? stripSensitiveFields(event.data, excludeFields) : event.data;
|
|
486
|
+
const sanitizedPreviousData = event.previousData && excludeFields.length > 0 ? stripSensitiveFields(event.previousData, excludeFields) : event.previousData;
|
|
436
487
|
try {
|
|
437
488
|
await stream.writeSSE({
|
|
438
489
|
event: `${event.table}.${event.type}`,
|
|
@@ -440,8 +491,8 @@ function createSubscribeHandler(config) {
|
|
|
440
491
|
type: event.type,
|
|
441
492
|
table: event.table,
|
|
442
493
|
recordId: event.recordId,
|
|
443
|
-
data:
|
|
444
|
-
previousData:
|
|
494
|
+
data: sanitizedData,
|
|
495
|
+
previousData: sanitizedPreviousData,
|
|
445
496
|
timestamp: event.timestamp
|
|
446
497
|
}),
|
|
447
498
|
id: `${event.table}-${event.recordId}-${Date.now()}`
|
|
@@ -450,23 +501,38 @@ function createSubscribeHandler(config) {
|
|
|
450
501
|
}
|
|
451
502
|
};
|
|
452
503
|
subscription = emitter.onTable(table, listener);
|
|
453
|
-
|
|
454
|
-
try {
|
|
455
|
-
await stream.writeSSE({
|
|
456
|
-
event: "heartbeat",
|
|
457
|
-
data: JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString() })
|
|
458
|
-
});
|
|
459
|
-
} catch {
|
|
460
|
-
}
|
|
461
|
-
}, heartbeatInterval);
|
|
462
|
-
stream.onAbort(() => {
|
|
504
|
+
const cleanup = () => {
|
|
463
505
|
subscription.unsubscribe();
|
|
464
|
-
|
|
465
|
-
|
|
506
|
+
const count = connectionCounts.get(table) || 1;
|
|
507
|
+
if (count <= 1) {
|
|
508
|
+
connectionCounts.delete(table);
|
|
509
|
+
} else {
|
|
510
|
+
connectionCounts.set(table, count - 1);
|
|
466
511
|
}
|
|
512
|
+
};
|
|
513
|
+
stream.onAbort(() => {
|
|
514
|
+
cleanup();
|
|
467
515
|
});
|
|
516
|
+
const startTime = Date.now();
|
|
517
|
+
let lastHeartbeat = startTime;
|
|
468
518
|
while (!stream.closed) {
|
|
469
519
|
await stream.sleep(1e3);
|
|
520
|
+
const now = Date.now();
|
|
521
|
+
if (now - startTime >= connectionTimeout) {
|
|
522
|
+
stream.abort();
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
if (now - lastHeartbeat >= heartbeatInterval) {
|
|
526
|
+
lastHeartbeat = now;
|
|
527
|
+
try {
|
|
528
|
+
await stream.writeSSE({
|
|
529
|
+
event: "heartbeat",
|
|
530
|
+
data: JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString() })
|
|
531
|
+
});
|
|
532
|
+
} catch {
|
|
533
|
+
break;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
470
536
|
}
|
|
471
537
|
});
|
|
472
538
|
};
|
|
@@ -756,8 +822,11 @@ var MemoryIdempotencyStorage = class {
|
|
|
756
822
|
cleanupInterval;
|
|
757
823
|
/** Timestamp of last cleanup run */
|
|
758
824
|
lastCleanup = 0;
|
|
825
|
+
/** Maximum number of entries before evicting oldest */
|
|
826
|
+
maxEntries;
|
|
759
827
|
constructor(options) {
|
|
760
828
|
this.cleanupInterval = options?.cleanupInterval ?? 6e4;
|
|
829
|
+
this.maxEntries = options?.maxEntries ?? 1e4;
|
|
761
830
|
}
|
|
762
831
|
maybeCleanup() {
|
|
763
832
|
if (this.cleanupInterval <= 0) return;
|
|
@@ -792,6 +861,12 @@ var MemoryIdempotencyStorage = class {
|
|
|
792
861
|
}
|
|
793
862
|
async set(key, entry, ttlMs) {
|
|
794
863
|
this.maybeCleanup();
|
|
864
|
+
if (this.maxEntries > 0 && this.entries.size >= this.maxEntries && !this.entries.has(key)) {
|
|
865
|
+
const oldestKey = this.entries.keys().next().value;
|
|
866
|
+
if (oldestKey !== void 0) {
|
|
867
|
+
this.entries.delete(oldestKey);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
795
870
|
this.entries.set(key, {
|
|
796
871
|
entry,
|
|
797
872
|
expiresAt: Date.now() + ttlMs
|
|
@@ -866,7 +941,9 @@ function idempotency(config) {
|
|
|
866
941
|
if (!storage) {
|
|
867
942
|
return next();
|
|
868
943
|
}
|
|
869
|
-
const
|
|
944
|
+
const userId = getContextVar(ctx, "userId") || "anonymous";
|
|
945
|
+
const scopedKey = `${userId}:${idempotencyKey}`;
|
|
946
|
+
const existing = await storage.get(scopedKey);
|
|
870
947
|
if (existing) {
|
|
871
948
|
return new Response(existing.body, {
|
|
872
949
|
status: existing.statusCode,
|
|
@@ -877,7 +954,7 @@ function idempotency(config) {
|
|
|
877
954
|
}
|
|
878
955
|
});
|
|
879
956
|
}
|
|
880
|
-
const locked = await storage.isLocked(
|
|
957
|
+
const locked = await storage.isLocked(scopedKey);
|
|
881
958
|
if (locked) {
|
|
882
959
|
return ctx.json(
|
|
883
960
|
{
|
|
@@ -890,7 +967,7 @@ function idempotency(config) {
|
|
|
890
967
|
409
|
|
891
968
|
);
|
|
892
969
|
}
|
|
893
|
-
const acquired = await storage.lock(
|
|
970
|
+
const acquired = await storage.lock(scopedKey, lockTimeoutMs);
|
|
894
971
|
if (!acquired) {
|
|
895
972
|
return ctx.json(
|
|
896
973
|
{
|
|
@@ -912,15 +989,15 @@ function idempotency(config) {
|
|
|
912
989
|
headers[key] = value;
|
|
913
990
|
});
|
|
914
991
|
const entry = {
|
|
915
|
-
key:
|
|
992
|
+
key: scopedKey,
|
|
916
993
|
statusCode: response.status,
|
|
917
994
|
body,
|
|
918
995
|
headers,
|
|
919
996
|
createdAt: Date.now()
|
|
920
997
|
};
|
|
921
|
-
await storage.set(
|
|
998
|
+
await storage.set(scopedKey, entry, ttlMs);
|
|
922
999
|
} finally {
|
|
923
|
-
await storage.unlock(
|
|
1000
|
+
await storage.unlock(scopedKey);
|
|
924
1001
|
}
|
|
925
1002
|
};
|
|
926
1003
|
}
|
package/dist/logging/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PathPattern, R as RedactField, d as LoggingConfig, e as LoggingStorage, a as LogEntry, c as LogQueryOptions } from '../types-
|
|
2
|
-
export { b as LogLevel, L as LoggingEnv, f as RequestBodyConfig, g as RequestLogEntry, h as ResponseBodyConfig, i as ResponseLogEntry } from '../types-
|
|
1
|
+
import { P as PathPattern, R as RedactField, d as LoggingConfig, e as LoggingStorage, a as LogEntry, c as LogQueryOptions } from '../types-DnQWCfXp.js';
|
|
2
|
+
export { b as LogLevel, L as LoggingEnv, f as RequestBodyConfig, g as RequestLogEntry, h as ResponseBodyConfig, i as ResponseLogEntry } from '../types-DnQWCfXp.js';
|
|
3
3
|
import { Env, Context, MiddlewareHandler } from 'hono';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -50,10 +50,10 @@ declare function shouldExcludePath(path: string, includePaths: PathPattern[], ex
|
|
|
50
50
|
*
|
|
51
51
|
* @param ctx - Hono context
|
|
52
52
|
* @param ipHeader - Header name for proxy IP (default: 'X-Forwarded-For')
|
|
53
|
-
* @param trustProxy - Whether to trust proxy headers (default:
|
|
53
|
+
* @param trustProxy - Whether to trust proxy headers (default: false)
|
|
54
54
|
* @returns The client IP address or undefined
|
|
55
55
|
*/
|
|
56
|
-
declare function extractClientIp<E extends Env>(ctx: Context<E>, ipHeader?: string,
|
|
56
|
+
declare function extractClientIp<E extends Env>(ctx: Context<E>, ipHeader?: string, _trustProxy?: boolean): string | undefined;
|
|
57
57
|
/**
|
|
58
58
|
* Extract headers from a Headers object to a plain object.
|
|
59
59
|
*
|
package/dist/logging/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { MemoryLoggingStorage } from '../chunk-
|
|
2
|
-
export { createLoggingMiddleware, extractClientIp, extractHeaders, extractQuery, extractUserId, generateRequestId, getLoggingStorage, getRequestId, getRequestStartTime, isAllowedContentType, matchPath, redactHeaders, redactObject, setLoggingStorage, shouldExcludePath, shouldRedact, truncateBody } from '../chunk-
|
|
1
|
+
export { MemoryLoggingStorage } from '../chunk-I36Y45QN.js';
|
|
2
|
+
export { createLoggingMiddleware, extractClientIp, extractHeaders, extractQuery, extractUserId, generateRequestId, getLoggingStorage, getRequestId, getRequestStartTime, isAllowedContentType, matchPath, redactHeaders, redactObject, setLoggingStorage, shouldExcludePath, shouldRedact, truncateBody } from '../chunk-Y74QJH7Y.js';
|
|
3
3
|
import '../chunk-6LS3LNIH.js';
|
|
4
4
|
import '../chunk-U3SUUXJK.js';
|
|
5
5
|
import '../chunk-FST5S5UY.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { F as FixedWindowEntry, K as KeyExtractor, a as KeyStrategy, O as OnRateLimitExceeded, P as PathPattern, b as RateLimitAlgorithm, c as RateLimitConfig, d as RateLimitEntry, R as RateLimitEnv, e as RateLimitResult, f as RateLimitStorage, g as RateLimitTier, S as SlidingWindowEntry, T as TierFunction } from '../types-
|
|
2
|
-
export { M as MemoryRateLimitStorage, d as MemoryRateLimitStorageOptions, R as RateLimitExceededException, e as RedisRateLimitClient, f as RedisRateLimitStorage, g as RedisRateLimitStorageOptions, h as createRateLimitMiddleware, i as extractAPIKey, j as extractIP, k as extractUserId, l as generateKey, m as getRateLimitStorage, n as matchPath, r as resetRateLimit, s as setRateLimitStorage, o as shouldSkipPath } from '../index-
|
|
1
|
+
export { F as FixedWindowEntry, K as KeyExtractor, a as KeyStrategy, O as OnRateLimitExceeded, P as PathPattern, b as RateLimitAlgorithm, c as RateLimitConfig, d as RateLimitEntry, R as RateLimitEnv, e as RateLimitResult, f as RateLimitStorage, g as RateLimitTier, S as SlidingWindowEntry, T as TierFunction } from '../types-BO3G_MZk.js';
|
|
2
|
+
export { M as MemoryRateLimitStorage, d as MemoryRateLimitStorageOptions, R as RateLimitExceededException, e as RedisRateLimitClient, f as RedisRateLimitStorage, g as RedisRateLimitStorageOptions, h as createRateLimitMiddleware, i as extractAPIKey, j as extractIP, k as extractUserId, l as generateKey, m as getRateLimitStorage, n as matchPath, r as resetRateLimit, s as setRateLimitStorage, o as shouldSkipPath } from '../index-431Ovi2o.js';
|
|
3
3
|
import 'hono';
|
|
4
4
|
import 'hono/http-exception';
|
|
5
5
|
import 'zod';
|
package/dist/rate-limit/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { MemoryRateLimitStorage, RedisRateLimitStorage } from '../chunk-MANRQHEB.js';
|
|
2
|
-
export { RateLimitExceededException, createRateLimitMiddleware, extractAPIKey, extractIP, extractUserId2 as extractUserId, generateKey, getRateLimitStorage, matchPath2 as matchPath, resetRateLimit, setRateLimitStorage, shouldSkipPath } from '../chunk-
|
|
2
|
+
export { RateLimitExceededException, createRateLimitMiddleware, extractAPIKey, extractIP, extractUserId2 as extractUserId, generateKey, getRateLimitStorage, matchPath2 as matchPath, resetRateLimit, setRateLimitStorage, shouldSkipPath } from '../chunk-Y74QJH7Y.js';
|
|
3
3
|
import '../chunk-6LS3LNIH.js';
|
|
4
4
|
import '../chunk-U3SUUXJK.js';
|
|
5
5
|
import '../chunk-FST5S5UY.js';
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Env, MiddlewareHandler, Context } from 'hono';
|
|
2
|
-
import { f as RateLimitStorage } from '../types-
|
|
3
|
-
import { e as LoggingStorage } from '../types-
|
|
2
|
+
import { f as RateLimitStorage } from '../types-BO3G_MZk.js';
|
|
3
|
+
import { e as LoggingStorage } from '../types-DnQWCfXp.js';
|
|
4
4
|
import { f as CacheStorage } from '../types-DlIkjpdK.js';
|
|
5
5
|
import { a as AuditLogStorage, c as VersioningStorage } from '../versioning-BG8-R7C0.js';
|
|
6
6
|
import { M as MemoryAPIKeyStorage } from '../memory-B_NZbOQP.js';
|
package/dist/storage/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createAPIKeyStorageMiddleware, createAuditStorageMiddleware, createCacheStorageMiddleware, createLoggingStorageMiddleware, createRateLimitStorageMiddleware, createStorageMiddleware, createVersioningStorageMiddleware } from '../chunk-ZCHXXN7T.js';
|
|
2
|
-
export { resolveAPIKeyStorage, resolveAuditStorage, resolveCacheStorage, resolveLoggingStorage, resolveRateLimitStorage, resolveVersioningStorage } from '../chunk-
|
|
2
|
+
export { resolveAPIKeyStorage, resolveAuditStorage, resolveCacheStorage, resolveLoggingStorage, resolveRateLimitStorage, resolveVersioningStorage } from '../chunk-Y74QJH7Y.js';
|
|
3
3
|
import '../chunk-6LS3LNIH.js';
|
|
4
4
|
import '../chunk-U3SUUXJK.js';
|
|
5
5
|
export { StorageRegistry, createNullableRegistry, createRegistryWithDefault } from '../chunk-FST5S5UY.js';
|
|
@@ -192,8 +192,8 @@ interface RateLimitConfig<E extends Env = Env> {
|
|
|
192
192
|
ipHeader?: string;
|
|
193
193
|
/**
|
|
194
194
|
* Whether to trust the proxy header for IP extraction.
|
|
195
|
-
* Set to
|
|
196
|
-
* @default
|
|
195
|
+
* Set to true if behind a trusted proxy.
|
|
196
|
+
* @default false
|
|
197
197
|
*/
|
|
198
198
|
trustProxy?: boolean;
|
|
199
199
|
/**
|