@plyaz/types 1.18.0 → 1.18.2
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/dist/api/endpoints/featureFlags/endpoints.d.ts +83 -0
- package/dist/api/endpoints/featureFlags/index.d.ts +8 -0
- package/dist/api/endpoints/featureFlags/types.d.ts +153 -0
- package/dist/api/endpoints/index.d.ts +1 -0
- package/dist/api/endpoints/types.d.ts +2 -1
- package/dist/api/index.cjs +52 -0
- package/dist/api/index.cjs.map +1 -1
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +52 -0
- package/dist/api/index.js.map +1 -1
- package/dist/core/events/index.d.ts +4 -0
- package/dist/core/events/payloads.d.ts +168 -0
- package/dist/core/featureFlag/enums.d.ts +11 -6
- package/dist/core/featureFlag/types.d.ts +146 -1
- package/dist/core/index.d.ts +3 -0
- package/dist/core/modules.d.ts +408 -0
- package/dist/db/audit.types.d.ts +22 -0
- package/dist/db/config.types.d.ts +21 -1
- package/dist/db/database.types.d.ts +2 -0
- package/dist/db/databaseAdapter.d.ts +13 -3
- package/dist/db/databaseService.d.ts +21 -48
- package/dist/db/dbEnums.d.ts +33 -5
- package/dist/db/extensions.types.d.ts +35 -0
- package/dist/db/features-config.types.d.ts +28 -2
- package/dist/db/health.types.d.ts +16 -0
- package/dist/db/index.cjs +20 -3
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.ts +5 -0
- package/dist/db/index.js +20 -4
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.types.d.ts +60 -0
- package/dist/db/seeds.types.d.ts +49 -0
- package/dist/db/tenant.types.d.ts +14 -0
- package/dist/errors/codes.d.ts +8 -0
- package/dist/errors/enums.d.ts +3 -0
- package/dist/errors/index.cjs +55 -0
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.js +55 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/examples/index.cjs +76 -0
- package/dist/examples/index.cjs.map +1 -0
- package/dist/examples/index.d.ts +17 -0
- package/dist/examples/index.js +68 -0
- package/dist/examples/index.js.map +1 -0
- package/dist/examples/schemas.d.ts +119 -0
- package/dist/examples/types.d.ts +103 -0
- package/dist/features/feature-flag/types.d.ts +62 -32
- package/dist/index.cjs +107 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +103 -14
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
|
|
5
|
+
// @plyaz package - Built with tsup
|
|
6
|
+
|
|
7
|
+
var NAME_MIN_LENGTH = 3;
|
|
8
|
+
var NAME_MAX_LENGTH = 100;
|
|
9
|
+
var DECIMAL_PRECISION_MULTIPLIER = 100;
|
|
10
|
+
var PAGINATION_MAX_LIMIT = 100;
|
|
11
|
+
var PAGINATION_DEFAULT_LIMIT = 20;
|
|
12
|
+
var CreateExampleSchema = zod.z.object({
|
|
13
|
+
// String with sanitization (trim)
|
|
14
|
+
name: zod.z.string().trim().min(NAME_MIN_LENGTH, `Name must be at least ${NAME_MIN_LENGTH} characters`).max(NAME_MAX_LENGTH, `Name must be at most ${NAME_MAX_LENGTH} characters`),
|
|
15
|
+
// Optional string with sanitization (trim + empty to undefined)
|
|
16
|
+
description: zod.z.string().trim().optional().transform((val) => val ?? void 0),
|
|
17
|
+
// Number with sanitization (round to 2 decimal places)
|
|
18
|
+
amount: zod.z.number().positive("Amount must be positive").transform(
|
|
19
|
+
(val) => Math.round(val * DECIMAL_PRECISION_MULTIPLIER) / DECIMAL_PRECISION_MULTIPLIER
|
|
20
|
+
),
|
|
21
|
+
// Boolean with default
|
|
22
|
+
is_visible: zod.z.boolean().default(true)
|
|
23
|
+
});
|
|
24
|
+
var UpdateExampleSchema = CreateExampleSchema;
|
|
25
|
+
var PatchExampleSchema = CreateExampleSchema.partial();
|
|
26
|
+
var QueryExampleSchema = zod.z.object({
|
|
27
|
+
// Pagination
|
|
28
|
+
page: zod.z.coerce.number().int().positive().default(1),
|
|
29
|
+
limit: zod.z.coerce.number().int().min(1).max(PAGINATION_MAX_LIMIT).default(PAGINATION_DEFAULT_LIMIT),
|
|
30
|
+
// Sorting
|
|
31
|
+
sort_by: zod.z.enum(["name", "amount", "created_at", "updated_at"]).default("created_at"),
|
|
32
|
+
sort_order: zod.z.enum(["asc", "desc"]).default("desc"),
|
|
33
|
+
// Filters
|
|
34
|
+
status: zod.z.enum(["draft", "active", "archived"]).optional(),
|
|
35
|
+
is_visible: zod.z.coerce.boolean().optional(),
|
|
36
|
+
min_amount: zod.z.coerce.number().positive().optional(),
|
|
37
|
+
max_amount: zod.z.coerce.number().positive().optional(),
|
|
38
|
+
// Search
|
|
39
|
+
search: zod.z.string().trim().optional()
|
|
40
|
+
});
|
|
41
|
+
var DeleteExampleSchema = zod.z.object({
|
|
42
|
+
// Soft delete flag
|
|
43
|
+
soft: zod.z.boolean().default(true),
|
|
44
|
+
// Reason for audit
|
|
45
|
+
reason: zod.z.string().trim().optional()
|
|
46
|
+
});
|
|
47
|
+
var ExampleResponseSchema = zod.z.object({
|
|
48
|
+
id: zod.z.string().uuid(),
|
|
49
|
+
name: zod.z.string(),
|
|
50
|
+
description: zod.z.string().nullable(),
|
|
51
|
+
owner_id: zod.z.string().uuid(),
|
|
52
|
+
status: zod.z.enum(["draft", "active", "archived"]),
|
|
53
|
+
amount: zod.z.number(),
|
|
54
|
+
is_visible: zod.z.boolean(),
|
|
55
|
+
created_at: zod.z.string().datetime(),
|
|
56
|
+
updated_at: zod.z.string().datetime()
|
|
57
|
+
});
|
|
58
|
+
var ExampleListResponseSchema = zod.z.object({
|
|
59
|
+
data: zod.z.array(ExampleResponseSchema),
|
|
60
|
+
meta: zod.z.object({
|
|
61
|
+
page: zod.z.number(),
|
|
62
|
+
limit: zod.z.number(),
|
|
63
|
+
total: zod.z.number(),
|
|
64
|
+
total_pages: zod.z.number()
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
exports.CreateExampleSchema = CreateExampleSchema;
|
|
69
|
+
exports.DeleteExampleSchema = DeleteExampleSchema;
|
|
70
|
+
exports.ExampleListResponseSchema = ExampleListResponseSchema;
|
|
71
|
+
exports.ExampleResponseSchema = ExampleResponseSchema;
|
|
72
|
+
exports.PatchExampleSchema = PatchExampleSchema;
|
|
73
|
+
exports.QueryExampleSchema = QueryExampleSchema;
|
|
74
|
+
exports.UpdateExampleSchema = UpdateExampleSchema;
|
|
75
|
+
//# sourceMappingURL=index.cjs.map
|
|
76
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/examples/schemas.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Example Schemas\n *\n * Demonstrates Zod schema patterns for validation + sanitization.\n * These schemas are used by @plyaz/core validators.\n *\n * Key concepts:\n * - Validation: min, max, email, regex, etc.\n * - Sanitization: trim, toLowerCase, transform, default\n */\n\nimport { z } from 'zod';\n\n// ─────────────────────────────────────────────────────────────────\n// Schema Constants\n// ─────────────────────────────────────────────────────────────────\n\n/** Minimum length for name field */\nconst NAME_MIN_LENGTH = 3;\n/** Maximum length for name field */\nconst NAME_MAX_LENGTH = 100;\n/** Multiplier for rounding to 2 decimal places */\nconst DECIMAL_PRECISION_MULTIPLIER = 100;\n/** Maximum items per page for pagination */\nconst PAGINATION_MAX_LIMIT = 100;\n/** Default items per page for pagination */\nconst PAGINATION_DEFAULT_LIMIT = 20;\n\n// ─────────────────────────────────────────────────────────────────\n// Create Schema (POST)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for creating an example entity\n * Handles both validation AND sanitization\n */\nexport const CreateExampleSchema = z.object({\n // String with sanitization (trim)\n name: z\n .string()\n .trim()\n .min(NAME_MIN_LENGTH, `Name must be at least ${NAME_MIN_LENGTH} characters`)\n .max(NAME_MAX_LENGTH, `Name must be at most ${NAME_MAX_LENGTH} characters`),\n\n // Optional string with sanitization (trim + empty to undefined)\n description: z\n .string()\n .trim()\n .optional()\n .transform(val => val ?? undefined),\n\n // Number with sanitization (round to 2 decimal places)\n amount: z\n .number()\n .positive('Amount must be positive')\n .transform(\n val => Math.round(val * DECIMAL_PRECISION_MULTIPLIER) / DECIMAL_PRECISION_MULTIPLIER\n ),\n\n // Boolean with default\n is_visible: z.boolean().default(true),\n});\n\n// ─────────────────────────────────────────────────────────────────\n// Update Schema (PUT - full replacement)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for full update (PUT)\n * All fields required (replaces entire entity)\n */\nexport const UpdateExampleSchema = CreateExampleSchema;\n\n// ─────────────────────────────────────────────────────────────────\n// Patch Schema (PATCH - partial update)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for partial update (PATCH)\n * All fields optional\n */\nexport const PatchExampleSchema = CreateExampleSchema.partial();\n\n// ─────────────────────────────────────────────────────────────────\n// Query/Filter Schema (GET with params)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for query parameters (GET list)\n */\nexport const QueryExampleSchema = z.object({\n // Pagination\n page: z.coerce.number().int().positive().default(1),\n limit: z.coerce.number().int().min(1).max(PAGINATION_MAX_LIMIT).default(PAGINATION_DEFAULT_LIMIT),\n\n // Sorting\n sort_by: z.enum(['name', 'amount', 'created_at', 'updated_at']).default('created_at'),\n sort_order: z.enum(['asc', 'desc']).default('desc'),\n\n // Filters\n status: z.enum(['draft', 'active', 'archived']).optional(),\n is_visible: z.coerce.boolean().optional(),\n min_amount: z.coerce.number().positive().optional(),\n max_amount: z.coerce.number().positive().optional(),\n\n // Search\n search: z.string().trim().optional(),\n});\n\n// ─────────────────────────────────────────────────────────────────\n// Delete Schema (DELETE with params)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for delete operation\n * Can include options like soft delete, cascade, etc.\n */\nexport const DeleteExampleSchema = z.object({\n // Soft delete flag\n soft: z.boolean().default(true),\n\n // Reason for audit\n reason: z.string().trim().optional(),\n});\n\n// ─────────────────────────────────────────────────────────────────\n// Response Schema (validate API response)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for validating API response\n */\nexport const ExampleResponseSchema = z.object({\n id: z.string().uuid(),\n name: z.string(),\n description: z.string().nullable(),\n owner_id: z.string().uuid(),\n status: z.enum(['draft', 'active', 'archived']),\n amount: z.number(),\n is_visible: z.boolean(),\n created_at: z.string().datetime(),\n updated_at: z.string().datetime(),\n});\n\n/**\n * Schema for list response with pagination\n */\nexport const ExampleListResponseSchema = z.object({\n data: z.array(ExampleResponseSchema),\n meta: z.object({\n page: z.number(),\n limit: z.number(),\n total: z.number(),\n total_pages: z.number(),\n }),\n});\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example Domain Types & Schemas
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates the pattern for domain types in @plyaz/types.
|
|
5
|
+
* Used by @plyaz/core for testing and as reference implementation.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import {
|
|
10
|
+
* CreateExampleSchema,
|
|
11
|
+
* CreateExampleDTO,
|
|
12
|
+
* ExampleEntity,
|
|
13
|
+
* } from '@plyaz/types/examples';
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export { CreateExampleSchema, UpdateExampleSchema, PatchExampleSchema, QueryExampleSchema, DeleteExampleSchema, ExampleResponseSchema, ExampleListResponseSchema, } from './schemas';
|
|
17
|
+
export type { CreateExampleDTO, UpdateExampleDTO, PatchExampleDTO, QueryExampleDTO, DeleteExampleDTO, ExampleResponseDTO, ExampleListResponseDTO, ExampleEntity, ExampleStoreItem, ExampleStoreState, ExampleCreatedPayload, ExampleUpdatedPayload, ExampleDeletedPayload, ExampleValidationFailedPayload, } from './types';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
// @plyaz package - Built with tsup
|
|
4
|
+
|
|
5
|
+
var NAME_MIN_LENGTH = 3;
|
|
6
|
+
var NAME_MAX_LENGTH = 100;
|
|
7
|
+
var DECIMAL_PRECISION_MULTIPLIER = 100;
|
|
8
|
+
var PAGINATION_MAX_LIMIT = 100;
|
|
9
|
+
var PAGINATION_DEFAULT_LIMIT = 20;
|
|
10
|
+
var CreateExampleSchema = z.object({
|
|
11
|
+
// String with sanitization (trim)
|
|
12
|
+
name: z.string().trim().min(NAME_MIN_LENGTH, `Name must be at least ${NAME_MIN_LENGTH} characters`).max(NAME_MAX_LENGTH, `Name must be at most ${NAME_MAX_LENGTH} characters`),
|
|
13
|
+
// Optional string with sanitization (trim + empty to undefined)
|
|
14
|
+
description: z.string().trim().optional().transform((val) => val ?? void 0),
|
|
15
|
+
// Number with sanitization (round to 2 decimal places)
|
|
16
|
+
amount: z.number().positive("Amount must be positive").transform(
|
|
17
|
+
(val) => Math.round(val * DECIMAL_PRECISION_MULTIPLIER) / DECIMAL_PRECISION_MULTIPLIER
|
|
18
|
+
),
|
|
19
|
+
// Boolean with default
|
|
20
|
+
is_visible: z.boolean().default(true)
|
|
21
|
+
});
|
|
22
|
+
var UpdateExampleSchema = CreateExampleSchema;
|
|
23
|
+
var PatchExampleSchema = CreateExampleSchema.partial();
|
|
24
|
+
var QueryExampleSchema = z.object({
|
|
25
|
+
// Pagination
|
|
26
|
+
page: z.coerce.number().int().positive().default(1),
|
|
27
|
+
limit: z.coerce.number().int().min(1).max(PAGINATION_MAX_LIMIT).default(PAGINATION_DEFAULT_LIMIT),
|
|
28
|
+
// Sorting
|
|
29
|
+
sort_by: z.enum(["name", "amount", "created_at", "updated_at"]).default("created_at"),
|
|
30
|
+
sort_order: z.enum(["asc", "desc"]).default("desc"),
|
|
31
|
+
// Filters
|
|
32
|
+
status: z.enum(["draft", "active", "archived"]).optional(),
|
|
33
|
+
is_visible: z.coerce.boolean().optional(),
|
|
34
|
+
min_amount: z.coerce.number().positive().optional(),
|
|
35
|
+
max_amount: z.coerce.number().positive().optional(),
|
|
36
|
+
// Search
|
|
37
|
+
search: z.string().trim().optional()
|
|
38
|
+
});
|
|
39
|
+
var DeleteExampleSchema = z.object({
|
|
40
|
+
// Soft delete flag
|
|
41
|
+
soft: z.boolean().default(true),
|
|
42
|
+
// Reason for audit
|
|
43
|
+
reason: z.string().trim().optional()
|
|
44
|
+
});
|
|
45
|
+
var ExampleResponseSchema = z.object({
|
|
46
|
+
id: z.string().uuid(),
|
|
47
|
+
name: z.string(),
|
|
48
|
+
description: z.string().nullable(),
|
|
49
|
+
owner_id: z.string().uuid(),
|
|
50
|
+
status: z.enum(["draft", "active", "archived"]),
|
|
51
|
+
amount: z.number(),
|
|
52
|
+
is_visible: z.boolean(),
|
|
53
|
+
created_at: z.string().datetime(),
|
|
54
|
+
updated_at: z.string().datetime()
|
|
55
|
+
});
|
|
56
|
+
var ExampleListResponseSchema = z.object({
|
|
57
|
+
data: z.array(ExampleResponseSchema),
|
|
58
|
+
meta: z.object({
|
|
59
|
+
page: z.number(),
|
|
60
|
+
limit: z.number(),
|
|
61
|
+
total: z.number(),
|
|
62
|
+
total_pages: z.number()
|
|
63
|
+
})
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
export { CreateExampleSchema, DeleteExampleSchema, ExampleListResponseSchema, ExampleResponseSchema, PatchExampleSchema, QueryExampleSchema, UpdateExampleSchema };
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/examples/schemas.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Example Schemas\n *\n * Demonstrates Zod schema patterns for validation + sanitization.\n * These schemas are used by @plyaz/core validators.\n *\n * Key concepts:\n * - Validation: min, max, email, regex, etc.\n * - Sanitization: trim, toLowerCase, transform, default\n */\n\nimport { z } from 'zod';\n\n// ─────────────────────────────────────────────────────────────────\n// Schema Constants\n// ─────────────────────────────────────────────────────────────────\n\n/** Minimum length for name field */\nconst NAME_MIN_LENGTH = 3;\n/** Maximum length for name field */\nconst NAME_MAX_LENGTH = 100;\n/** Multiplier for rounding to 2 decimal places */\nconst DECIMAL_PRECISION_MULTIPLIER = 100;\n/** Maximum items per page for pagination */\nconst PAGINATION_MAX_LIMIT = 100;\n/** Default items per page for pagination */\nconst PAGINATION_DEFAULT_LIMIT = 20;\n\n// ─────────────────────────────────────────────────────────────────\n// Create Schema (POST)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for creating an example entity\n * Handles both validation AND sanitization\n */\nexport const CreateExampleSchema = z.object({\n // String with sanitization (trim)\n name: z\n .string()\n .trim()\n .min(NAME_MIN_LENGTH, `Name must be at least ${NAME_MIN_LENGTH} characters`)\n .max(NAME_MAX_LENGTH, `Name must be at most ${NAME_MAX_LENGTH} characters`),\n\n // Optional string with sanitization (trim + empty to undefined)\n description: z\n .string()\n .trim()\n .optional()\n .transform(val => val ?? undefined),\n\n // Number with sanitization (round to 2 decimal places)\n amount: z\n .number()\n .positive('Amount must be positive')\n .transform(\n val => Math.round(val * DECIMAL_PRECISION_MULTIPLIER) / DECIMAL_PRECISION_MULTIPLIER\n ),\n\n // Boolean with default\n is_visible: z.boolean().default(true),\n});\n\n// ─────────────────────────────────────────────────────────────────\n// Update Schema (PUT - full replacement)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for full update (PUT)\n * All fields required (replaces entire entity)\n */\nexport const UpdateExampleSchema = CreateExampleSchema;\n\n// ─────────────────────────────────────────────────────────────────\n// Patch Schema (PATCH - partial update)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for partial update (PATCH)\n * All fields optional\n */\nexport const PatchExampleSchema = CreateExampleSchema.partial();\n\n// ─────────────────────────────────────────────────────────────────\n// Query/Filter Schema (GET with params)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for query parameters (GET list)\n */\nexport const QueryExampleSchema = z.object({\n // Pagination\n page: z.coerce.number().int().positive().default(1),\n limit: z.coerce.number().int().min(1).max(PAGINATION_MAX_LIMIT).default(PAGINATION_DEFAULT_LIMIT),\n\n // Sorting\n sort_by: z.enum(['name', 'amount', 'created_at', 'updated_at']).default('created_at'),\n sort_order: z.enum(['asc', 'desc']).default('desc'),\n\n // Filters\n status: z.enum(['draft', 'active', 'archived']).optional(),\n is_visible: z.coerce.boolean().optional(),\n min_amount: z.coerce.number().positive().optional(),\n max_amount: z.coerce.number().positive().optional(),\n\n // Search\n search: z.string().trim().optional(),\n});\n\n// ─────────────────────────────────────────────────────────────────\n// Delete Schema (DELETE with params)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for delete operation\n * Can include options like soft delete, cascade, etc.\n */\nexport const DeleteExampleSchema = z.object({\n // Soft delete flag\n soft: z.boolean().default(true),\n\n // Reason for audit\n reason: z.string().trim().optional(),\n});\n\n// ─────────────────────────────────────────────────────────────────\n// Response Schema (validate API response)\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Schema for validating API response\n */\nexport const ExampleResponseSchema = z.object({\n id: z.string().uuid(),\n name: z.string(),\n description: z.string().nullable(),\n owner_id: z.string().uuid(),\n status: z.enum(['draft', 'active', 'archived']),\n amount: z.number(),\n is_visible: z.boolean(),\n created_at: z.string().datetime(),\n updated_at: z.string().datetime(),\n});\n\n/**\n * Schema for list response with pagination\n */\nexport const ExampleListResponseSchema = z.object({\n data: z.array(ExampleResponseSchema),\n meta: z.object({\n page: z.number(),\n limit: z.number(),\n total: z.number(),\n total_pages: z.number(),\n }),\n});\n"]}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example Schemas
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates Zod schema patterns for validation + sanitization.
|
|
5
|
+
* These schemas are used by @plyaz/core validators.
|
|
6
|
+
*
|
|
7
|
+
* Key concepts:
|
|
8
|
+
* - Validation: min, max, email, regex, etc.
|
|
9
|
+
* - Sanitization: trim, toLowerCase, transform, default
|
|
10
|
+
*/
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
/**
|
|
13
|
+
* Schema for creating an example entity
|
|
14
|
+
* Handles both validation AND sanitization
|
|
15
|
+
*/
|
|
16
|
+
export declare const CreateExampleSchema: z.ZodObject<{
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
description: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string, string>>;
|
|
19
|
+
amount: z.ZodPipe<z.ZodNumber, z.ZodTransform<number, number>>;
|
|
20
|
+
is_visible: z.ZodDefault<z.ZodBoolean>;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
/**
|
|
23
|
+
* Schema for full update (PUT)
|
|
24
|
+
* All fields required (replaces entire entity)
|
|
25
|
+
*/
|
|
26
|
+
export declare const UpdateExampleSchema: z.ZodObject<{
|
|
27
|
+
name: z.ZodString;
|
|
28
|
+
description: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string, string>>;
|
|
29
|
+
amount: z.ZodPipe<z.ZodNumber, z.ZodTransform<number, number>>;
|
|
30
|
+
is_visible: z.ZodDefault<z.ZodBoolean>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
/**
|
|
33
|
+
* Schema for partial update (PATCH)
|
|
34
|
+
* All fields optional
|
|
35
|
+
*/
|
|
36
|
+
export declare const PatchExampleSchema: z.ZodObject<{
|
|
37
|
+
name: z.ZodOptional<z.ZodString>;
|
|
38
|
+
description: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string, string>>>;
|
|
39
|
+
amount: z.ZodOptional<z.ZodPipe<z.ZodNumber, z.ZodTransform<number, number>>>;
|
|
40
|
+
is_visible: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
/**
|
|
43
|
+
* Schema for query parameters (GET list)
|
|
44
|
+
*/
|
|
45
|
+
export declare const QueryExampleSchema: z.ZodObject<{
|
|
46
|
+
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
47
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
48
|
+
sort_by: z.ZodDefault<z.ZodEnum<{
|
|
49
|
+
name: "name";
|
|
50
|
+
created_at: "created_at";
|
|
51
|
+
updated_at: "updated_at";
|
|
52
|
+
amount: "amount";
|
|
53
|
+
}>>;
|
|
54
|
+
sort_order: z.ZodDefault<z.ZodEnum<{
|
|
55
|
+
asc: "asc";
|
|
56
|
+
desc: "desc";
|
|
57
|
+
}>>;
|
|
58
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
59
|
+
active: "active";
|
|
60
|
+
draft: "draft";
|
|
61
|
+
archived: "archived";
|
|
62
|
+
}>>;
|
|
63
|
+
is_visible: z.ZodOptional<z.ZodCoercedBoolean<unknown>>;
|
|
64
|
+
min_amount: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
65
|
+
max_amount: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
66
|
+
search: z.ZodOptional<z.ZodString>;
|
|
67
|
+
}, z.core.$strip>;
|
|
68
|
+
/**
|
|
69
|
+
* Schema for delete operation
|
|
70
|
+
* Can include options like soft delete, cascade, etc.
|
|
71
|
+
*/
|
|
72
|
+
export declare const DeleteExampleSchema: z.ZodObject<{
|
|
73
|
+
soft: z.ZodDefault<z.ZodBoolean>;
|
|
74
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
75
|
+
}, z.core.$strip>;
|
|
76
|
+
/**
|
|
77
|
+
* Schema for validating API response
|
|
78
|
+
*/
|
|
79
|
+
export declare const ExampleResponseSchema: z.ZodObject<{
|
|
80
|
+
id: z.ZodString;
|
|
81
|
+
name: z.ZodString;
|
|
82
|
+
description: z.ZodNullable<z.ZodString>;
|
|
83
|
+
owner_id: z.ZodString;
|
|
84
|
+
status: z.ZodEnum<{
|
|
85
|
+
active: "active";
|
|
86
|
+
draft: "draft";
|
|
87
|
+
archived: "archived";
|
|
88
|
+
}>;
|
|
89
|
+
amount: z.ZodNumber;
|
|
90
|
+
is_visible: z.ZodBoolean;
|
|
91
|
+
created_at: z.ZodString;
|
|
92
|
+
updated_at: z.ZodString;
|
|
93
|
+
}, z.core.$strip>;
|
|
94
|
+
/**
|
|
95
|
+
* Schema for list response with pagination
|
|
96
|
+
*/
|
|
97
|
+
export declare const ExampleListResponseSchema: z.ZodObject<{
|
|
98
|
+
data: z.ZodArray<z.ZodObject<{
|
|
99
|
+
id: z.ZodString;
|
|
100
|
+
name: z.ZodString;
|
|
101
|
+
description: z.ZodNullable<z.ZodString>;
|
|
102
|
+
owner_id: z.ZodString;
|
|
103
|
+
status: z.ZodEnum<{
|
|
104
|
+
active: "active";
|
|
105
|
+
draft: "draft";
|
|
106
|
+
archived: "archived";
|
|
107
|
+
}>;
|
|
108
|
+
amount: z.ZodNumber;
|
|
109
|
+
is_visible: z.ZodBoolean;
|
|
110
|
+
created_at: z.ZodString;
|
|
111
|
+
updated_at: z.ZodString;
|
|
112
|
+
}, z.core.$strip>>;
|
|
113
|
+
meta: z.ZodObject<{
|
|
114
|
+
page: z.ZodNumber;
|
|
115
|
+
limit: z.ZodNumber;
|
|
116
|
+
total: z.ZodNumber;
|
|
117
|
+
total_pages: z.ZodNumber;
|
|
118
|
+
}, z.core.$strip>;
|
|
119
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example Types
|
|
3
|
+
*
|
|
4
|
+
* TypeScript interfaces and types for the example domain.
|
|
5
|
+
* Inferred from Zod schemas where possible.
|
|
6
|
+
*/
|
|
7
|
+
import type { z } from 'zod';
|
|
8
|
+
import type { CreateExampleSchema, UpdateExampleSchema, PatchExampleSchema, QueryExampleSchema, DeleteExampleSchema, ExampleResponseSchema, ExampleListResponseSchema } from './schemas';
|
|
9
|
+
import type { CoreEntityCreatedPayload, CoreEntityUpdatedPayload, CoreEntityDeletedPayload, CoreValidationFailedPayload } from '../core/events';
|
|
10
|
+
/**
|
|
11
|
+
* Create request DTO (POST body)
|
|
12
|
+
*/
|
|
13
|
+
export type CreateExampleDTO = z.infer<typeof CreateExampleSchema>;
|
|
14
|
+
/**
|
|
15
|
+
* Update request DTO (PUT body - full replacement)
|
|
16
|
+
*/
|
|
17
|
+
export type UpdateExampleDTO = z.infer<typeof UpdateExampleSchema>;
|
|
18
|
+
/**
|
|
19
|
+
* Patch request DTO (PATCH body - partial update)
|
|
20
|
+
*/
|
|
21
|
+
export type PatchExampleDTO = z.infer<typeof PatchExampleSchema>;
|
|
22
|
+
/**
|
|
23
|
+
* Query params DTO (GET list)
|
|
24
|
+
*/
|
|
25
|
+
export type QueryExampleDTO = z.infer<typeof QueryExampleSchema>;
|
|
26
|
+
/**
|
|
27
|
+
* Delete options DTO (DELETE)
|
|
28
|
+
*/
|
|
29
|
+
export type DeleteExampleDTO = z.infer<typeof DeleteExampleSchema>;
|
|
30
|
+
/**
|
|
31
|
+
* Single entity response DTO
|
|
32
|
+
*/
|
|
33
|
+
export type ExampleResponseDTO = z.infer<typeof ExampleResponseSchema>;
|
|
34
|
+
/**
|
|
35
|
+
* List response with pagination
|
|
36
|
+
*/
|
|
37
|
+
export type ExampleListResponseDTO = z.infer<typeof ExampleListResponseSchema>;
|
|
38
|
+
/**
|
|
39
|
+
* Example domain entity
|
|
40
|
+
* Represents the fully hydrated domain model
|
|
41
|
+
*/
|
|
42
|
+
export interface ExampleEntity {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
description: string | null;
|
|
46
|
+
ownerId: string;
|
|
47
|
+
status: 'draft' | 'active' | 'archived';
|
|
48
|
+
amount: number;
|
|
49
|
+
isVisible: boolean;
|
|
50
|
+
createdAt: Date;
|
|
51
|
+
updatedAt: Date;
|
|
52
|
+
isActive: boolean;
|
|
53
|
+
hasDescription: () => boolean;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Store state for example entity
|
|
57
|
+
* Serializable (no Date objects, no functions)
|
|
58
|
+
*/
|
|
59
|
+
export interface ExampleStoreItem {
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
description: string | null;
|
|
63
|
+
ownerId: string;
|
|
64
|
+
status: ExampleEntity['status'];
|
|
65
|
+
amount: number;
|
|
66
|
+
isVisible: boolean;
|
|
67
|
+
createdAt: string;
|
|
68
|
+
updatedAt: string;
|
|
69
|
+
isActive: boolean;
|
|
70
|
+
isSelected?: boolean;
|
|
71
|
+
isLoading?: boolean;
|
|
72
|
+
isDeleting?: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Store state for example list
|
|
76
|
+
*/
|
|
77
|
+
export interface ExampleStoreState {
|
|
78
|
+
items: ExampleStoreItem[];
|
|
79
|
+
loading: boolean;
|
|
80
|
+
error: string | null;
|
|
81
|
+
page: number;
|
|
82
|
+
limit: number;
|
|
83
|
+
total: number;
|
|
84
|
+
totalPages: number;
|
|
85
|
+
filters: Partial<QueryExampleDTO>;
|
|
86
|
+
selectedIds: Set<string>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Event payload for example:created
|
|
90
|
+
*/
|
|
91
|
+
export type ExampleCreatedPayload = CoreEntityCreatedPayload<ExampleEntity, ExampleStoreItem>;
|
|
92
|
+
/**
|
|
93
|
+
* Event payload for example:updated
|
|
94
|
+
*/
|
|
95
|
+
export type ExampleUpdatedPayload = CoreEntityUpdatedPayload<ExampleEntity, ExampleStoreItem>;
|
|
96
|
+
/**
|
|
97
|
+
* Event payload for example:deleted
|
|
98
|
+
*/
|
|
99
|
+
export type ExampleDeletedPayload = CoreEntityDeletedPayload;
|
|
100
|
+
/**
|
|
101
|
+
* Event payload for example:validation:failed
|
|
102
|
+
*/
|
|
103
|
+
export type ExampleValidationFailedPayload = CoreValidationFailedPayload;
|
|
@@ -95,7 +95,16 @@ export interface FeatureFlagConfig<FeatureFlagKey extends string> extends SetOpt
|
|
|
95
95
|
/** Database configuration (required if provider is 'database') */
|
|
96
96
|
databaseConfig?: {
|
|
97
97
|
connectionString: string;
|
|
98
|
+
/** Table name for feature flags (default: 'feature_flags') */
|
|
98
99
|
tableName: string;
|
|
100
|
+
/** Table name for feature flag rules (default: 'feature_flag_rules') */
|
|
101
|
+
rulesTableName?: string;
|
|
102
|
+
/** Table name for feature flag evaluations (default: 'feature_flag_evaluations') */
|
|
103
|
+
evaluationsTableName?: string;
|
|
104
|
+
/** Table name for feature flag overrides (default: 'feature_flag_overrides') */
|
|
105
|
+
overridesTableName?: string;
|
|
106
|
+
/** Schema for evaluations table (default: 'public', use 'audit' for partitioned tables) */
|
|
107
|
+
evaluationsSchema?: string;
|
|
99
108
|
options?: Record<string, unknown>;
|
|
100
109
|
};
|
|
101
110
|
/** Redis configuration (required if provider is 'redis') */
|
|
@@ -170,11 +179,22 @@ export interface FeatureFlagProviderProps<FeatureFlagKey extends string, Feature
|
|
|
170
179
|
}>;
|
|
171
180
|
}
|
|
172
181
|
/**
|
|
173
|
-
*
|
|
182
|
+
* Request DTO for creating a feature flag.
|
|
183
|
+
* Used by both the provider interface and API endpoints.
|
|
184
|
+
* @typeParam FeatureFlagKey - Feature flag key type (defaults to string)
|
|
174
185
|
*/
|
|
175
|
-
export interface CreateFlagRequest<FeatureFlagKey extends string> extends Partial<WithEnvironment>, SetOptional<Enabled, 'isEnabled'>, SetOptional<Describable, 'description'>, Named, KeyValuePair<FeatureFlagKey, FeatureFlagValue> {
|
|
186
|
+
export interface CreateFlagRequest<FeatureFlagKey extends string = string> extends Partial<WithEnvironment>, SetOptional<Enabled, 'isEnabled'>, SetOptional<Describable, 'description'>, Named, KeyValuePair<FeatureFlagKey, FeatureFlagValue> {
|
|
176
187
|
rolloutPercentage?: number;
|
|
177
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Response structure for fetching feature flag data.
|
|
191
|
+
* Contains both flags and their associated rules.
|
|
192
|
+
* @typeParam FeatureFlagKey - Feature flag key type (defaults to string)
|
|
193
|
+
*/
|
|
194
|
+
export interface FetchFeatureFlagDataResponse<FeatureFlagKey extends string = string> {
|
|
195
|
+
flags: FeatureFlag<FeatureFlagKey>[];
|
|
196
|
+
rules: FeatureFlagRule<FeatureFlagKey>[];
|
|
197
|
+
}
|
|
178
198
|
/**
|
|
179
199
|
* Backend Provider health status information.
|
|
180
200
|
*/
|
|
@@ -184,10 +204,38 @@ export interface ProviderHealthStatus extends Initializable {
|
|
|
184
204
|
}
|
|
185
205
|
/**
|
|
186
206
|
* Main interface for feature flag providers.
|
|
207
|
+
*
|
|
208
|
+
* The provider acts as the unified service layer for feature flag operations.
|
|
209
|
+
* All operations (read, write, override) go through the provider interface,
|
|
210
|
+
* regardless of the underlying storage backend.
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* ```typescript
|
|
214
|
+
* // Controller uses provider directly
|
|
215
|
+
* @Controller('feature-flags')
|
|
216
|
+
* export class FeatureFlagController {
|
|
217
|
+
* constructor(
|
|
218
|
+
* @Inject('FEATURE_FLAG_PROVIDER')
|
|
219
|
+
* private readonly provider: FeatureFlagProvider<FeatureFlagKey>,
|
|
220
|
+
* ) {}
|
|
221
|
+
*
|
|
222
|
+
* @Get(':key')
|
|
223
|
+
* async getFlag(@Param('key') key: string) {
|
|
224
|
+
* return this.provider.getFlag(key as FeatureFlagKey);
|
|
225
|
+
* }
|
|
226
|
+
*
|
|
227
|
+
* @Post()
|
|
228
|
+
* async createFlag(@Body() data: CreateFlagRequest<FeatureFlagKey>) {
|
|
229
|
+
* return this.provider.createFlag(data);
|
|
230
|
+
* }
|
|
231
|
+
* }
|
|
232
|
+
* ```
|
|
187
233
|
*/
|
|
188
234
|
export interface FeatureFlagProvider<FeatureFlagKey extends string> extends Refreshable {
|
|
189
235
|
/** Initializes the provider by loading initial data */
|
|
190
236
|
initialize(): Promise<void>;
|
|
237
|
+
/** Disposes of the provider, cleaning up resources */
|
|
238
|
+
dispose(): void;
|
|
191
239
|
/** Evaluates a feature flag and returns full evaluation details */
|
|
192
240
|
getFlag(key: FeatureFlagKey, context?: FeatureFlagContext): Promise<FeatureFlagEvaluation<FeatureFlagKey>>;
|
|
193
241
|
/** Evaluates all feature flags for the given context */
|
|
@@ -196,20 +244,24 @@ export interface FeatureFlagProvider<FeatureFlagKey extends string> extends Refr
|
|
|
196
244
|
isEnabled(key: FeatureFlagKey, context?: FeatureFlagContext): Promise<boolean>;
|
|
197
245
|
/** Gets the value of a feature flag with optional type casting */
|
|
198
246
|
getValue<T = FeatureFlagValue>(key: FeatureFlagKey, context?: FeatureFlagContext): Promise<T>;
|
|
199
|
-
/** Subscribes to flag changes and updates */
|
|
200
|
-
subscribe(callback: () => void): () => void;
|
|
201
247
|
/** Sets an override for a specific flag key */
|
|
202
248
|
setOverride(key: FeatureFlagKey, value: FeatureFlagValue): void;
|
|
203
249
|
/** Removes an override for a specific flag key */
|
|
204
250
|
removeOverride(key: FeatureFlagKey): void;
|
|
205
251
|
/** Clears all overrides */
|
|
206
252
|
clearOverrides(): void;
|
|
207
|
-
/**
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
|
|
253
|
+
/** Subscribes to flag changes and updates */
|
|
254
|
+
subscribe(callback: () => void): () => void;
|
|
255
|
+
/** Creates a new feature flag */
|
|
256
|
+
createFlag(data: CreateFlagRequest<FeatureFlagKey>): Promise<FeatureFlag<FeatureFlagKey>>;
|
|
257
|
+
/** Updates an existing feature flag */
|
|
258
|
+
updateFlag(key: FeatureFlagKey, data: Partial<CreateFlagRequest<FeatureFlagKey>>): Promise<FeatureFlag<FeatureFlagKey>>;
|
|
259
|
+
/** Deletes a feature flag */
|
|
260
|
+
deleteFlag(key: FeatureFlagKey): Promise<void>;
|
|
261
|
+
/** Gets all rules for a specific flag */
|
|
262
|
+
getRules(key: FeatureFlagKey): Promise<FeatureFlagRule<FeatureFlagKey>[]>;
|
|
263
|
+
/** Gets all enabled rules across all flags */
|
|
264
|
+
getAllRules(): Promise<FeatureFlagRule<FeatureFlagKey>[]>;
|
|
213
265
|
/** Optional: Sync features at runtime (for providers that support dynamic updates) */
|
|
214
266
|
syncFeatures?(newFeatures: Record<FeatureFlagKey, FeatureFlagValue>): Promise<void>;
|
|
215
267
|
}
|
|
@@ -258,28 +310,6 @@ export interface FeatureFlagHelpers<FeatureFlagKey extends string = string> {
|
|
|
258
310
|
isAllEnabled: (keys: FeatureFlagKey[], context?: FeatureFlagContext) => Promise<boolean>;
|
|
259
311
|
whenEnabled: <T>(key: FeatureFlagKey, callback: () => T | Promise<T>, fallback?: () => T | Promise<T>, context?: FeatureFlagContext) => Promise<T | undefined>;
|
|
260
312
|
}
|
|
261
|
-
/**
|
|
262
|
-
* Response structure for fetching feature flag data.
|
|
263
|
-
* Contains both flags and their associated rules.
|
|
264
|
-
*
|
|
265
|
-
* @template FeatureFlagKey - Type of feature flag keys
|
|
266
|
-
*
|
|
267
|
-
* @example
|
|
268
|
-
* ```typescript
|
|
269
|
-
* const response: FetchFeatureFlagDataResponse<AppFeatures> = {
|
|
270
|
-
* flags: [
|
|
271
|
-
* { key: 'newUI', name: 'New UI', value: true, isEnabled: true }
|
|
272
|
-
* ],
|
|
273
|
-
* rules: [
|
|
274
|
-
* { flagKey: 'newUI', conditions: { userRole: 'beta' }, value: true }
|
|
275
|
-
* ]
|
|
276
|
-
* };
|
|
277
|
-
* ```
|
|
278
|
-
*/
|
|
279
|
-
export interface FetchFeatureFlagDataResponse<FeatureFlagKey extends string> {
|
|
280
|
-
flags: FeatureFlag<FeatureFlagKey>[];
|
|
281
|
-
rules: FeatureFlagRule<FeatureFlagKey>[];
|
|
282
|
-
}
|
|
283
313
|
/**
|
|
284
314
|
* Input for error handling test cases
|
|
285
315
|
*/
|