@simtlix/simfinity-js 1.6.0 → 1.7.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 +271 -0
- package/package.json +1 -1
- package/src/index.js +25 -10
package/README.md
CHANGED
|
@@ -1232,6 +1232,11 @@ const newBook = await simfinity.saveObject('Book', {
|
|
|
1232
1232
|
const BookModel = simfinity.getModel(BookType);
|
|
1233
1233
|
const books = await BookModel.find({ author: 'Douglas Adams' });
|
|
1234
1234
|
|
|
1235
|
+
// Get the GraphQL type definition by name
|
|
1236
|
+
const UserType = simfinity.getType('User');
|
|
1237
|
+
console.log(UserType.name); // 'User'
|
|
1238
|
+
console.log(UserType.getFields()); // Access GraphQL fields
|
|
1239
|
+
|
|
1235
1240
|
// Get the input type for a GraphQL type
|
|
1236
1241
|
const BookInput = simfinity.getInputType(BookType);
|
|
1237
1242
|
```
|
|
@@ -2122,4 +2127,270 @@ When the plugin is correctly set up, your GraphQL response will include the coun
|
|
|
2122
2127
|
|
|
2123
2128
|
This setup allows you to efficiently manage and display pagination information in your GraphQL applications.
|
|
2124
2129
|
|
|
2130
|
+
## 📖 API Reference
|
|
2131
|
+
|
|
2132
|
+
Simfinity.js provides several utility methods for programmatic access to your GraphQL types and data:
|
|
2133
|
+
|
|
2134
|
+
### `getType(typeName)`
|
|
2135
|
+
|
|
2136
|
+
Retrieves a GraphQL type definition from the internal types registry.
|
|
2137
|
+
|
|
2138
|
+
**Parameters:**
|
|
2139
|
+
- `typeName` (string | GraphQLObjectType): The name of the type or a GraphQL type object
|
|
2140
|
+
|
|
2141
|
+
**Returns:**
|
|
2142
|
+
- `GraphQLObjectType | null`: The GraphQL type definition, or null if not found
|
|
2143
|
+
|
|
2144
|
+
**Examples:**
|
|
2145
|
+
|
|
2146
|
+
```javascript
|
|
2147
|
+
import { getType } from '@simtlix/simfinity-js';
|
|
2148
|
+
|
|
2149
|
+
// Get type by string name
|
|
2150
|
+
const UserType = getType('User');
|
|
2151
|
+
if (UserType) {
|
|
2152
|
+
console.log(UserType.name); // 'User'
|
|
2153
|
+
|
|
2154
|
+
// Access field definitions
|
|
2155
|
+
const fields = UserType.getFields();
|
|
2156
|
+
console.log(Object.keys(fields)); // ['id', 'name', 'email', ...]
|
|
2157
|
+
|
|
2158
|
+
// Check specific field
|
|
2159
|
+
const nameField = fields.name;
|
|
2160
|
+
console.log(nameField.type); // GraphQLString
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
// Get type by GraphQL type object
|
|
2164
|
+
const BookType = getType(SomeBookType);
|
|
2165
|
+
|
|
2166
|
+
// Safe access - returns null if not found
|
|
2167
|
+
const nonExistentType = getType('NonExistent');
|
|
2168
|
+
console.log(nonExistentType); // null
|
|
2169
|
+
```
|
|
2170
|
+
|
|
2171
|
+
**Use Cases:**
|
|
2172
|
+
- **Type introspection**: Examine type definitions programmatically
|
|
2173
|
+
- **Dynamic schema analysis**: Build tools that analyze your GraphQL schema
|
|
2174
|
+
- **Runtime type checking**: Validate types exist before operations
|
|
2175
|
+
- **Admin interfaces**: Build dynamic forms based on type definitions
|
|
2176
|
+
- **Circular reference resolution**: Prevent import cycles when types reference each other
|
|
2177
|
+
|
|
2178
|
+
### Preventing Circular References with `getType`
|
|
2179
|
+
|
|
2180
|
+
When you have types that reference each other (like User and Group), using `getType` prevents circular import issues:
|
|
2181
|
+
|
|
2182
|
+
```javascript
|
|
2183
|
+
import { GraphQLObjectType, GraphQLID, GraphQLString, GraphQLList } from 'graphql';
|
|
2184
|
+
import { getType } from '@simtlix/simfinity-js';
|
|
2185
|
+
|
|
2186
|
+
// User type that references Group
|
|
2187
|
+
const UserType = new GraphQLObjectType({
|
|
2188
|
+
name: 'User',
|
|
2189
|
+
fields: () => ({
|
|
2190
|
+
id: { type: GraphQLID },
|
|
2191
|
+
name: { type: GraphQLString },
|
|
2192
|
+
email: { type: GraphQLString },
|
|
2193
|
+
|
|
2194
|
+
// Reference Group type by name to avoid circular imports
|
|
2195
|
+
groups: {
|
|
2196
|
+
type: new GraphQLList(() => getType('Group')), // Use getType instead of direct import
|
|
2197
|
+
extensions: {
|
|
2198
|
+
relation: {
|
|
2199
|
+
connectionField: 'members',
|
|
2200
|
+
displayField: 'name'
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
},
|
|
2204
|
+
|
|
2205
|
+
// Single group reference
|
|
2206
|
+
primaryGroup: {
|
|
2207
|
+
type: () => getType('Group'), // Lazy evaluation with getType
|
|
2208
|
+
extensions: {
|
|
2209
|
+
relation: {
|
|
2210
|
+
connectionField: 'primaryGroupId',
|
|
2211
|
+
displayField: 'name'
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
})
|
|
2216
|
+
});
|
|
2217
|
+
|
|
2218
|
+
// Group type that references User
|
|
2219
|
+
const GroupType = new GraphQLObjectType({
|
|
2220
|
+
name: 'Group',
|
|
2221
|
+
fields: () => ({
|
|
2222
|
+
id: { type: GraphQLID },
|
|
2223
|
+
name: { type: GraphQLString },
|
|
2224
|
+
description: { type: GraphQLString },
|
|
2225
|
+
|
|
2226
|
+
// Reference User type by name to avoid circular imports
|
|
2227
|
+
members: {
|
|
2228
|
+
type: new GraphQLList(() => getType('User')), // Use getType instead of direct import
|
|
2229
|
+
extensions: {
|
|
2230
|
+
relation: {
|
|
2231
|
+
connectionField: 'groups',
|
|
2232
|
+
displayField: 'name'
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
},
|
|
2236
|
+
|
|
2237
|
+
// Single user reference (admin)
|
|
2238
|
+
admin: {
|
|
2239
|
+
type: () => getType('User'), // Lazy evaluation with getType
|
|
2240
|
+
extensions: {
|
|
2241
|
+
relation: {
|
|
2242
|
+
connectionField: 'adminId',
|
|
2243
|
+
displayField: 'name'
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
})
|
|
2248
|
+
});
|
|
2249
|
+
|
|
2250
|
+
// Register types with simfinity
|
|
2251
|
+
simfinity.connect(null, UserType, 'user', 'users');
|
|
2252
|
+
simfinity.connect(null, GroupType, 'group', 'groups');
|
|
2253
|
+
|
|
2254
|
+
// Create schema - resolvers will be auto-generated for all relationships
|
|
2255
|
+
const schema = simfinity.createSchema();
|
|
2256
|
+
```
|
|
2257
|
+
|
|
2258
|
+
**Benefits of this approach:**
|
|
2259
|
+
|
|
2260
|
+
1. **🔄 No Circular Imports**: Each file can import `getType` without importing other type definitions
|
|
2261
|
+
2. **⚡ Lazy Resolution**: Types are resolved at schema creation time when all types are registered
|
|
2262
|
+
3. **🛡️ Type Safety**: Still maintains GraphQL type checking and validation
|
|
2263
|
+
4. **🧹 Clean Architecture**: Separates type definitions from type relationships
|
|
2264
|
+
5. **📦 Better Modularity**: Each type can be in its own file without import dependencies
|
|
2265
|
+
|
|
2266
|
+
**File Structure Example:**
|
|
2267
|
+
|
|
2268
|
+
```
|
|
2269
|
+
types/
|
|
2270
|
+
├── User.js // Defines UserType using getType('Group')
|
|
2271
|
+
├── Group.js // Defines GroupType using getType('User')
|
|
2272
|
+
└── index.js // Registers all types and creates schema
|
|
2273
|
+
```
|
|
2274
|
+
|
|
2275
|
+
```javascript
|
|
2276
|
+
// types/User.js
|
|
2277
|
+
import { GraphQLObjectType, GraphQLID, GraphQLString, GraphQLList } from 'graphql';
|
|
2278
|
+
import { getType } from '@simtlix/simfinity-js';
|
|
2279
|
+
|
|
2280
|
+
export const UserType = new GraphQLObjectType({
|
|
2281
|
+
name: 'User',
|
|
2282
|
+
fields: () => ({
|
|
2283
|
+
id: { type: GraphQLID },
|
|
2284
|
+
name: { type: GraphQLString },
|
|
2285
|
+
groups: {
|
|
2286
|
+
type: new GraphQLList(() => getType('Group')),
|
|
2287
|
+
extensions: { relation: { connectionField: 'members' } }
|
|
2288
|
+
}
|
|
2289
|
+
})
|
|
2290
|
+
});
|
|
2291
|
+
|
|
2292
|
+
// types/Group.js
|
|
2293
|
+
import { GraphQLObjectType, GraphQLID, GraphQLString, GraphQLList } from 'graphql';
|
|
2294
|
+
import { getType } from '@simtlix/simfinity-js';
|
|
2295
|
+
|
|
2296
|
+
export const GroupType = new GraphQLObjectType({
|
|
2297
|
+
name: 'Group',
|
|
2298
|
+
fields: () => ({
|
|
2299
|
+
id: { type: GraphQLID },
|
|
2300
|
+
name: { type: GraphQLString },
|
|
2301
|
+
members: {
|
|
2302
|
+
type: new GraphQLList(() => getType('User')),
|
|
2303
|
+
extensions: { relation: { connectionField: 'groups' } }
|
|
2304
|
+
}
|
|
2305
|
+
})
|
|
2306
|
+
});
|
|
2307
|
+
|
|
2308
|
+
// types/index.js
|
|
2309
|
+
import { UserType } from './User.js';
|
|
2310
|
+
import { GroupType } from './Group.js';
|
|
2311
|
+
import simfinity from '@simtlix/simfinity-js';
|
|
2312
|
+
|
|
2313
|
+
// Register all types
|
|
2314
|
+
simfinity.connect(null, UserType, 'user', 'users');
|
|
2315
|
+
simfinity.connect(null, GroupType, 'group', 'groups');
|
|
2316
|
+
|
|
2317
|
+
// Create schema with auto-generated resolvers
|
|
2318
|
+
export const schema = simfinity.createSchema();
|
|
2319
|
+
```
|
|
2320
|
+
|
|
2321
|
+
### `getModel(gqltype)`
|
|
2322
|
+
|
|
2323
|
+
Retrieves the Mongoose model associated with a GraphQL type.
|
|
2324
|
+
|
|
2325
|
+
**Parameters:**
|
|
2326
|
+
- `gqltype` (GraphQLObjectType): The GraphQL type object
|
|
2327
|
+
|
|
2328
|
+
**Returns:**
|
|
2329
|
+
- `MongooseModel`: The associated Mongoose model
|
|
2330
|
+
|
|
2331
|
+
**Example:**
|
|
2332
|
+
|
|
2333
|
+
```javascript
|
|
2334
|
+
const BookModel = simfinity.getModel(BookType);
|
|
2335
|
+
const books = await BookModel.find({ author: 'Douglas Adams' });
|
|
2336
|
+
```
|
|
2337
|
+
|
|
2338
|
+
### `getInputType(type)`
|
|
2339
|
+
|
|
2340
|
+
Retrieves the input type for mutations associated with a GraphQL type.
|
|
2341
|
+
|
|
2342
|
+
**Parameters:**
|
|
2343
|
+
- `type` (GraphQLObjectType): The GraphQL type object
|
|
2344
|
+
|
|
2345
|
+
**Returns:**
|
|
2346
|
+
- `GraphQLInputObjectType`: The input type for mutations
|
|
2347
|
+
|
|
2348
|
+
**Example:**
|
|
2349
|
+
|
|
2350
|
+
```javascript
|
|
2351
|
+
const BookInput = simfinity.getInputType(BookType);
|
|
2352
|
+
console.log(BookInput.getFields()); // Input fields for mutations
|
|
2353
|
+
```
|
|
2354
|
+
|
|
2355
|
+
### `saveObject(typeName, args, session?)`
|
|
2356
|
+
|
|
2357
|
+
Programmatically save an object outside of GraphQL mutations.
|
|
2358
|
+
|
|
2359
|
+
**Parameters:**
|
|
2360
|
+
- `typeName` (string): The name of the GraphQL type
|
|
2361
|
+
- `args` (object): The data to save
|
|
2362
|
+
- `session` (MongooseSession, optional): Database session for transactions
|
|
2363
|
+
|
|
2364
|
+
**Returns:**
|
|
2365
|
+
- `Promise<object>`: The saved object
|
|
2366
|
+
|
|
2367
|
+
**Example:**
|
|
2368
|
+
|
|
2369
|
+
```javascript
|
|
2370
|
+
const newBook = await simfinity.saveObject('Book', {
|
|
2371
|
+
title: 'New Book',
|
|
2372
|
+
author: 'Author Name'
|
|
2373
|
+
}, session);
|
|
2374
|
+
```
|
|
2375
|
+
|
|
2376
|
+
### `createSchema(includedQueryTypes?, includedMutationTypes?, includedCustomMutations?)`
|
|
2377
|
+
|
|
2378
|
+
Creates the final GraphQL schema with all connected types.
|
|
2379
|
+
|
|
2380
|
+
**Parameters:**
|
|
2381
|
+
- `includedQueryTypes` (array, optional): Limit query types to include
|
|
2382
|
+
- `includedMutationTypes` (array, optional): Limit mutation types to include
|
|
2383
|
+
- `includedCustomMutations` (array, optional): Limit custom mutations to include
|
|
2384
|
+
|
|
2385
|
+
**Returns:**
|
|
2386
|
+
- `GraphQLSchema`: The complete GraphQL schema
|
|
2387
|
+
|
|
2388
|
+
**Example:**
|
|
2389
|
+
|
|
2390
|
+
```javascript
|
|
2391
|
+
const schema = simfinity.createSchema();
|
|
2392
|
+
```
|
|
2393
|
+
|
|
2394
|
+
*Built with ❤️ by [Simtlix](https://github.com/simtlix)*
|
|
2395
|
+
|
|
2125
2396
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1535,13 +1535,34 @@ const buildRootQuery = (name, includedTypes) => {
|
|
|
1535
1535
|
/* Creating a new GraphQL Schema, with options query which defines query
|
|
1536
1536
|
we will allow users to use when they are making request. */
|
|
1537
1537
|
export const createSchema = (includedQueryTypes,
|
|
1538
|
-
includedMutationTypes, includedCustomMutations) =>
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1538
|
+
includedMutationTypes, includedCustomMutations) => {
|
|
1539
|
+
|
|
1540
|
+
// Auto-generate resolvers for all registered types now that all types are available
|
|
1541
|
+
Object.values(typesDict.types).forEach(typeInfo => {
|
|
1542
|
+
if (typeInfo.gqltype) {
|
|
1543
|
+
autoGenerateResolvers(typeInfo.gqltype);
|
|
1544
|
+
}
|
|
1545
|
+
});
|
|
1546
|
+
|
|
1547
|
+
return new GraphQLSchema({
|
|
1548
|
+
query: buildRootQuery('RootQueryType', includedQueryTypes),
|
|
1549
|
+
mutation: buildMutation('Mutation', includedMutationTypes, includedCustomMutations),
|
|
1550
|
+
});
|
|
1551
|
+
};
|
|
1542
1552
|
|
|
1543
1553
|
export const getModel = (gqltype) => typesDict.types[gqltype.name].model;
|
|
1544
1554
|
|
|
1555
|
+
export const getType = (typeName) => {
|
|
1556
|
+
if (typeof typeName === 'string') {
|
|
1557
|
+
return typesDict.types[typeName]?.gqltype;
|
|
1558
|
+
}
|
|
1559
|
+
// If it's already a GraphQL type object, get by its name
|
|
1560
|
+
if (typeName && typeName.name) {
|
|
1561
|
+
return typesDict.types[typeName.name]?.gqltype;
|
|
1562
|
+
}
|
|
1563
|
+
return null;
|
|
1564
|
+
};
|
|
1565
|
+
|
|
1545
1566
|
export const registerMutation = (name, description, inputModel, outputModel, callback) => {
|
|
1546
1567
|
registeredMutations[name] = {
|
|
1547
1568
|
description,
|
|
@@ -1617,9 +1638,6 @@ export const connect = (model, gqltype, simpleEntityEndpointName,
|
|
|
1617
1638
|
};
|
|
1618
1639
|
|
|
1619
1640
|
typesDictForUpdate.types[gqltype.name] = { ...typesDict.types[gqltype.name] };
|
|
1620
|
-
|
|
1621
|
-
// Auto-generate resolve methods for relationship fields if not already defined
|
|
1622
|
-
autoGenerateResolvers(gqltype);
|
|
1623
1641
|
};
|
|
1624
1642
|
|
|
1625
1643
|
export const addNoEndpointType = (gqltype) => {
|
|
@@ -1648,9 +1666,6 @@ export const addNoEndpointType = (gqltype) => {
|
|
|
1648
1666
|
};
|
|
1649
1667
|
|
|
1650
1668
|
typesDictForUpdate.types[gqltype.name] = { ...typesDict.types[gqltype.name] };
|
|
1651
|
-
|
|
1652
|
-
// Auto-generate resolve methods for relationship fields if not already defined
|
|
1653
|
-
autoGenerateResolvers(gqltype);
|
|
1654
1669
|
};
|
|
1655
1670
|
|
|
1656
1671
|
export { createValidatedScalar };
|