@marianmeres/collection-types 1.8.1 → 1.9.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/README.md CHANGED
@@ -1,3 +1,181 @@
1
1
  # @marianmeres/collection-types
2
2
 
3
- Shared type definitions for internal use within the @marianmeres ecosystem. Type-only package with no runtime code.
3
+ Type definitions and schema utilities for the @marianmeres/collection ecosystem.
4
+
5
+ ## Overview
6
+
7
+ This package provides:
8
+
9
+ 1. **Core Types**: Model, Collection, Relation, Schema definitions
10
+ 2. **Domain Types**: Typed interfaces for all stack-xyz domains
11
+ 3. **Schema Builder**: `createObjectSchema<T>()` for type-safe schema definitions
12
+
13
+ ## Installation
14
+
15
+ ```typescript
16
+ import type {
17
+ Model,
18
+ Collection,
19
+ UUID,
20
+ ProductData,
21
+ CustomerData,
22
+ } from "@marianmeres/collection-types";
23
+
24
+ import {
25
+ createObjectSchema,
26
+ type ExtendedSchema,
27
+ } from "@marianmeres/collection-types";
28
+ ```
29
+
30
+ ## Type Layers
31
+
32
+ The collection system uses a layered type structure:
33
+
34
+ | Layer | Interface | Purpose |
35
+ |-------|-----------|---------|
36
+ | Input | `ModelDTOIn` | User-provided fields for create/update |
37
+ | Output | `ModelDTOOut` | Response with server-generated fields |
38
+ | Database | `ModelDbRow` | Full row including internal fields |
39
+ | Typed | `Model<T>` | Generic model with typed `data` field |
40
+
41
+ ```typescript
42
+ import type { Model } from "@marianmeres/collection-types";
43
+ import type { ProductData } from "@marianmeres/collection-types";
44
+
45
+ type ProductModel = Model<ProductData>;
46
+ // ProductModel.data is typed as ProductData
47
+ ```
48
+
49
+ ## Domain Types
50
+
51
+ ### Core Types
52
+
53
+ | File | Exports |
54
+ |------|---------|
55
+ | `model.ts` | ModelDTOIn, ModelDTOOut, ModelDbRow, Model |
56
+ | `collection.ts` | Collection, CollectionDTOIn, CollectionDTOOut |
57
+ | `relation.ts` | Relation, RelationType |
58
+ | `schema.ts` | PropertyDefinition, SchemaDefinition |
59
+ | `utils.ts` | UUID, LtreePath, ISODateString, MaybeLocalized |
60
+
61
+ ### E-commerce Types
62
+
63
+ | File | Exports |
64
+ |------|---------|
65
+ | `session.ts` | SessionData, CartData, CartItem |
66
+ | `customer.ts` | CustomerData, AddressData |
67
+ | `order.ts` | OrderData, OrderEventData, OrderLineItem, OrderTotals |
68
+ | `payment.ts` | PaymentData, PaymentIntent, PaymentResult |
69
+
70
+ ### Stack Domain Types
71
+
72
+ | File | Exports |
73
+ |------|---------|
74
+ | `account.ts` | AccountData, PasswordData, TokenData |
75
+ | `product.ts` | ProductData, CategoryData |
76
+ | `project.ts` | ConfigData, ConfigDataDefault, ConfigDataRbac |
77
+ | `template.ts` | TemplateData |
78
+ | `email.ts` | EmailData, EmailStatus |
79
+ | `asset.ts` | AssetData, AssetVariant, ModelAsset |
80
+ | `example.ts` | ExampleData, ExampleDataDefault, CommentData |
81
+
82
+ ## Type-Safe Schema Definitions
83
+
84
+ Use `createObjectSchema<T>()` to catch property typos at compile time.
85
+
86
+ ### The Problem
87
+
88
+ Without type safety, typos in schema property names are not caught:
89
+
90
+ ```typescript
91
+ // BAD: TypeScript does NOT catch the typo "namex"
92
+ const schema = {
93
+ type: "object",
94
+ properties: {
95
+ namex: { type: "string" }, // Typo! Should be "name"
96
+ },
97
+ };
98
+ ```
99
+
100
+ ### The Solution
101
+
102
+ ```typescript
103
+ import {
104
+ createObjectSchema,
105
+ type ProductData,
106
+ } from "@marianmeres/collection-types";
107
+
108
+ // GOOD: TypeScript catches typos!
109
+ const schema = createObjectSchema<ProductData>({
110
+ type: "object",
111
+ required: ["name"],
112
+ properties: {
113
+ namex: { type: "string" }, // TS Error: 'namex' does not exist
114
+ },
115
+ });
116
+ ```
117
+
118
+ ### Defining Data Interfaces
119
+
120
+ Data interfaces must include:
121
+
122
+ 1. **Data fields** with their types
123
+ 2. **UI-only fields** (relations) as `never` type
124
+ 3. **Index signature** for `Model<T>` compatibility
125
+
126
+ ```typescript
127
+ export interface ProductData {
128
+ // Data fields
129
+ name: string;
130
+ price?: number;
131
+ sku?: string;
132
+
133
+ // UI-only fields (never stored in data)
134
+ category?: never;
135
+ images?: never;
136
+
137
+ // Index signature for Model<T> compatibility
138
+ [key: string]: unknown;
139
+ }
140
+ ```
141
+
142
+ ### Extended Schemas
143
+
144
+ For schemas using `__extends`, use `ExtendedSchema`:
145
+
146
+ ```typescript
147
+ import { type ExtendedSchema } from "@marianmeres/collection-types";
148
+
149
+ const schemas = {
150
+ default: createObjectSchema<ProductData>({
151
+ type: "object",
152
+ required: ["name"],
153
+ properties: {
154
+ name: { type: "string" },
155
+ price: { type: "integer" },
156
+ },
157
+ }),
158
+
159
+ premium: {
160
+ __extends: "default",
161
+ properties: {
162
+ warranty_years: { type: "integer" },
163
+ },
164
+ } as ExtendedSchema,
165
+ };
166
+ ```
167
+
168
+ ## Best Practices
169
+
170
+ 1. Define all domain interfaces in this package
171
+ 2. Use `createObjectSchema<T>()` for base schemas
172
+ 3. Use `as ExtendedSchema` for `__extends` schemas
173
+ 4. Include UI-only fields as `never` type
174
+ 5. Keep index signature for Model<T> compatibility
175
+ 6. Re-export types from stack package mod.ts
176
+
177
+ See `workspace/stack-example/README.md` for comprehensive examples.
178
+
179
+ ## License
180
+
181
+ MIT
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Account domain types for the stack-account module.
3
+ *
4
+ * Includes account, password, and token collection types.
5
+ */
6
+ /** Account model data */
7
+ export interface AccountData {
8
+ email: string;
9
+ roles?: string[];
10
+ isVerified?: boolean;
11
+ /** Index signature for Model<T> compatibility */
12
+ [key: string]: unknown;
13
+ }
14
+ /** Password model data (stores hashed passwords) */
15
+ export interface PasswordData {
16
+ hash: string;
17
+ /** Index signature for Model<T> compatibility */
18
+ [key: string]: unknown;
19
+ }
20
+ /** Token model data (for auth tokens) */
21
+ export interface TokenData {
22
+ validFrom?: string;
23
+ validUntil?: string;
24
+ roles?: string[];
25
+ jwt?: string;
26
+ email?: string;
27
+ /** Index signature for Model<T> compatibility */
28
+ [key: string]: unknown;
29
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Account domain types for the stack-account module.
3
+ *
4
+ * Includes account, password, and token collection types.
5
+ */
6
+ export {};
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Email domain types for the stack-email module.
3
+ *
4
+ * Email log types for audit trail of sent emails.
5
+ */
6
+ /** Email status values */
7
+ export type EmailStatus = "queued" | "sent" | "failed";
8
+ /** Email model data (audit log entry) */
9
+ export interface EmailData {
10
+ to?: string;
11
+ from?: string;
12
+ subject?: string;
13
+ body_html?: string;
14
+ body_text?: string;
15
+ reply_to?: string;
16
+ cc?: string;
17
+ bcc?: string;
18
+ /** Email delivery status */
19
+ status?: EmailStatus;
20
+ /** Transport used (e.g., "smtp", "sendgrid") */
21
+ transport?: string;
22
+ /** Timestamp when email was sent */
23
+ sent_at?: string;
24
+ /** Error message if delivery failed */
25
+ error?: string;
26
+ /** External ID from email provider */
27
+ external_id?: string;
28
+ /** Job UID for async email processing */
29
+ job_uid?: string;
30
+ /** Index signature for Model<T> compatibility */
31
+ [key: string]: unknown;
32
+ }
package/dist/email.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Email domain types for the stack-email module.
3
+ *
4
+ * Email log types for audit trail of sent emails.
5
+ */
6
+ export {};
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Example domain types for the stack-example reference module.
3
+ *
4
+ * These types are used for testing and demonstrating all collection features
5
+ * including multiple model types, relations, and various field types.
6
+ */
7
+ import type { MaybeLocalized } from "./utils.js";
8
+ /** Example model data - default type */
9
+ export interface ExampleDataDefault {
10
+ name: string;
11
+ description?: MaybeLocalized<string>;
12
+ slug: string;
13
+ release_date?: string;
14
+ status?: "draft" | "published" | "archived";
15
+ custom?: Record<string, unknown>;
16
+ comments?: never;
17
+ images?: never;
18
+ global_asset?: never;
19
+ owner?: never;
20
+ /** Index signature for Model<T> compatibility */
21
+ [key: string]: unknown;
22
+ }
23
+ /** Example model data - foo type (extends default with string field) */
24
+ export interface ExampleDataFoo extends ExampleDataDefault {
25
+ foo_specific?: string;
26
+ }
27
+ /** Example model data - bar type (extends default with number and date fields) */
28
+ export interface ExampleDataBar extends ExampleDataDefault {
29
+ bar_specific?: number;
30
+ bar_date?: string;
31
+ }
32
+ /** Union of all example data types */
33
+ export type ExampleData = ExampleDataDefault | ExampleDataFoo | ExampleDataBar;
34
+ /** Comment model data for testing strong relations */
35
+ export interface CommentData {
36
+ body: string;
37
+ author_name?: string;
38
+ created_at?: string;
39
+ /** Index signature for Model<T> compatibility */
40
+ [key: string]: unknown;
41
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Example domain types for the stack-example reference module.
3
+ *
4
+ * These types are used for testing and demonstrating all collection features
5
+ * including multiple model types, relations, and various field types.
6
+ */
7
+ export {};
package/dist/mod.d.ts CHANGED
@@ -1,19 +1,28 @@
1
1
  /**
2
2
  * @module @marianmeres/collection-types
3
3
  *
4
- * Type definitions for the collection management system.
5
- * Pure interfaces with no runtime code - safe for type-only imports.
4
+ * Type definitions and schema utilities for the collection management system.
5
+ *
6
+ * Includes:
7
+ * - Core types: Model, Collection, Relation, Schema
8
+ * - Domain types: Account, Product, Order, Customer, Session, etc.
9
+ * - Schema builder: createObjectSchema<T>() for type-safe schema definitions
6
10
  *
7
11
  * @example
8
12
  * ```typescript
13
+ * // Type-only imports
9
14
  * import type {
10
15
  * Model,
11
16
  * Collection,
12
- * Relation,
13
- * RelationType,
14
- * PropertyDefinition,
15
- * ApiResponse,
16
17
  * UUID,
18
+ * ProductData,
19
+ * CustomerData,
20
+ * } from "@marianmeres/collection-types";
21
+ *
22
+ * // Schema builder (runtime import)
23
+ * import {
24
+ * createObjectSchema,
25
+ * type ExtendedSchema,
17
26
  * } from "@marianmeres/collection-types";
18
27
  * ```
19
28
  */
@@ -31,3 +40,10 @@ export * from "./customer.js";
31
40
  export * from "./order.js";
32
41
  export * from "./payment.js";
33
42
  export * from "./external-domain.js";
43
+ export * from "./account.js";
44
+ export * from "./product.js";
45
+ export * from "./project.js";
46
+ export * from "./template.js";
47
+ export * from "./email.js";
48
+ export * from "./example.js";
49
+ export * from "./schema-builder.js";
package/dist/mod.js CHANGED
@@ -1,19 +1,28 @@
1
1
  /**
2
2
  * @module @marianmeres/collection-types
3
3
  *
4
- * Type definitions for the collection management system.
5
- * Pure interfaces with no runtime code - safe for type-only imports.
4
+ * Type definitions and schema utilities for the collection management system.
5
+ *
6
+ * Includes:
7
+ * - Core types: Model, Collection, Relation, Schema
8
+ * - Domain types: Account, Product, Order, Customer, Session, etc.
9
+ * - Schema builder: createObjectSchema<T>() for type-safe schema definitions
6
10
  *
7
11
  * @example
8
12
  * ```typescript
13
+ * // Type-only imports
9
14
  * import type {
10
15
  * Model,
11
16
  * Collection,
12
- * Relation,
13
- * RelationType,
14
- * PropertyDefinition,
15
- * ApiResponse,
16
17
  * UUID,
18
+ * ProductData,
19
+ * CustomerData,
20
+ * } from "@marianmeres/collection-types";
21
+ *
22
+ * // Schema builder (runtime import)
23
+ * import {
24
+ * createObjectSchema,
25
+ * type ExtendedSchema,
17
26
  * } from "@marianmeres/collection-types";
18
27
  * ```
19
28
  */
@@ -40,3 +49,17 @@ export * from "./order.js";
40
49
  export * from "./payment.js";
41
50
  // Cross-domain reference support
42
51
  export * from "./external-domain.js";
52
+ // Account domain types
53
+ export * from "./account.js";
54
+ // Product domain types
55
+ export * from "./product.js";
56
+ // Project/config domain types
57
+ export * from "./project.js";
58
+ // Template domain types
59
+ export * from "./template.js";
60
+ // Email domain types
61
+ export * from "./email.js";
62
+ // Example domain types (reference implementation)
63
+ export * from "./example.js";
64
+ // Schema builder utilities (type-safe schema definitions)
65
+ export * from "./schema-builder.js";
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Product domain types for the stack-product module.
3
+ *
4
+ * Includes product and category collection types.
5
+ */
6
+ import type { MaybeLocalized } from "./utils.js";
7
+ /** Product model data */
8
+ export interface ProductData {
9
+ name: string;
10
+ sku?: string;
11
+ /** Price in cents (integer) */
12
+ price?: number;
13
+ slug?: string;
14
+ short_description?: MaybeLocalized<string>;
15
+ description?: MaybeLocalized<string>;
16
+ /** Whether product has an associated image */
17
+ has_image?: boolean;
18
+ custom?: Record<string, unknown>;
19
+ category?: never;
20
+ /** Index signature for Model<T> compatibility */
21
+ [key: string]: unknown;
22
+ }
23
+ /** Category model data */
24
+ export interface CategoryData {
25
+ name: string;
26
+ slug?: string;
27
+ short_description?: MaybeLocalized<string>;
28
+ description?: MaybeLocalized<string>;
29
+ custom?: Record<string, unknown>;
30
+ images?: never;
31
+ /** Index signature for Model<T> compatibility */
32
+ [key: string]: unknown;
33
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Product domain types for the stack-product module.
3
+ *
4
+ * Includes product and category collection types.
5
+ */
6
+ export {};
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Project domain types for the stack-project module.
3
+ *
4
+ * Includes config collection types with default, _system, and _rbac subtypes.
5
+ */
6
+ /** Config model data - default type */
7
+ export interface ConfigDataDefault {
8
+ key: string;
9
+ value?: unknown;
10
+ internal_description?: string;
11
+ /** Index signature for Model<T> compatibility */
12
+ [key: string]: unknown;
13
+ }
14
+ /** Permission definition for RBAC */
15
+ export interface RbacPermission {
16
+ name: string;
17
+ description?: string;
18
+ }
19
+ /** Role definition for RBAC */
20
+ export interface RbacRole {
21
+ name: string;
22
+ description?: string;
23
+ permissions?: string[];
24
+ }
25
+ /** Group definition for RBAC */
26
+ export interface RbacGroup {
27
+ name: string;
28
+ description?: string;
29
+ roles?: string[];
30
+ }
31
+ /** Config model data - _rbac type (extends default) */
32
+ export interface ConfigDataRbac extends ConfigDataDefault {
33
+ groups?: RbacGroup[];
34
+ roles?: RbacRole[];
35
+ permissions?: RbacPermission[];
36
+ }
37
+ /** Union of all config data types */
38
+ export type ConfigData = ConfigDataDefault | ConfigDataRbac;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Project domain types for the stack-project module.
3
+ *
4
+ * Includes config collection types with default, _system, and _rbac subtypes.
5
+ */
6
+ export {};
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Type-safe schema builder utilities.
3
+ *
4
+ * Provides compile-time validation that JSON Schema property keys
5
+ * match the corresponding TypeScript interface.
6
+ */
7
+ import type { MaybeLocalized } from "./utils.js";
8
+ import type { PropertyDefinition } from "./schema.js";
9
+ /**
10
+ * Removes index signature from a type, keeping only explicitly defined keys.
11
+ * This allows createObjectSchema to validate keys even when the interface
12
+ * has [key: string]: unknown for Model<T> compatibility.
13
+ */
14
+ type KnownKeys<T> = {
15
+ [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K];
16
+ };
17
+ /** Type-safe schema properties - only known keys from T allowed */
18
+ type SchemaProperties<T> = {
19
+ [K in keyof KnownKeys<T>]?: PropertyDefinition;
20
+ };
21
+ /** Type-safe object schema definition */
22
+ export type ObjectSchema<T> = {
23
+ type: "object";
24
+ required?: (keyof KnownKeys<T>)[];
25
+ properties: SchemaProperties<T>;
26
+ additionalProperties?: boolean;
27
+ _title?: MaybeLocalized<string>;
28
+ _description?: MaybeLocalized<string>;
29
+ _searchable?: boolean;
30
+ };
31
+ /** Extended schema (loose typing for __extends patterns) */
32
+ export type ExtendedSchema = {
33
+ __extends: string;
34
+ properties?: Record<string, PropertyDefinition>;
35
+ _title?: MaybeLocalized<string>;
36
+ _description?: MaybeLocalized<string>;
37
+ };
38
+ /**
39
+ * Create a type-safe object schema.
40
+ * TypeScript will error if property keys don't exist in T.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * import { createObjectSchema } from "@marianmeres/collection-types";
45
+ *
46
+ * interface ProductData {
47
+ * name: string;
48
+ * price: number;
49
+ * }
50
+ *
51
+ * const schema = createObjectSchema<ProductData>({
52
+ * type: "object",
53
+ * required: ["name", "price"],
54
+ * properties: {
55
+ * name: { type: "string" }, // OK
56
+ * price: { type: "number" }, // OK
57
+ * namex: { type: "string" }, // Error: 'namex' not in ProductData
58
+ * },
59
+ * });
60
+ * ```
61
+ */
62
+ export declare function createObjectSchema<T>(schema: ObjectSchema<T>): ObjectSchema<T>;
63
+ export {};
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Type-safe schema builder utilities.
3
+ *
4
+ * Provides compile-time validation that JSON Schema property keys
5
+ * match the corresponding TypeScript interface.
6
+ */
7
+ // -----------------------------------------------------------------------------
8
+ // Functions
9
+ // -----------------------------------------------------------------------------
10
+ /**
11
+ * Create a type-safe object schema.
12
+ * TypeScript will error if property keys don't exist in T.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { createObjectSchema } from "@marianmeres/collection-types";
17
+ *
18
+ * interface ProductData {
19
+ * name: string;
20
+ * price: number;
21
+ * }
22
+ *
23
+ * const schema = createObjectSchema<ProductData>({
24
+ * type: "object",
25
+ * required: ["name", "price"],
26
+ * properties: {
27
+ * name: { type: "string" }, // OK
28
+ * price: { type: "number" }, // OK
29
+ * namex: { type: "string" }, // Error: 'namex' not in ProductData
30
+ * },
31
+ * });
32
+ * ```
33
+ */
34
+ export function createObjectSchema(schema) {
35
+ return schema;
36
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Template domain types for the stack-template module.
3
+ *
4
+ * Templates use Handlebars for variable substitution and MJML for email HTML rendering.
5
+ */
6
+ /** Template model data */
7
+ export interface TemplateData {
8
+ slug: string;
9
+ name: string;
10
+ description?: string;
11
+ /** Email subject line (Handlebars template) */
12
+ subject?: string;
13
+ /** Email body in MJML format (Handlebars template) */
14
+ body_mjml?: string;
15
+ /** Plain text email body (Handlebars template) */
16
+ body_text?: string;
17
+ /** JSON Schema for template variables validation */
18
+ variables_schema?: Record<string, unknown>;
19
+ /** Sample data for template preview */
20
+ sample_data?: Record<string, unknown>;
21
+ /** Template language code */
22
+ lang?: string;
23
+ /** Whether template is active */
24
+ is_active?: boolean;
25
+ /** Index signature for Model<T> compatibility */
26
+ [key: string]: unknown;
27
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Template domain types for the stack-template module.
3
+ *
4
+ * Templates use Handlebars for variable substitution and MJML for email HTML rendering.
5
+ */
6
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/collection-types",
3
- "version": "1.8.1",
3
+ "version": "1.9.0",
4
4
  "type": "module",
5
5
  "main": "dist/mod.js",
6
6
  "types": "dist/mod.d.ts",