├── .github
├── ISSUE_TEMPLATE.md
├── main.workflow
└── workflows
│ ├── nodejs.yml
│ └── release.yml
├── .gitignore
├── .huskyrc
├── .nvmrc
├── .prettierIgnore
├── .prettierrc
├── Alerts.vue
├── BaseLayout.vue
├── CHANGELOG.md
├── LICENSE
├── __tests__
└── validation
│ └── rules
│ ├── accepted.test.js
│ ├── after.test.js
│ ├── after_or_equal.test.js
│ ├── alpha.test.js
│ ├── alpha_num.test.js
│ ├── array.test.js
│ ├── before.test.js
│ ├── before_or_equal.test.js
│ ├── between.js
│ ├── boolean.test.js
│ ├── confirmed.test.js
│ ├── date.test.js
│ ├── different.test.js
│ ├── email.test.js
│ ├── image.test.js
│ ├── integer.test.js
│ ├── max.test.js
│ ├── mimetypes.test.js
│ ├── min.test.js
│ ├── nullable.test.js
│ ├── numeric.test.js
│ ├── regex.test.js
│ ├── required.test.js
│ ├── required_if.test.js
│ ├── required_unless.test.js
│ ├── required_with.test.js
│ ├── required_with_all.test.js
│ ├── required_without.test.js
│ ├── required_without_all.test.js
│ ├── same.test.js
│ ├── size.test.js
│ ├── string.test.js
│ └── url.test.js
├── babel.config.js
├── commitlint.config.js
├── components
└── Alert.vue
├── jest.config.js
├── package-lock.json
├── package.json
├── readme.md
├── release.config.js
├── src
├── config
│ ├── ConfigInterface.ts
│ ├── ConfigService.ts
│ └── ConfigServiceProvider.ts
├── cookies
│ ├── CookieInterface.ts
│ ├── CookieService.ts
│ └── CookieServiceProvider.ts
├── foundation
│ ├── Application.ts
│ ├── ApplicationInterface.ts
│ └── ContainerMixin.ts
├── globals.ts
├── http
│ ├── AxiosHttpService.ts
│ ├── HttpServiceInterface.ts
│ ├── HttpServiceProvider.ts
│ ├── config.ts
│ └── interfaces
│ │ ├── HttpErrorInterface.ts
│ │ ├── HttpMiddlewareInterface.ts
│ │ ├── HttpRequestConfigInterface.ts
│ │ └── HttpResponseInterface.ts
├── index.ts
├── plugins
│ ├── alerts
│ │ ├── AlertService.ts
│ │ ├── AlertServiceInterface.ts
│ │ ├── AlertServiceProvider.ts
│ │ ├── Alerts.ts
│ │ ├── alert-store
│ │ │ ├── AlertStore.ts
│ │ │ ├── actions.ts
│ │ │ ├── mutations.ts
│ │ │ ├── state.ts
│ │ │ └── stateInterface.ts
│ │ ├── config.ts
│ │ └── models
│ │ │ └── AlertModel.ts
│ ├── autoRegisterComponents
│ │ └── AutoRegisterComponentServiceProvider.ts
│ ├── autoRegisterDirectives
│ │ └── AutoRegisterDirectiveServiceProvider.ts
│ ├── autoRegisterFilters
│ │ └── AutoRegisterFilterServiceProvider.ts
│ ├── autoRegisterLayouts
│ │ └── AutoRegisterLayoutServiceProvider.ts
│ ├── autoRegisterMixins
│ │ └── AutoRegisterMixinServiceProvider.ts
│ └── forms
│ │ ├── Form.ts
│ │ ├── FormServiceProvider.ts
│ │ └── FormsPlugin.ts
├── routing
│ ├── Route.ts
│ ├── RouteMiddlewareInterface.ts
│ ├── RouterInterface.ts
│ ├── RoutesInterface.ts
│ ├── RoutingServiceProvider.ts
│ ├── VueRouterService.ts
│ └── config.ts
├── state
│ ├── StateServiceInterface.ts
│ ├── StateServiceProvider.ts
│ ├── StoreModule.ts
│ └── VuexService.ts
├── storage
│ ├── StorageService.ts
│ ├── StorageServiceInterface.ts
│ └── StorageServiceProvider.ts
├── support
│ ├── Model.ts
│ ├── ServiceProvider.ts
│ └── ServiceProviderInterface.ts
├── utilities
│ ├── camelize.ts
│ ├── clone.ts
│ ├── dashify.ts
│ ├── filterEmpty.ts
│ ├── getByDot.ts
│ ├── index.ts
│ ├── isEmpty.ts
│ ├── setByDot.ts
│ └── uncamelize.ts
├── validation
│ ├── Validation.ts
│ ├── ValidationServiceInterface.ts
│ ├── ValidationServiceProvider.ts
│ ├── Validator.ts
│ ├── VarieValidationService.ts
│ ├── config.ts
│ ├── directive
│ │ └── Validate.ts
│ └── rules
│ │ ├── accepted.ts
│ │ ├── after.ts
│ │ ├── after_or_equal.ts
│ │ ├── alpha.ts
│ │ ├── alpha_num.ts
│ │ ├── array.ts
│ │ ├── before.ts
│ │ ├── before_or_equal.ts
│ │ ├── between.ts
│ │ ├── boolean.ts
│ │ ├── confirmed.ts
│ │ ├── date.ts
│ │ ├── different.ts
│ │ ├── email.ts
│ │ ├── image.ts
│ │ ├── index.ts
│ │ ├── integer.ts
│ │ ├── max.ts
│ │ ├── mimetypes.ts
│ │ ├── min.ts
│ │ ├── nullable.ts
│ │ ├── numeric.ts
│ │ ├── regex.ts
│ │ ├── required.ts
│ │ ├── required_if.ts
│ │ ├── required_unless.ts
│ │ ├── required_with.ts
│ │ ├── required_with_all.ts
│ │ ├── required_without.ts
│ │ ├── required_without_all.ts
│ │ ├── same.ts
│ │ ├── size.ts
│ │ ├── string.ts
│ │ └── url.ts
└── vue-component.d.ts
├── stubs
├── appMiddleware.ts
├── component.vue
├── directive.ts
├── filter.ts
├── mixin.ts
├── model.ts
├── provider.ts
├── routeMiddleware.ts
├── rule.ts
├── service.ts
├── store
│ ├── actions.ts
│ ├── getters.ts
│ ├── index.ts
│ ├── mutations.ts
│ ├── state.ts
│ └── stateInterface.ts
└── validator.ts
└── tsconfig.json
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | - Varie Version: #.#.#
2 | - Node Version: #.#.#
3 |
4 | ### Description:
5 |
6 | ### Steps To Reproduce:
7 |
--------------------------------------------------------------------------------
/.github/main.workflow:
--------------------------------------------------------------------------------
1 | workflow "Build, Test, and Publish" {
2 | resolves = ["Release"]
3 | on = "release"
4 | }
5 |
6 | # Filter for master branch
7 | action "Is Master" {
8 | uses = "actions/bin/filter@master"
9 | args = "branch master"
10 | }
11 |
12 | action "Install Dependencies" {
13 | needs = "Is Master"
14 | uses = "actions/npm@master"
15 | args = "ci"
16 | }
17 |
18 | action "Install Peer Dependencies" {
19 | needs = "Install Dependencies"
20 | uses = "actions/npm@master"
21 | args = "run installPeers"
22 | }
23 |
24 | action "Test" {
25 | needs = "Install Peer Dependencies"
26 | uses = "actions/npm@master"
27 | args = "test"
28 | }
29 |
30 | action "Build" {
31 | needs = "Test"
32 | uses = "actions/npm@master"
33 | args = "build"
34 | }
35 |
36 | action "Release" {
37 | needs = "Build"
38 | uses = "actions/npm@master"
39 | args = "run release"
40 | secrets = ["GITHUB_TOKEN", "NPM_TOKEN"]
41 | }
42 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Node CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - "*" # matches every branch
7 | - "*/*" # matches every branch containing a single '/'
8 | - "!master" # excludes master
9 |
10 | jobs:
11 | test:
12 | name: Test on node ${{ matrix.node_version }} and ${{ matrix.os }}
13 | runs-on: ${{ matrix.os }}
14 | strategy:
15 | matrix:
16 | node_version: [10.x, 12.x]
17 | os: [ubuntu-latest, macOS-latest]
18 |
19 | steps:
20 | - uses: actions/checkout@v1
21 | - name: Use Node.js ${{ matrix.node_version }}
22 | uses: actions/setup-node@v1
23 | with:
24 | version: ${{ matrix.node_version }}
25 |
26 | - name: npm install, build and test
27 | run: |
28 | npm ci
29 | npm run installPeers
30 | npm run build
31 | npm test
32 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Semantic Release
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | push:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | build:
13 |
14 | runs-on: ubuntu-latest
15 |
16 | strategy:
17 | matrix:
18 | node-version: [12.x]
19 |
20 | steps:
21 | - uses: actions/checkout@v1
22 | - name: Use Node.js ${{ matrix.node-version }}
23 | uses: actions/setup-node@v1
24 | with:
25 | node-version: ${{ matrix.node-version }}
26 | - name: npm install, build, test, and release
27 | run: |
28 | npm ci
29 | npm run installPeers
30 | npm run build
31 | npm test
32 | npm run release
33 | env:
34 | CI: true
35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log*
3 | lib
4 |
--------------------------------------------------------------------------------
/.huskyrc:
--------------------------------------------------------------------------------
1 | # ~/.huskyrc
2 | export NVM_DIR="$HOME/.nvm"
3 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
4 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 12.13.1
2 |
3 |
--------------------------------------------------------------------------------
/.prettierIgnore:
--------------------------------------------------------------------------------
1 | lib/
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi" : true,
6 | "singleQuote": false,
7 | "trailingComma": "all",
8 | "bracketSpacing" : true,
9 | "jsxBracketSameLine": false,
10 | "arrowParens": "always",
11 | "rangeStart" : 0,
12 | "requirePragma" : false,
13 | "insertPragma" : false,
14 | "proseWrap" : "preserve"
15 | }
--------------------------------------------------------------------------------
/Alerts.vue:
--------------------------------------------------------------------------------
1 |
79 |
80 |
81 |
86 |
87 |
88 |
102 |
--------------------------------------------------------------------------------
/BaseLayout.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See
4 | [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [1.0.1](https://github.com/variejs/varie-framework/compare/v1.0.0...v1.0.1) (2020-01-21)
7 |
8 |
9 | ### Bug Fixes
10 |
11 | * 🐛 build to es5 ([bad0129](https://github.com/variejs/varie-framework/commit/bad01299e8fabe1d54e31439e12e31d4cad4918b))
12 |
13 | # 1.0.0 (2019-12-01)
14 |
15 |
16 | ### Bug Fixes
17 |
18 | * 🐛 casing for application ([#91](https://github.com/variejs/varie-framework/issues/91)) ([79d334d](https://github.com/variejs/varie-framework/commit/79d334da03658b7ae576cf0e42238d96e3a3c6a3))
19 | * 🐛 props should be defaulted to true instead of an object ([557bcd9](https://github.com/variejs/varie-framework/commit/557bcd9093bf5f6447c90087ddfac49df3b41f93))
20 |
21 |
22 | ### BREAKING CHANGES
23 |
24 | * route props are now defaulted to true
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 variejs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/accepted.test.js:
--------------------------------------------------------------------------------
1 | import accepted from "../../../src/validation/rules/accepted";
2 |
3 | test("test accepted rule", () => {
4 | expect(accepted.passes(1)).toBe(true);
5 | expect(accepted.passes(true)).toBe(true);
6 | expect(accepted.passes("yes")).toBe(true);
7 |
8 | expect(accepted.passes("1")).toBe(false);
9 | expect(accepted.passes("true")).toBe(false);
10 | });
11 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/after.test.js:
--------------------------------------------------------------------------------
1 | import after from "../../../src/validation/rules/after";
2 |
3 | test("test after rule", () => {
4 | expect(after.passes("1999-11-22", ["1990-11-22"])).toBe(true);
5 | expect(after.passes("1989-11-22", ["1990-11-22"])).toBe(false);
6 | expect(after.passes("1989-13-11", ["1990-11-22"])).toBe(false);
7 | expect(after.passes("89-13-11", ["1990-11-22"])).toBe(false);
8 | expect(after.passes("11", ["1990-11-22"])).toBe(false);
9 | });
10 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/after_or_equal.test.js:
--------------------------------------------------------------------------------
1 | import after_or_equal from "../../../src/validation/rules/after_or_equal";
2 |
3 | test("test after or equal rule", () => {
4 | expect(after_or_equal.passes("1999-11-23", ["1990-11-22"])).toBe(true);
5 | expect(after_or_equal.passes("1990-11-22", ["1990-11-22"])).toBe(true);
6 | expect(after_or_equal.passes("1990-11-21", ["1990-11-22"])).toBe(false);
7 | expect(after_or_equal.passes("1990-11-20", ["1990-11-22"])).toBe(false);
8 | });
9 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/alpha.test.js:
--------------------------------------------------------------------------------
1 | import alpha from "../../../src/validation/rules/alpha";
2 |
3 | test("test alpha rule", () => {
4 | let valid = ["abc", "ABC", "FoObar"];
5 |
6 | let invalid = ["abc1", " foo ", "", "ÄBC", "FÜübar", "Jön", "Heiß", "123"];
7 |
8 | valid.forEach((value) => {
9 | expect(alpha.passes(value)).toBe(true);
10 | });
11 |
12 | invalid.forEach((value) => {
13 | expect(alpha.passes(value)).toBe(false);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/alpha_num.test.js:
--------------------------------------------------------------------------------
1 | import alpha_num from "../../../src/validation/rules/alpha_num";
2 |
3 | test("test alpha num rule", () => {
4 | let valid = ["abc123", "ABC11", "123"];
5 |
6 | let invalid = [" foo ", "", "ÄBC", "FÜübar", "Jön", "Heiß"];
7 |
8 | valid.forEach((value) => {
9 | expect(alpha_num.passes(value)).toBe(true);
10 | });
11 |
12 | invalid.forEach((value) => {
13 | expect(alpha_num.passes(value)).toBe(false);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/array.test.js:
--------------------------------------------------------------------------------
1 | import array from "../../../src/validation/rules/array";
2 |
3 | test("test array rule", () => {
4 | let valid = [[1, 2, 3]];
5 |
6 | let invalid = [" foo ", {}];
7 |
8 | valid.forEach((value) => {
9 | expect(array.passes(value)).toBe(true);
10 | });
11 |
12 | invalid.forEach((value) => {
13 | expect(array.passes(value)).toBe(false);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/before.test.js:
--------------------------------------------------------------------------------
1 | import before from "../../../src/validation/rules/before";
2 |
3 | test("test before rule", () => {
4 | expect(before.passes("1999-11-22", ["1990-11-22"])).toBe(false);
5 | expect(before.passes("1989-11-22", ["1990-11-22"])).toBe(true);
6 | expect(before.passes("1989-13-11", ["1990-11-22"])).toBe(false);
7 | expect(before.passes("89-13-11", ["1990-11-22"])).toBe(false);
8 | expect(before.passes("11", ["1990-11-22"])).toBe(false);
9 | });
10 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/before_or_equal.test.js:
--------------------------------------------------------------------------------
1 | import before_or_equal from "../../../src/validation/rules/before_or_equal";
2 |
3 | test("test before or equal rule", () => {
4 | expect(before_or_equal.passes("1999-11-23", ["1990-11-22"])).toBe(false);
5 | expect(before_or_equal.passes("1990-11-22", ["1990-11-22"])).toBe(true);
6 | expect(before_or_equal.passes("1990-11-21", ["1990-11-22"])).toBe(true);
7 | expect(before_or_equal.passes("1990-11-20", ["1990-11-22"])).toBe(true);
8 | });
9 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/between.js:
--------------------------------------------------------------------------------
1 | import between from "../../../src/validation/rules/between";
2 | import min from "../../../src/validation/rules/min";
3 |
4 | test("test between rule", () => {
5 | expect(min.passes("a", [3, 10])).toBe(false);
6 | expect(min.passes("asd", [3, 10])).toBe(true);
7 | expect(min.passes("abdadfaaa", [3, 10])).toBe(true);
8 | expect(min.passes("abdadfaa", [3, 10])).toBe(true);
9 |
10 | expect(between.passes(5, [1, 10])).toBe(true);
11 | expect(between.passes(123, [1, 10])).toBe(false);
12 |
13 | // act as a file
14 | expect(
15 | between.passes(
16 | {
17 | size: 3500000, // 3500 kb
18 | },
19 | [2000, 4000],
20 | ),
21 | ).toBe(true);
22 | expect(
23 | between.passes(
24 | {
25 | size: 1500000, // 1500 kb
26 | },
27 | [2000, 4000],
28 | ),
29 | ).toBe(false);
30 | });
31 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/boolean.test.js:
--------------------------------------------------------------------------------
1 | import boolean from "../../../src/validation/rules/boolean";
2 |
3 | test("test boolean rule", () => {
4 | let valid = [true, false, 0, 1];
5 |
6 | let invalid = ["1", "0", 2, "abc"];
7 |
8 | valid.forEach((value) => {
9 | expect(boolean.passes(value)).toBe(true);
10 | });
11 |
12 | invalid.forEach((value) => {
13 | expect(boolean.passes(value)).toBe(false);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/confirmed.test.js:
--------------------------------------------------------------------------------
1 | import confirmed from "../../../src/validation/rules/confirmed";
2 |
3 | test("test confirmed rule", () => {
4 | expect(
5 | confirmed.passes(
6 | "abc",
7 | [],
8 | {
9 | password: "abc",
10 | password_confirmation: "abc",
11 | },
12 | "password",
13 | ),
14 | ).toBe(true);
15 |
16 | expect(
17 | confirmed.passes(
18 | "abc",
19 | [],
20 | {
21 | password: "abc",
22 | password_confirmation: "abcd",
23 | },
24 | "password",
25 | ),
26 | ).toBe(false);
27 |
28 | expect(
29 | confirmed.passes(
30 | "abc",
31 | [],
32 | {
33 | password: "abc",
34 | },
35 | "password",
36 | ),
37 | ).toBe(false);
38 | });
39 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/date.test.js:
--------------------------------------------------------------------------------
1 | import date from "../../../src/validation/rules/date";
2 |
3 | test("test date rule", () => {
4 | expect(date.passes(new Date())).toBe(true);
5 | expect(date.passes("1999-11-22")).toBe(true);
6 | expect(date.passes("89-13-11")).toBe(false);
7 | expect(date.passes("11")).toBe(false);
8 | });
9 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/different.test.js:
--------------------------------------------------------------------------------
1 | import different from "../../../src/validation/rules/different";
2 |
3 | test("test different rule", () => {
4 | expect(
5 | different.passes("abcd", ["name"], {
6 | name: "abc",
7 | }),
8 | ).toBe(true);
9 | expect(
10 | different.passes("abc", ["name"], {
11 | name: "abc",
12 | }),
13 | ).toBe(false);
14 | });
15 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/email.test.js:
--------------------------------------------------------------------------------
1 | import email from "../../../src/validation/rules/email";
2 |
3 | function repeat(str, count) {
4 | let result = "";
5 | for (; count; count--) {
6 | result += str;
7 | }
8 | return result;
9 | }
10 |
11 | test("test email rule", () => {
12 | let valid = [
13 | "foo@bar.com",
14 | "x@x.au",
15 | "foo@bar.com.au",
16 | "foo+bar@bar.com",
17 | "hans.m端ller@test.com",
18 | "hans@m端ller.com",
19 | "test|123@m端ller.com",
20 | "test123+ext@gmail.com",
21 | "some.name.midd.leNa.me+extension@GoogleMail.com",
22 | '"foobar"@example.com',
23 | '" foo m端ller "@example.com',
24 | '"foo\\@bar"@example.com',
25 | `${repeat("a", 64)}@${repeat("a", 63)}.com`,
26 | `${repeat("a", 64)}@${repeat("a", 63)}.com`,
27 | `${repeat("a", 31)}@gmail.com`,
28 | "test@gmail.com",
29 | "test.1@gmail.com",
30 | ];
31 |
32 | let invalid = [
33 | "invalidemail@",
34 | "invalid.com",
35 | "@invalid.com",
36 | "foo@bar.com.",
37 | "somename@gmail.com",
38 | "foo@bar.co.uk.",
39 | "z@co.c",
40 | "gmailgmailgmailgmailgmail@gmail.com",
41 | `${repeat("a", 64)}@${repeat("a", 251)}.com`,
42 | `${repeat("a", 65)}@${repeat("a", 250)}.com`,
43 | `${repeat("a", 64)}@${repeat("a", 64)}.com`,
44 | `${repeat("a", 64)}@${repeat("a", 63)}.${repeat("a", 63)}.${repeat(
45 | "a",
46 | 63,
47 | )}.${repeat("a", 58)}.com`,
48 | "test1@invalid.co m",
49 | "test2@invalid.co m",
50 | "test3@invalid.co m",
51 | "test4@invalid.co m",
52 | "test5@invalid.co m",
53 | "test6@invalid.co m",
54 | "test7@invalid.co m",
55 | "test8@invalid.co m",
56 | "test9@invalid.co m",
57 | "test10@invalid.co m",
58 | "test11@invalid.co m",
59 | "test12@invalid.co m",
60 | "test13@invalid.co m",
61 | "multiple..dots@stillinvalid.com",
62 | "test123+invalid! sub_address@gmail.com",
63 | "gmail...ignores...dots...@gmail.com",
64 | "ends.with.dot.@gmail.com",
65 | "multiple..dots@gmail.com",
66 | 'wrong()[]",:;<>@@gmail.com',
67 | '"wrong()[]",:;<>@@gmail.com',
68 | ];
69 |
70 | valid.forEach((value) => {
71 | expect(email.passes(value)).toBe(true);
72 | });
73 |
74 | invalid.forEach((value) => {
75 | expect(email.passes(value)).toBe(false);
76 | });
77 | });
78 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/image.test.js:
--------------------------------------------------------------------------------
1 | import image from "../../../src/validation/rules/image";
2 |
3 | test("test image rule", () => {
4 | let valid = ["jpg", "svg", "jpeg", "png", "bmp", "gif"];
5 |
6 | let invalid = ["blah", "mp4", "pdf"];
7 |
8 | valid.forEach((value) => {
9 | expect(
10 | image.passes({
11 | name: `some_name.${value}`,
12 | }),
13 | ).toBe(true);
14 | });
15 |
16 | valid.forEach((value) => {
17 | expect(
18 | image.passes({
19 | type: `${value}`,
20 | }),
21 | ).toBe(true);
22 | });
23 |
24 | invalid.forEach((value) => {
25 | expect(
26 | image.passes({
27 | name: `some_name.${value}`,
28 | }),
29 | ).toBe(false);
30 | });
31 |
32 | // invalid.forEach(value => {
33 | // expect(
34 | // image.passes({
35 | // type: `${value}`
36 | // })
37 | // ).toBe(false);
38 | // });
39 | });
40 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/integer.test.js:
--------------------------------------------------------------------------------
1 | import integer from "../../../src/validation/rules/integer";
2 |
3 | test("test integer rule", () => {
4 | let valid = [1, 1231, 123123123, 1231232131];
5 |
6 | let invalid = [1.1, "1.1", "12", 12313.14];
7 |
8 | valid.forEach((value) => {
9 | expect(integer.passes(value)).toBe(true);
10 | });
11 |
12 | invalid.forEach((value) => {
13 | expect(integer.passes(value)).toBe(false);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/max.test.js:
--------------------------------------------------------------------------------
1 | import max from "../../../src/validation/rules/max";
2 |
3 | test("test max rule", () => {
4 | expect(max.passes("asd", [3])).toBe(true);
5 | expect(max.passes("123", [3])).toBe(true);
6 | expect(max.passes("1234", [3])).toBe(false);
7 |
8 | expect(max.passes(9, [10])).toBe(true);
9 | expect(max.passes(10, [10])).toBe(true);
10 | expect(max.passes(123, [10])).toBe(false);
11 |
12 | // act as a file
13 | expect(
14 | max.passes(
15 | {
16 | size: 3500000, // 3500 kb
17 | },
18 | [4000],
19 | ),
20 | ).toBe(true);
21 |
22 | expect(
23 | max.passes(
24 | {
25 | size: 4096000, // 4000 kb
26 | },
27 | [4000],
28 | ),
29 | ).toBe(true);
30 |
31 | expect(
32 | max.passes(
33 | {
34 | size: 5500000, // 5500 kb
35 | },
36 | [4000],
37 | ),
38 | ).toBe(false);
39 | });
40 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/mimetypes.test.js:
--------------------------------------------------------------------------------
1 | import mimetypes from "../../../src/validation/rules/mimetypes";
2 |
3 | class MockFile {
4 | constructor(type) {
5 | this.type = type;
6 | }
7 | }
8 |
9 | test("test mimetype rule", () => {
10 | let valid = ["jpg", "svg", "jpeg", "png", "bmp", "gif"];
11 |
12 | let invalid = ["blah", "mp4", "pdf"];
13 |
14 | valid.forEach((value) => {
15 | expect(mimetypes.passes(new MockFile(value), valid)).toBe(true);
16 | });
17 |
18 | invalid.forEach((value) => {
19 | expect(mimetypes.passes(new MockFile(value), valid)).toBe(false);
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/min.test.js:
--------------------------------------------------------------------------------
1 | import min from "../../../src/validation/rules/min";
2 | import max from "../../../src/validation/rules/max";
3 |
4 | test("test min rule", () => {
5 | expect(min.passes("asd", [3])).toBe(true);
6 | expect(min.passes("12", [3])).toBe(false);
7 | expect(min.passes("1234", [3])).toBe(true);
8 |
9 | expect(min.passes(9, [10])).toBe(false);
10 | expect(min.passes(10, [10])).toBe(true);
11 | expect(min.passes(123, [10])).toBe(true);
12 |
13 | expect(
14 | min.passes(
15 | {
16 | size: 3500000, // 3500 kb
17 | },
18 | [4000],
19 | ),
20 | ).toBe(false);
21 |
22 | expect(
23 | min.passes(
24 | {
25 | size: 4096000, // 4000 kb
26 | },
27 | [4000],
28 | ),
29 | ).toBe(true);
30 |
31 | expect(
32 | min.passes(
33 | {
34 | size: 5500000, // 5500 kb
35 | },
36 | [4000],
37 | ),
38 | ).toBe(true);
39 | });
40 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/nullable.test.js:
--------------------------------------------------------------------------------
1 | import nullable from "../../../src/validation/rules/nullable";
2 |
3 | test("test nullable rule", () => {
4 | let valid = ["", " ", {}, [], undefined, null];
5 |
6 | let invalid = [" foo ", { test: true }, [1]];
7 |
8 | valid.forEach((value) => {
9 | expect(nullable.passes(value)).toBe(true);
10 | });
11 |
12 | invalid.forEach((value) => {
13 | expect(nullable.passes(value)).toBe(false);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/numeric.test.js:
--------------------------------------------------------------------------------
1 | import numeric from "../../../src/validation/rules/numeric";
2 |
3 | test("test numeric rule", () => {
4 | let valid = [1, 2.15, 123];
5 |
6 | let invalid = [" foo "];
7 |
8 | valid.forEach((value) => {
9 | expect(numeric.passes(value)).toBe(true);
10 | });
11 |
12 | invalid.forEach((value) => {
13 | expect(numeric.passes(value)).toBe(false);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/regex.test.js:
--------------------------------------------------------------------------------
1 | import regex from "../../../src/validation/rules/regex";
2 |
3 | test("test regex rule", () => {
4 | let valid = [/^[A-Za-z0-9]+$/, "^[A-Za-z0-9]+$"];
5 |
6 | let invalid = [/abc/, "abc"];
7 |
8 | valid.forEach((value) => {
9 | expect(regex.passes("ABC123", [value])).toBe(true);
10 | });
11 |
12 | valid.forEach((value) => {
13 | expect(regex.passes("...FAIL...", [value])).toBe(false);
14 | });
15 |
16 | invalid.forEach((value) => {
17 | expect(regex.passes("...FAIL...", [value])).toBe(false);
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/required.test.js:
--------------------------------------------------------------------------------
1 | import required from "../../../src/validation/rules/required";
2 |
3 | test("test required rule", () => {
4 | expect(required.passes("abc")).toBe(true);
5 | expect(required.passes({ test: true })).toBe(true);
6 | expect(required.passes([1])).toBe(true);
7 |
8 | expect(required.passes("")).toBe(false);
9 | expect(required.passes({})).toBe(false);
10 | expect(required.passes([])).toBe(false);
11 | expect(required.passes(null)).toBe(false);
12 | expect(required.passes(undefined)).toBe(false);
13 | });
14 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/required_if.test.js:
--------------------------------------------------------------------------------
1 | import required_if from "../../../src/validation/rules/required_if";
2 |
3 | test("test required if rule", () => {
4 | expect(
5 | required_if.passes("asdfadsf", ["name", "abc"], {
6 | name: "abc",
7 | }),
8 | ).toBe(true);
9 |
10 | expect(
11 | required_if.passes("", ["name", "abc"], {
12 | name: "abc",
13 | }),
14 | ).toBe(false);
15 |
16 | expect(
17 | required_if.passes("", ["name"], {
18 | name: "abc",
19 | }),
20 | ).toBe(false);
21 |
22 | expect(
23 | required_if.passes("", ["name"], {
24 | name: null,
25 | }),
26 | ).toBe(true);
27 | });
28 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/required_unless.test.js:
--------------------------------------------------------------------------------
1 | import required_unless from "../../../src/validation/rules/required_unless";
2 |
3 | test("test required unless rule", () => {
4 | expect(
5 | required_unless.passes("abc", ["name", "abc"], {
6 | name: "abc",
7 | }),
8 | ).toBe(true);
9 |
10 | expect(
11 | required_unless.passes("", ["name", "abc"], {
12 | name: "abc",
13 | }),
14 | ).toBe(false);
15 |
16 | expect(
17 | required_unless.passes("", ["name"], {
18 | name: "abc",
19 | }),
20 | ).toBe(false);
21 |
22 | expect(
23 | required_unless.passes("", ["name"], {
24 | name: "",
25 | }),
26 | ).toBe(true);
27 | });
28 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/required_with.test.js:
--------------------------------------------------------------------------------
1 | import required_with from "../../../src/validation/rules/required_with";
2 |
3 | test("test required with rule", () => {
4 | expect(
5 | required_with.passes("abc", ["name"], {
6 | name: "abc",
7 | }),
8 | ).toBe(true);
9 |
10 | expect(
11 | required_with.passes("", ["name"], {
12 | name: "abc",
13 | }),
14 | ).toBe(false);
15 |
16 | expect(
17 | required_with.passes("", ["name", "sir_name"], {
18 | name: "",
19 | sir_name: "test",
20 | }),
21 | ).toBe(false);
22 | });
23 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/required_with_all.test.js:
--------------------------------------------------------------------------------
1 | import required_with_all from "../../../src/validation/rules/required_with_all";
2 |
3 | test("test required with all rule", () => {
4 | expect(
5 | required_with_all.passes("abc", ["name"], {
6 | name: "abc",
7 | }),
8 | ).toBe(true);
9 |
10 | expect(
11 | required_with_all.passes("", ["name"], {
12 | name: "abc",
13 | }),
14 | ).toBe(false);
15 |
16 | expect(
17 | required_with_all.passes("", ["name", "sir_name"], {
18 | name: "",
19 | sir_name: "test",
20 | }),
21 | ).toBe(true);
22 |
23 | expect(
24 | required_with_all.passes("", ["name", "sir_name"], {
25 | name: "asdfadsf",
26 | sir_name: "test",
27 | }),
28 | ).toBe(false);
29 | });
30 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/required_without.test.js:
--------------------------------------------------------------------------------
1 | import required_without from "../../../src/validation/rules/required_without";
2 |
3 | test("test required without rule", () => {
4 | expect(
5 | required_without.passes("abc", ["name"], {
6 | name: "abc",
7 | }),
8 | ).toBe(true);
9 |
10 | expect(
11 | required_without.passes("", ["name"], {
12 | name: "",
13 | }),
14 | ).toBe(false);
15 |
16 | expect(
17 | required_without.passes("", ["name"], {
18 | name: "abc",
19 | }),
20 | ).toBe(true);
21 |
22 | expect(
23 | required_without.passes("", ["name", "sir_name"], {
24 | name: "",
25 | sir_name: "test",
26 | }),
27 | ).toBe(false);
28 | });
29 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/required_without_all.test.js:
--------------------------------------------------------------------------------
1 | import required_without_all from "../../../src/validation/rules/required_without_all";
2 |
3 | test("test without all rule", () => {
4 | expect(
5 | required_without_all.passes("abc", ["name"], {
6 | name: "abc",
7 | }),
8 | ).toBe(true);
9 |
10 | expect(
11 | required_without_all.passes("", ["name"], {
12 | name: "abc",
13 | }),
14 | ).toBe(true);
15 |
16 | expect(
17 | required_without_all.passes("", ["name", "sir_name"], {
18 | name: "",
19 | sir_name: "test",
20 | }),
21 | ).toBe(true);
22 |
23 | expect(
24 | required_without_all.passes("", ["name", "sir_name"], {
25 | name: "asdfasdf",
26 | sir_name: "test",
27 | }),
28 | ).toBe(true);
29 |
30 | expect(
31 | required_without_all.passes("", ["name", "sir_name"], {
32 | name: "",
33 | sir_name: "",
34 | }),
35 | ).toBe(false);
36 | });
37 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/same.test.js:
--------------------------------------------------------------------------------
1 | import same from "../../../src/validation/rules/same";
2 |
3 | test("test same rule", () => {
4 | let valid = ["abc"];
5 |
6 | let invalid = [" foo ", {}];
7 |
8 | valid.forEach((value) => {
9 | expect(
10 | same.passes(value, ["name"], {
11 | name: "abc",
12 | }),
13 | ).toBe(true);
14 | });
15 |
16 | invalid.forEach((value) => {
17 | expect(
18 | same.passes(value, ["name"], {
19 | name: "abc",
20 | }),
21 | ).toBe(false);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/size.test.js:
--------------------------------------------------------------------------------
1 | import size from "../../../src/validation/rules/size";
2 |
3 | test("test size rule", () => {
4 | expect(size.passes(9, [10])).toBe(false);
5 | expect(size.passes(10, [10])).toBe(true);
6 | expect(size.passes(123, [10])).toBe(false);
7 |
8 | // act as a file
9 | expect(
10 | size.passes(
11 | {
12 | size: 3500000, // 3500 kb
13 | },
14 | [4000],
15 | ),
16 | ).toBe(false);
17 |
18 | expect(
19 | size.passes(
20 | {
21 | size: 4096000, // 4000 kb
22 | },
23 | [4000],
24 | ),
25 | ).toBe(true);
26 |
27 | expect(
28 | size.passes(
29 | {
30 | size: 5500000, // 5500 kb
31 | },
32 | [4000],
33 | ),
34 | ).toBe(false);
35 | });
36 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/string.test.js:
--------------------------------------------------------------------------------
1 | import string from "../../../src/validation/rules/string";
2 |
3 | test("test string rule", () => {
4 | expect(string.passes("abc")).toBe(true);
5 | expect(string.passes(123)).toBe(false);
6 | expect(string.passes("123")).toBe(true);
7 | });
8 |
--------------------------------------------------------------------------------
/__tests__/validation/rules/url.test.js:
--------------------------------------------------------------------------------
1 | import url from "../../../src/validation/rules/url";
2 |
3 | test("test url rule", () => {
4 | let valid = [
5 | "foobar.com",
6 | "www.foobar.com",
7 | "foobar.com/",
8 | "valid.au",
9 | "http://www.foobar.com/",
10 | "HTTP://WWW.FOOBAR.COM/",
11 | "https://www.foobar.com/",
12 | "HTTPS://WWW.FOOBAR.COM/",
13 | "http://www.foobar.com:23/",
14 | "http://www.foobar.com:65535/",
15 | "http://www.foobar.com:5/",
16 | "https://www.foobar.com/",
17 | "ftp://www.foobar.com/",
18 | "http://www.foobar.com/~foobar",
19 | "http://user:pass@www.foobar.com/",
20 | "http://user:@www.foobar.com/",
21 | "http://127.0.0.1/",
22 | "http://10.0.0.0/",
23 | "http://189.123.14.13/",
24 | "http://duckduckgo.com/?q=%2F",
25 | "http://foobar.com/t$-_.+!*'(),",
26 | "http://foobar.com/?foo=bar#baz=qux",
27 | "http://foobar.com?foo=bar",
28 | "http://foobar.com#baz=qux",
29 | "http://www.xn--froschgrn-x9a.net/",
30 | "http://xn--froschgrn-x9a.com/",
31 | "http://foo--bar.com",
32 | "http://høyfjellet.no",
33 | "http://xn--j1aac5a4g.xn--j1amh",
34 | "http://xn------eddceddeftq7bvv7c4ke4c.xn--p1ai",
35 | "http://кулік.укр",
36 | "test.com?ref=http://test2.com",
37 | "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html",
38 | "http://[1080:0:0:0:8:800:200C:417A]/index.html",
39 | "http://[3ffe:2a00:100:7031::1]",
40 | "http://[1080::8:800:200C:417A]/foo",
41 | "http://[::192.9.5.5]/ipng",
42 | "http://[::FFFF:129.144.52.38]:80/index.html",
43 | "http://[2010:836B:4179::836B:4179]",
44 | ];
45 |
46 | let invalid = [
47 | "http://localhost:3000/",
48 | "//foobar.com",
49 | "xyz://foobar.com",
50 | "invalid/",
51 | "invalid.x",
52 | "invalid.",
53 | ".com",
54 | "http://com/",
55 | "http://300.0.0.1/",
56 | "mailto:foo@bar.com",
57 | "rtmp://foobar.com",
58 | "http://www.xn--.com/",
59 | "http://xn--.com/",
60 | "http://www.foobar.com:0/",
61 | "http://www.foobar.com:70000/",
62 | "http://www.foobar.com:99999/",
63 | "http://www.-foobar.com/",
64 | "http://www.foobar-.com/",
65 | "http://foobar/# lol",
66 | "http://foobar/? lol",
67 | "http://foobar/ lol/",
68 | "http://lol @foobar.com/",
69 | "http://lol:lol @foobar.com/",
70 | "http://lol:lol:lol@foobar.com/",
71 | "http://lol: @foobar.com/",
72 | "http://www.foo_bar.com/",
73 | "http://www.foobar.com/\t",
74 | "http://\n@www.foobar.com/",
75 | "",
76 | `http://foobar.com/${new Array(2083).join("f")}`,
77 | "http://*.foo.com",
78 | "*.foo.com",
79 | "!.foo.com",
80 | "http://example.com.",
81 | "http://localhost:61500this is an invalid url!!!!",
82 | "////foobar.com",
83 | "http:////foobar.com",
84 | "https://example.com/foo//",
85 | ];
86 |
87 | valid.forEach((value) => {
88 | expect(url.passes(value)).toBe(true);
89 | });
90 |
91 | invalid.forEach((value) => {
92 | expect(url.passes(value)).toBe(false);
93 | });
94 | });
95 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | // babel.config.js
2 | module.exports = {
3 | presets: [
4 | ["@babel/preset-env", { targets: { node: "current" } }],
5 | "@babel/preset-typescript",
6 | ],
7 | };
8 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ["@commitlint/config-conventional"] };
2 |
--------------------------------------------------------------------------------
/components/Alert.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ×
6 |
7 |
{{ alert.title }}
8 |
9 |
10 |
11 |
12 |
13 |
33 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | // For a detailed explanation regarding each configuration property, visit:
2 | // https://jestjs.io/docs/en/configuration.html
3 |
4 | module.exports = {
5 | // All imported modules in your tests should be mocked automatically
6 | // automock: false,
7 |
8 | // Stop running tests after `n` failures
9 | // bail: 0,
10 |
11 | // Respect "browser" field in package.json when resolving modules
12 | // browser: false,
13 |
14 | // The directory where Jest should store its cached dependency information
15 | // cacheDirectory: "/private/var/folders/r2/bykjzw3x2w9g5qsm5xvbb4400000gn/T/jest_dx",
16 |
17 | // Automatically clear mock calls and instances between every test
18 | clearMocks: true,
19 |
20 | // Indicates whether the coverage information should be collected while executing the test
21 | // collectCoverage: false,
22 |
23 | // An array of glob patterns indicating a set of files for which coverage information should be collected
24 | // collectCoverageFrom: null,
25 |
26 | // The directory where Jest should output its coverage files
27 | // coverageDirectory: null,
28 |
29 | // An array of regexp pattern strings used to skip coverage collection
30 | // coveragePathIgnorePatterns: [
31 | // "/node_modules/"
32 | // ],
33 |
34 | // A list of reporter names that Jest uses when writing coverage reports
35 | // coverageReporters: [
36 | // "json",
37 | // "text",
38 | // "lcov",
39 | // "clover"
40 | // ],
41 |
42 | // An object that configures minimum threshold enforcement for coverage results
43 | // coverageThreshold: null,
44 |
45 | // A path to a custom dependency extractor
46 | // dependencyExtractor: null,
47 |
48 | // Make calling deprecated APIs throw helpful error messages
49 | // errorOnDeprecated: false,
50 |
51 | // Force coverage collection from ignored files using an array of glob patterns
52 | // forceCoverageMatch: [],
53 |
54 | // A path to a module which exports an async function that is triggered once before all test suites
55 | // globalSetup: null,
56 |
57 | // A path to a module which exports an async function that is triggered once after all test suites
58 | // globalTeardown: null,
59 |
60 | // A set of global variables that need to be available in all test environments
61 | // globals: {},
62 |
63 | // An array of directory names to be searched recursively up from the requiring module's location
64 | // moduleDirectories: [
65 | // "node_modules"
66 | // ],
67 |
68 | // An array of file extensions your modules use
69 | // moduleFileExtensions: [
70 | // "js",
71 | // "json",
72 | // "jsx",
73 | // "ts",
74 | // "tsx",
75 | // "node"
76 | // ],
77 |
78 | // A map from regular expressions to module names that allow to stub out resources with a single module
79 | // moduleNameMapper: {},
80 |
81 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
82 | // modulePathIgnorePatterns: [],
83 |
84 | // Activates notifications for test results
85 | // notify: false,
86 |
87 | // An enum that specifies notification mode. Requires { notify: true }
88 | // notifyMode: "failure-change",
89 |
90 | // A preset that is used as a base for Jest's configuration
91 | // preset: null,
92 |
93 | // Run tests from one or more projects
94 | // projects: null,
95 |
96 | // Use this configuration option to add custom reporters to Jest
97 | // reporters: undefined,
98 |
99 | // Automatically reset mock state between every test
100 | // resetMocks: false,
101 |
102 | // Reset the module registry before running each individual test
103 | // resetModules: false,
104 |
105 | // A path to a custom resolver
106 | // resolver: null,
107 |
108 | // Automatically restore mock state between every test
109 | // restoreMocks: false,
110 |
111 | // The root directory that Jest should scan for tests and modules within
112 | // rootDir: null,
113 |
114 | // A list of paths to directories that Jest should use to search for files in
115 | // roots: [
116 | // ""
117 | // ],
118 |
119 | // Allows you to use a custom runner instead of Jest's default test runner
120 | // runner: "jest-runner",
121 |
122 | // The paths to modules that run some code to configure or set up the testing environment before each test
123 | // setupFiles: [],
124 |
125 | // A list of paths to modules that run some code to configure or set up the testing framework before each test
126 | // setupFilesAfterEnv: [],
127 |
128 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing
129 | // snapshotSerializers: [],
130 |
131 | // The test environment that will be used for testing
132 | testEnvironment: "node",
133 |
134 | // Options that will be passed to the testEnvironment
135 | // testEnvironmentOptions: {},
136 |
137 | // Adds a location field to test results
138 | // testLocationInResults: false,
139 |
140 | // The glob patterns Jest uses to detect test files
141 | // testMatch: [
142 | // "**/__tests__/**/*.[jt]s?(x)",
143 | // "**/?(*.)+(spec|test).[tj]s?(x)"
144 | // ],
145 |
146 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
147 | // testPathIgnorePatterns: [
148 | // "/node_modules/"
149 | // ],
150 |
151 | // The regexp pattern or array of patterns that Jest uses to detect test files
152 | // testRegex: [],
153 |
154 | // This option allows the use of a custom results processor
155 | // testResultsProcessor: null,
156 |
157 | // This option allows use of a custom test runner
158 | // testRunner: "jasmine2",
159 |
160 | // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
161 | // testURL: "http://localhost",
162 |
163 | // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
164 | // timers: "real",
165 |
166 | // A map from regular expressions to paths to transformers
167 | // transform: null,
168 |
169 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
170 | // transformIgnorePatterns: [
171 | // "/node_modules/"
172 | // ],
173 |
174 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
175 | // unmockedModulePathPatterns: undefined,
176 |
177 | // Indicates whether each individual test should be reported during the run
178 | // verbose: null,
179 |
180 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
181 | // watchPathIgnorePatterns: [],
182 |
183 | // Whether to use watchman for file crawling
184 | // watchman: true,
185 | };
186 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "varie",
3 | "version": "1.0.1",
4 | "description": "VueJS Framework",
5 | "main": "./lib/index.js",
6 | "typings": "./lib/index",
7 | "types": "./lib/index",
8 | "repository": "git@github.com:variejs/varie-framework.git",
9 | "author": "Luke Policinski",
10 | "license": "MIT",
11 | "dependencies": {
12 | "axios": "^0.19.0",
13 | "camelcase": "^5.3.1",
14 | "clone-deep": "^4.0.1",
15 | "dashify": "^2.0.0",
16 | "inversify": "^5.0.1",
17 | "inversify-inject-decorators": "^3.1.0",
18 | "reflect-metadata": "^0.1.13",
19 | "validator": "^12.1.0"
20 | },
21 | "devDependencies": {
22 | "@babel/core": "^7.7.4",
23 | "@babel/preset-env": "^7.7.4",
24 | "@babel/preset-typescript": "^7.7.4",
25 | "@commitlint/cli": "^8.2.0",
26 | "@commitlint/config-conventional": "^8.2.0",
27 | "@semantic-release/changelog": "^3.0.6",
28 | "@semantic-release/git": "^7.0.18",
29 | "@types/node": "^12.12.14",
30 | "@types/validator": "^12.0.1",
31 | "@types/webpack-env": "^1.14.1",
32 | "babel-jest": "^24.9.0",
33 | "git-cz": "^3.3.0",
34 | "husky": "^3.1.0",
35 | "jest": "^24.9.0",
36 | "prettier": "^1.19.1",
37 | "pretty-quick": "^2.0.1",
38 | "semantic-release": "^15.13.31",
39 | "ts-jest": "^24.2.0",
40 | "typescript": "^3.7.2"
41 | },
42 | "peerDependencies": {
43 | "vue": "^2.5.17",
44 | "vue-router": "^3.0.1",
45 | "vuex": "^3.0.1"
46 | },
47 | "scripts": {
48 | "build": "tsc",
49 | "watch": "tsc --watch",
50 | "test": "jest",
51 | "commit": "npx git-cz",
52 | "installPeers": "npm install vue vue-router vuex --no-save",
53 | "release": "semantic-release"
54 | },
55 | "husky": {
56 | "hooks": {
57 | "pre-commit": "pretty-quick --staged",
58 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
59 | }
60 | },
61 | "files": [
62 | "lib",
63 | "src",
64 | "stubs",
65 | "components",
66 | "BaseLayout.vue",
67 | "Alerts.vue"
68 | ],
69 | "sideEffects": [
70 | "*.vue"
71 | ]
72 | }
73 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
> **Note:** This repository contains the core code of the Varie framework. Visit the main [Varie Repository](https://github.com/variejs/varie) to get started.
## About Varie
Varie is a Typescript framework for rapidly building powerful and elegant Vue.js applications. Bringing
in concepts from other languages to speed up your development. Whether working in
a small / large teams, Varie elevates your starting point to ramp into
development.
### Notable Features
- Validation
- CLI Plugin
- Fluent Router
- State Management
- Request Middleware
- Authentication System
- Customizable Modern Bundler
- Dependency Injection System (DI)
## License
The Varie framework is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).
--------------------------------------------------------------------------------
/release.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | "@semantic-release/commit-analyzer",
4 | "@semantic-release/release-notes-generator",
5 | [
6 | "@semantic-release/changelog",
7 | {
8 | changelogTitle:
9 | "# Changelog\n\nAll notable changes to this project will be documented in this file. See\n[Conventional Commits](https://conventionalcommits.org) for commit guidelines.",
10 | },
11 | ],
12 | [
13 | "@semantic-release/npm",
14 | ],
15 | [
16 | "@semantic-release/github",
17 | ],
18 | [
19 | "@semantic-release/git",
20 | {
21 | message:
22 | "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}",
23 | },
24 | ],
25 | ],
26 | };
27 |
--------------------------------------------------------------------------------
/src/config/ConfigInterface.ts:
--------------------------------------------------------------------------------
1 | export default interface ConfigInterface {
2 | set(parameter: string, value: any): any;
3 | get(parameter: string, defaultValue?: string | null): any;
4 | }
5 |
--------------------------------------------------------------------------------
/src/config/ConfigService.ts:
--------------------------------------------------------------------------------
1 | import { injectable } from "inversify";
2 | import ConfigInterface from "./ConfigInterface";
3 | import { getByDot, setByDot } from "./../utilities";
4 |
5 | declare const __ENV_VARIABLES__: object;
6 |
7 | @injectable()
8 | export default class Config implements ConfigInterface {
9 | protected configs = __ENV_VARIABLES__;
10 |
11 | constructor() {
12 | let files = require.context("@config", true, /^\.\/.*\.(ts)$/);
13 |
14 | for (let filename of files.keys()) {
15 | let configName = filename
16 | .replace(/^\.\//, "")
17 | .replace(/\/$/, "")
18 | .replace(/\.js/, "")
19 | .replace(/\.ts/, "");
20 |
21 | this.configs[configName] = Object.assign(
22 | {},
23 | files(filename).default,
24 | this.configs[configName],
25 | );
26 | }
27 | }
28 |
29 | public get(path: string, defaultValue: any) {
30 | return getByDot(this.configs, path, defaultValue);
31 | }
32 |
33 | public set(path: string, value: any) {
34 | return setByDot(this.configs, path, value);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/config/ConfigServiceProvider.ts:
--------------------------------------------------------------------------------
1 | declare const global: any;
2 | import ConfigService from "./ConfigService";
3 | import ConfigInterface from "./ConfigInterface";
4 | import ServiceProvider from "../support/ServiceProvider";
5 |
6 | export default class ConfigServiceProvider extends ServiceProvider {
7 | public register() {
8 | this.app.singleton("ConfigService", ConfigService);
9 | global.$config = this.app.make("ConfigService");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/cookies/CookieInterface.ts:
--------------------------------------------------------------------------------
1 | export default interface CookieInterface {
2 | get(name: string): any;
3 | set(
4 | name: string,
5 | value: any,
6 | days?: number,
7 | path?: string,
8 | domain?: string,
9 | secure?: boolean,
10 | );
11 | remove(name: string, path?: string, domain?: string);
12 | hasItem(name: string): boolean;
13 | }
14 |
--------------------------------------------------------------------------------
/src/cookies/CookieService.ts:
--------------------------------------------------------------------------------
1 | import { injectable } from "inversify";
2 | import CookieInterface from "./CookieInterface";
3 |
4 | // https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie/Simple_document.cookie_framework
5 |
6 | @injectable()
7 | export default class CookieService implements CookieInterface {
8 | public get(name: string) {
9 | if (!name) {
10 | return null;
11 | }
12 | return (
13 | decodeURIComponent(
14 | document.cookie.replace(
15 | new RegExp(
16 | "(?:(?:^|.*;)\\s*" +
17 | encodeURIComponent(name).replace(/[\-\.\+\*]/g, "\\$&") +
18 | "\\s*\\=\\s*([^;]*).*$)|^.*$",
19 | ),
20 | "$1",
21 | ),
22 | ) || null
23 | );
24 | }
25 |
26 | public set(
27 | name: string,
28 | value: any,
29 | days: number = 1,
30 | path: string = "/",
31 | domain?: string,
32 | secure?: boolean,
33 | ) {
34 | let expires = new Date();
35 | expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);
36 | if (!name || /^(?:expires|max\-age|path|domain|secure)$/i.test(name)) {
37 | return false;
38 | }
39 | document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(
40 | value,
41 | )}; expires=${expires.toUTCString()}${domain ? "; domain=" + domain : ""}${
42 | path ? "; path=" + path : ""
43 | }${secure ? "; secure" : ""}`;
44 | }
45 |
46 | public remove(name: string, path?: string, domain?: string) {
47 | if (!this.hasItem(name)) {
48 | return false;
49 | }
50 | document.cookie =
51 | encodeURIComponent(name) +
52 | "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" +
53 | (domain ? "; domain=" + domain : "") +
54 | (path ? "; path=" + path : "");
55 | }
56 |
57 | public hasItem(name: string) {
58 | if (!name || /^(?:expires|max\-age|path|domain|secure)$/i.test(name)) {
59 | return false;
60 | }
61 | return new RegExp(
62 | "(?:^|;\\s*)" +
63 | encodeURIComponent(name).replace(/[\-\.\+\*]/g, "\\$&") +
64 | "\\s*\\=",
65 | ).test(document.cookie);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/cookies/CookieServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import CookieService from "./CookieService";
2 | import CookieInterface from "./CookieInterface";
3 | import ServiceProvider from "../support/ServiceProvider";
4 |
5 | export default class CookieServiceProvider extends ServiceProvider {
6 | public register() {
7 | this.app.singleton("CookieService", CookieService);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/foundation/Application.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import "reflect-metadata";
3 | import { Container } from "inversify";
4 | import ContainerMixin from "./ContainerMixin";
5 | import ApplicationInterface from "./ApplicationInterface";
6 | import ServiceProviderInterface from "../support/ServiceProviderInterface";
7 |
8 | declare const global: any;
9 |
10 | export default class Application implements ApplicationInterface {
11 | protected app;
12 |
13 | private container: Container;
14 | private providers: Array = [];
15 | private appProviders = require("@config/app").default.providers;
16 |
17 | constructor() {
18 | this.app = this;
19 | global.$app = this.app;
20 | Vue.prototype["$app"] = this.app;
21 | this.container = new Container();
22 | this.constant("app", this.app);
23 | }
24 |
25 | public async boot(): Promise {
26 | new ContainerMixin().registerMixin(this);
27 | await this.registerConfiguredProviders();
28 | await this.bootProviders();
29 | return this;
30 | }
31 |
32 | public bind(abstract: string, concrete: AnyClass) {
33 | this.container.bind(abstract).to(concrete);
34 | }
35 |
36 | public singleton(abstract: string, concrete: AnyClass) {
37 | this.container
38 | .bind(abstract)
39 | .to(concrete)
40 | .inSingletonScope();
41 | }
42 |
43 | public constant(key: string, constant: any) {
44 | this.container.bind(key).toConstantValue(constant);
45 | }
46 |
47 | public make(abstract: string): T {
48 | return this.container.get(abstract);
49 | }
50 |
51 | public addProvider(provider) {
52 | this.providers.push(provider);
53 | }
54 |
55 | public isBound(key) {
56 | return this.container.isBound(key);
57 | }
58 |
59 | private async registerConfiguredProviders() {
60 | for (let provider in this.appProviders) {
61 | await this.getAppProvider(provider);
62 | }
63 | }
64 |
65 | private async getAppProvider(
66 | provider: string,
67 | ): Promise {
68 | return new this.appProviders[provider](this.app).register();
69 | }
70 |
71 | private async bootProviders() {
72 | for (const provider in this.providers) {
73 | await this.providers[provider].boot();
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/foundation/ApplicationInterface.ts:
--------------------------------------------------------------------------------
1 | import ServiceProvider from "./../support/ServiceProvider";
2 |
3 | export default interface ApplicationInterface {
4 | boot(): any;
5 | make(abstract: string): T;
6 | constant(key: string, constant: any): void;
7 | bind(abstract: string, concrete: any): void;
8 | singleton(abstract: string, concrete: any): void;
9 | isBound(key: string): boolean;
10 | addProvider(serviceProvider: ServiceProvider);
11 | }
12 |
--------------------------------------------------------------------------------
/src/foundation/ContainerMixin.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import camelize from "../utilities/camelize";
3 | import ApplicationInterface from "./ApplicationInterface";
4 |
5 | export default class ContainerMixin {
6 | registerMixin(app: ApplicationInterface) {
7 | Vue.mixin({
8 | beforeCreate() {
9 | let services = this.$options.$inject || [];
10 | services.forEach((service: string) => {
11 | this[camelize(service)] = app.make(service);
12 | });
13 | },
14 | });
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/globals.ts:
--------------------------------------------------------------------------------
1 | import ConfigInterface from "./config/ConfigInterface";
2 | import ApplicationInterface from "./foundation/ApplicationInterface";
3 |
4 | declare global {
5 | const $config: ConfigInterface;
6 | const $app: ApplicationInterface;
7 |
8 | type AnyClass = { new (): any };
9 | }
10 |
--------------------------------------------------------------------------------
/src/http/AxiosHttpService.ts:
--------------------------------------------------------------------------------
1 | import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
2 | import { inject, injectable } from "inversify";
3 | import HttpServiceInterface from "./HttpServiceInterface";
4 | import ApplicationInterface from "../foundation/ApplicationInterface";
5 | import HttpMiddlewareInterface from "./interfaces/HttpMiddlewareInterface";
6 |
7 | @injectable()
8 | export default class AxiosHttpService implements HttpServiceInterface {
9 | protected middleware = {};
10 | protected axios: AxiosInstance;
11 | protected app: ApplicationInterface;
12 |
13 | constructor(
14 | @inject("app") app: ApplicationInterface,
15 | @inject("ConfigService") configService,
16 | ) {
17 | this.app = app;
18 | this.axios = axios.create(configService.get("http"));
19 | }
20 |
21 | public delete(url: string, config = {}) {
22 | return this.axios.delete(url, config);
23 | }
24 |
25 | public get(url: string, config = {}) {
26 | return this.axios.get(url, config);
27 | }
28 |
29 | public head(url: string, config = {}) {
30 | return this.axios.head(url, config);
31 | }
32 |
33 | public options(url: string, config = {}) {
34 | // https://github.com/axios/axios/pull/2341
35 | // @ts-ignore
36 | return this.axios.options(url, config);
37 | }
38 |
39 | public post(url: string, data: object, config = {}) {
40 | return this.axios.post(url, data, config);
41 | }
42 |
43 | public put(url: string, data: object, config = {}) {
44 | return this.axios.put(url, data, config);
45 | }
46 |
47 | public patch(url: string, data: object, config = {}) {
48 | return this.axios.patch(url, data, config);
49 | }
50 |
51 | public request(config = {}) {
52 | return this.axios.request(config);
53 | }
54 |
55 | public registerMiddleware(Middleware: new () => HttpMiddlewareInterface) {
56 | let middlewareName = `httpMiddleware${Middleware.name}`;
57 | this.app.bind(middlewareName, Middleware);
58 | let middleware = this.app.make(middlewareName);
59 | this.middleware[middleware.constructor.name] = {
60 | request: this.axios.interceptors.request.use((config) => {
61 | if (middleware.request) {
62 | return middleware.request(config);
63 | }
64 | return config;
65 | }),
66 | response: this.axios.interceptors.response.use(
67 | function(response) {
68 | if (middleware.response) {
69 | return middleware.response(response);
70 | }
71 | return response;
72 | },
73 | function(error) {
74 | if (middleware.responseError) {
75 | return Promise.reject(middleware.responseError(error));
76 | }
77 | return Promise.reject(error);
78 | },
79 | ),
80 | };
81 | }
82 |
83 | public unregisterMiddleware(Middleware: new () => HttpMiddlewareInterface) {
84 | let middleware = new Middleware().constructor.name;
85 | axios.interceptors.request.eject(this.middleware[middleware].request);
86 | axios.interceptors.response.eject(this.middleware[middleware].response);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/http/HttpServiceInterface.ts:
--------------------------------------------------------------------------------
1 | import HttpResponseInterface from "./interfaces/HttpResponseInterface";
2 | import HttpMiddlewareInterface from "./interfaces/HttpMiddlewareInterface";
3 | import HttpRequestConfigInterface from "./interfaces/HttpRequestConfigInterface";
4 |
5 | export default interface HttpServiceInterface {
6 | get(
7 | url: string,
8 | config?: HttpRequestConfigInterface,
9 | ): Promise;
10 | put(
11 | url: string,
12 | data: object,
13 | config?: HttpRequestConfigInterface,
14 | ): Promise;
15 | post(
16 | url: string,
17 | data?: object,
18 | config?: HttpRequestConfigInterface,
19 | ): Promise;
20 | patch(
21 | url: string,
22 | data: object,
23 | config?: HttpRequestConfigInterface,
24 | ): Promise;
25 | delete(
26 | url: string,
27 | config?: HttpRequestConfigInterface,
28 | ): Promise;
29 | head(
30 | url: string,
31 | config?: HttpRequestConfigInterface,
32 | ): Promise;
33 | options(url: string, config?: HttpRequestConfigInterface);
34 | request(config?: HttpRequestConfigInterface);
35 | registerMiddleware(middleware: new () => HttpMiddlewareInterface);
36 | unregisterMiddleware(middleware: new () => HttpMiddlewareInterface);
37 | }
38 |
--------------------------------------------------------------------------------
/src/http/HttpServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import HttpConfig from "./config";
2 | import AxiosHttpService from "./AxiosHttpService";
3 | import ServiceProvider from "../support/ServiceProvider";
4 | import HttpServiceInterface from "./HttpServiceInterface";
5 |
6 | export default class HttpServiceProvider extends ServiceProvider {
7 | public boot() {
8 | let $httpService = this.app.make("HttpService");
9 | require("@app/middleware").default.forEach((middleware) => {
10 | $httpService.registerMiddleware(middleware);
11 | });
12 | }
13 |
14 | public register() {
15 | this.mergeConfigFrom(HttpConfig, "http");
16 | this.app.singleton("HttpService", AxiosHttpService);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/http/config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | /*
3 | |--------------------------------------------------------------------------
4 | | Base URL
5 | |--------------------------------------------------------------------------
6 | |
7 | | Sometimes you need to setup a base url for all your requests
8 | |
9 | */
10 | baseURL: null,
11 |
12 | /*
13 | |--------------------------------------------------------------------------
14 | | Customized Headers
15 | |--------------------------------------------------------------------------
16 | |
17 | | If you need to attach headers with every requests you should do that here
18 | |
19 | */
20 | headers: {
21 | common: {
22 | "X-Requested-With": "XMLHttpRequest",
23 | },
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/src/http/interfaces/HttpErrorInterface.ts:
--------------------------------------------------------------------------------
1 | import HttpRequestConfigInterface from "./HttpRequestConfigInterface";
2 | import HttpResponseInterface from "./HttpResponseInterface";
3 |
4 | export default interface HttpRequestInterface extends Error {
5 | config: HttpRequestConfigInterface;
6 | code?: string;
7 | request?: any;
8 | response?: HttpResponseInterface;
9 | }
10 |
--------------------------------------------------------------------------------
/src/http/interfaces/HttpMiddlewareInterface.ts:
--------------------------------------------------------------------------------
1 | import HttpErrorInterface from "./HttpErrorInterface";
2 | import HttpResponseInterface from "./HttpResponseInterface";
3 | import HttpRequestConfigInterface from "./HttpRequestConfigInterface";
4 |
5 | export default interface HttpMiddlewareInterface {
6 | request(
7 | config: HttpRequestConfigInterface,
8 | ): HttpRequestConfigInterface | Promise;
9 | response(
10 | response: HttpResponseInterface,
11 | ): HttpResponseInterface | Promise;
12 | responseError(responseError: HttpErrorInterface);
13 | }
14 |
--------------------------------------------------------------------------------
/src/http/interfaces/HttpRequestConfigInterface.ts:
--------------------------------------------------------------------------------
1 | export default interface HttpRequestConfigInterface {
2 | url?: string;
3 | method?: string;
4 | baseURL?: string;
5 | headers?: any;
6 | params?: any;
7 | paramsSerializer?: (params: any) => string;
8 | data?: any;
9 | timeout?: number;
10 | withCredentials?: boolean;
11 | responseType?: string;
12 | xsrfCookieName?: string;
13 | xsrfHeaderName?: string;
14 | maxContentLength?: number;
15 | validateStatus?: (status: number) => boolean;
16 | maxRedirects?: number;
17 | httpAgent?: any;
18 | httpsAgent?: any;
19 | }
20 |
--------------------------------------------------------------------------------
/src/http/interfaces/HttpResponseInterface.ts:
--------------------------------------------------------------------------------
1 | import HttpRequestConfigInterface from "./HttpRequestConfigInterface";
2 |
3 | export default interface HttpResponseInterface {
4 | data: T;
5 | status: number;
6 | statusText: string;
7 | headers: any;
8 | config: HttpRequestConfigInterface;
9 | request?: any;
10 | }
11 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import * as utilities from "./utilities";
2 | import Application from "./foundation/Application";
3 |
4 | // Core Service Providers
5 | import HttpServiceProvider from "./http/HttpServiceProvider";
6 | import StateServiceProvider from "./state/StateServiceProvider";
7 | import ConfigServiceProvider from "./config/ConfigServiceProvider";
8 | import CookieServiceProvider from "./cookies/CookieServiceProvider";
9 | import RoutingServiceProvider from "./routing/RoutingServiceProvider";
10 | import StorageServiceProvider from "./storage/StorageServiceProvider";
11 |
12 | // Support Service Providers
13 | import Model from "./support/Model";
14 | import ServiceProvider from "./support/ServiceProvider";
15 |
16 | // Plugin Service Providers
17 | import FormServiceProvider from "./plugins/forms/FormServiceProvider";
18 | import AlertServiceProvider from "./plugins/alerts/AlertServiceProvider";
19 | import ValidationServiceProvider from "./validation/ValidationServiceProvider";
20 |
21 | // Auto Register Service Providers
22 | import AutoRegisterMixinServiceProvider from "./plugins/autoRegisterMixins/AutoRegisterMixinServiceProvider";
23 | import AutoRegisterFilterServiceProvider from "./plugins/autoRegisterFilters/AutoRegisterFilterServiceProvider";
24 | import AutoRegisterLayoutServiceProvider from "./plugins/autoRegisterLayouts/AutoRegisterLayoutServiceProvider";
25 | import AutoRegisterComponentServiceProvider from "./plugins/autoRegisterComponents/AutoRegisterComponentServiceProvider";
26 | import AutoRegisterDirectiveServiceProvider from "./plugins/autoRegisterDirectives/AutoRegisterDirectiveServiceProvider";
27 |
28 | export {
29 | Model,
30 | utilities,
31 | Application,
32 | ServiceProvider,
33 | FormServiceProvider,
34 | HttpServiceProvider,
35 | StateServiceProvider,
36 | AlertServiceProvider,
37 | ConfigServiceProvider,
38 | CookieServiceProvider,
39 | RoutingServiceProvider,
40 | StorageServiceProvider,
41 | ValidationServiceProvider,
42 | AutoRegisterMixinServiceProvider,
43 | AutoRegisterFilterServiceProvider,
44 | AutoRegisterLayoutServiceProvider,
45 | AutoRegisterComponentServiceProvider,
46 | AutoRegisterDirectiveServiceProvider,
47 | };
48 |
--------------------------------------------------------------------------------
/src/plugins/alerts/AlertService.ts:
--------------------------------------------------------------------------------
1 | import { Store } from "vuex";
2 | import { inject, injectable } from "inversify";
3 | import ConfigInterface from "../../config/ConfigInterface";
4 | import StateServiceInterface from "../../state/StateServiceInterface";
5 |
6 | @injectable()
7 | class AlertService {
8 | protected store: Store;
9 | protected configService: {
10 | duration: number;
11 | };
12 |
13 | constructor(
14 | @inject("ConfigService") $config: ConfigInterface,
15 | @inject("StateService") stateService: StateServiceInterface,
16 | ) {
17 | this.store = stateService.getStore();
18 | this.configService = $config.get("alerts");
19 | }
20 |
21 | public error(message: string, title: string = "Error", duration?: number) {
22 | this.makeAlert(message, title, duration, "error");
23 | }
24 |
25 | public info(message: string, title: string = "Info", duration?: number) {
26 | this.makeAlert(message, title, duration, "info");
27 | }
28 |
29 | public success(
30 | message: string,
31 | title: string = "Success",
32 | duration?: number,
33 | ) {
34 | this.makeAlert(message, title, duration, "success");
35 | }
36 |
37 | public warning(
38 | message: string,
39 | title: string = "Warning",
40 | duration?: number,
41 | ) {
42 | this.makeAlert(message, title, duration, "warning");
43 | }
44 |
45 | protected makeAlert(
46 | message: string,
47 | title: string,
48 | duration?: number,
49 | severity?: string,
50 | ) {
51 | if (duration === undefined) {
52 | duration = this.configService.duration;
53 | }
54 | this.store.dispatch("varie/alerts/add", {
55 | message: message,
56 | duration: duration,
57 | severity: severity,
58 | title: title ? title : `${severity}!!`,
59 | });
60 | }
61 | }
62 |
63 | export default AlertService;
64 |
--------------------------------------------------------------------------------
/src/plugins/alerts/AlertServiceInterface.ts:
--------------------------------------------------------------------------------
1 | export default interface AlertServiceInterface {
2 | showError(message: string, title?: string, duration?: number): void;
3 | showInfo(message: string, title?: string, duration?: number): void;
4 | showSuccess(message: string, title?: string, duration?: number): void;
5 | showWarning(message: string, title?: string, duration?: number): void;
6 | }
7 |
--------------------------------------------------------------------------------
/src/plugins/alerts/AlertServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Alerts from "./Alerts";
3 | import config from "./config";
4 | import AlertService from "./AlertService";
5 | import VuexService from "../../state/VuexService";
6 | import AlertServiceInterface from "./AlertServiceInterface";
7 | import ServiceProvider from "../../support/ServiceProvider";
8 |
9 | export default class AlertServiceProvider extends ServiceProvider {
10 | public boot() {
11 | Vue.use(new Alerts(this.app.make("ConfigService")), {
12 | store: this.app.make("StateService").getStore(),
13 | service: this.app.make("AlertService"),
14 | });
15 | }
16 |
17 | public register() {
18 | this.mergeConfigFrom(config, "alerts");
19 | this.app.singleton("AlertService", AlertService);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/plugins/alerts/Alerts.ts:
--------------------------------------------------------------------------------
1 | import AlertService from "./AlertService";
2 | import { VueConstructor } from "vue/types/vue";
3 | import AlertStore from "./alert-store/AlertStore";
4 | import ConfigInterface from "../../config/ConfigInterface";
5 |
6 | export default class Alerts {
7 | protected config: {
8 | duration: number;
9 | };
10 |
11 | constructor($config: ConfigInterface) {
12 | this.config = $config.get("alerts");
13 | }
14 |
15 | public install(Vue: VueConstructor, { store, service }) {
16 | store.registerModule(["varie", "alerts"], new AlertStore());
17 | Vue.mixin({
18 | computed: {
19 | alertService: (): AlertService => {
20 | return service;
21 | },
22 | },
23 | });
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/plugins/alerts/alert-store/AlertStore.ts:
--------------------------------------------------------------------------------
1 | import state from "./state";
2 | import Actions from "./actions";
3 | import Mutations from "./mutations";
4 | import { injectable } from "inversify";
5 |
6 | @injectable()
7 | export default class AlertStore {
8 | public name;
9 | public state;
10 | public actions;
11 | public mutations;
12 | public namespaced;
13 |
14 | constructor() {
15 | this.state = state;
16 | this.name = "alerts";
17 | this.namespaced = true;
18 | this.actions = new Actions();
19 | this.mutations = new Mutations();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/plugins/alerts/alert-store/actions.ts:
--------------------------------------------------------------------------------
1 | import { ActionContext } from "vuex";
2 | // @ts-ignore
3 | import RootState from "@store/rootState";
4 | import { AlertState } from "./stateInterface";
5 | import AlertModel from "./../models/AlertModel";
6 |
7 | export default class Actions {
8 | public add = (
9 | context: ActionContext,
10 | alert: AlertModel,
11 | ) => {
12 | context.commit("add", alert);
13 | };
14 |
15 | public remove = (
16 | context: ActionContext,
17 | alert: AlertModel,
18 | ) => {
19 | context.commit("remove", alert);
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/src/plugins/alerts/alert-store/mutations.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import { AlertState } from "./stateInterface";
3 | import AlertModel from "./../models/AlertModel";
4 |
5 | export default class Mutations {
6 | public add = (state: AlertState, alert: AlertModel) => {
7 | alert.id = this.guid();
8 | state.alerts.push(alert);
9 | };
10 |
11 | public remove = (state: AlertState, alert: AlertModel) => {
12 | Vue.set(
13 | state,
14 | "alerts",
15 | state.alerts.filter((tempAlert) => {
16 | return alert.id !== tempAlert.id;
17 | }),
18 | );
19 | };
20 |
21 | // TODO - this needs to be moved out
22 | protected guid() {
23 | function s4() {
24 | return Math.floor((1 + Math.random()) * 0x10000)
25 | .toString(16)
26 | .substring(1);
27 | }
28 | return (
29 | s4() +
30 | s4() +
31 | "-" +
32 | s4() +
33 | "-" +
34 | s4() +
35 | "-" +
36 | s4() +
37 | "-" +
38 | s4() +
39 | s4() +
40 | s4()
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/plugins/alerts/alert-store/state.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | alerts: [],
3 | };
4 |
--------------------------------------------------------------------------------
/src/plugins/alerts/alert-store/stateInterface.ts:
--------------------------------------------------------------------------------
1 | import AlertModel from "./../models/AlertModel";
2 | export interface AlertState {
3 | alerts: Array;
4 | }
5 |
--------------------------------------------------------------------------------
/src/plugins/alerts/config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | /*
3 | |--------------------------------------------------------------------------
4 | | Duration
5 | |--------------------------------------------------------------------------
6 | |
7 | | How long a alert will show up, 0 will make it a forever living alert.
8 | |
9 | */
10 |
11 | duration: 0,
12 | };
13 |
--------------------------------------------------------------------------------
/src/plugins/alerts/models/AlertModel.ts:
--------------------------------------------------------------------------------
1 | export default interface AlertModel {
2 | title: string;
3 | message: string;
4 | severity: string;
5 | id: null | number | string;
6 | duration: number | undefined | null;
7 | }
8 |
--------------------------------------------------------------------------------
/src/plugins/autoRegisterComponents/AutoRegisterComponentServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import dashify from "../../utilities/dashify";
3 | import ServiceProvider from "../../support/ServiceProvider";
4 |
5 | export default class AutoRegisterComponentServiceProvider extends ServiceProvider {
6 | public register() {}
7 |
8 | public boot() {
9 | let files = require.context("@components", true, /^\.\/.*\.(vue)$/);
10 | files.keys().forEach((filename) => {
11 | Vue.component(this.getComponentName(filename), files(filename).default);
12 | });
13 | }
14 |
15 | protected getComponentName(filename: string) {
16 | return dashify(filename.replace(".vue", ""));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/plugins/autoRegisterDirectives/AutoRegisterDirectiveServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import ServiceProvider from "../../support/ServiceProvider";
2 |
3 | export default class AutoRegisterDirectiveServiceProvider extends ServiceProvider {
4 | public register() {}
5 |
6 | public boot() {
7 | let files = require.context("@app/directives", true, /^\.\/.*\.(ts|js)$/);
8 | files.keys().forEach((filename) => {
9 | files(filename);
10 | });
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/plugins/autoRegisterFilters/AutoRegisterFilterServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import camelize from "../../utilities/camelize";
3 | import ServiceProvider from "../../support/ServiceProvider";
4 |
5 | export default class AutoRegisterFilterServiceProvider extends ServiceProvider {
6 | public register() {}
7 |
8 | public boot() {
9 | let files = require.context("@app/filters", true, /^\.\/.*\.(ts|js)$/);
10 | files.keys().forEach((filename) => {
11 | Vue.filter(this.getFilterName(filename), files(filename).default);
12 | });
13 | }
14 |
15 | protected getFilterName(filename: string) {
16 | return camelize(filename.replace(".ts", ""));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/plugins/autoRegisterLayouts/AutoRegisterLayoutServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import dashify from "../../utilities/dashify";
3 | import ServiceProvider from "../../support/ServiceProvider";
4 |
5 | export default class AutoRegisterLayoutServiceProvider extends ServiceProvider {
6 | public register() {}
7 |
8 | public boot() {
9 | let files = require.context("@views/layouts", false, /^\.\/.*\.(vue)$/);
10 | files.keys().forEach((filename) => {
11 | Vue.component(this.getComponentName(filename), files(filename).default);
12 | });
13 | }
14 |
15 | protected getComponentName(filename: string) {
16 | return `${dashify(filename.replace(".vue", ""))}-layout`;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/plugins/autoRegisterMixins/AutoRegisterMixinServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import ServiceProvider from "../../support/ServiceProvider";
3 |
4 | export default class AutoRegisterMixinServiceProvider extends ServiceProvider {
5 | public register() {}
6 |
7 | public boot() {
8 | let files = require.context("@app/mixins", true, /^\.\/.*\.(ts|js)$/);
9 | files.keys().forEach((filename) => {
10 | Vue.mixin(files(filename));
11 | });
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/plugins/forms/Form.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import filterEmpty from "./../../utilities/filterEmpty";
3 | import ValidationServiceInterface from "../../validation/ValidationServiceInterface";
4 |
5 | // TODO - we could use setters / getters to remove _'s for public things
6 | class Form {
7 | public _rules: object = {};
8 | public _messages: object = {};
9 |
10 | protected _validator;
11 | protected _initialData: any;
12 | protected _originalData: any;
13 |
14 | constructor(data: object, validationService?: ValidationServiceInterface) {
15 | if (validationService) {
16 | this._validator = validationService;
17 | }
18 | this.fill(data);
19 | this.setAsOriginalData();
20 | this._initialData = this.data(false);
21 | }
22 |
23 | public fill(data) {
24 | for (let key in data) {
25 | Vue.set(this, key, data[key]);
26 | }
27 | return this;
28 | }
29 |
30 | public merge(data) {
31 | for (let key in data) {
32 | if (data[key] && this.hasOwnProperty(key)) {
33 | Vue.set(this, key, data[key]);
34 | }
35 | }
36 | return this;
37 | }
38 |
39 | public validation({ rules, messages }) {
40 | this._rules = rules;
41 | this._messages = messages;
42 | return this;
43 | }
44 |
45 | public isValid() {
46 | if (this._validator) {
47 | let errors = this._validator.validate(
48 | this.data(),
49 | this._rules,
50 | this._messages,
51 | );
52 | if (Object.keys(errors).length) {
53 | return false;
54 | }
55 | }
56 | return true;
57 | }
58 |
59 | public data(removeEmpty = true) {
60 | let data = {};
61 | let tempData = Object.assign({}, this);
62 |
63 | delete tempData._rules;
64 | delete tempData._messages;
65 | delete tempData._validator;
66 | delete tempData._initialData;
67 | delete tempData._originalData;
68 |
69 | for (let field in tempData) {
70 | data[`${field}`] = this[field];
71 | }
72 |
73 | if (removeEmpty) {
74 | return filterEmpty(data);
75 | }
76 | return data;
77 | }
78 |
79 | public setAsOriginalData() {
80 | this._originalData = this.data();
81 | return this;
82 | }
83 |
84 | public reset() {
85 | for (let field in this.data()) {
86 | this.remove(field);
87 | }
88 | this.fill(this._originalData);
89 | return this;
90 | }
91 |
92 | initial() {
93 | this.fill(this._initialData).setAsOriginalData();
94 | return this;
95 | }
96 |
97 | public remove(key) {
98 | Vue.delete(this, key);
99 | return this;
100 | }
101 |
102 | public errors() {
103 | return this._validator.validate(this.data(), this._rules, this._messages);
104 | }
105 |
106 | public isDirty(property?) {
107 | let data = this.data();
108 | let originalData = this._originalData;
109 | if (property) {
110 | return (
111 | (data.hasOwnProperty(property) &&
112 | !originalData.hasOwnProperty(property)) ||
113 | data[property] !== originalData[property]
114 | );
115 | }
116 | return JSON.stringify(data) !== JSON.stringify(originalData);
117 | }
118 | }
119 |
120 | export default Form;
121 |
--------------------------------------------------------------------------------
/src/plugins/forms/FormServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import { PluginObject } from "vue";
3 | import FormsPlugin from "./FormsPlugin";
4 | import ServiceProvider from "../../support/ServiceProvider";
5 |
6 | export default class FormServiceProvider extends ServiceProvider {
7 | public boot() {
8 | Vue.use(this.app.make>("FormService"));
9 | }
10 | public register() {
11 | this.app.singleton("FormService", FormsPlugin);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/plugins/forms/FormsPlugin.ts:
--------------------------------------------------------------------------------
1 | import Form from "./Form";
2 | import { inject, injectable } from "inversify";
3 | import { VueConstructor } from "vue/types/vue";
4 |
5 | @injectable()
6 | class Forms {
7 | @inject("ValidationService") protected validateService;
8 |
9 | public install(Vue: VueConstructor) {
10 | Vue.mixin({
11 | methods: {
12 | createForm: (data: object) => {
13 | return new Form(data, this.validateService);
14 | },
15 | },
16 | });
17 | }
18 | }
19 |
20 | export default Forms;
21 |
--------------------------------------------------------------------------------
/src/routing/Route.ts:
--------------------------------------------------------------------------------
1 | export default class Route {
2 | public path;
3 | public name;
4 | public alias;
5 | public group;
6 | public props;
7 | public components;
8 | public meta: {
9 | data?: object;
10 | layout?: string;
11 | middleware?: Array;
12 | } = {};
13 |
14 | protected component;
15 |
16 | constructor(
17 | path: string,
18 | components: string | object | Array,
19 | props: (() => void) | boolean | object = true,
20 | ) {
21 | this.path = path;
22 | this.props = props;
23 |
24 | this.registerComponents(components);
25 | }
26 |
27 | public setName(name: string): this {
28 | this.name = name;
29 | return this;
30 | }
31 |
32 | public setMeta(data): this {
33 | this.meta = Object.assign(this.meta, data);
34 | return this;
35 | }
36 |
37 | public setAlias(alias) {
38 | this.alias = alias;
39 | return this;
40 | }
41 |
42 | public setLayout(layout) {
43 | this.meta.layout = layout;
44 | return this;
45 | }
46 |
47 | protected registerComponents(components) {
48 | if (typeof components === "object" && !components.__file) {
49 | this.components = {};
50 | for (let name in components) {
51 | this.components[name] = components[name];
52 | }
53 | } else {
54 | this.component = components;
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/routing/RouteMiddlewareInterface.ts:
--------------------------------------------------------------------------------
1 | import { Route, Location } from "vue-router";
2 |
3 | export default interface RouteMiddlewareInterface {
4 | handler(to: Route, from: Route, next: (route?: Location) => void): void;
5 | }
6 |
--------------------------------------------------------------------------------
/src/routing/RouterInterface.ts:
--------------------------------------------------------------------------------
1 | import Route from "./Route";
2 |
3 | export default interface RouterInterface {
4 | getRouter(): any;
5 | route(
6 | path: string,
7 | component: object,
8 | props?: (() => void) | boolean | object,
9 | ): Route;
10 | group(routes: Function): this;
11 | middleware(middleware: Array): this;
12 | prefix(prefix: string): this;
13 | area(area: object): this;
14 | redirect(path: string, redirect: string): this;
15 | layout(layout: string): this;
16 | data(data: object): this;
17 | // TODO - this should not be any
18 | register(routes: any, ...services: Array): this;
19 | }
20 |
--------------------------------------------------------------------------------
/src/routing/RoutesInterface.ts:
--------------------------------------------------------------------------------
1 | export default interface RoutesInterface {
2 | register();
3 | }
4 |
--------------------------------------------------------------------------------
/src/routing/RoutingServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import RouterConfig from "./config";
2 | import VueRouterService from "./VueRouterService";
3 | import ServiceProvider from "../support/ServiceProvider";
4 |
5 | export default class RoutingServiceProvider extends ServiceProvider {
6 | public $router;
7 |
8 | public boot() {
9 | this.$router = this.app.make("RouterService");
10 |
11 | // @ts-ignore
12 | if (typeof this.map === "function") {
13 | // @ts-ignore
14 | this.map();
15 | } else {
16 | throw "Your routing service provider must have a map function.";
17 | }
18 |
19 | this.$router.buildRouter();
20 | }
21 |
22 | public register() {
23 | this.mergeConfigFrom(RouterConfig, "router");
24 | this.app.singleton("RouterService", VueRouterService);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/routing/VueRouterService.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Route from "./Route";
3 | import VueRouter from "vue-router";
4 | import clone from "./../utilities/clone";
5 | import { inject, injectable } from "inversify";
6 | import RouterInterface from "./RouterInterface";
7 | import ConfigInterface from "../config/ConfigInterface";
8 | import RouteMiddlewareInterface from "./RouteMiddlewareInterface";
9 | import ApplicationInterface from "../foundation/ApplicationInterface";
10 |
11 | interface GroupInfo {
12 | path: string;
13 | component: object;
14 | area: null | object;
15 | children: Array;
16 | meta: {
17 | data: object;
18 | layout: string;
19 | middleware: Array;
20 | };
21 | }
22 |
23 | interface RedirectRoute {
24 | path: string;
25 | redirect: string;
26 | }
27 |
28 | @injectable()
29 | export default class VueRouterService implements RouterInterface {
30 | public router;
31 | public routes: Array = [];
32 |
33 | protected groupInfo;
34 | protected currentGroupLevel = 0;
35 | protected app: ApplicationInterface;
36 | protected groups: Array = [];
37 | protected configService: ConfigInterface;
38 | protected wildCardRoutes: Array = [];
39 |
40 | constructor(
41 | @inject("app") app: ApplicationInterface,
42 | @inject("ConfigService") configService: ConfigInterface,
43 | ) {
44 | this.app = app;
45 | this.configService = configService;
46 | this.resetGroup();
47 | Vue.use(VueRouter);
48 | }
49 |
50 | public getRouter() {
51 | return this.router;
52 | }
53 |
54 | public register(routes, ...services) {
55 | routes(this, services);
56 | return this;
57 | }
58 |
59 | public buildRouter() {
60 | if (this.wildCardRoutes.length) {
61 | this.wildCardRoutes.forEach((route) => {
62 | if (route.group) {
63 | route.group.children.push(route);
64 | } else {
65 | this.routes.push(route);
66 | }
67 | });
68 | }
69 | this.router = new VueRouter(
70 | Object.assign({}, this.configService.get("router"), {
71 | routes: this.routes,
72 | }),
73 | );
74 |
75 | this.setupMiddleware();
76 | }
77 |
78 | public route(path: string, component: string | object, props = true): Route {
79 | let route = new Route(path, component, props);
80 |
81 | if (this.currentGroupLevel > -1) {
82 | // children routes cannot begin with a `/` as they would not be children
83 | route.path = route.path.replace(/^\/*/g, "");
84 |
85 | if (route.path === "*") {
86 | route.group = this.groups[this.currentGroupLevel];
87 | this.wildCardRoutes.push(route);
88 | } else {
89 | this.groups[this.currentGroupLevel].children.push(route);
90 | }
91 |
92 | let tempName = "";
93 | let groupIndex = this.currentGroupLevel;
94 | for (groupIndex; groupIndex > -1; groupIndex--) {
95 | tempName =
96 | this.groups[groupIndex].path !== "/"
97 | ? this.groups[groupIndex].path + "/" + tempName
98 | : tempName;
99 | }
100 | this.convertRoutePathToRouteName(route, tempName + route.path);
101 |
102 | route.meta.middleware = this.groups[
103 | this.currentGroupLevel
104 | ].meta.middleware;
105 |
106 | route.meta.data = this.groups[this.currentGroupLevel].meta.data;
107 |
108 | return route;
109 | }
110 |
111 | if (route.path === "*") {
112 | this.wildCardRoutes.push(route);
113 | } else {
114 | route.setMeta(this.groupInfo.meta);
115 | this.routes.push(route);
116 | }
117 |
118 | this.convertRoutePathToRouteName(route);
119 | return route;
120 | }
121 |
122 | protected convertRoutePathToRouteName(route: Route, path?: string) {
123 | path = path ? path : route.path;
124 | if (path) {
125 | route.setName(
126 | path
127 | .replace(/^\/|\/$/g, "")
128 | .replace(/(\/?)(:.*?)(\/|$)/g, ".")
129 | .replace(/^\.|\.$/g, "")
130 | .toLowerCase(),
131 | );
132 | }
133 | }
134 |
135 | public middleware(middleware: Array) {
136 | this.groupInfo.meta.middleware = this.groupInfo.meta.middleware.concat(
137 | middleware,
138 | );
139 | return this;
140 | }
141 |
142 | public redirect(path: string, redirect: string) {
143 | this.routes.push({
144 | path: path,
145 | redirect: redirect,
146 | });
147 | return this;
148 | }
149 |
150 | public group(routes: Function) {
151 | this.currentGroupLevel++;
152 | this.groups.push(clone(this.groupInfo));
153 | // Areas only apply to 1 group not all subsequent children groups
154 | delete this.groupInfo.area;
155 | routes();
156 | this.resetGroup();
157 | return this;
158 | }
159 |
160 | public area(area: object) {
161 | this.groupInfo.area = area;
162 | return this;
163 | }
164 |
165 | public prefix(prefix: string) {
166 | this.groupInfo.path = prefix || "";
167 | if (this.currentGroupLevel > -1) {
168 | this.groupInfo.path = this.groupInfo.path.replace(/^\/*/g, "");
169 | }
170 | return this;
171 | }
172 |
173 | public layout(layout) {
174 | this.groupInfo.meta.layout = layout;
175 | return this;
176 | }
177 |
178 | public data(data) {
179 | this.groupInfo.meta.data = data;
180 | return this;
181 | }
182 |
183 | /**
184 | * We loop through all middleware of that route
185 | * Making sure we resolve them one at a time
186 | */
187 | public setupMiddleware() {
188 | this.router.beforeResolve((to, from, next) => {
189 | let stopMiddleware = false;
190 | if (to.meta.middleware && to.meta.middleware.length) {
191 | return to.meta.middleware.reduce(
192 | (promise, currentValue, currentIndex) => {
193 | return promise.then(() => {
194 | if (stopMiddleware === false) {
195 | return this.getMiddleware(currentValue).handler(
196 | to,
197 | from,
198 | (options) => {
199 | if (options) {
200 | next(options);
201 | stopMiddleware = true;
202 | return;
203 | } else if (currentIndex === to.meta.middleware.length - 1) {
204 | return next();
205 | }
206 | },
207 | );
208 | }
209 | });
210 | },
211 | Promise.resolve(),
212 | );
213 | }
214 | next();
215 | });
216 | }
217 |
218 | protected getMiddleware(middleware) {
219 | let containerMiddlewareName = `routerMiddleware${middleware.name}`;
220 | if (!this.app.isBound(containerMiddlewareName)) {
221 | this.app.bind(
222 | containerMiddlewareName,
223 | middleware,
224 | );
225 | }
226 | return this.app.make(containerMiddlewareName);
227 | }
228 |
229 | /**
230 | * We build all the group information by looping through each level
231 | *
232 | * Each group will go up in a level with a child group is made
233 | *
234 | * We then go through each grouping and set middleware / areas
235 | * and place the children for that group.
236 | *
237 | * By going up and down for each group we retain the data for the group level
238 | * allowing us to chain in a pretty way
239 | */
240 | protected resetGroup() {
241 | this.groupInfo = {
242 | path: "/",
243 | meta: {
244 | data: {},
245 | middleware: [],
246 | layout: this.configService.get("view.defaultLayout", "public"),
247 | },
248 | area: null,
249 | children: [],
250 | component: {
251 | template: " ",
252 | },
253 | };
254 |
255 | if (this.groups.length) {
256 | let childGroup = this.groups[this.currentGroupLevel];
257 | let parentGroup = this.groups[this.currentGroupLevel - 1];
258 |
259 | if (childGroup.area) {
260 | childGroup.component = childGroup.area;
261 | delete childGroup.area;
262 | }
263 |
264 | if (parentGroup) {
265 | if (childGroup.path === parentGroup.path) {
266 | childGroup.path = "";
267 | }
268 | this.groupInfo.meta.data = parentGroup.meta.data;
269 | this.groupInfo.meta.layout = parentGroup.meta.layout;
270 | this.groupInfo.meta.middleware = parentGroup.meta.middleware;
271 | parentGroup.children.push(childGroup);
272 | }
273 |
274 | this.groups.splice(this.currentGroupLevel, 1);
275 |
276 | if (this.currentGroupLevel === 0) {
277 | this.routes.push(childGroup);
278 | }
279 | }
280 |
281 | this.currentGroupLevel--;
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/src/routing/config.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | /*
3 | |--------------------------------------------------------------------------
4 | | Mode
5 | |--------------------------------------------------------------------------
6 | |
7 | | Configure the router mode.
8 | |
9 | | Supported : "hash", "history", "abstract"
10 | |
11 | */
12 |
13 | mode: "history",
14 |
15 | /*
16 | |--------------------------------------------------------------------------
17 | | Base
18 | |--------------------------------------------------------------------------
19 | |
20 | | The base URL of the app.
21 | |
22 | */
23 |
24 | base: "/",
25 |
26 | /*
27 | |--------------------------------------------------------------------------
28 | | Link active class
29 | |--------------------------------------------------------------------------
30 | |
31 | | When a link is active this class will be attached to it.
32 | |
33 | */
34 |
35 | linkActiveClass: "router-link-active",
36 |
37 | /*
38 | |--------------------------------------------------------------------------
39 | | Link exact class
40 | |--------------------------------------------------------------------------
41 | |
42 | | When a link exactly matches the current url this class will be attached to it.
43 | |
44 | */
45 |
46 | linkExactActiveClass: "router-link-exact-active",
47 |
48 | /*
49 | |--------------------------------------------------------------------------
50 | | Scroll Behavior
51 | |--------------------------------------------------------------------------
52 | |
53 | | Allows for a customized global scrolling function
54 | |
55 | */
56 |
57 | scrollBehavior: null,
58 |
59 | /*
60 | |--------------------------------------------------------------------------
61 | | Query Parser
62 | |--------------------------------------------------------------------------
63 | |
64 | | Provide custom query string parser.
65 | |
66 | */
67 |
68 | parseQuery: null,
69 |
70 | /*
71 | |--------------------------------------------------------------------------
72 | | Stringify function
73 | |--------------------------------------------------------------------------
74 | |
75 | | Provide custom query stringify function.
76 | |
77 | */
78 |
79 | stringifyQuery: null,
80 |
81 | /*
82 | |--------------------------------------------------------------------------
83 | | Fallback links
84 | |--------------------------------------------------------------------------
85 | |
86 | | Controls whether the router should fallback to hash mode when the
87 | | browser does not support history.pushState. Defaults to true.
88 | |
89 | */
90 |
91 | fallback: true,
92 | };
93 |
--------------------------------------------------------------------------------
/src/state/StateServiceInterface.ts:
--------------------------------------------------------------------------------
1 | export default interface StateServiceInterface {
2 | getStore(): any;
3 | registerStore(store: any): StateServiceInterface;
4 | }
5 |
--------------------------------------------------------------------------------
/src/state/StateServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import VuexService from "./VuexService";
2 | import ServiceProvider from "../support/ServiceProvider";
3 | import StateServiceInterface from "./StateServiceInterface";
4 |
5 | export default class StateServiceProvider extends ServiceProvider {
6 | public $store;
7 |
8 | public boot() {
9 | this.$store = this.app.make("StateService");
10 |
11 | // @ts-ignore
12 | if (typeof this.map === "function") {
13 | // @ts-ignore
14 | this.map();
15 | } else {
16 | throw "Your state service provider must have a map function.";
17 | }
18 | }
19 |
20 | public register() {
21 | this.app.singleton("StateService", VuexService);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/state/StoreModule.ts:
--------------------------------------------------------------------------------
1 | import { Store } from "vuex";
2 | type GenericObject = { [key: string]: any };
3 | import { injectable, inject } from "inversify";
4 |
5 | @injectable()
6 | export default class StoreModule {
7 | public name;
8 | public modules = {};
9 | public namespaced = true;
10 | public state: GenericObject = {};
11 | public actions: GenericObject = {};
12 | public getters: GenericObject = {};
13 | public mutations: GenericObject = {};
14 | public $modules: Array = [];
15 |
16 | setName(name) {
17 | this.name = name;
18 | return this;
19 | }
20 |
21 | addState(state) {
22 | this.state = Object.assign({}, this.state, state);
23 | return this;
24 | }
25 |
26 | addActions(actions) {
27 | if (typeof actions === "function") {
28 | actions = actions();
29 | }
30 | this.actions = Object.assign({}, this.actions, actions);
31 | return this;
32 | }
33 |
34 | addMutations(mutations) {
35 | if (typeof mutations === "function") {
36 | mutations = mutations();
37 | }
38 | this.mutations = Object.assign({}, this.mutations, mutations);
39 | return this;
40 | }
41 |
42 | addGetters(getters) {
43 | if (typeof getters === "function") {
44 | getters = getters();
45 | }
46 | this.getters = Object.assign({}, this.getters, getters);
47 | return this;
48 | }
49 |
50 | addModule(store) {
51 | this.$modules.push(store);
52 | return this;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/state/VuexService.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex, { Store } from "vuex";
3 | import StoreModule from "./StoreModule";
4 | import camelize from "../utilities/camelize";
5 | import { inject, injectable } from "inversify";
6 | import StateServiceInterface from "./StateServiceInterface";
7 | import ApplicationInterface from "../foundation/ApplicationInterface";
8 |
9 | @injectable()
10 | export default class VuexService implements StateServiceInterface {
11 | protected store: Store;
12 | protected app: ApplicationInterface;
13 |
14 | constructor(@inject("app") app: ApplicationInterface) {
15 | Vue.use(Vuex);
16 | this.app = app;
17 | this.store = new Vuex.Store({});
18 | this.store.registerModule("varie", {
19 | namespaced: true,
20 | state: {},
21 | });
22 | }
23 |
24 | public getStore(): Store {
25 | return this.store;
26 | }
27 |
28 | public registerStore(Store: StoreModule) {
29 | let store = this.bindStore(Store);
30 | this.store.registerModule(
31 | this.getStoreName(store),
32 | this.registerSubModules(store),
33 | );
34 | return this;
35 | }
36 |
37 | protected registerSubModules(store: StoreModule) {
38 | store.$modules.forEach((Module) => {
39 | let module = this.bindStore(Module);
40 | store.modules[this.getStoreName(module)] = this.registerSubModules(
41 | module,
42 | );
43 | });
44 | return store;
45 | }
46 |
47 | protected getStoreName(store: StoreModule) {
48 | if (!store.name) {
49 | throw "Your store does not have a name";
50 | }
51 | return store.name;
52 | }
53 |
54 | protected bindStore(Store: StoreModule) {
55 | let moduleAbstractName = camelize(`store ${Store.name}`);
56 | this.app.singleton(moduleAbstractName, Store);
57 | return this.app.make(moduleAbstractName);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/storage/StorageService.ts:
--------------------------------------------------------------------------------
1 | import { injectable } from "inversify";
2 | import StorageServiceInterface from "./StorageServiceInterface";
3 |
4 | @injectable()
5 | export default class StorageService implements StorageServiceInterface {
6 | public get(key: string): any {
7 | return localStorage.getItem(key);
8 | }
9 |
10 | public set(key: string, value: any): void {
11 | localStorage.setItem(key, value);
12 | }
13 |
14 | public remove(key): void {
15 | localStorage.removeItem(key);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/storage/StorageServiceInterface.ts:
--------------------------------------------------------------------------------
1 | export default interface StorageServiceInterface {
2 | get(key: string): any;
3 | set(key: string, value: any): void;
4 | remove(key: string): void;
5 | }
6 |
--------------------------------------------------------------------------------
/src/storage/StorageServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import StorageService from "./StorageService";
2 | import ServiceProvider from "../support/ServiceProvider";
3 | import StorageServiceInterface from "./StorageServiceInterface";
4 |
5 | export default class StorageServiceProvider extends ServiceProvider {
6 | public register() {
7 | this.app.singleton(
8 | "StorageService",
9 | StorageService,
10 | );
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/support/Model.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 |
3 | export default class Model {
4 | constructor(data: object) {
5 | this.defaults();
6 | Object.assign(this, data);
7 | }
8 |
9 | protected defaults() {
10 | // ...
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/support/ServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import { injectable } from "inversify";
2 | import ConfigInterface from "../config/ConfigInterface";
3 | import ServiceProviderInterface from "./ServiceProviderInterface";
4 | import ApplicationInterface from "./../foundation/ApplicationInterface";
5 |
6 | @injectable()
7 | export default class ServiceProvider implements ServiceProviderInterface {
8 | public app: ApplicationInterface;
9 |
10 | constructor(app: ApplicationInterface) {
11 | this.app = app;
12 | this.app.addProvider(this);
13 | }
14 |
15 | protected mergeConfigFrom(frameworkConfig: any, key: string) {
16 | let appConfig = this.app.make("ConfigService").get(key);
17 |
18 | for (let appConfigKey in appConfig) {
19 | if (appConfig[appConfigKey] !== undefined) {
20 | if (
21 | frameworkConfig[appConfigKey] instanceof Object &&
22 | appConfig[appConfigKey] instanceof Object
23 | ) {
24 | Object.assign(frameworkConfig[appConfigKey], appConfig[appConfigKey]);
25 | } else {
26 | frameworkConfig[appConfigKey] = appConfig[appConfigKey];
27 | }
28 | }
29 | }
30 | $config.set(key, frameworkConfig);
31 | }
32 |
33 | public boot() {}
34 | }
35 |
--------------------------------------------------------------------------------
/src/support/ServiceProviderInterface.ts:
--------------------------------------------------------------------------------
1 | export default interface ServiceProviderInterface {
2 | boot(): any;
3 | register?(): any;
4 | }
5 |
--------------------------------------------------------------------------------
/src/utilities/camelize.ts:
--------------------------------------------------------------------------------
1 | import camelCase from "camelcase";
2 |
3 | export default function(data: string) {
4 | return camelCase(data);
5 | }
6 |
--------------------------------------------------------------------------------
/src/utilities/clone.ts:
--------------------------------------------------------------------------------
1 | import * as cloneDeep from "clone-deep";
2 |
3 | export default function(data: object) {
4 | return cloneDeep(data);
5 | }
6 |
--------------------------------------------------------------------------------
/src/utilities/dashify.ts:
--------------------------------------------------------------------------------
1 | import * as dashify from "dashify";
2 |
3 | export default function(string: string) {
4 | return dashify(string);
5 | }
6 |
--------------------------------------------------------------------------------
/src/utilities/filterEmpty.ts:
--------------------------------------------------------------------------------
1 | export default function(data: object) {
2 | for (let propName in data) {
3 | if (data[propName] === null || data[propName] === undefined) {
4 | delete data[propName];
5 | }
6 | }
7 | return data;
8 | }
9 |
--------------------------------------------------------------------------------
/src/utilities/getByDot.ts:
--------------------------------------------------------------------------------
1 | export default function(data: object, path: string, defaultValue?: any) {
2 | let value = path.split(".").reduce(function(prev: object, curr: string) {
3 | return prev ? prev[curr] : undefined;
4 | }, data);
5 |
6 | return value !== undefined ? value : defaultValue;
7 | }
8 |
--------------------------------------------------------------------------------
/src/utilities/index.ts:
--------------------------------------------------------------------------------
1 | import camelize from "./camelize";
2 | import clone from "./clone";
3 | import dashify from "./dashify";
4 | import filterEmpty from "./filterEmpty";
5 | import getByDot from "./getByDot";
6 | import isEmpty from "./isEmpty";
7 | import setByDot from "./setByDot";
8 | import uncamelize from "./uncamelize";
9 |
10 | export {
11 | camelize,
12 | clone,
13 | dashify,
14 | filterEmpty,
15 | getByDot,
16 | isEmpty,
17 | setByDot,
18 | uncamelize,
19 | };
20 |
--------------------------------------------------------------------------------
/src/utilities/isEmpty.ts:
--------------------------------------------------------------------------------
1 | export default function(value: object | string | null | Array) {
2 | //check for empty object {}, array []
3 | if (value !== null && typeof value === "object") {
4 | if (Object.keys(value).length === 0) {
5 | return true;
6 | }
7 | } else if (
8 | value == null ||
9 | (typeof value === "string" && value.replace(/\s+/, "") === "")
10 | ) {
11 | //check for undefined, null and ""
12 | return true;
13 | }
14 |
15 | return false;
16 | }
17 |
--------------------------------------------------------------------------------
/src/utilities/setByDot.ts:
--------------------------------------------------------------------------------
1 | export default function(data: object, path: string, value: any) {
2 | let parts = path.split(".");
3 | return parts.reduce(function(prev: object, curr: string, ix: number) {
4 | return ix + 1 == parts.length ? (prev[curr] = value) : prev[curr] || {};
5 | }, data);
6 | }
7 |
--------------------------------------------------------------------------------
/src/utilities/uncamelize.ts:
--------------------------------------------------------------------------------
1 | export default function(string: string) {
2 | return string
3 | .replace(/([a-z])([A-Z])/g, "$1 $2")
4 | .replace(/\b([A-Z]+)([A-Z])([a-z])/, "$1 $2$3")
5 | .toLowerCase();
6 | }
7 |
--------------------------------------------------------------------------------
/src/validation/Validation.ts:
--------------------------------------------------------------------------------
1 | import isNumeric from "validator/lib/isNumeric";
2 | import { getByDot, uncamelize } from "./../utilities";
3 | import ConfigInterface from "../config/ConfigInterface";
4 |
5 | export default class Validation {
6 | public errors: object = {};
7 |
8 | protected data: object;
9 | protected configService;
10 | protected schema: object;
11 | protected messages: object;
12 | protected rules: object = {};
13 |
14 | /**
15 | * The size related validation rules.
16 | *
17 | * @var array
18 | */
19 | protected sizeRules = ["between", "min", "max", "size"];
20 |
21 | constructor(
22 | data: object,
23 | schema: object,
24 | messages: object,
25 | configService: ConfigInterface,
26 | ) {
27 | this.data = data;
28 | this.schema = schema;
29 | this.messages = messages;
30 | this.configService = configService;
31 | this.rules = this.configService.get("validation.rules");
32 | }
33 |
34 | public validate() {
35 | return this.validateSchema(this.schema);
36 | }
37 |
38 | protected validateSchema(schema: any, key?: string) {
39 | for (let field in schema) {
40 | if (typeof schema[field] === "object") {
41 | this.validateSchema(schema[field], key ? `${key}.${field}` : field);
42 | } else {
43 | let ruleField = key ? `${key}.${field}` : field;
44 | this.checkRules(ruleField, schema[field]);
45 | }
46 | }
47 | return this.errors;
48 | }
49 |
50 | protected checkRules(field: string, rules: string) {
51 | let rulesArray = rules.split("|");
52 | if (rulesArray.length) {
53 | for (let ruleIndex in rulesArray) {
54 | let tempRule = rulesArray[ruleIndex].split(":");
55 | let rule = tempRule[0];
56 | let parameters: Array = [];
57 | if (tempRule[1]) {
58 | parameters = tempRule[1].split(",");
59 | }
60 |
61 | parameters = parameters.map((parameter) => {
62 | if (parameter === "false") {
63 | return false;
64 | }
65 | if (parameter === "true") {
66 | return true;
67 | }
68 | let number = parseFloat(parameter);
69 | if (!isNaN(number)) {
70 | return number;
71 | }
72 | return parameter;
73 | });
74 |
75 | let ruleClass = this.getRule(rule);
76 | if (ruleClass === undefined) {
77 | throw `We cannot find the rule ${rule}`;
78 | }
79 |
80 | if (
81 | !ruleClass.passes(
82 | this.getValue(field),
83 | parameters,
84 | this.data,
85 | field,
86 | ) &&
87 | rule !== "nullable"
88 | ) {
89 | this.errors[field] = this.makeReplacements(
90 | this.getMessage(rule, field),
91 | rule,
92 | field,
93 | parameters,
94 | );
95 | break;
96 | }
97 |
98 | if (rule === "nullable") {
99 | break;
100 | }
101 | }
102 | }
103 | }
104 |
105 | protected getRule(rule: string) {
106 | return this.rules[rule];
107 | }
108 |
109 | protected makeReplacements(
110 | message: string,
111 | rule: string,
112 | field: string,
113 | parameters: any,
114 | ) {
115 | let ruleFunctions = this.getRule(rule);
116 | if (!message) {
117 | return `The ${field} fails the validation.`;
118 | }
119 | message = message.replace(":field", uncamelize(field.replace(".", "s ")));
120 | if (ruleFunctions.replacers) {
121 | ruleFunctions.replacers().forEach((replacer: string, index: number) => {
122 | if (parameters[index]) {
123 | message = message.replace(
124 | `:${replacer}`,
125 | typeof parameters[index] === "string"
126 | ? uncamelize(
127 | parameters[index].replace("_", " ").replace(".", "s "),
128 | )
129 | : parameters[index],
130 | );
131 | }
132 | });
133 | }
134 |
135 | if (message.indexOf(":values") > -1) {
136 | message.replace(":values", parameters.join(", "));
137 | }
138 |
139 | return message;
140 | }
141 |
142 | protected getValue(field: string) {
143 | return getByDot(this.data, field);
144 | }
145 |
146 | protected getMessage(rule: string, field: string) {
147 | let customMessage = getByDot(this.messages, field);
148 |
149 | if (customMessage) {
150 | return customMessage;
151 | }
152 |
153 | if (this.sizeRules.indexOf(rule) > -1) {
154 | return this.getSizeMessage(field, rule);
155 | }
156 |
157 | let tempRule = this.getRule(rule).message;
158 | if (tempRule) {
159 | return tempRule();
160 | }
161 |
162 | return this.getMessageFromLocale(rule);
163 | }
164 |
165 | protected getSizeMessage(field: string, rule: string) {
166 | let type = "string";
167 | let locale = this.configService.get("app.locale");
168 | let value = getByDot(this.data, field);
169 |
170 | if (typeof value === "object") {
171 | type = "file";
172 | } else if (Array.isArray(value)) {
173 | type = "array";
174 | } else if (isNumeric(value)) {
175 | type = "numeric";
176 | }
177 |
178 | return this.configService.get(`validation.${locale}.${rule}.${type}`);
179 | }
180 |
181 | protected getMessageFromLocale(rule: string) {
182 | let locale = this.configService.get("app.locale");
183 | return this.configService.get(`validation.${locale}.${rule}`);
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/src/validation/ValidationServiceInterface.ts:
--------------------------------------------------------------------------------
1 | export default interface ValidationServiceInterface {}
2 |
--------------------------------------------------------------------------------
/src/validation/ValidationServiceProvider.ts:
--------------------------------------------------------------------------------
1 | import ValidationConfig from "./config";
2 | import ServiceProvider from "../support/ServiceProvider";
3 | import VarieValidationService from "./VarieValidationService";
4 | import ValidationServiceInterface from "./ValidationServiceInterface";
5 |
6 | export default class ValidationServiceProvider extends ServiceProvider {
7 | public boot() {
8 | require("./directive/Validate");
9 | }
10 |
11 | public register() {
12 | this.mergeConfigFrom(ValidationConfig, "validation");
13 |
14 | let files = require.context("@resources/lang", true, /validation\.(ts)$/);
15 |
16 | for (let filename of files.keys()) {
17 | $config.set(
18 | `validation.${filename
19 | .replace("./", "")
20 | .split("/")
21 | .shift()}`,
22 | files(filename).default,
23 | );
24 | }
25 |
26 | this.app.singleton(
27 | "ValidationService",
28 | VarieValidationService,
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/validation/Validator.ts:
--------------------------------------------------------------------------------
1 | import Form from "../plugins/forms/Form";
2 | import { inject, injectable } from "inversify";
3 | import ValidationServiceInterface from "./ValidationServiceInterface";
4 |
5 | @injectable()
6 | export default class Validator extends Form {
7 | public rules = {};
8 | public messages = {};
9 |
10 | // TODO - should re-think how this validator is used , not a fan of how I thought of it the first time
11 | constructor(
12 | @inject("ValidationService") validationService: ValidationServiceInterface,
13 | ) {
14 | super({}, validationService);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/validation/VarieValidationService.ts:
--------------------------------------------------------------------------------
1 | import Validation from "./Validation";
2 | import { injectable, inject } from "inversify";
3 | import ValidationServiceInterface from "./ValidationServiceInterface";
4 |
5 | @injectable()
6 | export default class ValidationService implements ValidationServiceInterface {
7 | protected configService;
8 |
9 | constructor(@inject("ConfigService") configService) {
10 | this.configService = configService;
11 | }
12 |
13 | public validate(data: object, schema: object, messages = {}) {
14 | return new Validation(
15 | data,
16 | schema,
17 | messages,
18 | this.configService,
19 | ).validate();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/validation/config.ts:
--------------------------------------------------------------------------------
1 | import Rules from "./rules";
2 |
3 | export default {
4 | /*
5 | |--------------------------------------------------------------------------
6 | | Custom Rules
7 | |--------------------------------------------------------------------------
8 | |
9 | | You can supply your custom rules here
10 | |
11 | */
12 |
13 | rules: Rules,
14 | };
15 |
--------------------------------------------------------------------------------
/src/validation/directive/Validate.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Form from "../../plugins/forms/Form";
3 |
4 | function checkForErrors(formElement, form: Form) {
5 | let errors = form.errors();
6 | formElement.querySelectorAll("*[validate]").forEach((el) => {
7 | if (el.hasAttribute("touched") && errors[el.name]) {
8 | return attachError(el, errors[el.name]);
9 | }
10 | removeErrors(el);
11 | });
12 | }
13 |
14 | function attachError(el: HTMLInputElement, error) {
15 | let validationElement = getValidationErrorElement(el);
16 | if (!validationElement) {
17 | el.insertAdjacentHTML(
18 | "afterend",
19 | `${error}
`,
20 | );
21 | } else {
22 | // @ts-ignore
23 | validationElement.innerHTML = error;
24 | }
25 | }
26 |
27 | function removeErrors(el: HTMLInputElement) {
28 | let validationElement = getValidationErrorElement(el);
29 | if (validationElement) {
30 | // @ts-ignore
31 | validationElement.remove();
32 | }
33 | }
34 |
35 | function getValidationErrorElement(
36 | el: HTMLInputElement,
37 | ): HTMLInputElement | boolean {
38 | let sibling = el.nextSibling;
39 | // @ts-ignore
40 | if (sibling && sibling.classList) {
41 | // @ts-ignore
42 | return sibling.classList.contains("validation-error") && sibling;
43 | }
44 | return false;
45 | }
46 |
47 | // @ts-ignore
48 | Vue.directive("form", {
49 | inserted(formElement: HTMLInputElement, vNode) {
50 | // @ts-ignore
51 | formElement
52 | .querySelectorAll("*[validate]")
53 | // @ts-ignore
54 | .forEach((el: HTMLInputElement) => {
55 | switch (el.type) {
56 | case "radio":
57 | case "checkbox":
58 | el.onchange = () => {
59 | el.setAttribute("touched", "true");
60 | checkForErrors(formElement, vNode.value);
61 | };
62 | break;
63 | default:
64 | el.oninput = () => {
65 | checkForErrors(formElement, vNode.value);
66 | el.onblur = () => {
67 | el.setAttribute("touched", "true");
68 | checkForErrors(formElement, vNode.value);
69 | };
70 | };
71 | break;
72 | }
73 | });
74 | },
75 | });
76 |
--------------------------------------------------------------------------------
/src/validation/rules/accepted.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: any) {
3 | let validValues = ["yes", "on", 1, true];
4 |
5 | return validValues.indexOf(value) > -1;
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/src/validation/rules/after.ts:
--------------------------------------------------------------------------------
1 | import isDate from "./date";
2 | import isAfter from "validator/lib/isAfter";
3 |
4 | export default {
5 | passes(value: any, parameters: Array) {
6 | if (value && isDate.passes(value)) {
7 | return isAfter(value, parameters[0]);
8 | }
9 | return false;
10 | },
11 |
12 | replacers() {
13 | return ["date"];
14 | },
15 | };
16 |
--------------------------------------------------------------------------------
/src/validation/rules/after_or_equal.ts:
--------------------------------------------------------------------------------
1 | import isDate from "./date";
2 | import isAfter from "validator/lib/isAfter";
3 | import isBefore from "validator/lib/isBefore";
4 |
5 | export default {
6 | passes(value: any, parameters: Array) {
7 | if (value && isDate.passes(value)) {
8 | return (
9 | isAfter(value, parameters[0]) ||
10 | (!isAfter(value, parameters[0]) && !isBefore(value, parameters[0]))
11 | );
12 | }
13 | return false;
14 | },
15 |
16 | replacers() {
17 | return ["date"];
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/src/validation/rules/alpha.ts:
--------------------------------------------------------------------------------
1 | import isAlpha from "validator/lib/isAlpha";
2 |
3 | export default {
4 | passes(value: any) {
5 | return isAlpha(value);
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/src/validation/rules/alpha_num.ts:
--------------------------------------------------------------------------------
1 | import isAlphanumeric from "validator/lib/isAlphanumeric";
2 |
3 | export default {
4 | passes(value: any) {
5 | return isAlphanumeric(value);
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/src/validation/rules/array.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: any) {
3 | return Array.isArray(value);
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/src/validation/rules/before.ts:
--------------------------------------------------------------------------------
1 | import isDate from "./date";
2 | import isBefore from "validator/lib/isBefore";
3 |
4 | export default {
5 | passes(value: any, parameters: Array) {
6 | if (value && isDate.passes(value)) {
7 | return isBefore(value, parameters[0]);
8 | }
9 | return false;
10 | },
11 |
12 | replacers() {
13 | return ["date"];
14 | },
15 | };
16 |
--------------------------------------------------------------------------------
/src/validation/rules/before_or_equal.ts:
--------------------------------------------------------------------------------
1 | import isDate from "./date";
2 | import isAfter from "validator/lib/isAfter";
3 | import isBefore from "validator/lib/isBefore";
4 |
5 | export default {
6 | passes(value: any, parameters: Array) {
7 | if (value && isDate.passes(value)) {
8 | return (
9 | isBefore(value, parameters[0]) ||
10 | (!isAfter(value, parameters[0]) && !isBefore(value, parameters[0]))
11 | );
12 | }
13 | return false;
14 | },
15 |
16 | replacers() {
17 | return ["date"];
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/src/validation/rules/between.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: { size: number }, parameters: Array) {
3 | if (value) {
4 | let min = parameters[0];
5 | let max = parameters[1];
6 |
7 | if (Array.isArray(value) || typeof value === "string") {
8 | return min <= value.length && max >= value.length;
9 | } else if (typeof value === "object") {
10 | return min <= value.size / 1024 && max >= value.size / 1024;
11 | }
12 |
13 | return min <= value && max >= value;
14 | }
15 | },
16 |
17 | replacers() {
18 | return ["min", "max"];
19 | },
20 | };
21 |
--------------------------------------------------------------------------------
/src/validation/rules/boolean.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: any) {
3 | return value === true || value === false || value === 0 || value === 1;
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/src/validation/rules/confirmed.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: any, parameters: Array, formData: object, currentField) {
3 | return formData[`${currentField}_confirmation`] === value;
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/src/validation/rules/date.ts:
--------------------------------------------------------------------------------
1 | import isISO8601 from "validator/lib/isISO8601";
2 | import isRFC3339 from "validator/lib/isRFC3339";
3 |
4 | export default {
5 | passes(value: any) {
6 | if (value) {
7 | return value instanceof Date || isISO8601(value) || isRFC3339(value);
8 | }
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/src/validation/rules/different.ts:
--------------------------------------------------------------------------------
1 | import { getByDot } from "./../../utilities";
2 |
3 | export default {
4 | passes(value: any, parameters: Array, data: {}): boolean {
5 | return value !== getByDot(data, parameters[0]);
6 | },
7 |
8 | replacers() {
9 | return ["other"];
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/src/validation/rules/email.ts:
--------------------------------------------------------------------------------
1 | import isEmail from "validator/lib/isEmail";
2 |
3 | export default {
4 | passes(value: any) {
5 | return isEmail(value);
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/src/validation/rules/image.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(files: File | Array) {
3 | if (files) {
4 | if (!Array.isArray(files)) {
5 | files = [files];
6 | }
7 | let validLength = 0;
8 |
9 | let fileTypeRegex = new RegExp(/(jpg|svg|jpeg|png|bmp|gif)$/i);
10 | let fileNameRegex = new RegExp(/\.(jpg|svg|jpeg|png|bmp|gif)$/i);
11 |
12 | files.forEach((file) => {
13 | if (fileNameRegex.test(file.name) || fileTypeRegex.test(file.type)) {
14 | validLength++;
15 | }
16 | });
17 |
18 | return validLength === files.length;
19 | }
20 |
21 | return true;
22 | },
23 |
24 | replacers() {
25 | return ["values"];
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/src/validation/rules/index.ts:
--------------------------------------------------------------------------------
1 | import accepted from "./accepted";
2 | import after from "./after";
3 | import after_or_equal from "./after_or_equal";
4 | import alpha from "./alpha";
5 | import alpha_num from "./alpha_num";
6 | import array from "./array";
7 | import confirmed from "./confirmed";
8 | import before from "./before";
9 | import before_or_equal from "./before_or_equal";
10 | import between from "./between";
11 | import boolean from "./boolean";
12 | import date from "./date";
13 | import different from "./different";
14 | import email from "./email";
15 | import image from "./image";
16 | import integer from "./integer";
17 | import max from "./max";
18 | import mimetypes from "./mimetypes";
19 | import min from "./min";
20 | import nullable from "./nullable";
21 | import numeric from "./numeric";
22 | import regex from "./regex";
23 | import required from "./required";
24 | import required_if from "./required_if";
25 | import required_unless from "./required_unless";
26 | import required_with from "./required_with";
27 | import required_with_all from "./required_with_all";
28 | import required_without from "./required_without";
29 | import required_without_all from "./required_without_all";
30 | import same from "./same";
31 | import string from "./string";
32 | import size from "./size";
33 | import url from "./url";
34 |
35 | export default {
36 | accepted,
37 | after,
38 | after_or_equal,
39 | alpha,
40 | alpha_num,
41 | array,
42 | before,
43 | before_or_equal,
44 | between,
45 | boolean,
46 | confirmed,
47 | date,
48 | different,
49 | email,
50 | image,
51 | integer,
52 | max,
53 | mimetypes,
54 | min,
55 | nullable,
56 | numeric,
57 | regex,
58 | required,
59 | required_if,
60 | required_unless,
61 | required_with,
62 | required_with_all,
63 | required_without,
64 | required_without_all,
65 | same,
66 | size,
67 | string,
68 | url,
69 | };
70 |
--------------------------------------------------------------------------------
/src/validation/rules/integer.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: any) {
3 | return Number.isInteger(value);
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/src/validation/rules/max.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: { size: number }, attributes: Array) {
3 | if (value) {
4 | let max = attributes[0];
5 |
6 | if (Array.isArray(value) || typeof value === "string") {
7 | return value.length <= max;
8 | } else if (typeof value === "object") {
9 | return value.size / 1024 <= max;
10 | }
11 |
12 | return value <= max;
13 | }
14 | return true;
15 | },
16 |
17 | replacers() {
18 | return ["max", "size"];
19 | },
20 | };
21 |
--------------------------------------------------------------------------------
/src/validation/rules/mimetypes.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(files: File | Array, parameters: Array) {
3 | if (files) {
4 | if (!Array.isArray(files)) {
5 | files = [files];
6 | }
7 | let validLength = 0;
8 |
9 | const regex = new RegExp(
10 | `${parameters.join("|").replace("*", ".+")}$`,
11 | "i",
12 | );
13 |
14 | files.forEach((file) => {
15 | if (regex.test(file.type)) {
16 | validLength++;
17 | }
18 | });
19 |
20 | return validLength === files.length;
21 | }
22 |
23 | return true;
24 | },
25 |
26 | replacers() {
27 | return ["values"];
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/src/validation/rules/min.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: { size: number }, attributes: Array) {
3 | if (value) {
4 | let min = attributes[0];
5 |
6 | if (Array.isArray(value) || typeof value === "string") {
7 | return value.length >= min;
8 | } else if (typeof value === "object") {
9 | return value.size / 1024 >= min;
10 | }
11 |
12 | return value >= min;
13 | }
14 | return true;
15 | },
16 |
17 | replacers() {
18 | return ["min"];
19 | },
20 | };
21 |
--------------------------------------------------------------------------------
/src/validation/rules/nullable.ts:
--------------------------------------------------------------------------------
1 | import isEmpty from "../../utilities/isEmpty";
2 |
3 | export default {
4 | passes(value: any) {
5 | return isEmpty(value);
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/src/validation/rules/numeric.ts:
--------------------------------------------------------------------------------
1 | import isNumeric from "validator/lib/isNumeric";
2 |
3 | export default {
4 | passes(value: any) {
5 | if (typeof value === "number") {
6 | return true;
7 | }
8 | return isNumeric(value);
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/src/validation/rules/regex.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: any, parameters: Array) {
3 | let regex = parameters[0];
4 |
5 | if (regex instanceof RegExp) {
6 | return regex.test(value);
7 | } else if (typeof regex === "string") {
8 | return new RegExp(regex).test(String(value));
9 | }
10 |
11 | return false;
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/src/validation/rules/required.ts:
--------------------------------------------------------------------------------
1 | import { isEmpty } from "./../../utilities";
2 |
3 | export default {
4 | passes(value: any): boolean {
5 | return !isEmpty(value);
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/src/validation/rules/required_if.ts:
--------------------------------------------------------------------------------
1 | import { getByDot, isEmpty } from "./../../utilities";
2 |
3 | export default {
4 | passes(value: any, parameters, data: {}): boolean {
5 | if (isEmpty(value)) {
6 | let requiredValue = getByDot(data, parameters[0]);
7 | return (
8 | isEmpty(requiredValue) ||
9 | (!isEmpty(parameters[1]) && requiredValue !== parameters[1])
10 | );
11 | }
12 | return true;
13 | },
14 |
15 | replacers() {
16 | return ["other", "value"];
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/src/validation/rules/required_unless.ts:
--------------------------------------------------------------------------------
1 | import { getByDot, isEmpty } from "./../../utilities";
2 |
3 | // required_unless
4 | export default {
5 | passes(value: any, parameters: Array, data: {}): boolean {
6 | if (isEmpty(value)) {
7 | return getByDot(data, parameters[0]) === value;
8 | }
9 | return true;
10 | },
11 |
12 | replacers() {
13 | return ["other", "value"];
14 | },
15 | };
16 |
--------------------------------------------------------------------------------
/src/validation/rules/required_with.ts:
--------------------------------------------------------------------------------
1 | import { getByDot } from "./../../utilities";
2 |
3 | export default {
4 | passes(value: any, parameters: Array, data: {}): boolean {
5 | if (!value) {
6 | let required = false;
7 | parameters.forEach((parameter) => {
8 | let parameterValue = getByDot(data, parameter);
9 | if (required === true || parameterValue) {
10 | required = true;
11 | }
12 | });
13 | return !required;
14 | }
15 | return true;
16 | },
17 |
18 | replacers() {
19 | return ["values"];
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/src/validation/rules/required_with_all.ts:
--------------------------------------------------------------------------------
1 | import { getByDot } from "./../../utilities";
2 |
3 | export default {
4 | passes(value: any, parameters: Array, data: {}): boolean {
5 | if (!value) {
6 | let validLength = 0;
7 | parameters.forEach((parameter) => {
8 | let parameterValue = getByDot(data, parameter);
9 | if (parameterValue) {
10 | validLength++;
11 | }
12 | });
13 | if (validLength === parameters.length) {
14 | return false;
15 | }
16 | }
17 | return true;
18 | },
19 |
20 | replacers() {
21 | return ["values"];
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/src/validation/rules/required_without.ts:
--------------------------------------------------------------------------------
1 | import { getByDot } from "./../../utilities";
2 |
3 | export default {
4 | passes(value: any, parameters: Array, data: {}): boolean {
5 | if (!value) {
6 | let required = true;
7 | parameters.forEach((parameter) => {
8 | let parameterValue = getByDot(data, parameter);
9 | if (required === false || !parameterValue) {
10 | required = false;
11 | }
12 | });
13 |
14 | return required;
15 | }
16 | return true;
17 | },
18 |
19 | replacers() {
20 | return ["values"];
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/src/validation/rules/required_without_all.ts:
--------------------------------------------------------------------------------
1 | import { getByDot } from "./../../utilities";
2 |
3 | export default {
4 | passes(value: any, parameters: Array, data: {}): boolean {
5 | if (!value) {
6 | let validLength = 0;
7 | parameters.forEach((parameter) => {
8 | let parameterValue = getByDot(data, parameter);
9 | if (parameterValue) {
10 | validLength++;
11 | }
12 | });
13 | if (validLength === 0) {
14 | return false;
15 | }
16 | }
17 | return true;
18 | },
19 | replacers() {
20 | return ["values"];
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/src/validation/rules/same.ts:
--------------------------------------------------------------------------------
1 | import { getByDot } from "./../../utilities";
2 |
3 | export default {
4 | passes(value: any, parameters: Array, data: {}): boolean {
5 | return value === getByDot(data, parameters[0]);
6 | },
7 |
8 | replacers() {
9 | return ["other"];
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/src/validation/rules/size.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: { size: number }, attributes: Array) {
3 | if (value) {
4 | let size = attributes[0];
5 |
6 | if (Array.isArray(value) || typeof value === "string") {
7 | return value.length === size;
8 | } else if (typeof value === "object") {
9 | return value.size / 1024 === size;
10 | }
11 |
12 | return value === size;
13 | }
14 | return true;
15 | },
16 |
17 | replacers() {
18 | return ["max", "size"];
19 | },
20 | };
21 |
--------------------------------------------------------------------------------
/src/validation/rules/string.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: any): boolean {
3 | return typeof value === "string";
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/src/validation/rules/url.ts:
--------------------------------------------------------------------------------
1 | import isURL from "validator/lib/isURL";
2 |
3 | export default {
4 | passes(value: any): boolean {
5 | return isURL(value);
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/src/vue-component.d.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 |
3 | declare module "vue/types/options" {
4 | interface ComponentOptions {
5 | $inject?: Array;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/stubs/appMiddleware.ts:
--------------------------------------------------------------------------------
1 | import { injectable } from "inversify";
2 | import { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios";
3 | import HttpMiddlewareInterface from "varie/lib/http/interfaces/HttpMiddlewareInterface";
4 |
5 | @injectable()
6 | export default class temp implements HttpMiddlewareInterface {
7 | public request(config: AxiosRequestConfig) {
8 | return config;
9 | }
10 |
11 | public response(response: AxiosResponse) {
12 | return response;
13 | }
14 |
15 | public responseError(error: AxiosError) {
16 | return error;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/stubs/component.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
--------------------------------------------------------------------------------
/stubs/directive.ts:
--------------------------------------------------------------------------------
1 | // https://vuejs.org/v2/guide/custom-directive.html
2 | import Vue from "vue";
3 |
4 | Vue.directive("temp", {
5 | inserted: function(el, binding) {
6 | // ...
7 | },
8 | });
9 |
--------------------------------------------------------------------------------
/stubs/filter.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 |
3 | Vue.filter("temp", (value) => {
4 | return value;
5 | });
6 |
--------------------------------------------------------------------------------
/stubs/mixin.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 |
3 | Vue.mixin({
4 | methods: {
5 | //
6 | },
7 | computed: {
8 | //
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/stubs/model.ts:
--------------------------------------------------------------------------------
1 | import Model from "varie/lib/support/Model";
2 |
3 | export default class tempModel extends Model {
4 | protected defaults() {
5 | // ...
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/stubs/provider.ts:
--------------------------------------------------------------------------------
1 | import ServiceProvider from "varie/lib/support/ServiceProvider";
2 |
3 | /*
4 | |--------------------------------------------------------------------------
5 | | App Service Provider
6 | |--------------------------------------------------------------------------
7 | | You can bind various items to the app here, or can create other
8 | | custom providers that bind the container
9 | |
10 | */
11 | export default class tempProvider extends ServiceProvider {
12 | public async boot() {
13 | // ...
14 | }
15 |
16 | public async register() {
17 | // ...
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/stubs/routeMiddleware.ts:
--------------------------------------------------------------------------------
1 | import { Route, Location } from "vue-router";
2 | import { injectable, inject } from "inversify";
3 | import RouteMiddlewareInterface from "varie/lib/routing/RouteMiddlewareInterface";
4 |
5 | @injectable()
6 | export default class temp implements RouteMiddlewareInterface {
7 | handler(to: Route, from: Route, next: (route?: Location) => void) {
8 | next();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/stubs/rule.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | passes(value: any, parameters = [], data: {}) {
3 | return true;
4 | },
5 |
6 | message() {
7 | return "This :field has this message to display";
8 | },
9 | };
10 |
--------------------------------------------------------------------------------
/stubs/service.ts:
--------------------------------------------------------------------------------
1 | import { injectable, inject } from "inversify";
2 | import ConfigInterface from "varie/lib/config/ConfigInterface";
3 |
4 | @injectable()
5 | export default class BroadcastService {
6 | protected configService: ConfigInterface;
7 |
8 | constructor(@inject("ConfigService") configService) {
9 | this.configService = configService;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/stubs/store/actions.ts:
--------------------------------------------------------------------------------
1 | import { ActionContext } from "vuex";
2 | import RootState from "@store/rootState";
3 | import { tempState } from "./stateInterface";
4 |
5 | export default function(httpService) {
6 | return {
7 | sampleAction: (context: ActionContext, data) => {
8 | return httpService.post("/some-url", {
9 | data,
10 | });
11 | },
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/stubs/store/getters.ts:
--------------------------------------------------------------------------------
1 | import { tempState } from "./stateInterface";
2 |
3 | export default function() {
4 | return {
5 | SAMPLE_GETTER: (state: tempState) => {
6 | return state;
7 | },
8 | };
9 | }
10 |
--------------------------------------------------------------------------------
/stubs/store/index.ts:
--------------------------------------------------------------------------------
1 | import state from "./state";
2 | import actions from "./actions";
3 | import getters from "./getters";
4 | import mutations from "./mutations";
5 | import StoreModule from "varie/lib/state/StoreModule";
6 | import { injectable, inject, unmanaged } from "inversify";
7 |
8 | @injectable()
9 | export default class temp extends StoreModule {
10 | constructor(@inject("HttpService") httpService) {
11 | super();
12 | this.setName("store_name")
13 | .addState(state)
14 | .addActions(actions(httpService))
15 | .addMutations(mutations)
16 | .addGetters(getters);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/stubs/store/mutations.ts:
--------------------------------------------------------------------------------
1 | import { tempState } from "./stateInterface";
2 |
3 | export default function() {
4 | return {
5 | SAMPLE_MUTATION: (state: tempState, data) => {},
6 | };
7 | }
8 |
--------------------------------------------------------------------------------
/stubs/store/state.ts:
--------------------------------------------------------------------------------
1 | export default {};
2 |
--------------------------------------------------------------------------------
/stubs/store/stateInterface.ts:
--------------------------------------------------------------------------------
1 | export interface tempState {}
2 |
--------------------------------------------------------------------------------
/stubs/validator.ts:
--------------------------------------------------------------------------------
1 | import { injectable } from "inversify";
2 | import Validator from "varie/lib/validation/Validator";
3 |
4 | @injectable()
5 | export default class temp extends Validator {
6 | public rules = {
7 | //
8 | };
9 |
10 | public messages = {
11 | //
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "outDir": "./lib/",
5 | "moduleResolution": "node",
6 | "lib": ["es6", "dom", "dom.iterable"],
7 | "target": "es5",
8 | "strict": true,
9 | "types": [
10 | "vue",
11 | "vuex",
12 | "node",
13 | "validator",
14 | "vue-router",
15 | "webpack-env",
16 | "reflect-metadata"
17 | ],
18 | "declaration": true,
19 | "noImplicitAny": false,
20 | "inlineSourceMap": true,
21 | "emitDecoratorMetadata": true,
22 | "experimentalDecorators": true,
23 | "allowSyntheticDefaultImports": true
24 | },
25 | "include": ["src/**/*"]
26 | }
27 |
--------------------------------------------------------------------------------