|
9 | 9 | DocumentEvent, |
10 | 10 | getStreamID, |
11 | 11 | } from '@ceramic-sdk/model-instance-protocol' |
| 12 | +import type { ModelDefinition } from '@ceramic-sdk/model-protocol' |
12 | 13 | import { StreamClient, type StreamState } from '@ceramic-sdk/stream-client' |
13 | 14 | import type { DIDString } from '@didtools/codecs' |
14 | 15 | import type { DID } from 'dids' |
@@ -38,7 +39,12 @@ export type CreateSingletonParams = { |
38 | 39 | * Parameters for creating an instance of a model. |
39 | 40 | */ |
40 | 41 | export type CreateInstanceParams<T extends UnknownContent = UnknownContent> = |
41 | | - Omit<CreateInitEventParams<T>, 'controller'> & { |
| 42 | + Omit<CreateInitEventParams<T>, 'controller' | 'content'> & { |
| 43 | + /** The model definition containing account relation info */ |
| 44 | + modelDefinition?: ModelDefinition |
| 45 | + /** The document content */ |
| 46 | + content?: T |
| 47 | + /** The controller DID */ |
42 | 48 | controller?: DID |
43 | 49 | } |
44 | 50 |
|
@@ -103,18 +109,82 @@ export class ModelInstanceClient extends StreamClient { |
103 | 109 | } |
104 | 110 |
|
105 | 111 | /** |
106 | | - * Creates an instance of a model. The model must have an account relation of list or set. |
| 112 | + * Creates an instance based on the model definition's account relation type. |
| 113 | + * - LIST: Creates a new instance with random unique value |
| 114 | + * - SET: Creates a deterministic instance based on specified field values |
| 115 | + * - SINGLE: Creates a singleton instance |
| 116 | + * |
| 117 | + * @param params - Parameters for creating the instance |
| 118 | + * @returns The commit ID of the created instance |
107 | 119 | */ |
108 | 120 | async createInstance<T extends UnknownContent = UnknownContent>( |
109 | 121 | params: CreateInstanceParams<T>, |
110 | 122 | ): Promise<CommitID> { |
111 | | - const { controller, ...rest } = params |
112 | | - const event = await createInitEvent({ |
113 | | - ...rest, |
114 | | - controller: this.getDID(controller), |
115 | | - }) |
116 | | - const cid = await this.ceramic.postEventType(SignedEvent, event) |
117 | | - return CommitID.fromStream(getStreamID(cid)) |
| 123 | + const { |
| 124 | + model, |
| 125 | + modelDefinition, |
| 126 | + content, |
| 127 | + controller, |
| 128 | + shouldIndex, |
| 129 | + modelVersion, |
| 130 | + } = params |
| 131 | + |
| 132 | + // Default to 'list' if no modelDefinition provided (backward compatibility) |
| 133 | + const relationType = modelDefinition?.accountRelation?.type || 'list' |
| 134 | + |
| 135 | + switch (relationType) { |
| 136 | + case 'list': { |
| 137 | + const event = await createInitEvent({ |
| 138 | + model, |
| 139 | + content: content ?? null, |
| 140 | + controller: this.getDID(controller), |
| 141 | + shouldIndex, |
| 142 | + modelVersion, |
| 143 | + }) |
| 144 | + const cid = await this.ceramic.postEventType(SignedEvent, event) |
| 145 | + return CommitID.fromStream(getStreamID(cid)) |
| 146 | + } |
| 147 | + |
| 148 | + case 'single': { |
| 149 | + return this.createSingleton({ |
| 150 | + model, |
| 151 | + controller: this.getDID(controller), |
| 152 | + }) |
| 153 | + } |
| 154 | + |
| 155 | + case 'set': { |
| 156 | + if (!modelDefinition || !modelDefinition.accountRelation) { |
| 157 | + throw new Error('Model definition is required for SET relations') |
| 158 | + } |
| 159 | + |
| 160 | + // We know it's a SET relation, so fields must exist |
| 161 | + const fields = ( |
| 162 | + modelDefinition.accountRelation as { type: 'set'; fields: string[] } |
| 163 | + ).fields |
| 164 | + if (!fields || fields.length === 0) { |
| 165 | + throw new Error('SET relation must specify fields') |
| 166 | + } |
| 167 | + |
| 168 | + // Extract "unique" components from content |
| 169 | + const unique = fields.map((field: string) => { |
| 170 | + const value = |
| 171 | + content && typeof content === 'object' |
| 172 | + ? (content as Record<string, unknown>)[field] |
| 173 | + : undefined |
| 174 | + return value == null ? '' : String(value) |
| 175 | + }) |
| 176 | + |
| 177 | + const uniqueValue = new TextEncoder().encode(unique.join('|')) |
| 178 | + return this.createSingleton({ |
| 179 | + model, |
| 180 | + controller: this.getDID(controller), |
| 181 | + uniqueValue, |
| 182 | + }) |
| 183 | + } |
| 184 | + |
| 185 | + default: |
| 186 | + throw new Error(`Unknown account relation type: ${relationType}`) |
| 187 | + } |
118 | 188 | } |
119 | 189 |
|
120 | 190 | /** |
|
0 commit comments