@simtlix/simfinity-js 1.5.0 → 1.6.0
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 +1100 -8
- package/eslint.config.mjs +29 -21
- package/package.json +6 -23
- package/src/const/QLOperator.js +2 -4
- package/src/const/QLSort.js +3 -5
- package/src/const/QLValue.js +2 -4
- package/src/errors/internal-server.error.js +2 -2
- package/src/errors/simfinity.error.js +1 -1
- package/src/index.js +29 -31
- package/tests/prevent-collection-creation.test.js +7 -6
- package/tests/validated-scalar.test.js +7 -4
package/eslint.config.mjs
CHANGED
|
@@ -16,48 +16,56 @@ export default [
|
|
|
16
16
|
{
|
|
17
17
|
ignores: ["node_modules/*", "data/*", "eslint.config.mjs"],
|
|
18
18
|
},
|
|
19
|
-
|
|
19
|
+
js.configs.recommended,
|
|
20
20
|
{
|
|
21
21
|
files: ["**/*.js"],
|
|
22
22
|
languageOptions: {
|
|
23
23
|
globals: {
|
|
24
|
-
...globals.commonjs,
|
|
25
24
|
...globals.node,
|
|
26
|
-
...globals.
|
|
25
|
+
...globals.es2024,
|
|
27
26
|
},
|
|
28
|
-
|
|
29
27
|
ecmaVersion: 2024,
|
|
30
|
-
sourceType: "
|
|
28
|
+
sourceType: "module",
|
|
31
29
|
},
|
|
32
|
-
|
|
33
30
|
rules: {
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
31
|
+
// Code style and best practices (relaxed to match existing code)
|
|
32
|
+
"quotes": ["error", "single"],
|
|
33
|
+
"semi": ["error", "always"],
|
|
34
|
+
"comma-dangle": ["error", "always-multiline"],
|
|
35
|
+
"object-curly-spacing": ["error", "always"],
|
|
36
|
+
"array-bracket-spacing": ["error", "never"],
|
|
37
|
+
|
|
38
|
+
// ES6+ features
|
|
39
|
+
"prefer-const": "error",
|
|
40
|
+
"no-var": "error",
|
|
41
|
+
"prefer-arrow-callback": "off", // Allow function declarations
|
|
42
|
+
"arrow-spacing": "error",
|
|
43
|
+
|
|
44
|
+
// Best practices
|
|
45
|
+
"no-console": "off", // Allow console for this project
|
|
46
|
+
"no-underscore-dangle": "off", // Allow underscore dangle for MongoDB _id
|
|
38
47
|
"no-await-in-loop": "off",
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
"max-len": "off", // Disable max-len for now
|
|
49
|
+
"indent": "off", // Disable indent for now to match existing style
|
|
50
|
+
|
|
51
|
+
// Parameter reassignment (common in GraphQL resolvers)
|
|
52
|
+
"no-param-reassign": ["error", { "props": false }],
|
|
53
|
+
|
|
54
|
+
// Function formatting
|
|
44
55
|
"function-paren-newline": "off",
|
|
45
56
|
"function-call-argument-newline": "off",
|
|
46
|
-
|
|
57
|
+
|
|
58
|
+
// Restricted syntax
|
|
47
59
|
"no-restricted-syntax": ["error", {
|
|
48
60
|
selector: "ForInStatement",
|
|
49
61
|
message: "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.",
|
|
50
62
|
}, {
|
|
51
|
-
selector: "LabeledStatement",
|
|
63
|
+
selector: "LabeledStatement",
|
|
52
64
|
message: "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.",
|
|
53
65
|
}, {
|
|
54
66
|
selector: "WithStatement",
|
|
55
67
|
message: "`with` is disallowed in strict mode because it makes code impossible to predict and optimize.",
|
|
56
68
|
}],
|
|
57
|
-
|
|
58
|
-
"import/no-unresolved": ["error", {
|
|
59
|
-
ignore: ["graphql", "mongoose"],
|
|
60
|
-
}],
|
|
61
69
|
},
|
|
62
70
|
},
|
|
63
71
|
];
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simtlix/simfinity-js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"scripts": {
|
|
7
|
-
"test": "
|
|
8
|
-
"test:watch": "
|
|
9
|
-
"test:coverage": "
|
|
8
|
+
"test": "vitest run",
|
|
9
|
+
"test:watch": "vitest",
|
|
10
|
+
"test:coverage": "vitest --coverage",
|
|
10
11
|
"lint": "eslint '**/*.js'",
|
|
11
12
|
"lint-fix": "eslint --fix '**/*.js'"
|
|
12
13
|
},
|
|
@@ -24,34 +25,16 @@
|
|
|
24
25
|
"mongoose": "^8.16.2"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
|
-
"@eslint/compat": "^1.2.0",
|
|
28
|
-
"@eslint/eslintrc": "^3.1.0",
|
|
29
28
|
"@eslint/js": "^9.30.1",
|
|
30
29
|
"eslint": "^9.30.1",
|
|
31
|
-
"eslint-config-airbnb-base": "^15.0.0",
|
|
32
|
-
"eslint-plugin-import": "^2.32.0",
|
|
33
|
-
"ghooks": "^2.0.4",
|
|
34
30
|
"globals": "^16.3.0",
|
|
35
|
-
"
|
|
31
|
+
"vitest": "^3.2.4"
|
|
36
32
|
},
|
|
37
33
|
"config": {
|
|
38
|
-
"ghooks": {
|
|
39
|
-
"pre-commit": "npm run lint || npm run lint-fix"
|
|
40
|
-
},
|
|
41
34
|
"owner": "simtlix"
|
|
42
35
|
},
|
|
43
36
|
"optionalDependencies": {
|
|
44
37
|
"graphql": "^16.11.0",
|
|
45
38
|
"mongoose": "^8.16.2"
|
|
46
|
-
},
|
|
47
|
-
"jest": {
|
|
48
|
-
"testEnvironment": "node",
|
|
49
|
-
"testMatch": [
|
|
50
|
-
"**/tests/**/*.test.js"
|
|
51
|
-
],
|
|
52
|
-
"collectCoverageFrom": [
|
|
53
|
-
"src/**/*.js",
|
|
54
|
-
"!src/index.js"
|
|
55
|
-
]
|
|
56
39
|
}
|
|
57
40
|
}
|
package/src/const/QLOperator.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { GraphQLEnumType } = graphql;
|
|
1
|
+
import { GraphQLEnumType } from 'graphql';
|
|
4
2
|
|
|
5
3
|
const QLOperator = new GraphQLEnumType({
|
|
6
4
|
name: 'QLOperator',
|
|
@@ -38,4 +36,4 @@ const QLOperator = new GraphQLEnumType({
|
|
|
38
36
|
},
|
|
39
37
|
});
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
export default QLOperator;
|
package/src/const/QLSort.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const {
|
|
1
|
+
import {
|
|
4
2
|
GraphQLInputObjectType,
|
|
5
3
|
GraphQLNonNull,
|
|
6
4
|
GraphQLEnumType,
|
|
7
5
|
GraphQLString,
|
|
8
|
-
}
|
|
6
|
+
} from 'graphql';
|
|
9
7
|
|
|
10
8
|
const QLSortOrder = new GraphQLEnumType({
|
|
11
9
|
name: 'QLSortOrder',
|
|
@@ -27,4 +25,4 @@ const QLSort = new GraphQLInputObjectType({
|
|
|
27
25
|
}),
|
|
28
26
|
});
|
|
29
27
|
|
|
30
|
-
|
|
28
|
+
export default QLSort;
|
package/src/const/QLValue.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { GraphQLScalarType, Kind } = graphql;
|
|
1
|
+
import { GraphQLScalarType, Kind } from 'graphql';
|
|
4
2
|
|
|
5
3
|
function parseQLValue(value) {
|
|
6
4
|
return value;
|
|
@@ -38,4 +36,4 @@ const QLValue = new GraphQLScalarType({
|
|
|
38
36
|
},
|
|
39
37
|
});
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
export default QLValue;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import SimfinityError from './simfinity.error.js';
|
|
2
2
|
|
|
3
3
|
class InternalServerError extends SimfinityError {
|
|
4
4
|
constructor(message, cause) {
|
|
@@ -8,4 +8,4 @@ class InternalServerError extends SimfinityError {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
export default InternalServerError;
|
package/src/index.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
const mongoose = require('mongoose');
|
|
3
|
-
|
|
4
|
-
const SimfinityError = require('./errors/simfinity.error');
|
|
5
|
-
const InternalServerError = require('./errors/internal-server.error');
|
|
6
|
-
const QLOperator = require('./const/QLOperator');
|
|
7
|
-
const QLValue = require('./const/QLValue');
|
|
8
|
-
const QLSort = require('./const/QLSort');
|
|
9
|
-
|
|
10
|
-
mongoose.set('strictQuery', false);
|
|
11
|
-
|
|
12
|
-
const {
|
|
1
|
+
import {
|
|
13
2
|
GraphQLObjectType, GraphQLString, GraphQLID, GraphQLSchema, GraphQLList,
|
|
14
3
|
GraphQLNonNull, GraphQLInputObjectType, GraphQLScalarType, __Field,
|
|
15
4
|
GraphQLInt, GraphQLEnumType, GraphQLBoolean, GraphQLFloat, Kind,
|
|
16
|
-
}
|
|
5
|
+
} from 'graphql';
|
|
6
|
+
import mongoose from 'mongoose';
|
|
7
|
+
|
|
8
|
+
import SimfinityError from './errors/simfinity.error.js';
|
|
9
|
+
import InternalServerError from './errors/internal-server.error.js';
|
|
10
|
+
import QLOperator from './const/QLOperator.js';
|
|
11
|
+
import QLValue from './const/QLValue.js';
|
|
12
|
+
import QLSort from './const/QLSort.js';
|
|
13
|
+
|
|
14
|
+
mongoose.set('strictQuery', false);
|
|
17
15
|
|
|
18
16
|
// Adding 'extensions' field into instronspection query
|
|
19
17
|
const RelationType = new GraphQLObjectType({
|
|
@@ -83,19 +81,19 @@ const buildErrorFormatter = (callback) => {
|
|
|
83
81
|
|
|
84
82
|
const middlewares = [];
|
|
85
83
|
|
|
86
|
-
|
|
84
|
+
export const use = (middleware) => {
|
|
87
85
|
middlewares.push(middleware);
|
|
88
86
|
};
|
|
89
87
|
|
|
90
|
-
|
|
88
|
+
export { buildErrorFormatter };
|
|
91
89
|
|
|
92
|
-
|
|
90
|
+
export { SimfinityError };
|
|
93
91
|
|
|
94
|
-
|
|
92
|
+
export { InternalServerError };
|
|
95
93
|
|
|
96
94
|
let preventCollectionCreation = false;
|
|
97
95
|
|
|
98
|
-
|
|
96
|
+
export const preventCreatingCollection = (prevent) => {
|
|
99
97
|
preventCollectionCreation = !!prevent;
|
|
100
98
|
};
|
|
101
99
|
|
|
@@ -416,7 +414,7 @@ const buildInputType = (gqltype) => {
|
|
|
416
414
|
|
|
417
415
|
const getInputType = (type) => typesDict.types[type.name].inputType;
|
|
418
416
|
|
|
419
|
-
|
|
417
|
+
export { getInputType };
|
|
420
418
|
|
|
421
419
|
const buildPendingInputTypes = (waitingForInputType) => {
|
|
422
420
|
const stillWaitingInputType = {};
|
|
@@ -549,17 +547,17 @@ const iterateonCollectionFields = async (materializedModel, gqltype, objectId, s
|
|
|
549
547
|
for (const [collectionFieldKey, collectionField] of
|
|
550
548
|
Object.entries(materializedModel.collectionFields)) {
|
|
551
549
|
if (collectionField.added) {
|
|
552
|
-
|
|
550
|
+
|
|
553
551
|
await executeItemFunction(gqltype, collectionFieldKey, objectId, session,
|
|
554
552
|
collectionField.added, operations.SAVE);
|
|
555
553
|
}
|
|
556
554
|
if (collectionField.updated) {
|
|
557
|
-
|
|
555
|
+
|
|
558
556
|
await executeItemFunction(gqltype, collectionFieldKey, objectId, session,
|
|
559
557
|
collectionField.updated, operations.UPDATE);
|
|
560
558
|
}
|
|
561
559
|
if (collectionField.deleted) {
|
|
562
|
-
|
|
560
|
+
|
|
563
561
|
await executeItemFunction(gqltype, collectionFieldKey, objectId, session,
|
|
564
562
|
collectionField.deleted, operations.DELETE);
|
|
565
563
|
}
|
|
@@ -681,7 +679,7 @@ const onSaveObject = async (Model, gqltype, controller, args, session, linkToPar
|
|
|
681
679
|
return result;
|
|
682
680
|
};
|
|
683
681
|
|
|
684
|
-
|
|
682
|
+
export const saveObject = async (typeName, args, session) => {
|
|
685
683
|
const type = typesDict.types[typeName];
|
|
686
684
|
return onSaveObject(type.model, type.gqltype, type.controller, args, session);
|
|
687
685
|
};
|
|
@@ -1389,9 +1387,9 @@ const buildQuery = async (input, gqltype, isCount) => {
|
|
|
1389
1387
|
|
|
1390
1388
|
if (sort.field.indexOf('.') >= 0) {
|
|
1391
1389
|
const sortParts = sort.field.split('.');
|
|
1392
|
-
|
|
1390
|
+
|
|
1393
1391
|
fixedSortField = sortParts[0];
|
|
1394
|
-
|
|
1392
|
+
|
|
1395
1393
|
for (let i = 1; i < sortParts.length - 1; i++) {
|
|
1396
1394
|
fixedSortField += `_${sortParts[i]}`;
|
|
1397
1395
|
}
|
|
@@ -1536,15 +1534,15 @@ const buildRootQuery = (name, includedTypes) => {
|
|
|
1536
1534
|
|
|
1537
1535
|
/* Creating a new GraphQL Schema, with options query which defines query
|
|
1538
1536
|
we will allow users to use when they are making request. */
|
|
1539
|
-
|
|
1537
|
+
export const createSchema = (includedQueryTypes,
|
|
1540
1538
|
includedMutationTypes, includedCustomMutations) => new GraphQLSchema({
|
|
1541
1539
|
query: buildRootQuery('RootQueryType', includedQueryTypes),
|
|
1542
1540
|
mutation: buildMutation('Mutation', includedMutationTypes, includedCustomMutations),
|
|
1543
1541
|
});
|
|
1544
1542
|
|
|
1545
|
-
|
|
1543
|
+
export const getModel = (gqltype) => typesDict.types[gqltype.name].model;
|
|
1546
1544
|
|
|
1547
|
-
|
|
1545
|
+
export const registerMutation = (name, description, inputModel, outputModel, callback) => {
|
|
1548
1546
|
registeredMutations[name] = {
|
|
1549
1547
|
description,
|
|
1550
1548
|
inputModel,
|
|
@@ -1602,7 +1600,7 @@ const autoGenerateResolvers = (gqltype) => {
|
|
|
1602
1600
|
}
|
|
1603
1601
|
};
|
|
1604
1602
|
|
|
1605
|
-
|
|
1603
|
+
export const connect = (model, gqltype, simpleEntityEndpointName,
|
|
1606
1604
|
listEntitiesEndpointName, controller, onModelCreated, stateMachine) => {
|
|
1607
1605
|
waitingInputType[gqltype.name] = {
|
|
1608
1606
|
model,
|
|
@@ -1624,7 +1622,7 @@ module.exports.connect = (model, gqltype, simpleEntityEndpointName,
|
|
|
1624
1622
|
autoGenerateResolvers(gqltype);
|
|
1625
1623
|
};
|
|
1626
1624
|
|
|
1627
|
-
|
|
1625
|
+
export const addNoEndpointType = (gqltype) => {
|
|
1628
1626
|
waitingInputType[gqltype.name] = {
|
|
1629
1627
|
gqltype,
|
|
1630
1628
|
};
|
|
@@ -1655,4 +1653,4 @@ module.exports.addNoEndpointType = (gqltype) => {
|
|
|
1655
1653
|
autoGenerateResolvers(gqltype);
|
|
1656
1654
|
};
|
|
1657
1655
|
|
|
1658
|
-
|
|
1656
|
+
export { createValidatedScalar };
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
describe, test, expect, beforeEach, afterEach, vi,
|
|
3
|
+
} from 'vitest';
|
|
4
|
+
import mongoose from 'mongoose';
|
|
5
|
+
import { GraphQLObjectType, GraphQLString, GraphQLID } from 'graphql';
|
|
6
|
+
import * as simfinity from '../src/index.js';
|
|
4
7
|
|
|
5
8
|
describe('preventCreatingCollection option', () => {
|
|
6
9
|
let createCollectionSpy;
|
|
7
10
|
|
|
8
11
|
beforeEach(() => {
|
|
9
|
-
// Reset modules to have a clean state for each test
|
|
10
|
-
jest.resetModules();
|
|
11
12
|
// Spy on the createCollection method of the mongoose model prototype
|
|
12
|
-
createCollectionSpy =
|
|
13
|
+
createCollectionSpy = vi.spyOn(mongoose.Model, 'createCollection').mockImplementation(() => Promise.resolve());
|
|
13
14
|
});
|
|
14
15
|
|
|
15
16
|
afterEach(() => {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import {
|
|
2
|
+
describe, test, expect, beforeAll,
|
|
3
|
+
} from 'vitest';
|
|
4
|
+
import {
|
|
2
5
|
GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLID, GraphQLList, GraphQLNonNull,
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
} from 'graphql';
|
|
7
|
+
import { createValidatedScalar } from '../src/index.js';
|
|
8
|
+
import * as simfinity from '../src/index.js';
|
|
6
9
|
|
|
7
10
|
describe('Custom Validated Scalar Types', () => {
|
|
8
11
|
let EmailScalar;
|