@@ -21,6 +21,7 @@ import {
2121 core ,
2222 commits ,
2323 collections ,
24+ JSONValue ,
2425} from './index.js' ;
2526import { authenticate , fetchWebSocket , startWebsocket } from './websockets.js' ;
2627
@@ -38,6 +39,17 @@ type AddResourcesOpts = {
3839 skipCommitCompare ?: boolean ;
3940} ;
4041
42+ type CreateResourceOptions = {
43+ /** Optional subject of the new resource, if not given the store will generate a random subject */
44+ subject ?: string ;
45+ /** Parent the subject belongs to, defaults to the serverUrl */
46+ parent ?: string ;
47+ /** Subject(s) of the resources class */
48+ isA ?: string | string [ ] ;
49+ /** Any additional properties the resource should have */
50+ propVals ?: Record < string , JSONValue > ;
51+ } ;
52+
4153export interface StoreOpts {
4254 /** The default store URL, where to send commits and where to create new instances */
4355 serverUrl ?: string ;
@@ -184,6 +196,39 @@ export class Store {
184196 this . notify ( resource . __internalObject ) ;
185197 }
186198
199+ /**
200+ * A helper function for creating new resources.
201+ * Options take:
202+ * subject (optional) - defaults to random subject,
203+ * parent (optional) - defaults to serverUrl,
204+ * isA (optional),
205+ * properties (optional) - any additional properties to be set on the resource.
206+ */
207+ public async newResource < C extends OptionalClass = UnknownClass > (
208+ options : CreateResourceOptions = { } ,
209+ ) : Promise < Resource < C > > {
210+ const { subject, parent, isA, propVals } = options ;
211+
212+ const normalizedIsA = Array . isArray ( isA ) ? isA : [ isA ] ;
213+ const newSubject = subject ?? this . createSubject ( normalizedIsA [ 0 ] , parent ) ;
214+
215+ const resource = this . getResourceLoading ( newSubject , { newResource : true } ) ;
216+
217+ if ( normalizedIsA [ 0 ] ) {
218+ await resource . addClasses ( this , ...( normalizedIsA as string [ ] ) ) ;
219+ }
220+
221+ await resource . set ( core . properties . parent , parent ?? this . serverUrl , this ) ;
222+
223+ if ( propVals ) {
224+ for ( const [ key , value ] of Object . entries ( propVals ) ) {
225+ await resource . set ( key , value , this ) ;
226+ }
227+ }
228+
229+ return resource ;
230+ }
231+
187232 /** Checks if a subject is free to use */
188233 public async checkSubjectTaken ( subject : string ) : Promise < boolean > {
189234 const r = this . resources . get ( subject ) ;
0 commit comments