|
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,70 @@ 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 { model, modelDefinition, content, controller, shouldIndex, modelVersion } = params |
| 124 | + |
| 125 | + // Default to 'list' if no modelDefinition provided (backward compatibility) |
| 126 | + const relationType = modelDefinition?.accountRelation?.type || 'list' |
| 127 | + |
| 128 | + switch (relationType) { |
| 129 | + case 'list': { |
| 130 | + const event = await createInitEvent({ |
| 131 | + model, |
| 132 | + content: content ?? null, |
| 133 | + controller: this.getDID(controller), |
| 134 | + shouldIndex, |
| 135 | + modelVersion, |
| 136 | + }) |
| 137 | + const cid = await this.ceramic.postEventType(SignedEvent, event) |
| 138 | + return CommitID.fromStream(getStreamID(cid)) |
| 139 | + } |
| 140 | + |
| 141 | + case 'single': { |
| 142 | + return this.createSingleton({ |
| 143 | + model, |
| 144 | + controller: this.getDID(controller), |
| 145 | + }) |
| 146 | + } |
| 147 | + |
| 148 | + case 'set': { |
| 149 | + if (!modelDefinition || !modelDefinition.accountRelation) { |
| 150 | + throw new Error('Model definition is required for SET relations') |
| 151 | + } |
| 152 | + |
| 153 | + // We know it's a SET relation, so fields must exist |
| 154 | + const fields = (modelDefinition.accountRelation as { type: 'set'; fields: string[] }).fields |
| 155 | + if (!fields || fields.length === 0) { |
| 156 | + throw new Error('SET relation must specify fields') |
| 157 | + } |
| 158 | + |
| 159 | + // Extract "unique" components from content |
| 160 | + const unique = fields.map((field: string) => { |
| 161 | + const value = content && typeof content === 'object' ? (content as any)[field] : undefined |
| 162 | + return value == null ? '' : String(value) |
| 163 | + }) |
| 164 | + |
| 165 | + const uniqueValue = new TextEncoder().encode(unique.join('|')) |
| 166 | + return this.createSingleton({ |
| 167 | + model, |
| 168 | + controller: this.getDID(controller), |
| 169 | + uniqueValue, |
| 170 | + }) |
| 171 | + } |
| 172 | + |
| 173 | + default: |
| 174 | + throw new Error(`Unknown account relation type: ${relationType}`) |
| 175 | + } |
118 | 176 | } |
119 | 177 |
|
120 | 178 | /** |
|
0 commit comments