jaypie 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,7 +34,7 @@ Does NOT use Kubernetes, Docker, Terraform, or the "Serverless" framework.
34
34
 
35
35
  #### Eject Anything ⏏️
36
36
 
37
- Jaypie embraces "ejectability," the philosophy that any part of the framework can be removed (and therefore replaced) without disturbing the whole.
37
+ Jaypie embraces "ejectability," the philosophy that any part of the code can be removed (and therefore replaced) without disturbing the whole.
38
38
 
39
39
  #### Mock Everywhere 🎴
40
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaypie",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "author": "Finlayson Studio",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -12,10 +12,12 @@
12
12
  "lint": "eslint .",
13
13
  "new": "hygen jaypie vite",
14
14
  "test": "vitest",
15
- "test:spec:index": "vitest run ./src/__tests__/index.spec.js"
15
+ "test:spec:dynamicExport.function": "vitest run ./src/__tests__/dynamicExport.function.spec.js",
16
+ "test:spec:index": "vitest run ./src/__tests__/index.spec.js",
17
+ "test:spec:mongoose.package": "vitest run ./src/__tests__/mongoose.package.spec.js"
16
18
  },
17
19
  "dependencies": {
18
- "@jaypie/core": "^0.3.3"
20
+ "@jaypie/core": "^0.4.0"
19
21
  },
20
22
  "devDependencies": {
21
23
  "eslint": "^8.57.0",
@@ -28,5 +30,21 @@
28
30
  "prettier": "^3.2.5",
29
31
  "sort-package-json": "^2.8.0",
30
32
  "vitest": "^1.4.0"
33
+ },
34
+ "peerDependencies": {
35
+ "@jaypie/aws": "^0.1.1",
36
+ "@jaypie/lambda": "^0.1.1",
37
+ "@jaypie/mongoose": "^0.1.1"
38
+ },
39
+ "peerDependenciesMeta": {
40
+ "@jaypie/aws": {
41
+ "optional": true
42
+ },
43
+ "@jaypie/lambda": {
44
+ "optional": true
45
+ },
46
+ "@jaypie/mongoose": {
47
+ "optional": true
48
+ }
31
49
  }
32
50
  }
@@ -0,0 +1,110 @@
1
+ import {
2
+ afterEach,
3
+ beforeAll,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ it,
8
+ vi,
9
+ } from "vitest";
10
+
11
+ // Subject
12
+ import dynamicExport from "../dynamicExport.function.js";
13
+
14
+ //
15
+ //
16
+ // Mock constants
17
+ //
18
+
19
+ const MOCK = {
20
+ MODULE: "mock-module",
21
+ };
22
+
23
+ //
24
+ //
25
+ // Mock environment
26
+ //
27
+
28
+ const DEFAULT_ENV = process.env;
29
+ beforeEach(() => {
30
+ process.env = { ...process.env };
31
+ });
32
+ afterEach(() => {
33
+ process.env = DEFAULT_ENV;
34
+ vi.clearAllMocks();
35
+ });
36
+
37
+ //
38
+ //
39
+ // Run tests
40
+ //
41
+
42
+ describe("Dynamic Export Function", () => {
43
+ it("Is a function", () => {
44
+ expect(dynamicExport).toBeFunction();
45
+ });
46
+ describe("Error Handling", () => {
47
+ it("Throws if exports is not an array", () => {
48
+ expect(() => dynamicExport({ exports: "string" })).toThrow();
49
+ });
50
+ it("Throws if exports is an empty array", () => {
51
+ expect(() => dynamicExport({ exports: [] })).toThrow();
52
+ });
53
+ it("Throws if moduleImport is not a string", () => {
54
+ expect(() => dynamicExport({ moduleImport: 123 })).toThrow();
55
+ });
56
+ });
57
+ describe("Happy Path", () => {
58
+ it("Returns an object", () => {
59
+ expect(dynamicExport({ moduleImport: MOCK.MODULE })).toBeObject();
60
+ });
61
+ it("Returns an object with the exports", () => {
62
+ const exports = ["default", "named"];
63
+ const result = dynamicExport({ exports, moduleImport: MOCK.MODULE });
64
+ expect(result).toContainKeys(exports);
65
+ });
66
+ it("Returns an object with the exports as functions", () => {
67
+ const exports = ["default", "named"];
68
+ const result = dynamicExport({ exports, moduleImport: MOCK.MODULE });
69
+ expect(result.default).toBeFunction();
70
+ expect(result.named).toBeFunction();
71
+ });
72
+ it("Exported functions throw if the real module is not installed", async () => {
73
+ const exports = ["default"];
74
+ const result = dynamicExport({ exports, moduleImport: MOCK.MODULE });
75
+ await expect(result.default()).rejects.toThrow();
76
+ });
77
+ });
78
+ describe("Features", () => {
79
+ const mockDefaultFunction = vi.fn();
80
+ const mockNamedFunction = vi.fn();
81
+ const mockScalar = "scalar";
82
+ beforeAll(() => {
83
+ vi.doMock(MOCK.MODULE, () => {
84
+ return {
85
+ default: mockDefaultFunction,
86
+ named: mockNamedFunction,
87
+ scalar: mockScalar,
88
+ };
89
+ });
90
+ });
91
+ it("Calls the default function", async () => {
92
+ const exports = ["default", "named"];
93
+ const result = dynamicExport({ exports, moduleImport: MOCK.MODULE });
94
+ await result.default();
95
+ expect(mockDefaultFunction).toHaveBeenCalled();
96
+ });
97
+ it("Calls the named function", async () => {
98
+ const exports = ["default", "named"];
99
+ const result = dynamicExport({ exports, moduleImport: MOCK.MODULE });
100
+ await result.named();
101
+ expect(mockNamedFunction).toHaveBeenCalled();
102
+ });
103
+ it.todo("Returns the scalar", async () => {
104
+ const exports = ["scalar"];
105
+ const result = dynamicExport({ exports, moduleImport: MOCK.MODULE });
106
+ expect(result.scalar).not.toBeFunction();
107
+ expect(result.scalar).toBe(mockScalar);
108
+ });
109
+ });
110
+ });
@@ -0,0 +1,81 @@
1
+ import {
2
+ afterEach,
3
+ beforeAll,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ it,
8
+ vi,
9
+ } from "vitest";
10
+
11
+ // Subject
12
+ import { connectFromSecretEnv, disconnect } from "../mongoose.package.js";
13
+
14
+ //
15
+ //
16
+ // Mock constants
17
+ //
18
+
19
+ //
20
+ //
21
+ // Mock modules
22
+ //
23
+
24
+ //
25
+ //
26
+ // Mock environment
27
+ //
28
+
29
+ const DEFAULT_ENV = process.env;
30
+ beforeEach(() => {
31
+ process.env = { ...process.env };
32
+ });
33
+ afterEach(() => {
34
+ process.env = DEFAULT_ENV;
35
+ vi.clearAllMocks();
36
+ });
37
+
38
+ //
39
+ //
40
+ // Run tests
41
+ //
42
+
43
+ describe("Mongoose Package", () => {
44
+ it("Works", () => {
45
+ expect(connectFromSecretEnv).toBeFunction();
46
+ expect(disconnect).toBeFunction();
47
+ });
48
+ describe("Error Handling", () => {
49
+ it("Throws a configuration error if Mongoose is not installed", async () => {
50
+ try {
51
+ await connectFromSecretEnv();
52
+ } catch (error) {
53
+ expect(error.isProjectError).toBeTrue();
54
+ }
55
+ expect.assertions(1);
56
+ });
57
+ });
58
+ describe("Features", () => {
59
+ const mockConnectFromSecretEnv = vi.fn();
60
+ const mockDisconnect = vi.fn();
61
+ beforeAll(() => {
62
+ vi.doMock("@jaypie/mongoose", () => {
63
+ return {
64
+ connectFromSecretEnv: mockConnectFromSecretEnv,
65
+ disconnect: mockDisconnect,
66
+ mongoose: {
67
+ disconnect: mockDisconnect,
68
+ },
69
+ };
70
+ });
71
+ });
72
+ it("Calls @jaypie/mongoose for connectFromSecretEnv", async () => {
73
+ await connectFromSecretEnv();
74
+ expect(mockConnectFromSecretEnv).toHaveBeenCalled();
75
+ });
76
+ it("Calls @jaypie/mongoose for disconnect", async () => {
77
+ await disconnect();
78
+ expect(mockDisconnect).toHaveBeenCalled();
79
+ });
80
+ });
81
+ });
@@ -0,0 +1,12 @@
1
+ import { JAYPIE } from "@jaypie/core";
2
+ import dynamicExport from "./dynamicExport.function.js";
3
+
4
+ //
5
+ //
6
+ // Export
7
+ //
8
+
9
+ export const { getSecret } = dynamicExport({
10
+ exports: ["getSecret"],
11
+ moduleImport: JAYPIE.LIB.AWS,
12
+ });
@@ -0,0 +1,55 @@
1
+ import { ConfigurationError, JAYPIE, moduleLogger } from "@jaypie/core";
2
+
3
+ //
4
+ //
5
+ // Helper Functions
6
+ //
7
+
8
+ let _importedModule;
9
+ async function dynamicImport(module) {
10
+ if (!_importedModule) {
11
+ try {
12
+ // eslint-disable-next-line import/no-unresolved
13
+ _importedModule = await import(module);
14
+ } catch (error) {
15
+ moduleLogger
16
+ .with({ lib: JAYPIE.LIB.JAYPIE })
17
+ .error(`[jaypie] ${module} could not be imported`);
18
+ if (process.env.NODE_ENV === "test") {
19
+ if (!_importedModule) {
20
+ // eslint-disable-next-line no-console
21
+ console.warn(
22
+ `[jaypie] Caught error importing ${module} -- Is it installed?`,
23
+ );
24
+ }
25
+ // eslint-disable-next-line no-console
26
+ console.error(error);
27
+ }
28
+ throw new ConfigurationError();
29
+ }
30
+ }
31
+ return _importedModule;
32
+ }
33
+
34
+ //
35
+ //
36
+ // Main
37
+ //
38
+
39
+ export default ({ exports = ["default"], moduleImport } = {}) => {
40
+ // Validate
41
+ if (Array.isArray(exports) && !exports.length) {
42
+ throw new ConfigurationError();
43
+ }
44
+ if (!moduleImport || typeof moduleImport !== "string") {
45
+ throw new ConfigurationError();
46
+ }
47
+ // Setup
48
+ return exports.reduce((acc, key) => {
49
+ acc[key] = async () => {
50
+ const imported = await dynamicImport(moduleImport);
51
+ return await imported[key]();
52
+ };
53
+ return acc;
54
+ }, {});
55
+ };
package/src/index.js CHANGED
@@ -4,3 +4,7 @@
4
4
  //
5
5
 
6
6
  export * from "@jaypie/core";
7
+
8
+ export * from "./aws.package.js";
9
+ export * from "./lambda.package.js";
10
+ export * from "./mongoose.package.js";
@@ -0,0 +1,12 @@
1
+ import { JAYPIE } from "@jaypie/core";
2
+ import dynamicExport from "./dynamicExport.function.js";
3
+
4
+ //
5
+ //
6
+ // Export
7
+ //
8
+
9
+ export const { lambdaHandler } = dynamicExport({
10
+ exports: ["lambdaHandler"],
11
+ moduleImport: JAYPIE.LIB.LAMBDA,
12
+ });
@@ -0,0 +1,12 @@
1
+ import { JAYPIE } from "@jaypie/core";
2
+ import dynamicExport from "./dynamicExport.function.js";
3
+
4
+ //
5
+ //
6
+ // Export
7
+ //
8
+
9
+ export const { connectFromSecretEnv, disconnect } = dynamicExport({
10
+ exports: ["connectFromSecretEnv", "disconnect"],
11
+ moduleImport: JAYPIE.LIB.MONGOOSE,
12
+ });