global-store 1.0.0-beta.21 → 1.0.0-beta.23

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.
Files changed (95) hide show
  1. package/LICENSE +1 -1
  2. package/dist/global-store.js +2 -0
  3. package/dist/global-store.js.map +1 -0
  4. package/index.js.flow +2 -2
  5. package/lib/compareVersion.d.ts +2 -1
  6. package/lib/compareVersion.d.ts.map +1 -0
  7. package/lib/compareVersion.js +5 -10
  8. package/lib/compareVersion.js.map +1 -1
  9. package/lib/createAsyncStore.d.ts +3 -2
  10. package/lib/createAsyncStore.d.ts.map +1 -0
  11. package/lib/createAsyncStore.js +16 -60
  12. package/lib/createAsyncStore.js.map +1 -1
  13. package/lib/createStore.d.ts +3 -2
  14. package/lib/createStore.d.ts.map +1 -0
  15. package/lib/createStore.js +14 -13
  16. package/lib/createStore.js.map +1 -1
  17. package/lib/index.d.ts +5 -4
  18. package/lib/index.d.ts.map +1 -0
  19. package/lib/index.js +4 -22
  20. package/lib/index.js.map +1 -1
  21. package/lib/shouldInvokeInitializer.d.ts +2 -1
  22. package/lib/shouldInvokeInitializer.d.ts.map +1 -0
  23. package/lib/shouldInvokeInitializer.js +8 -11
  24. package/lib/shouldInvokeInitializer.js.map +1 -1
  25. package/lib/toVersionArray.d.ts +3 -2
  26. package/lib/toVersionArray.d.ts.map +1 -0
  27. package/lib/toVersionArray.js +2 -7
  28. package/lib/toVersionArray.js.map +1 -1
  29. package/lib/types.d.ts +8 -3
  30. package/lib/types.d.ts.map +1 -0
  31. package/lib/types.js +1 -2
  32. package/lib/typesInternal.d.ts +5 -4
  33. package/lib/typesInternal.d.ts.map +1 -0
  34. package/lib/typesInternal.js +1 -2
  35. package/lib/util.d.ts +4 -3
  36. package/lib/util.d.ts.map +1 -0
  37. package/lib/util.js +24 -40
  38. package/lib/util.js.map +1 -1
  39. package/package.json +44 -65
  40. package/{README.md → readme.md} +18 -20
  41. package/dist/compareVersion.d.ts +0 -7
  42. package/dist/createAsyncStore.d.ts +0 -12
  43. package/dist/createStore.d.ts +0 -28
  44. package/dist/global-store.es.js +0 -127
  45. package/dist/global-store.es.js.map +0 -1
  46. package/dist/global-store.es5.js +0 -2
  47. package/dist/global-store.es5.js.map +0 -1
  48. package/dist/global-store.systemjs.js +0 -141
  49. package/dist/global-store.systemjs.js.map +0 -1
  50. package/dist/index.d.ts +0 -4
  51. package/dist/shouldInvokeInitializer.d.ts +0 -2
  52. package/dist/toVersionArray.d.ts +0 -3
  53. package/dist/types.d.ts +0 -9
  54. package/dist/util.d.ts +0 -14
  55. package/libm/compareVersion.d.ts +0 -7
  56. package/libm/compareVersion.js +0 -13
  57. package/libm/compareVersion.js.map +0 -1
  58. package/libm/createAsyncStore.d.ts +0 -12
  59. package/libm/createAsyncStore.js +0 -27
  60. package/libm/createAsyncStore.js.map +0 -1
  61. package/libm/createStore.d.ts +0 -28
  62. package/libm/createStore.js +0 -16
  63. package/libm/createStore.js.map +0 -1
  64. package/libm/index.d.ts +0 -4
  65. package/libm/index.js +0 -5
  66. package/libm/index.js.map +0 -1
  67. package/libm/shouldInvokeInitializer.d.ts +0 -2
  68. package/libm/shouldInvokeInitializer.js +0 -14
  69. package/libm/shouldInvokeInitializer.js.map +0 -1
  70. package/libm/toVersionArray.d.ts +0 -3
  71. package/libm/toVersionArray.js +0 -5
  72. package/libm/toVersionArray.js.map +0 -1
  73. package/libm/types.d.ts +0 -9
  74. package/libm/types.js +0 -2
  75. package/libm/types.js.map +0 -1
  76. package/libm/typesInternal.d.ts +0 -16
  77. package/libm/typesInternal.js +0 -2
  78. package/libm/typesInternal.js.map +0 -1
  79. package/libm/util.d.ts +0 -14
  80. package/libm/util.js +0 -57
  81. package/libm/util.js.map +0 -1
  82. package/ts/compareVersion.spec.ts +0 -9
  83. package/ts/compareVersion.ts +0 -14
  84. package/ts/createAsyncStore.spec.ts +0 -142
  85. package/ts/createAsyncStore.ts +0 -31
  86. package/ts/createStore.spec.ts +0 -217
  87. package/ts/createStore.ts +0 -43
  88. package/ts/index.spec.ts +0 -7
  89. package/ts/index.ts +0 -5
  90. package/ts/shouldInvokeInitializer.spec.ts +0 -41
  91. package/ts/shouldInvokeInitializer.ts +0 -17
  92. package/ts/toVersionArray.ts +0 -8
  93. package/ts/types.ts +0 -12
  94. package/ts/typesInternal.ts +0 -21
  95. package/ts/util.ts +0 -69
@@ -1,217 +0,0 @@
1
- import a from 'assertron'
2
- import { assertType } from 'type-plus'
3
- import { createStore, StoreValue } from '.'
4
-
5
- const moduleName = 'your-module'
6
-
7
- test('create with same id will get existing store', () => {
8
- const key = 'same-key'
9
- const version = 0
10
- const initializer = () => ({ a: 1 })
11
- const store1 = createStore({ moduleName, key, version, initializer })
12
- const store2 = createStore({ moduleName, key, version, initializer })
13
- store1.value.a = 2
14
-
15
- expect(store2.value).toEqual({ a: 2 })
16
- })
17
-
18
- test('initializer of the same version is skipped', () => {
19
- const key = 'skip-same-ver-init'
20
- const version = 0
21
- createStore({ moduleName, key, version, initializer: () => ({ a: 1 }) })
22
- createStore({ moduleName, key, version, initializer: () => { throw new Error('should not reach') } })
23
- })
24
-
25
- test('initializer receives empty object the first time', () => {
26
- let actual
27
- createStore({ moduleName, key: 'init-receive-empty-obj', version: 0, initializer: previous => actual = previous })
28
- expect(actual).toEqual({})
29
- })
30
-
31
- test('initialize receives the versions processed', () => {
32
- const key = 'init-receive-versions'
33
- createStore({
34
- moduleName, key, version: 0, initializer: (_, versions) => {
35
- expect(versions).toEqual([])
36
- return {}
37
- }
38
- })
39
- createStore({
40
- moduleName, key, version: 1, initializer: (_, versions) => {
41
- expect(versions).toEqual([0])
42
- return {}
43
- }
44
- })
45
- createStore({
46
- moduleName, key, version: 2, initializer: (_, versions) => {
47
- expect(versions).toEqual([0, 1])
48
- return {}
49
- }
50
- })
51
- })
52
-
53
- test('store is typed by the initializer', () => {
54
- const key = 'typed-by-initializer'
55
- const store1 = createStore({
56
- moduleName, key, version: 0, initializer: () => ({ a: 1 })
57
- })
58
- const store2 = createStore({
59
- moduleName, key, version: 1, initializer: prev => ({ ...prev, b: 1 })
60
- })
61
- assertType.isNumber(store1.value.a)
62
- assertType.isNumber(store2.value.b)
63
- })
64
-
65
- test('initialize input is partial T because previous version may not have the same data structure', () => {
66
- const key = 'initializer-receive-partial'
67
- const store = createStore<{ a: string }>({
68
- moduleName, key, version: 1,
69
- initializer: prev => ({
70
- a: 'abc',
71
- ...prev
72
- })
73
- })
74
-
75
- store.value.a = '123'
76
- })
77
-
78
- test('store type can be overridden', () => {
79
- const store = createStore<{ a: number | undefined }>({
80
- moduleName, key: 'override-type', version: 0, initializer: () => ({ a: undefined })
81
- })
82
- assertType<number | undefined>(store.value.a)
83
- })
84
-
85
- test('initializer receives the previous initial value', () => {
86
- const key = 'init-get-prev'
87
- createStore({ moduleName, key, version: 0, initializer: () => ({ a: 1 }) })
88
-
89
- let actual
90
- createStore({ moduleName, key, version: 1, initializer: prev => actual = prev })
91
-
92
- expect(actual).toEqual({ a: 1 })
93
- })
94
-
95
- test('reset() will reset object values', () => {
96
- const key = 'reset-obj'
97
- const store = createStore({ moduleName, key, version: 0, initializer: () => ({ a: { b: 2 } }) })
98
- store.value.a.b = 3
99
- store.reset()
100
-
101
- expect(store.value.a.b).toBe(2)
102
- })
103
-
104
- test('call reset() on 1st store gets latest initial value', () => {
105
- const key = '2nd-reset-get-1st'
106
- const store1 = createStore({ moduleName, key, version: 0, initializer: () => ({ a: 1 }) })
107
- createStore({ moduleName, key, version: 1, initializer: () => ({ a: 2, b: true }) })
108
- store1.reset()
109
- expect(store1.value).toEqual({ a: 2, b: true })
110
- })
111
-
112
- test('gets initial value', () => {
113
- const store = createStore({ moduleName, key: 'get-all', version: 0, initializer: () => ({ a: 1, b: 'b' }) })
114
- expect(store.value).toEqual({ a: 1, b: 'b' })
115
- })
116
-
117
- test('property reference are persisted', () => {
118
- const store = createStore({ moduleName, key: 'prop-ref', version: 0, initializer: () => ({ a: { b: 1 } }) })
119
- const orig = store.value
120
- orig.a = { b: 3 }
121
- const actual = store.value
122
- expect(actual.a).toEqual(orig.a)
123
- })
124
-
125
- describe('freeze store', () => {
126
- test('cannot add new property', () => {
127
- const store = createStore<{ a: number } & StoreValue>({ moduleName, key: 'freeze-no-add', version: 0, initializer: () => ({ a: 1 }) })
128
- store.freeze()
129
- store.value
130
- a.throws(() => store.value.b = 2, TypeError)
131
- })
132
-
133
- test('cannot be freezed again', () => {
134
- const store = createStore<any>({ moduleName, key: 'freeze-no-freeze', version: 0, initializer: () => ({ a: 1 }) })
135
- store.freeze()
136
-
137
- a.throws(() => store.freeze(), TypeError)
138
- })
139
-
140
-
141
- test('property values are frozen', () => {
142
- const store = createStore({ moduleName, key: 'prop-freeze', version: 0, initializer: () => ({ a: 1, b: true, c: 'str', d: {}, e: [] as any[] }) })
143
- store.freeze()
144
-
145
- a.throws(() => store.value.a = 2, TypeError)
146
- a.throws(() => store.value.b = false, TypeError)
147
- a.throws(() => store.value.c = 'abc', TypeError)
148
- a.throws(() => store.value.d = { z: 1 }, TypeError)
149
- a.throws(() => store.value.e = ['a'], TypeError)
150
- })
151
-
152
- test('object property is not frozen', () => {
153
- const store = createStore({ moduleName, key: 'obj-not-frozen', version: 0, initializer: () => ({ a: { b: 1, c: {} } }) })
154
- store.freeze()
155
- store.value.a.b = 2
156
- store.value.a.c = { p: 'power' }
157
- })
158
-
159
- test('array property is frozen', () => {
160
- const store = createStore({ moduleName, key: 'prop-array-freeze', version: 0, initializer: () => ({ arr: [] as any[], und: undefined }) })
161
- store.freeze()
162
-
163
- a.throws(() => store.value.arr.push('a'), TypeError)
164
- })
165
-
166
- test('object in array property is not frozen', () => {
167
- const store = createStore({
168
- moduleName,
169
- key: 'obj-in-array-not-frozen',
170
- version: 0,
171
- initializer: () => ({ a: [{ x: 'x' }] })
172
- })
173
- store.freeze()
174
- store.value.a[0].x = 'y'
175
- })
176
-
177
- test('freeze provided value but not array property', () => {
178
- const store = createStore({
179
- moduleName,
180
- key: 'not freeze array value',
181
- version: 0,
182
- initializer: () => ({ a: { b: 1 }, c: [{ x: 1 }] })
183
- })
184
-
185
- store.freeze(store.value)
186
- a.throws(() => store.value.a = { b: 2 }, TypeError)
187
- store.value.c.push({ x: 2 })
188
- })
189
- test('user can pre-freeze value', () => {
190
- const store = createStore({
191
- moduleName,
192
- key: 'self freeze',
193
- version: 0,
194
- initializer: () => ({ a: { b: 1 } })
195
- })
196
-
197
- store.freeze(Object.freeze(store.value))
198
- })
199
- })
200
-
201
- test('reset on freezed store will get new unfreezed value', () => {
202
- const store = createStore({
203
- moduleName,
204
- key: 'reset on freeze',
205
- version: 0,
206
- initializer: () => ({ a: { b: 1 } })
207
- })
208
-
209
- store.freeze()
210
- store.reset()
211
- store.value.a = { b: 2 }
212
- })
213
-
214
- test('key is optional', () => {
215
- const store = createStore({ moduleName, version: '1.0.0', initializer: () => ({ a: 1 }) })
216
- expect(store.value.a).toBe(1)
217
- })
package/ts/createStore.ts DELETED
@@ -1,43 +0,0 @@
1
- import { StoreOptions, StoreValue } from './types'
2
- import { Stores } from './typesInternal'
3
- import { freezeStoreValue, getStoreValue, initStoreValue, resetStoreValue } from './util'
4
-
5
- export type Store<T extends StoreValue> = {
6
- /**
7
- * The store value.
8
- */
9
- readonly value: T,
10
- /**
11
- * Freezes the store value.
12
- * @param value Optional new store value.
13
- * If supplied, this value will be freezed and used as the store value.
14
- * You can use this update the store value and freeze part of it.
15
- * If not supplied,
16
- * the original value will be freezed and its array property will also be freezed.
17
- */
18
- freeze(value?: { [k in keyof T]: Readonly<T[k]> }): void,
19
- /**
20
- * Resets the store to its initial value.
21
- * You should only use this during testing.
22
- */
23
- reset(): void,
24
- }
25
-
26
- const stores = Object.create(null) as Stores
27
-
28
- /**
29
- * Creates a store of type T.
30
- * @see https://www.npmjs.com/package/global-store
31
- */
32
- export function createStore<
33
- T extends StoreValue
34
- >({ moduleName, key, version, initializer }: StoreOptions<T>): Store<T> {
35
- const id = { moduleName, key }
36
- initStoreValue(stores, id, version, initializer)
37
-
38
- return {
39
- get value() { return getStoreValue<T>(stores, id) },
40
- freeze(value) { return freezeStoreValue(stores, id, value) },
41
- reset() { return resetStoreValue(stores, id) }
42
- }
43
- }
package/ts/index.spec.ts DELETED
@@ -1,7 +0,0 @@
1
- import defaultCreate, { createStore } from '.'
2
-
3
- describe('package', () => {
4
- test('default export is `createStore`', () => {
5
- expect(defaultCreate).toBe(createStore)
6
- })
7
- })
package/ts/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export * from './createAsyncStore'
2
- export * from './createStore'
3
- export { createStore as default } from './createStore'
4
- export * from './types'
5
-
@@ -1,41 +0,0 @@
1
- import { shouldInvokeInitializer } from './shouldInvokeInitializer'
2
-
3
- describe('numeric version', () => {
4
- test('true if no versions', () => {
5
- expect(shouldInvokeInitializer([], 0)).toBeTruthy()
6
- })
7
-
8
- test('true if no match major', () => {
9
- expect(shouldInvokeInitializer(['1.0.0'], 0)).toBeTruthy()
10
- })
11
-
12
- test('false if same version exist', () => {
13
- expect(shouldInvokeInitializer([0], 0)).toBeFalsy()
14
- expect(shouldInvokeInitializer([6], 6)).toBeFalsy()
15
- })
16
- });
17
-
18
- describe('string version', () => {
19
- test('true if no versions', () => {
20
- expect(shouldInvokeInitializer([], '1.0.0')).toBeTruthy()
21
- })
22
-
23
- test('true if no match major', () => {
24
- expect(shouldInvokeInitializer(['1.0.0'], '0.0.0')).toBeTruthy()
25
- })
26
-
27
- test('true if minor and patch is newer', () => {
28
- expect(shouldInvokeInitializer(['1.0.0'], '1.1.0')).toBeTruthy()
29
- expect(shouldInvokeInitializer(['1.0.0'], '1.0.1')).toBeTruthy()
30
- })
31
-
32
- test('false if same version exist', () => {
33
- expect(shouldInvokeInitializer([0], '0.0.0')).toBeFalsy()
34
- expect(shouldInvokeInitializer(['1.2.4'], '1.2.4')).toBeFalsy()
35
- })
36
-
37
- test('false if newer minor or patch already exist', () => {
38
- expect(shouldInvokeInitializer(['1.1.0'], '1.0.1')).toBeFalsy()
39
- expect(shouldInvokeInitializer(['1.0.2'], '1.0.1')).toBeFalsy()
40
- })
41
- })
@@ -1,17 +0,0 @@
1
- import { ParsedVersion, toVersionArray } from './toVersionArray'
2
- import { StoreVersion } from './types'
3
-
4
- export function shouldInvokeInitializer(versions: StoreVersion[], version: StoreVersion) {
5
- const vs = versions.map(toVersionArray)
6
- const v = toVersionArray(version)
7
- return noMatchMajor(vs, v) || hasNewVersion(vs, v)
8
- }
9
-
10
- function noMatchMajor(versions: ParsedVersion[], version: ParsedVersion) {
11
- return !versions.some(v => v[0] === version[0])
12
- }
13
-
14
- function hasNewVersion(versions: ParsedVersion[], version: ParsedVersion) {
15
- return versions.filter(v => v[0] === version[0])
16
- .some(v => version[1] > v[1] || (version[1] === v[1] && version[2] > v[2]))
17
- }
@@ -1,8 +0,0 @@
1
- import { StoreVersion } from './types'
2
-
3
- export type ParsedVersion = [number, number, number]
4
-
5
- export function toVersionArray(v: StoreVersion): ParsedVersion {
6
- return typeof v === 'number' ? [0, 0, v] :
7
- v.split('.').map(v => parseInt(v, 10)) as ParsedVersion
8
- }
package/ts/types.ts DELETED
@@ -1,12 +0,0 @@
1
- export type StoreValue = Record<string | symbol, unknown>
2
-
3
- export type StoreVersion = `${number}.${number}.${number}` | number
4
-
5
- export type StoreInitializer<T extends StoreValue> = (current: StoreValue, processedVersions: StoreVersion[]) => T
6
-
7
- export interface StoreOptions<T extends StoreValue> {
8
- moduleName: string,
9
- key?: string,
10
- version: StoreVersion,
11
- initializer: StoreInitializer<T>
12
- }
@@ -1,21 +0,0 @@
1
- import { StoreInitializer, StoreVersion, StoreValue } from './types'
2
-
3
- export interface StoreId { moduleName: string, key?: string }
4
-
5
- export type Stores = Record<
6
- StoreId['moduleName'],
7
- Record<
8
- string,
9
- { versions: StoreVersion[], initializers: StoreInitializer<StoreValue>[], value: StoreValue }
10
- >
11
- >
12
-
13
- export interface StoreCreator<S> {
14
- version: StoreVersion,
15
- resolve: (store: S) => void,
16
- initializer: StoreInitializer<StoreValue>
17
- }
18
-
19
- export type StoreCreators<Store> = Record<
20
- StoreId['moduleName'],
21
- Record<string, Array<StoreCreator<Store>>>>
package/ts/util.ts DELETED
@@ -1,69 +0,0 @@
1
- import { compareVersion } from './compareVersion'
2
- import { createStore } from './createStore'
3
- import { shouldInvokeInitializer } from './shouldInvokeInitializer'
4
- import { StoreInitializer, StoreValue, StoreVersion } from './types'
5
- import { StoreCreator, StoreId, Stores } from './typesInternal'
6
-
7
- export function getStoreValue<T extends StoreValue>(stores: Stores, id: StoreId): T {
8
- return getStore(stores, id).value as T
9
- }
10
-
11
- export function initStoreValue<T extends StoreValue>(stores: Stores, id: StoreId, version: StoreVersion, initializer: StoreInitializer<T>) {
12
- const store = getStore(stores, id)
13
- if (shouldInvokeInitializer(store.versions, version)) {
14
- store.initializers.push(initializer as StoreInitializer<StoreValue>)
15
- store.value = initializer(store.value as T, store.versions)
16
- store.versions.push(version)
17
- }
18
- }
19
-
20
- export function resetStoreValue(stores: Stores, id: StoreId) {
21
- const store = getStore(stores, id)
22
- const versions = store.versions
23
- store.versions = []
24
- store.value = store.initializers.reduce<StoreValue>((value, initializer, i) => {
25
- value = initializer(value, store.versions)
26
- store.versions.push(versions[i])
27
- return value
28
- }, {})
29
- }
30
-
31
- export function getStore(stores: Stores, id: StoreId) {
32
- const moduleStore = stores[id.moduleName] = stores[id.moduleName] || Object.create(null)
33
- const key = id.key ?? 'default'
34
- return moduleStore[key] = moduleStore[key] || { versions: [], value: {}, initializers: [] }
35
- }
36
-
37
- export function resolveCreators(moduleName: string, key: string, storeCreators: Array<StoreCreator<any>>, cs: typeof createStore) {
38
- sortByVersion(storeCreators).forEach(({ version, resolve, initializer }) => resolve(cs({ moduleName, key, version, initializer })))
39
- }
40
-
41
- export function sortByVersion<S>(storeCreators: Array<StoreCreator<S>>) {
42
- return storeCreators.sort((a, b) => compareVersion(a.version, b.version))
43
- }
44
-
45
- export function freezeStoreValue(stores: Stores, id: StoreId, value?: StoreValue) {
46
- const store = getStore(stores, id)
47
- store.value = value ?
48
- Object.isFrozen(value) ? value : Object.freeze(value) :
49
- freezeValue(store.value)
50
- }
51
-
52
- function freezeValue(storeValue: StoreValue) {
53
- if (Object.isFrozen(storeValue)) throw TypeError('Frozen value cannot be freezed again')
54
-
55
- Object.keys(storeValue).forEach(k => freezeIfIsArray(storeValue, k))
56
- // istanbul ignore next
57
- if (Object.getOwnPropertySymbols) {
58
- Object.getOwnPropertySymbols(storeValue).forEach(k => freezeIfIsArray(storeValue, k))
59
- }
60
-
61
- return Object.freeze(storeValue)
62
- }
63
-
64
- function freezeIfIsArray(storeValue: StoreValue, k: string | number | symbol) {
65
- const value = storeValue[k]
66
- if (Array.isArray(value)) {
67
- storeValue[k] = Object.freeze(value)
68
- }
69
- }