Skip to content

Commit dcc0ed4

Browse files
authored
fix (datafile manager): Add several small fixes including top-level entry point (#8)
Summary: This adds several small, but required, fixes: - Update README - Rename liveUpdates to autoUpdate - Increase minimum allowed update interval to 1000 ms - Increase default update interval to 5 minutes - Introduce abstract method for subclasses to provide default config. Use this for autoUpdate default true in node, false in browser - Add top-level entry points for node (index.node.ts) and browser (index.browser.ts) - package.json fixes: Fix license, move @types/node to dev dependencies, add build script, add browser/node entry points - Remove unused DatafileManagerConfig interface properties - Add missing license header in some files Test plan: Updated affected unit tests
1 parent cec5eee commit dcc0ed4

14 files changed

+179
-33
lines changed

packages/datafile-manager/README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Javascript SDK Datafile Manager
22

3-
TODO: Write this
3+
This package provides a datafile manager implementations for Node.js and the browser.
44

55
## Installation
66

@@ -10,4 +10,22 @@ npm install @optimizely/datafile-manager
1010

1111
## Usage
1212

13-
TODO
13+
```js
14+
const { DatafileManager } = require('@optimizely/datafile-manager')
15+
16+
const manager = new DatafileManager({
17+
sdkKey: '9LCprAQyd1bs1BBXZ3nVji',
18+
autoUpdate: true,
19+
updateInterval: 5000,
20+
})
21+
manager.start()
22+
manager.onReady().then(() => {
23+
const datafile = manager.get()
24+
console.log('Manager is ready with datafile: ')
25+
console.log(datafile)
26+
})
27+
manager.on('update', ({ datafile }) => {
28+
console.log('New datafile available: ')
29+
console.log(datafile)
30+
})
31+
```

packages/datafile-manager/__test__/browserDatafileManager.spec.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ describe('browserDatafileManager', () => {
4444

4545
const manager = new BrowserDatafileManager({
4646
sdkKey: '1234',
47-
liveUpdates: false,
47+
autoUpdate: false,
4848
})
4949
manager.start()
5050
expect(makeGetRequestSpy).toBeCalledTimes(1)
@@ -68,7 +68,7 @@ describe('browserDatafileManager', () => {
6868
})
6969
const manager = new BrowserDatafileManager({
7070
sdkKey: '1234',
71-
liveUpdates: true,
71+
autoUpdate: true,
7272
timeoutFactory: testTimeoutFactory,
7373
})
7474
manager.start()
@@ -82,4 +82,27 @@ describe('browserDatafileManager', () => {
8282

8383
await manager.stop()
8484
})
85+
86+
it('defaults to false for autoUpdate', async () => {
87+
makeGetRequestSpy.mockReturnValue({
88+
abort: jest.fn(),
89+
responsePromise: Promise.resolve({
90+
statusCode: 200,
91+
body: '{"foo":"bar"}',
92+
headers: {
93+
'last-modified': 'Fri, 08 Mar 2019 18:57:17 GMT',
94+
},
95+
})
96+
})
97+
const manager = new BrowserDatafileManager({
98+
sdkKey: '1234',
99+
timeoutFactory: testTimeoutFactory,
100+
})
101+
manager.start()
102+
await manager.onReady()
103+
// Should not set a timeout for a later update
104+
expect(testTimeoutFactory.timeoutFns.length).toBe(0)
105+
106+
await manager.stop()
107+
})
85108
})

packages/datafile-manager/__test__/httpPollingDatafileManager.spec.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class TestDatafileManager extends HTTPPollingDatafileManager {
5252
this.responsePromises.push(responsePromise)
5353
return { responsePromise, abort: jest.fn() }
5454
}
55+
56+
getConfigDefaults(): Partial<DatafileManagerConfig> {
57+
return {}
58+
}
5559
}
5660

5761
describe('httpPollingDatafileManager', () => {
@@ -96,9 +100,9 @@ describe('httpPollingDatafileManager', () => {
96100
})
97101
})
98102

99-
describe('when constructed with sdkKey only', () => {
103+
describe('when constructed with sdkKey and autoUpdate: true', () => {
100104
beforeEach(() => {
101-
manager = createTestManager({ sdkKey: '123', updateInterval: 10 })
105+
manager = createTestManager({ sdkKey: '123', updateInterval: 1000, autoUpdate: true })
102106
})
103107

104108
describe('initial state', () => {
@@ -145,7 +149,7 @@ describe('httpPollingDatafileManager', () => {
145149
manager.start()
146150
await manager.onReady()
147151
expect(setTimeoutSpy).toBeCalledTimes(1)
148-
expect(setTimeoutSpy.mock.calls[0][1]).toBe(10)
152+
expect(setTimeoutSpy.mock.calls[0][1]).toBe(1000)
149153
})
150154

151155
it('emits update events after live updates', async () => {
@@ -414,9 +418,9 @@ describe('httpPollingDatafileManager', () => {
414418
})
415419
})
416420

417-
describe('when constructed with sdkKey and liveUpdates: false', () => {
421+
describe('when constructed with sdkKey and autoUpdate: false', () => {
418422
beforeEach(() => {
419-
manager = createTestManager({ sdkKey: '123', liveUpdates: false })
423+
manager = createTestManager({ sdkKey: '123', autoUpdate: false })
420424
})
421425

422426
it('after being started, fetches the datafile and resolves onReady', async () => {
@@ -466,7 +470,7 @@ describe('httpPollingDatafileManager', () => {
466470
beforeEach(() => {
467471
manager = createTestManager({
468472
sdkKey: '456',
469-
updateInterval: 10,
473+
updateInterval: 1000,
470474
urlTemplate: 'https://localhost:5556/datafiles/$SDK_KEY',
471475
})
472476
})

packages/datafile-manager/__test__/nodeDatafileManager.spec.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ describe('nodeDatafileManager', () => {
4444

4545
const manager = new NodeDatafileManager({
4646
sdkKey: '1234',
47-
liveUpdates: false,
47+
autoUpdate: false,
4848
})
4949
manager.start()
5050
expect(makeGetRequestSpy).toBeCalledTimes(1)
@@ -68,7 +68,7 @@ describe('nodeDatafileManager', () => {
6868
})
6969
const manager = new NodeDatafileManager({
7070
sdkKey: '1234',
71-
liveUpdates: true,
71+
autoUpdate: true,
7272
timeoutFactory: testTimeoutFactory,
7373
})
7474
manager.start()
@@ -82,4 +82,29 @@ describe('nodeDatafileManager', () => {
8282

8383
await manager.stop()
8484
})
85+
86+
it('defaults to true for autoUpdate', async () => {
87+
makeGetRequestSpy.mockReturnValue({
88+
abort: jest.fn(),
89+
responsePromise: Promise.resolve({
90+
statusCode: 200,
91+
body: '{"foo":"bar"}',
92+
headers: {
93+
'last-modified': 'Fri, 08 Mar 2019 18:57:17 GMT',
94+
},
95+
})
96+
})
97+
const manager = new NodeDatafileManager({
98+
sdkKey: '1234',
99+
timeoutFactory: testTimeoutFactory,
100+
})
101+
manager.start()
102+
await manager.onReady()
103+
// Should set a timeout for a later update
104+
expect(testTimeoutFactory.timeoutFns.length).toBe(1)
105+
testTimeoutFactory.timeoutFns[0]()
106+
expect(makeGetRequestSpy).toBeCalledTimes(2)
107+
108+
await manager.stop()
109+
})
85110
})

packages/datafile-manager/package.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
"version": "0.1.0",
44
"description": "Optimizely Full Stack Datafile Manager",
55
"homepage": "https://github.com/optimizely/javascript-sdk/tree/master/packages/datafile-manager",
6-
"license": "MIT",
7-
"main": "lib/index.js",
6+
"license": "Apache-2.0",
7+
"engines": {
8+
"node": ">=4.0.0"
9+
},
10+
"main": "lib/index.node.js",
11+
"browser": "lib/index.browser.js",
812
"types": "lib/index.d.ts",
913
"directories": {
1014
"lib": "lib",
@@ -33,6 +37,7 @@
3337
"devDependencies": {
3438
"@types/jest": "^24.0.9",
3539
"@types/nock": "^9.3.1",
40+
"@types/node": "^11.11.7",
3641
"@types/sinon": "^7.0.10",
3742
"jest": "^24.1.0",
3843
"nock": "^10.0.6",
@@ -41,10 +46,10 @@
4146
"typescript": "^3.3.3333"
4247
},
4348
"dependencies": {
44-
"@optimizely/js-sdk-logging": "^0.1.0",
45-
"@types/node": "^11.10.5"
49+
"@optimizely/js-sdk-logging": "^0.1.0"
4650
},
4751
"scripts": {
48-
"test": "jest"
52+
"test": "jest",
53+
"build": "rm -r lib && tsc"
4954
}
5055
}

packages/datafile-manager/src/browserDatafileManager.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,16 @@
1717
import { makeGetRequest } from './browserRequest'
1818
import HttpPollingDatafileManager from './httpPollingDatafileManager'
1919
import { Headers, AbortableRequest } from './http';
20+
import { DatafileManagerConfig } from './datafileManager';
2021

2122
export default class BrowserDatafileManager extends HttpPollingDatafileManager {
2223
protected makeGetRequest(reqUrl: string, headers: Headers): AbortableRequest {
2324
return makeGetRequest(reqUrl, headers)
2425
}
26+
27+
protected getConfigDefaults(): Partial<DatafileManagerConfig> {
28+
return {
29+
autoUpdate: false,
30+
}
31+
}
2532
}

packages/datafile-manager/src/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
* limitations under the License.
1515
*/
1616

17-
export const DEFAULT_UPDATE_INTERVAL = 5000
17+
export const DEFAULT_UPDATE_INTERVAL = 5 * 60 * 1000 // 5 minutes
1818

19-
export const MIN_UPDATE_INTERVAL = 1
19+
export const MIN_UPDATE_INTERVAL = 1000
2020

2121
export const SDK_KEY_TOKEN = '$SDK_KEY'
2222

packages/datafile-manager/src/datafileManager.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,8 @@ export enum CacheDirective {
4545
}
4646

4747
export interface DatafileManagerConfig {
48-
cacheDirective?: CacheDirective
48+
autoUpdate?: boolean
4949
datafile?: string
50-
liveUpdates?: boolean
51-
maxCacheAge?: number
5250
sdkKey: string
5351
timeoutFactory?: TimeoutFactory,
5452
updateInterval?: number

packages/datafile-manager/src/httpPollingDatafileManager.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana
4141
// The request will be aborted if the manager is stopped while the request is in flight.
4242
protected abstract makeGetRequest(reqUrl: string, headers: Headers): AbortableRequest
4343

44+
// Return any default configuration options that should be applied
45+
protected abstract getConfigDefaults(): Partial<DatafileManagerConfig>
46+
4447
private currentDatafile: string | null
4548

4649
private readonly sdkKey: string
@@ -55,7 +58,7 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana
5558

5659
private readonly emitter: EventEmitter
5760

58-
private readonly liveUpdates: boolean
61+
private readonly autoUpdate: boolean
5962

6063
private readonly updateInterval: number
6164

@@ -74,14 +77,18 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana
7477
private backoffController: BackoffController
7578

7679
constructor(config: DatafileManagerConfig) {
80+
const configWithDefaultsApplied: DatafileManagerConfig = {
81+
...this.getConfigDefaults(),
82+
...config
83+
}
7784
const {
7885
datafile,
79-
liveUpdates = true,
86+
autoUpdate = false,
8087
sdkKey,
8188
timeoutFactory = DEFAULT_TIMEOUT_FACTORY,
8289
updateInterval = DEFAULT_UPDATE_INTERVAL,
8390
urlTemplate = DEFAULT_URL_TEMPLATE,
84-
} = config
91+
} = configWithDefaultsApplied
8592

8693
this.sdkKey = sdkKey
8794

@@ -108,7 +115,7 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana
108115

109116
this.timeoutFactory = timeoutFactory
110117
this.emitter = new EventEmitter()
111-
this.liveUpdates = liveUpdates
118+
this.autoUpdate = autoUpdate
112119
if (isValidUpdateInterval(updateInterval)) {
113120
this.updateInterval = updateInterval
114121
} else {
@@ -197,7 +204,7 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana
197204
this.currentDatafile = datafile
198205
if (!this.isReadyPromiseSettled) {
199206
this.resolveReadyPromise()
200-
} else if (this.liveUpdates) {
207+
} else if (this.autoUpdate) {
201208
const datafileUpdate: DatafileUpdate = {
202209
datafile,
203210
}
@@ -213,10 +220,10 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana
213220

214221
this.currentRequest = undefined
215222

216-
if (this.liveUpdates) {
223+
if (this.autoUpdate) {
217224
this.scheduleNextUpdate()
218225
}
219-
if (!this.isReadyPromiseSettled && !this.liveUpdates) {
226+
if (!this.isReadyPromiseSettled && !this.autoUpdate) {
220227
// We will never resolve ready, so reject it
221228
this.rejectReadyPromise(new Error('Failed to become ready'))
222229
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright 2019, Optimizely
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
export * from './datafileManager'
18+
export { default as DatafileManager } from './browserDatafileManager'
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright 2019, Optimizely
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
export * from './datafileManager'
18+
export { default as DatafileManager } from './nodeDatafileManager'

packages/datafile-manager/src/nodeDatafileManager.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,16 @@
1717
import { makeGetRequest } from './nodeRequest'
1818
import HttpPollingDatafileManager from './httpPollingDatafileManager'
1919
import { Headers, AbortableRequest } from './http';
20+
import { DatafileManagerConfig } from './datafileManager';
2021

2122
export default class NodeDatafileManager extends HttpPollingDatafileManager {
2223
protected makeGetRequest(reqUrl: string, headers: Headers): AbortableRequest {
2324
return makeGetRequest(reqUrl, headers)
2425
}
26+
27+
protected getConfigDefaults(): Partial<DatafileManagerConfig> {
28+
return {
29+
autoUpdate: true,
30+
}
31+
}
2532
}

0 commit comments

Comments
 (0)