object_store.go raw

   1  //go:build js && wasm
   2  // +build js,wasm
   3  
   4  package idb
   5  
   6  import (
   7  	"syscall/js"
   8  
   9  	"github.com/hack-pad/safejs"
  10  )
  11  
  12  // ObjectStoreOptions contains all available options for creating an ObjectStore
  13  type ObjectStoreOptions struct {
  14  	KeyPath       js.Value
  15  	AutoIncrement bool
  16  }
  17  
  18  // ObjectStore represents an object store in a database. Records within an object store are sorted according to their keys. This sorting enables fast insertion, look-up, and ordered retrieval.
  19  type ObjectStore struct {
  20  	base *baseObjectStore // don't embed to avoid generated docs with the wrong receiver type (ObjectStore vs *ObjectStore)
  21  }
  22  
  23  func wrapObjectStore(txn *Transaction, jsObjectStore safejs.Value) *ObjectStore {
  24  	return &ObjectStore{wrapBaseObjectStore(txn, jsObjectStore)}
  25  }
  26  
  27  // IndexNames returns a list of the names of indexes on objects in this object store.
  28  func (o *ObjectStore) IndexNames() ([]string, error) {
  29  	indexNames, err := o.base.jsObjectStore.Get("indexNames")
  30  	if err != nil {
  31  		return nil, err
  32  	}
  33  	return stringsFromArray(indexNames)
  34  }
  35  
  36  // KeyPath returns the key path of this object store. If this returns js.Null(), the application must provide a key for each modification operation.
  37  func (o *ObjectStore) KeyPath() (safejs.Value, error) {
  38  	return o.base.jsObjectStore.Get("keyPath")
  39  }
  40  
  41  // Name returns the name of this object store.
  42  func (o *ObjectStore) Name() (string, error) {
  43  	name, err := o.base.jsObjectStore.Get("name")
  44  	if err != nil {
  45  		return "", err
  46  	}
  47  	return name.String()
  48  }
  49  
  50  // Transaction returns the Transaction object to which this object store belongs.
  51  func (o *ObjectStore) Transaction() (*Transaction, error) {
  52  	if o.base.txn == (*Transaction)(nil) {
  53  		return nil, errNotInTransaction
  54  	}
  55  	return o.base.txn, nil
  56  }
  57  
  58  // AutoIncrement returns the value of the auto increment flag for this object store.
  59  func (o *ObjectStore) AutoIncrement() (bool, error) {
  60  	autoIncrement, err := o.base.jsObjectStore.Get("autoIncrement")
  61  	if err != nil {
  62  		return false, err
  63  	}
  64  	return autoIncrement.Bool()
  65  }
  66  
  67  // Add returns an AckRequest, and, in a separate thread, creates a structured clone of the value, and stores the cloned value in the object store. This is for adding new records to an object store.
  68  func (o *ObjectStore) Add(value safejs.Value) (*AckRequest, error) {
  69  	reqValue, err := o.base.jsObjectStore.Call("add", value)
  70  	if err != nil {
  71  		return nil, tryAsDOMException(err)
  72  	}
  73  	req := wrapRequest(o.base.txn, reqValue)
  74  	return newAckRequest(req), nil
  75  }
  76  
  77  // AddKey is the same as Add, but includes the key to use to identify the record.
  78  func (o *ObjectStore) AddKey(key, value safejs.Value) (*AckRequest, error) {
  79  	reqValue, err := o.base.jsObjectStore.Call("add", value, key)
  80  	if err != nil {
  81  		return nil, tryAsDOMException(err)
  82  	}
  83  	req := wrapRequest(o.base.txn, reqValue)
  84  	return newAckRequest(req), nil
  85  }
  86  
  87  // Clear returns an AckRequest, then clears this object store in a separate thread. This is for deleting all current records out of an object store.
  88  func (o *ObjectStore) Clear() (*AckRequest, error) {
  89  	reqValue, err := o.base.jsObjectStore.Call("clear")
  90  	if err != nil {
  91  		return nil, tryAsDOMException(err)
  92  	}
  93  	req := wrapRequest(o.base.txn, reqValue)
  94  	return newAckRequest(req), nil
  95  }
  96  
  97  // Count returns a UintRequest, and, in a separate thread, returns the total number of records in the store.
  98  func (o *ObjectStore) Count() (*UintRequest, error) {
  99  	return o.base.Count()
 100  }
 101  
 102  // CountKey returns a UintRequest, and, in a separate thread, returns the total number of records that match the provided key.
 103  func (o *ObjectStore) CountKey(key safejs.Value) (*UintRequest, error) {
 104  	return o.base.CountKey(key)
 105  }
 106  
 107  // CountRange returns a UintRequest, and, in a separate thread, returns the total number of records that match the provided KeyRange.
 108  func (o *ObjectStore) CountRange(keyRange *KeyRange) (*UintRequest, error) {
 109  	return o.base.CountRange(keyRange)
 110  }
 111  
 112  // CreateIndex creates a new index during a version upgrade, returning a new Index object in the connected database.
 113  func (o *ObjectStore) CreateIndex(name string, keyPath safejs.Value, options IndexOptions) (*Index, error) {
 114  	jsIndex, err := o.base.jsObjectStore.Call("createIndex", name, keyPath, map[string]interface{}{
 115  		"unique":     options.Unique,
 116  		"multiEntry": options.MultiEntry,
 117  	})
 118  	if err != nil {
 119  		return nil, tryAsDOMException(err)
 120  	}
 121  	return wrapIndex(o.base.txn, jsIndex), nil
 122  }
 123  
 124  // Delete returns an AckRequest, and, in a separate thread, deletes the store object selected by the specified key. This is for deleting individual records out of an object store.
 125  func (o *ObjectStore) Delete(key safejs.Value) (*AckRequest, error) {
 126  	reqValue, err := o.base.jsObjectStore.Call("delete", key)
 127  	if err != nil {
 128  		return nil, tryAsDOMException(err)
 129  	}
 130  	req := wrapRequest(o.base.txn, reqValue)
 131  	return newAckRequest(req), nil
 132  }
 133  
 134  // DeleteIndex destroys the specified index in the connected database, used during a version upgrade.
 135  func (o *ObjectStore) DeleteIndex(name string) error {
 136  	_, err := o.base.jsObjectStore.Call("deleteIndex", name)
 137  	return tryAsDOMException(err)
 138  }
 139  
 140  // GetAllKeys returns an ArrayRequest that retrieves record keys for all objects in the object store.
 141  func (o *ObjectStore) GetAllKeys() (*ArrayRequest, error) {
 142  	return o.base.GetAllKeys()
 143  }
 144  
 145  // GetAllKeysRange returns an ArrayRequest that retrieves record keys for all objects in the object store matching the specified query. If maxCount is 0, retrieves all objects matching the query.
 146  func (o *ObjectStore) GetAllKeysRange(query *KeyRange, maxCount uint) (*ArrayRequest, error) {
 147  	return o.base.GetAllKeysRange(query, maxCount)
 148  }
 149  
 150  // Get returns a Request, and, in a separate thread, returns the objects selected by the specified key. This is for retrieving specific records from an object store.
 151  func (o *ObjectStore) Get(key safejs.Value) (*Request, error) {
 152  	return o.base.Get(key)
 153  }
 154  
 155  // GetKey returns a Request, and, in a separate thread retrieves and returns the record key for the object matching the specified parameter.
 156  func (o *ObjectStore) GetKey(value safejs.Value) (*Request, error) {
 157  	return o.base.GetKey(value)
 158  }
 159  
 160  // Index opens an index from this object store after which it can, for example, be used to return a sequence of records sorted by that index using a cursor.
 161  func (o *ObjectStore) Index(name string) (*Index, error) {
 162  	jsIndex, err := o.base.jsObjectStore.Call("index", name)
 163  	if err != nil {
 164  		return nil, tryAsDOMException(err)
 165  	}
 166  	return wrapIndex(o.base.txn, jsIndex), nil
 167  }
 168  
 169  // Put returns a Request, and, in a separate thread, creates a structured clone of the value, and stores the cloned value in the object store. This is for updating existing records in an object store when the transaction's mode is readwrite.
 170  func (o *ObjectStore) Put(value safejs.Value) (*Request, error) {
 171  	reqValue, err := o.base.jsObjectStore.Call("put", value)
 172  	if err != nil {
 173  		return nil, tryAsDOMException(err)
 174  	}
 175  	return wrapRequest(o.base.txn, reqValue), nil
 176  }
 177  
 178  // PutKey is the same as Put, but includes the key to use to identify the record.
 179  func (o *ObjectStore) PutKey(key, value safejs.Value) (*Request, error) {
 180  	reqValue, err := o.base.jsObjectStore.Call("put", value, key)
 181  	if err != nil {
 182  		return nil, tryAsDOMException(err)
 183  	}
 184  	return wrapRequest(o.base.txn, reqValue), nil
 185  }
 186  
 187  // OpenCursor returns a CursorWithValueRequest, and, in a separate thread, returns a new CursorWithValue. Used for iterating through an object store by primary key with a cursor.
 188  func (o *ObjectStore) OpenCursor(direction CursorDirection) (*CursorWithValueRequest, error) {
 189  	return o.base.OpenCursor(direction)
 190  }
 191  
 192  // OpenCursorKey is the same as OpenCursor, but opens a cursor over the given key instead.
 193  func (o *ObjectStore) OpenCursorKey(key safejs.Value, direction CursorDirection) (*CursorWithValueRequest, error) {
 194  	return o.base.OpenCursorKey(key, direction)
 195  }
 196  
 197  // OpenCursorRange is the same as OpenCursor, but opens a cursor over the given range instead.
 198  func (o *ObjectStore) OpenCursorRange(keyRange *KeyRange, direction CursorDirection) (*CursorWithValueRequest, error) {
 199  	return o.base.OpenCursorRange(keyRange, direction)
 200  }
 201  
 202  // OpenKeyCursor returns a CursorRequest, and, in a separate thread, returns a new Cursor. Used for iterating through all keys in an object store.
 203  func (o *ObjectStore) OpenKeyCursor(direction CursorDirection) (*CursorRequest, error) {
 204  	return o.base.OpenKeyCursor(direction)
 205  }
 206  
 207  // OpenKeyCursorKey is the same as OpenKeyCursor, but opens a cursor over the given key instead.
 208  func (o *ObjectStore) OpenKeyCursorKey(key safejs.Value, direction CursorDirection) (*CursorRequest, error) {
 209  	return o.base.OpenKeyCursorKey(key, direction)
 210  }
 211  
 212  // OpenKeyCursorRange is the same as OpenKeyCursor, but opens a cursor over the given key range instead.
 213  func (o *ObjectStore) OpenKeyCursorRange(keyRange *KeyRange, direction CursorDirection) (*CursorRequest, error) {
 214  	return o.base.OpenKeyCursorRange(keyRange, direction)
 215  }
 216