From b6ab3e76be425b1cac9d6d3ee2ba40e420d945d3 Mon Sep 17 00:00:00 2001 From: Ian K Smith Date: Thu, 15 Aug 2019 13:15:07 -0600 Subject: [PATCH 1/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49d42a0..3297e71 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ const myLocalStorage = StorageProxy.createLocalStorage('my-namespace', { }); console.log(myLocalStorage.one.two.three) // => "three" -myLocalStorage.one.two.three.four.five = 'six'; // Works! +myLocalStorage.one.four.five = 'six'; // Works! ``` In TypeScript, you can define the shape of your stored data by passing a [generic type parameter](https://www.typescriptlang.org/docs/handbook/generics.html) to the factory function: From e39fbc887cb50fb703dd8bba5adbfa71a2c9931d Mon Sep 17 00:00:00 2001 From: Ian K Smith Date: Thu, 15 Aug 2019 13:15:28 -0600 Subject: [PATCH 2/7] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3297e71..1ca15e4 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,8 @@ const myLocalStorage = StorageProxy.createLocalStorage('my-namespace', { }, }); -console.log(myLocalStorage.one.two.three) // => "three" -myLocalStorage.one.four.five = 'six'; // Works! +console.log(myLocalStorage.one.two.three) // => "three" +myLocalStorage.one.four.five = 'six'; // Works! ``` In TypeScript, you can define the shape of your stored data by passing a [generic type parameter](https://www.typescriptlang.org/docs/handbook/generics.html) to the factory function: From a04e25787b0826f9f02a584bcd92c7e181458be8 Mon Sep 17 00:00:00 2001 From: Ian K Smith Date: Mon, 30 Sep 2019 23:51:06 -0600 Subject: [PATCH 3/7] Add some coverage for mutable 'Array.prototype' methods --- test/src/storage-proxy.spec.ts | 69 +++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/test/src/storage-proxy.spec.ts b/test/src/storage-proxy.spec.ts index 30ea514..9fb9c8a 100644 --- a/test/src/storage-proxy.spec.ts +++ b/test/src/storage-proxy.spec.ts @@ -10,6 +10,7 @@ import { StorageProxy, StorageTarget } from '../../src/lib'; const testNamespace = 'qwerty'; const testStr = 'hello world'; const testObj = { monty: 'python', numbers: [1, 2, 3] }; +const testArr = [1, 2, 3]; interface TestStorage { bar: string; @@ -19,6 +20,7 @@ interface TestStorage { example: string; }; alreadySetDefault: number; + arrayValue: number[]; } function getItem(storageTarget: StorageTarget, path: string) { @@ -48,9 +50,12 @@ export class StorageProxyTestFixture { public setupFixture() { localStorage.setItem( testNamespace, - JSON.stringify({ bar: testStr, test: 999, baz: testObj, alreadySetDefault: 999 }), + JSON.stringify({ bar: testStr, test: 999, baz: testObj, alreadySetDefault: 999, arrayValue: testArr }), + ); + sessionStorage.setItem( + testNamespace, + JSON.stringify({ bar: testStr, test: 999, baz: testObj, arrayValue: testArr }), ); - sessionStorage.setItem(testNamespace, JSON.stringify({ bar: testStr, test: 999, baz: testObj })); this.lStore = StorageProxy.createLocalStorage(testNamespace, { defaults: { example: testStr }, @@ -99,4 +104,64 @@ export class StorageProxyTestFixture { const data = this.sStore.bar; Expect(data).toEqual(testStr); } + + @Test('Validate `Array.prototype.push`') + public arrayPushTest() { + this.lStore.baz!.numbers.push(4, 5, 6); + this.lStore.arrayValue!.push(4, 5, 6); + const dataOne = this.lStore.baz!.numbers; + const dataTwo = this.lStore.arrayValue; + + const expected = [1, 2, 3, 4, 5, 6]; + Expect(dataOne).toEqual(expected); + Expect(dataTwo).toEqual(expected); + } + + @Test('Validate `Array.prototype.pop`') + public arrayPopTest() { + this.lStore.baz!.numbers.pop(); + this.lStore.arrayValue!.pop(); + const dataOne = this.lStore.baz!.numbers; + const dataTwo = this.lStore.arrayValue; + + const expected = [1, 2, 3, 4, 5]; + Expect(dataOne).toEqual(expected); + Expect(dataTwo).toEqual(expected); + } + + @Test('Validate `Array.prototype.unshift`') + public arrayUnshiftTest() { + this.lStore.baz!.numbers.unshift(999); + this.lStore.arrayValue!.unshift(999); + const dataOne = this.lStore.baz!.numbers; + const dataTwo = this.lStore.arrayValue; + + const expected = [999, 1, 2, 3, 4, 5]; + Expect(dataOne).toEqual(expected); + Expect(dataTwo).toEqual(expected); + } + + @Test('Validate `Array.prototype.shift`') + public arrayShiftTest() { + this.lStore.baz!.numbers.shift(); + this.lStore.arrayValue!.shift(); + const dataOne = this.lStore.baz!.numbers; + const dataTwo = this.lStore.arrayValue; + + const expected = [1, 2, 3, 4, 5]; + Expect(dataOne).toEqual(expected); + Expect(dataTwo).toEqual(expected); + } + + @Test('Validate `Array.prototype.splice`') + public arraySpliceTest() { + this.lStore.baz!.numbers.splice(1, 2, ...[999, 998]); + this.lStore.arrayValue!.splice(1, 2, ...[999, 998]); + const dataOne = this.lStore.baz!.numbers; + const dataTwo = this.lStore.arrayValue; + + const expected = [1, 999, 998, 4, 5]; + Expect(dataOne).toEqual(expected); + Expect(dataTwo).toEqual(expected); + } } From b066bfec077bfeb7e1a88ca50661ccf466a6644d Mon Sep 17 00:00:00 2001 From: Ian K Smith Date: Tue, 1 Oct 2019 00:00:03 -0600 Subject: [PATCH 4/7] Update CircleCI configuration --- .circleci/config.yml | 137 +++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 56 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 67d7a34..6310b36 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,5 +1,8 @@ # ---------------------------------------------------------------------------- # -# SETUP INSTRUCTIONS # +# CI INSTRUCTIONS # +# ~~~~~~~~~~~~~~~ # +# This configuration is optimized for continuous delivery of NPM packages # +# using Yarn + TypeScript. # # ---------------------------------------------------------------------------- # # # # 1. Environment variables required in CircleCI: # @@ -22,48 +25,77 @@ # # # lint -- Run a linter against source files. # # build -- Build output required for publishing to NPM. # -# test -- Run unit tests. # +# test -- Run unit/integration/e2e tests. # +# # +# ---------------------------------------------------------------------------- # +# # +# 4. Ensure the aliases for `&dependency-paths` and `&build-output-paths` # +# below properly reflect the dependency and output directories of your # +# app or module. # +# # +# ---------------------------------------------------------------------------- # +# # +# 5. [OPTIONAL] Configure GREN to your liking using `.grenrc`. # +# # +# See: https://github.com/github-tools/github-release-notes # # # # ---------------------------------------------------------------------------- # - version: 2.1 -# --- Alias anchor definitions ----------------------------------------------- # - -aliases: - - &workspace-root - /home/circleci/project +# --- YAML Aliases ----------------------------------------------------------- # - - &attach-workspace - attach_workspace: - at: *workspace-root - - - &dependency-cache-key - v1-dependency-cache-{{ checksum "yarn.lock" }} - - - &dependency-paths - paths: - - node_modules +aliases: [ + # List of dependency paths that should be persisted to the + # CircleCI workspace. + &dependency-paths [ + "node_modules" + ], - - &build-output-paths - paths: - - dist + # List of build output paths that should be persisted to the + # CircleCI workspace. + &build-output-paths [ + "dist" + ], - - &filter-default-branches - filters: - branches: - ignore: /^master$|^next$/ + # Yarn lockfile cache key (update "vN" => "vN+1" to cache-bust). + &dependency-cache-key "v1-dependency-cache-{{ checksum \"yarn.lock\" }}", - - &filter-release-branches-only - filters: - branches: - only: master + &workspace-root "/home/circleci/project", - - &filter-prerelease-branches-only - filters: - branches: - only: next + &attach-workspace { + attach_workspace: { + at: *workspace-root + } + }, + + # Filter pull requests not in "master" or "next" (development code) + &filter-default-branches { + filters: { + branches: { + ignore: "/^master$|^next$/" + } + } + }, + + # Filter pull requests in "master" only (production code). + &filter-release-branches-only { + filters: { + branches: { + only: "master" + } + } + }, + + # Filter pull requests in "next" only (pre-release code). + &filter-prerelease-branches-only { + filters: { + branches: { + only: "next" + } + } + }, +] # --- Executor definitions --------------------------------------------------- # @@ -75,8 +107,8 @@ executors: # --- Job definitions -------------------------------------------------------- # jobs: - # Installs Node dependencies via Yarn, caches them, then persists to the - # workspace. + # Installs Node dependencies via Yarn, caches them, then persists + # to the workspace. install-dependencies: executor: default steps: @@ -85,23 +117,23 @@ jobs: - restore_cache: key: *dependency-cache-key - run: - name: Install App Dependencies - command: yarn install --frozen-lockfile + name: Install Module Dependencies + command: yarn install - save_cache: - <<: *dependency-paths + paths: *dependency-paths key: *dependency-cache-key - persist_to_workspace: - <<: *dependency-paths + paths: *dependency-paths root: *workspace-root - # Runs the linter (tslint) on relevant source files. + # Runs the linter against relevant source files. lint: executor: default steps: - checkout - *attach-workspace - run: - name: Lint TypeScripts + name: Lint source files command: yarn lint # Builds modules and persists the build output to the workspace. @@ -114,10 +146,10 @@ jobs: name: Build modules command: yarn build - persist_to_workspace: - <<: *build-output-paths + paths: *build-output-paths root: *workspace-root - # Run unit tests. + # Run unit/integration/e2e tests. test: executor: default steps: @@ -179,7 +211,7 @@ jobs: - *attach-workspace - run: name: Install github-release-notes package - command: yarn add github-release-notes + command: yarn add -D -W github-release-notes - run: name: Generate release notes and publish to GitHub command: npx gren release --override --token $GITHUB_REPO_TOKEN @@ -193,16 +225,14 @@ jobs: - *attach-workspace - run: name: Install github-release-notes package - command: yarn add github-release-notes + command: yarn add -D -W github-release-notes - run: name: Generate release notes and publish to GitHub command: npx gren release --override --prerelease --token $GITHUB_REPO_TOKEN # --- Workflow definitions --------------------------------------------------- # -# This configuration is optimized for continuous delivery of NPM packages. workflows: - version: 2.1 # Builds modules, verifies code with the linter, and runs unit tests. pull-request: @@ -239,6 +269,8 @@ workflows: requires: - lint + # Manual approval step as a final gatekeeper to prevent + # possible mistakes! - confirm-release: type: approval requires: @@ -261,7 +293,7 @@ workflows: # Builds modules, verifies code with the linter, runs unit tests, and # publishes a pre-release version of the built package to NPM. - publish-canary-to-npm: + publish-prerelease-to-npm: jobs: - install-dependencies: *filter-prerelease-branches-only @@ -277,22 +309,15 @@ workflows: requires: - lint - - confirm-prerelease: - type: approval + - create-prerelease: requires: - build - test - - create-prerelease: - requires: - - confirm-prerelease - - tag-release: requires: - - confirm-prerelease - create-prerelease - create-prerelease-notes: requires: - - confirm-prerelease - tag-release From c88e804c359417178c25283f561152db5efa73b3 Mon Sep 17 00:00:00 2001 From: Ian K Smith Date: Tue, 1 Oct 2019 00:01:07 -0600 Subject: [PATCH 5/7] Update 'on-change' NPM dependency --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 757f90b..28a2cbf 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,6 @@ "typescript": "^3.0.3" }, "dependencies": { - "on-change": "^1.2.0" + "on-change": "^1.6.2" } } diff --git a/yarn.lock b/yarn.lock index d3c46e3..58be7b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2499,10 +2499,10 @@ object.values@^1.0.4: function-bind "^1.1.0" has "^1.0.1" -on-change@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/on-change/-/on-change-1.2.0.tgz#7ae7988f2ffe4746b46446d08abae373c4a0f853" - integrity sha512-TnxXuoxvoLwlnZVwdm4J/FdsBdBkMxuM57R5pQt+Bw751gKikNY3jmJUzaXNR79/+hHmA1dUqB8W8+RQlcsi0Q== +on-change@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/on-change/-/on-change-1.6.2.tgz#00f3ade48ffc1defdf315431964e7193ec102f88" + integrity sha512-PMIohH2WPA273fIfB+zyA7pkOmHNQxR6Z4xrDofgr5AGRhWRakGpmpb4cO3+N3wx9wkP929TO2J1w32qvzfsuA== once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" From ab224a4802c4e2331b78d2e875b28c03e711d477 Mon Sep 17 00:00:00 2001 From: Ian K Smith Date: Tue, 1 Oct 2019 00:04:59 -0600 Subject: [PATCH 6/7] Add raw storage assertions to array method tests --- test/src/storage-proxy.spec.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/src/storage-proxy.spec.ts b/test/src/storage-proxy.spec.ts index 9fb9c8a..2cae530 100644 --- a/test/src/storage-proxy.spec.ts +++ b/test/src/storage-proxy.spec.ts @@ -79,14 +79,14 @@ export class StorageProxyTestFixture { Expect(this.lStore.alreadySetDefault).toEqual(999); } - @Test('Set a `localStorage` key') + @Test('Set `localStorage` key') public setLocalStorageKeyTest() { this.lStore.fizz = 123; Expect(getItem(StorageTarget.Local, 'fizz')).toEqual(123); } - @Test('Set a `sessionStorage` key') + @Test('Set `sessionStorage` key') public setSessionStorageKeyTest() { this.sStore.fizz = 123; @@ -115,6 +115,8 @@ export class StorageProxyTestFixture { const expected = [1, 2, 3, 4, 5, 6]; Expect(dataOne).toEqual(expected); Expect(dataTwo).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'baz.numbers')).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'arrayValue')).toEqual(expected); } @Test('Validate `Array.prototype.pop`') @@ -127,6 +129,8 @@ export class StorageProxyTestFixture { const expected = [1, 2, 3, 4, 5]; Expect(dataOne).toEqual(expected); Expect(dataTwo).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'baz.numbers')).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'arrayValue')).toEqual(expected); } @Test('Validate `Array.prototype.unshift`') @@ -139,6 +143,8 @@ export class StorageProxyTestFixture { const expected = [999, 1, 2, 3, 4, 5]; Expect(dataOne).toEqual(expected); Expect(dataTwo).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'baz.numbers')).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'arrayValue')).toEqual(expected); } @Test('Validate `Array.prototype.shift`') @@ -151,6 +157,8 @@ export class StorageProxyTestFixture { const expected = [1, 2, 3, 4, 5]; Expect(dataOne).toEqual(expected); Expect(dataTwo).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'baz.numbers')).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'arrayValue')).toEqual(expected); } @Test('Validate `Array.prototype.splice`') @@ -163,5 +171,7 @@ export class StorageProxyTestFixture { const expected = [1, 999, 998, 4, 5]; Expect(dataOne).toEqual(expected); Expect(dataTwo).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'baz.numbers')).toEqual(expected); + Expect(getItem(StorageTarget.Local, 'arrayValue')).toEqual(expected); } } From ee071d0353e0702b2eef9fd0d5c0d19f8bdb10b8 Mon Sep 17 00:00:00 2001 From: Ian K Smith Date: Tue, 1 Oct 2019 00:12:15 -0600 Subject: [PATCH 7/7] v0.11.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28a2cbf..005068a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "storage-proxy", - "version": "0.11.2", + "version": "0.11.3", "description": "Use web storage (localStorage/sessionStorage) just like plain objects using ES6 Proxies.", "author": "Ian K Smith ", "license": "MIT",