@smartive/graphql-magic 23.12.0-next.1 → 23.12.0-next.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/CHANGELOG.md +2 -3
- package/dist/bin/gqm.cjs +21 -6
- package/dist/cjs/index.cjs +39 -25
- package/dist/esm/db/generate.d.ts +0 -1
- package/dist/esm/db/generate.js +7 -1
- package/dist/esm/db/generate.js.map +1 -1
- package/dist/esm/resolvers/resolvers.js +4 -27
- package/dist/esm/resolvers/resolvers.js.map +1 -1
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/time.d.ts +7 -0
- package/dist/esm/utils/time.js +23 -0
- package/dist/esm/utils/time.js.map +1 -0
- package/docs/docs/3-fields.md +1 -1
- package/package.json +1 -1
- package/src/bin/gqm/codegen.ts +13 -4
- package/src/db/generate.ts +8 -1
- package/src/resolvers/resolvers.ts +4 -33
- package/src/utils/index.ts +1 -0
- package/src/utils/time.ts +32 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
## [23.12.0-next.
|
|
1
|
+
## [23.12.0-next.2](https://github.com/smartive/graphql-magic/compare/v23.12.0-next.1...v23.12.0-next.2) (2026-03-31)
|
|
2
2
|
|
|
3
3
|
### Features
|
|
4
4
|
|
|
5
|
-
*
|
|
6
|
-
* add time type ([33adeec](https://github.com/smartive/graphql-magic/commit/33adeec46751f8ca29770b47d8d0ddfb2ce526bb))
|
|
5
|
+
* enhance Time type handling with strict format and utility functions ([a682c86](https://github.com/smartive/graphql-magic/commit/a682c8674e71581844606d580a56a518231121ad))
|
package/dist/bin/gqm.cjs
CHANGED
|
@@ -704,8 +704,7 @@ var PRIMITIVE_TYPES = {
|
|
|
704
704
|
Upload: "string",
|
|
705
705
|
Int: "number",
|
|
706
706
|
Float: "number",
|
|
707
|
-
String: "string"
|
|
708
|
-
Time: "string"
|
|
707
|
+
String: "string"
|
|
709
708
|
};
|
|
710
709
|
var OPTIONAL_SEED_FIELDS = ["createdAt", "createdById", "updatedAt", "updatedById", "deletedAt", "deletedById"];
|
|
711
710
|
var generateDBModels = (models, dateLibrary) => {
|
|
@@ -714,6 +713,10 @@ var generateDBModels = (models, dateLibrary) => {
|
|
|
714
713
|
indentNumberOfSpaces: 2
|
|
715
714
|
});
|
|
716
715
|
writer.write(DATE_CLASS_IMPORT[dateLibrary]).blankLine();
|
|
716
|
+
writer.write(`type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';`);
|
|
717
|
+
writer.write(`type Hour = \`0\${Digit}\` | \`1\${Digit}\` | \`2\${'0' | '1' | '2' | '3'}\`;`);
|
|
718
|
+
writer.write(`type Minute = \`\${'0' | '1' | '2' | '3' | '4' | '5'}\${Digit}\`;`);
|
|
719
|
+
writer.write(`export type Time = \`\${Hour}:\${Minute}\`;`).blankLine();
|
|
717
720
|
for (const [key, value2] of Object.entries(PRIMITIVE_TYPES)) {
|
|
718
721
|
writer.write(`export type ${key} = ${value2};`).blankLine();
|
|
719
722
|
}
|
|
@@ -795,6 +798,9 @@ var getFieldType = (field, dateLibrary, input2) => {
|
|
|
795
798
|
if (field.type === "DateTime") {
|
|
796
799
|
return (input2 ? `(${DATE_CLASS[dateLibrary]} | string)` : DATE_CLASS[dateLibrary]) + (field.list ? "[]" : "");
|
|
797
800
|
}
|
|
801
|
+
if (field.type === "Time") {
|
|
802
|
+
return `Time${field.list ? "[]" : ""}`;
|
|
803
|
+
}
|
|
798
804
|
return get(PRIMITIVE_TYPES, field.type) + (field.list ? "[]" : "");
|
|
799
805
|
default: {
|
|
800
806
|
const exhaustiveCheck = kind;
|
|
@@ -3212,13 +3218,18 @@ var generateGraphqlApiTypes = async (dateLibrary) => {
|
|
|
3212
3218
|
documents: void 0,
|
|
3213
3219
|
generates: {
|
|
3214
3220
|
[`${generatedFolderPath}/api/index.ts`]: {
|
|
3215
|
-
plugins: [
|
|
3221
|
+
plugins: [
|
|
3222
|
+
"typescript",
|
|
3223
|
+
"typescript-resolvers",
|
|
3224
|
+
{ add: { content: DATE_CLASS_IMPORT[dateLibrary] } },
|
|
3225
|
+
{ add: { content: `import type { Time } from '@smartive/graphql-magic';` } }
|
|
3226
|
+
]
|
|
3216
3227
|
}
|
|
3217
3228
|
},
|
|
3218
3229
|
config: {
|
|
3219
3230
|
scalars: {
|
|
3220
3231
|
DateTime: DATE_CLASS[dateLibrary],
|
|
3221
|
-
Time: "
|
|
3232
|
+
Time: "Time"
|
|
3222
3233
|
}
|
|
3223
3234
|
}
|
|
3224
3235
|
});
|
|
@@ -3232,7 +3243,11 @@ var generateGraphqlClientTypes = async () => {
|
|
|
3232
3243
|
documents: [graphqlQueriesPath, `${generatedFolderPath}/client/mutations.ts`],
|
|
3233
3244
|
generates: {
|
|
3234
3245
|
[`${generatedFolderPath}/client/index.ts`]: {
|
|
3235
|
-
plugins: [
|
|
3246
|
+
plugins: [
|
|
3247
|
+
"typescript",
|
|
3248
|
+
"typescript-operations",
|
|
3249
|
+
{ add: { content: `import type { Time } from '@smartive/graphql-magic';` } }
|
|
3250
|
+
]
|
|
3236
3251
|
}
|
|
3237
3252
|
},
|
|
3238
3253
|
config: {
|
|
@@ -3248,7 +3263,7 @@ var generateGraphqlClientTypes = async () => {
|
|
|
3248
3263
|
},
|
|
3249
3264
|
scalars: {
|
|
3250
3265
|
DateTime: "string",
|
|
3251
|
-
Time: "
|
|
3266
|
+
Time: "Time"
|
|
3252
3267
|
},
|
|
3253
3268
|
ignoreNoDocuments: true
|
|
3254
3269
|
}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -180,6 +180,7 @@ __export(index_exports, {
|
|
|
180
180
|
object: () => object,
|
|
181
181
|
or: () => or,
|
|
182
182
|
ors: () => ors,
|
|
183
|
+
parseTime: () => parseTime,
|
|
183
184
|
printSchema: () => printSchema,
|
|
184
185
|
printSchemaFromDocument: () => printSchemaFromDocument,
|
|
185
186
|
printSchemaFromModels: () => printSchemaFromModels,
|
|
@@ -189,6 +190,7 @@ __export(index_exports, {
|
|
|
189
190
|
restoreEntity: () => restoreEntity,
|
|
190
191
|
retry: () => retry,
|
|
191
192
|
scalar: () => scalar,
|
|
193
|
+
serializeTime: () => serializeTime,
|
|
192
194
|
summon: () => summon,
|
|
193
195
|
summonByKey: () => summonByKey,
|
|
194
196
|
summonByName: () => summonByName,
|
|
@@ -1079,8 +1081,7 @@ var PRIMITIVE_TYPES = {
|
|
|
1079
1081
|
Upload: "string",
|
|
1080
1082
|
Int: "number",
|
|
1081
1083
|
Float: "number",
|
|
1082
|
-
String: "string"
|
|
1083
|
-
Time: "string"
|
|
1084
|
+
String: "string"
|
|
1084
1085
|
};
|
|
1085
1086
|
var OPTIONAL_SEED_FIELDS = ["createdAt", "createdById", "updatedAt", "updatedById", "deletedAt", "deletedById"];
|
|
1086
1087
|
var generateDBModels = (models, dateLibrary) => {
|
|
@@ -1089,6 +1090,10 @@ var generateDBModels = (models, dateLibrary) => {
|
|
|
1089
1090
|
indentNumberOfSpaces: 2
|
|
1090
1091
|
});
|
|
1091
1092
|
writer.write(DATE_CLASS_IMPORT[dateLibrary]).blankLine();
|
|
1093
|
+
writer.write(`type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';`);
|
|
1094
|
+
writer.write(`type Hour = \`0\${Digit}\` | \`1\${Digit}\` | \`2\${'0' | '1' | '2' | '3'}\`;`);
|
|
1095
|
+
writer.write(`type Minute = \`\${'0' | '1' | '2' | '3' | '4' | '5'}\${Digit}\`;`);
|
|
1096
|
+
writer.write(`export type Time = \`\${Hour}:\${Minute}\`;`).blankLine();
|
|
1092
1097
|
for (const [key, value2] of Object.entries(PRIMITIVE_TYPES)) {
|
|
1093
1098
|
writer.write(`export type ${key} = ${value2};`).blankLine();
|
|
1094
1099
|
}
|
|
@@ -1170,6 +1175,9 @@ var getFieldType = (field, dateLibrary, input2) => {
|
|
|
1170
1175
|
if (field.type === "DateTime") {
|
|
1171
1176
|
return (input2 ? `(${DATE_CLASS[dateLibrary]} | string)` : DATE_CLASS[dateLibrary]) + (field.list ? "[]" : "");
|
|
1172
1177
|
}
|
|
1178
|
+
if (field.type === "Time") {
|
|
1179
|
+
return `Time${field.list ? "[]" : ""}`;
|
|
1180
|
+
}
|
|
1173
1181
|
return get(PRIMITIVE_TYPES, field.type) + (field.list ? "[]" : "");
|
|
1174
1182
|
default: {
|
|
1175
1183
|
const exhaustiveCheck = kind;
|
|
@@ -2016,6 +2024,30 @@ var applyWhere2 = (model, query, alias, where, aliases) => {
|
|
|
2016
2024
|
}
|
|
2017
2025
|
};
|
|
2018
2026
|
|
|
2027
|
+
// src/utils/time.ts
|
|
2028
|
+
var PARSE_TIME_RE = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
|
2029
|
+
var SERIALIZE_TIME_RE = /^([01]\d|2[0-3]):([0-5]\d)(?::[0-5]\d(?:\.\d+)?)?$/;
|
|
2030
|
+
var parseTime = (value2) => {
|
|
2031
|
+
if (typeof value2 !== "string") {
|
|
2032
|
+
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value2}`);
|
|
2033
|
+
}
|
|
2034
|
+
const match = value2.match(PARSE_TIME_RE);
|
|
2035
|
+
if (!match) {
|
|
2036
|
+
throw new Error(`Invalid Time value "${value2}". Expected HH:mm in 24-hour format.`);
|
|
2037
|
+
}
|
|
2038
|
+
return `${match[1]}:${match[2]}`;
|
|
2039
|
+
};
|
|
2040
|
+
var serializeTime = (value2) => {
|
|
2041
|
+
if (typeof value2 !== "string") {
|
|
2042
|
+
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value2}`);
|
|
2043
|
+
}
|
|
2044
|
+
const match = value2.match(SERIALIZE_TIME_RE);
|
|
2045
|
+
if (!match) {
|
|
2046
|
+
throw new Error(`Invalid Time value "${value2}". Expected HH:mm or HH:mm:ss.`);
|
|
2047
|
+
}
|
|
2048
|
+
return `${match[1]}:${match[2]}`;
|
|
2049
|
+
};
|
|
2050
|
+
|
|
2019
2051
|
// src/resolvers/resolver.ts
|
|
2020
2052
|
var import_cloneDeep2 = __toESM(require("lodash/cloneDeep"), 1);
|
|
2021
2053
|
var import_flatMap = __toESM(require("lodash/flatMap"), 1);
|
|
@@ -2898,26 +2930,6 @@ var doUpdate = async (model, currentEntity, update, ctx) => {
|
|
|
2898
2930
|
|
|
2899
2931
|
// src/resolvers/resolvers.ts
|
|
2900
2932
|
var import_graphql5 = require("graphql");
|
|
2901
|
-
var normalizeTimeToHHmmForSerialize = (value2) => {
|
|
2902
|
-
if (typeof value2 !== "string") {
|
|
2903
|
-
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value2}`);
|
|
2904
|
-
}
|
|
2905
|
-
const match = value2.match(/^(\d{2}:\d{2})/);
|
|
2906
|
-
if (!match) {
|
|
2907
|
-
throw new Error(`Invalid Time value "${value2}". Expected HH:mm.`);
|
|
2908
|
-
}
|
|
2909
|
-
return match[1];
|
|
2910
|
-
};
|
|
2911
|
-
var normalizeTimeToHHmmForParse = (value2) => {
|
|
2912
|
-
if (typeof value2 !== "string") {
|
|
2913
|
-
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value2}`);
|
|
2914
|
-
}
|
|
2915
|
-
const match = value2.match(/^(\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?$/);
|
|
2916
|
-
if (!match) {
|
|
2917
|
-
throw new Error(`Invalid Time value "${value2}". Expected HH:mm.`);
|
|
2918
|
-
}
|
|
2919
|
-
return `${match[1]}:${match[2]}`;
|
|
2920
|
-
};
|
|
2921
2933
|
var getResolvers = (models) => {
|
|
2922
2934
|
const resolvers = {
|
|
2923
2935
|
Query: merge2([
|
|
@@ -2937,13 +2949,13 @@ var getResolvers = (models) => {
|
|
|
2937
2949
|
Time: new import_graphql5.GraphQLScalarType({
|
|
2938
2950
|
name: "Time",
|
|
2939
2951
|
description: "Time without date and timezone (HH:mm)",
|
|
2940
|
-
serialize: (value2) => value2 == null ? value2 :
|
|
2941
|
-
parseValue: (value2) =>
|
|
2952
|
+
serialize: (value2) => value2 == null ? value2 : serializeTime(value2),
|
|
2953
|
+
parseValue: (value2) => parseTime(value2),
|
|
2942
2954
|
parseLiteral: (ast) => {
|
|
2943
2955
|
if (ast.kind !== import_graphql5.Kind.STRING) {
|
|
2944
2956
|
throw new Error(`Invalid literal for Time scalar. Expected STRING, got ${ast.kind}.`);
|
|
2945
2957
|
}
|
|
2946
|
-
return
|
|
2958
|
+
return parseTime(ast.value);
|
|
2947
2959
|
}
|
|
2948
2960
|
})
|
|
2949
2961
|
};
|
|
@@ -5215,6 +5227,7 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql7.buildAST
|
|
|
5215
5227
|
object,
|
|
5216
5228
|
or,
|
|
5217
5229
|
ors,
|
|
5230
|
+
parseTime,
|
|
5218
5231
|
printSchema,
|
|
5219
5232
|
printSchemaFromDocument,
|
|
5220
5233
|
printSchemaFromModels,
|
|
@@ -5224,6 +5237,7 @@ var printSchemaFromModels = (models) => printSchema((0, import_graphql7.buildAST
|
|
|
5224
5237
|
restoreEntity,
|
|
5225
5238
|
retry,
|
|
5226
5239
|
scalar,
|
|
5240
|
+
serializeTime,
|
|
5227
5241
|
summon,
|
|
5228
5242
|
summonByKey,
|
|
5229
5243
|
summonByName,
|
|
@@ -7,7 +7,6 @@ export declare const PRIMITIVE_TYPES: {
|
|
|
7
7
|
Int: string;
|
|
8
8
|
Float: string;
|
|
9
9
|
String: string;
|
|
10
|
-
Time: string;
|
|
11
10
|
};
|
|
12
11
|
export declare const generateDBModels: (models: Models, dateLibrary: DateLibrary) => string;
|
|
13
12
|
export declare const generateKnexTables: (models: Models) => string;
|
package/dist/esm/db/generate.js
CHANGED
|
@@ -8,7 +8,6 @@ export const PRIMITIVE_TYPES = {
|
|
|
8
8
|
Int: 'number',
|
|
9
9
|
Float: 'number',
|
|
10
10
|
String: 'string',
|
|
11
|
-
Time: 'string',
|
|
12
11
|
};
|
|
13
12
|
const OPTIONAL_SEED_FIELDS = ['createdAt', 'createdById', 'updatedAt', 'updatedById', 'deletedAt', 'deletedById'];
|
|
14
13
|
export const generateDBModels = (models, dateLibrary) => {
|
|
@@ -18,6 +17,10 @@ export const generateDBModels = (models, dateLibrary) => {
|
|
|
18
17
|
indentNumberOfSpaces: 2,
|
|
19
18
|
});
|
|
20
19
|
writer.write(DATE_CLASS_IMPORT[dateLibrary]).blankLine();
|
|
20
|
+
writer.write(`type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';`);
|
|
21
|
+
writer.write(`type Hour = \`0\${Digit}\` | \`1\${Digit}\` | \`2\${'0' | '1' | '2' | '3'}\`;`);
|
|
22
|
+
writer.write(`type Minute = \`\${'0' | '1' | '2' | '3' | '4' | '5'}\${Digit}\`;`);
|
|
23
|
+
writer.write(`export type Time = \`\${Hour}:\${Minute}\`;`).blankLine();
|
|
21
24
|
for (const [key, value] of Object.entries(PRIMITIVE_TYPES)) {
|
|
22
25
|
writer.write(`export type ${key} = ${value};`).blankLine();
|
|
23
26
|
}
|
|
@@ -118,6 +121,9 @@ const getFieldType = (field, dateLibrary, input) => {
|
|
|
118
121
|
if (field.type === 'DateTime') {
|
|
119
122
|
return (input ? `(${DATE_CLASS[dateLibrary]} | string)` : DATE_CLASS[dateLibrary]) + (field.list ? '[]' : '');
|
|
120
123
|
}
|
|
124
|
+
if (field.type === 'Time') {
|
|
125
|
+
return `Time${field.list ? '[]' : ''}`;
|
|
126
|
+
}
|
|
121
127
|
return get(PRIMITIVE_TYPES, field.type) + (field.list ? '[]' : '');
|
|
122
128
|
default: {
|
|
123
129
|
const exhaustiveCheck = kind;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/db/generate.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,GAAG,EAAe,GAAG,EAAE,aAAa,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,IAAI,CAAC;AAE3H,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAe,MAAM,gBAAgB,CAAC;AAE5E,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,EAAE,EAAE,QAAQ;IACZ,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,GAAG,EAAE,QAAQ;IACb,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/db/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,31 +1,8 @@
|
|
|
1
1
|
import { GraphQLScalarType, Kind } from 'graphql';
|
|
2
2
|
import { and, isCreatable, isRootModel, isUpdatable, merge, not, typeToField } from '../models/utils';
|
|
3
|
+
import { parseTime, serializeTime } from '../utils/time';
|
|
3
4
|
import { mutationResolver } from './mutations';
|
|
4
5
|
import { queryResolver } from './resolver';
|
|
5
|
-
const normalizeTimeToHHmmForSerialize = (value) => {
|
|
6
|
-
if (typeof value !== 'string') {
|
|
7
|
-
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value}`);
|
|
8
|
-
}
|
|
9
|
-
// Postgres `time` columns may serialize to `HH:mm:ss`.
|
|
10
|
-
// Be permissive here and just extract the leading `HH:mm`.
|
|
11
|
-
const match = value.match(/^(\d{2}:\d{2})/);
|
|
12
|
-
if (!match) {
|
|
13
|
-
throw new Error(`Invalid Time value "${value}". Expected HH:mm.`);
|
|
14
|
-
}
|
|
15
|
-
return match[1];
|
|
16
|
-
};
|
|
17
|
-
const normalizeTimeToHHmmForParse = (value) => {
|
|
18
|
-
if (typeof value !== 'string') {
|
|
19
|
-
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value}`);
|
|
20
|
-
}
|
|
21
|
-
// For input, we only accept time-without-timezone values.
|
|
22
|
-
// Accept `HH:mm` and `HH:mm:ss[.fraction]`, but explicitly reject `Z` and `+/-HH:mm`.
|
|
23
|
-
const match = value.match(/^(\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?$/);
|
|
24
|
-
if (!match) {
|
|
25
|
-
throw new Error(`Invalid Time value "${value}". Expected HH:mm.`);
|
|
26
|
-
}
|
|
27
|
-
return `${match[1]}:${match[2]}`;
|
|
28
|
-
};
|
|
29
6
|
export const getResolvers = (models) => {
|
|
30
7
|
const resolvers = {
|
|
31
8
|
Query: merge([
|
|
@@ -51,13 +28,13 @@ export const getResolvers = (models) => {
|
|
|
51
28
|
Time: new GraphQLScalarType({
|
|
52
29
|
name: 'Time',
|
|
53
30
|
description: 'Time without date and timezone (HH:mm)',
|
|
54
|
-
serialize: (value) => (value == null ? value :
|
|
55
|
-
parseValue: (value) =>
|
|
31
|
+
serialize: (value) => (value == null ? value : serializeTime(value)),
|
|
32
|
+
parseValue: (value) => parseTime(value),
|
|
56
33
|
parseLiteral: (ast) => {
|
|
57
34
|
if (ast.kind !== Kind.STRING) {
|
|
58
35
|
throw new Error(`Invalid literal for Time scalar. Expected STRING, got ${ast.kind}.`);
|
|
59
36
|
}
|
|
60
|
-
return
|
|
37
|
+
return parseTime(ast.value);
|
|
61
38
|
},
|
|
62
39
|
}),
|
|
63
40
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolvers.js","sourceRoot":"","sources":["../../../src/resolvers/resolvers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACtG,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"resolvers.js","sourceRoot":"","sources":["../../../src/resolvers/resolvers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACtG,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAc,EAAE,EAAE;IAC7C,MAAM,SAAS,GAAwB;QACrC,KAAK,EAAE,KAAK,CAAC;YACX;gBACE,EAAE,EAAE,aAAa;aAClB;YACD,GAAG,MAAM,CAAC,QAAQ;iBACf,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC;iBACpC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACf,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,aAAa;aACzC,CAAC,CAAC;YACL,GAAG,MAAM,CAAC,QAAQ;iBACf,MAAM,CAAC,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,aAAa,CAAC;iBAC5C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACf,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,aAAa;aACnC,CAAC,CAAC;YACL,GAAG,MAAM,CAAC,QAAQ;iBACf,MAAM,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC;iBAC1C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACf,CAAC,GAAG,KAAK,CAAC,WAAW,YAAY,CAAC,EAAE,aAAa;aAClD,CAAC,CAAC;SACN,CAAC;QACF,IAAI,EAAE,IAAI,iBAAiB,CAAC;YAC1B,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,wCAAwC;YACrD,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACpE,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;YACvC,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE;gBACpB,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;oBAC7B,MAAM,IAAI,KAAK,CAAC,yDAAyD,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;gBACxF,CAAC;gBAED,OAAO,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;SACF,CAAC;KACH,CAAC;IACF,MAAM,SAAS,GAAG;QAChB,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC5E,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,gBAAgB;SAC1C,CAAC,CAAC;QACH,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC5E,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,gBAAgB;SAC1C,CAAC,CAAC;QACH,GAAG,MAAM,CAAC,QAAQ;aACf,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;aACxB,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC;aACpC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACf,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,gBAAgB;YACzC,CAAC,UAAU,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,gBAAgB;SAC3C,CAAC,CAAC;KACN,CAAC;IAEF,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,SAAS,CAAC,QAAQ,GAAG,KAAK,CAAU,SAAS,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QACxD,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG;YACtB,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI;SAClC,CAAC;IACJ,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC"}
|
package/dist/esm/utils/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
|
|
2
|
+
type Hour = `0${Digit}` | `1${Digit}` | `2${'0' | '1' | '2' | '3'}`;
|
|
3
|
+
type Minute = `${'0' | '1' | '2' | '3' | '4' | '5'}${Digit}`;
|
|
4
|
+
export type Time = `${Hour}:${Minute}`;
|
|
5
|
+
export declare const parseTime: (value: unknown) => Time;
|
|
6
|
+
export declare const serializeTime: (value: unknown) => Time;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const PARSE_TIME_RE = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
|
2
|
+
const SERIALIZE_TIME_RE = /^([01]\d|2[0-3]):([0-5]\d)(?::[0-5]\d(?:\.\d+)?)?$/;
|
|
3
|
+
export const parseTime = (value) => {
|
|
4
|
+
if (typeof value !== 'string') {
|
|
5
|
+
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value}`);
|
|
6
|
+
}
|
|
7
|
+
const match = value.match(PARSE_TIME_RE);
|
|
8
|
+
if (!match) {
|
|
9
|
+
throw new Error(`Invalid Time value "${value}". Expected HH:mm in 24-hour format.`);
|
|
10
|
+
}
|
|
11
|
+
return `${match[1]}:${match[2]}`;
|
|
12
|
+
};
|
|
13
|
+
export const serializeTime = (value) => {
|
|
14
|
+
if (typeof value !== 'string') {
|
|
15
|
+
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value}`);
|
|
16
|
+
}
|
|
17
|
+
const match = value.match(SERIALIZE_TIME_RE);
|
|
18
|
+
if (!match) {
|
|
19
|
+
throw new Error(`Invalid Time value "${value}". Expected HH:mm or HH:mm:ss.`);
|
|
20
|
+
}
|
|
21
|
+
return `${match[1]}:${match[2]}`;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.js","sourceRoot":"","sources":["../../../src/utils/time.ts"],"names":[],"mappings":"AAMA,MAAM,aAAa,GAAG,6BAA6B,CAAC;AACpD,MAAM,iBAAiB,GAAG,oDAAoD,CAAC;AAE/E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAc,EAAQ,EAAE;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,oDAAoD,OAAO,KAAK,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,sCAAsC,CAAC,CAAC;IACtF,CAAC;IAED,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAU,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAc,EAAQ,EAAE;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,oDAAoD,OAAO,KAAK,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,gCAAgC,CAAC,CAAC;IAChF,CAAC;IAED,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAU,CAAC;AAC3C,CAAC,CAAC"}
|
package/docs/docs/3-fields.md
CHANGED
|
@@ -32,7 +32,7 @@ Primitive fields are fields where `kind` is either undefined or set to `'primiti
|
|
|
32
32
|
- `Float` with optional fields `floatType`, `double`, `precision`, `scale`
|
|
33
33
|
- `Upload`
|
|
34
34
|
|
|
35
|
-
`Time` values are expected in a
|
|
35
|
+
`Time` values are expected in a strict 24-hour format: `HH:mm` (from `00:00` to `23:59`).
|
|
36
36
|
|
|
37
37
|
Examples:
|
|
38
38
|
|
package/package.json
CHANGED
package/src/bin/gqm/codegen.ts
CHANGED
|
@@ -10,13 +10,18 @@ export const generateGraphqlApiTypes = async (dateLibrary: DateLibrary) => {
|
|
|
10
10
|
documents: undefined,
|
|
11
11
|
generates: {
|
|
12
12
|
[`${generatedFolderPath}/api/index.ts`]: {
|
|
13
|
-
plugins: [
|
|
13
|
+
plugins: [
|
|
14
|
+
'typescript',
|
|
15
|
+
'typescript-resolvers',
|
|
16
|
+
{ add: { content: DATE_CLASS_IMPORT[dateLibrary] } },
|
|
17
|
+
{ add: { content: `import type { Time } from '@smartive/graphql-magic';` } },
|
|
18
|
+
],
|
|
14
19
|
},
|
|
15
20
|
},
|
|
16
21
|
config: {
|
|
17
22
|
scalars: {
|
|
18
23
|
DateTime: DATE_CLASS[dateLibrary],
|
|
19
|
-
Time: '
|
|
24
|
+
Time: 'Time',
|
|
20
25
|
},
|
|
21
26
|
},
|
|
22
27
|
});
|
|
@@ -31,7 +36,11 @@ export const generateGraphqlClientTypes = async () => {
|
|
|
31
36
|
documents: [graphqlQueriesPath, `${generatedFolderPath}/client/mutations.ts`],
|
|
32
37
|
generates: {
|
|
33
38
|
[`${generatedFolderPath}/client/index.ts`]: {
|
|
34
|
-
plugins: [
|
|
39
|
+
plugins: [
|
|
40
|
+
'typescript',
|
|
41
|
+
'typescript-operations',
|
|
42
|
+
{ add: { content: `import type { Time } from '@smartive/graphql-magic';` } },
|
|
43
|
+
],
|
|
35
44
|
},
|
|
36
45
|
},
|
|
37
46
|
config: {
|
|
@@ -44,7 +53,7 @@ export const generateGraphqlClientTypes = async () => {
|
|
|
44
53
|
},
|
|
45
54
|
scalars: {
|
|
46
55
|
DateTime: 'string',
|
|
47
|
-
Time: '
|
|
56
|
+
Time: 'Time',
|
|
48
57
|
},
|
|
49
58
|
ignoreNoDocuments: true,
|
|
50
59
|
},
|
package/src/db/generate.ts
CHANGED
|
@@ -10,7 +10,6 @@ export const PRIMITIVE_TYPES = {
|
|
|
10
10
|
Int: 'number',
|
|
11
11
|
Float: 'number',
|
|
12
12
|
String: 'string',
|
|
13
|
-
Time: 'string',
|
|
14
13
|
};
|
|
15
14
|
|
|
16
15
|
const OPTIONAL_SEED_FIELDS = ['createdAt', 'createdById', 'updatedAt', 'updatedById', 'deletedAt', 'deletedById'];
|
|
@@ -24,6 +23,11 @@ export const generateDBModels = (models: Models, dateLibrary: DateLibrary) => {
|
|
|
24
23
|
|
|
25
24
|
writer.write(DATE_CLASS_IMPORT[dateLibrary]).blankLine();
|
|
26
25
|
|
|
26
|
+
writer.write(`type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';`);
|
|
27
|
+
writer.write(`type Hour = \`0\${Digit}\` | \`1\${Digit}\` | \`2\${'0' | '1' | '2' | '3'}\`;`);
|
|
28
|
+
writer.write(`type Minute = \`\${'0' | '1' | '2' | '3' | '4' | '5'}\${Digit}\`;`);
|
|
29
|
+
writer.write(`export type Time = \`\${Hour}:\${Minute}\`;`).blankLine();
|
|
30
|
+
|
|
27
31
|
for (const [key, value] of Object.entries(PRIMITIVE_TYPES)) {
|
|
28
32
|
writer.write(`export type ${key} = ${value};`).blankLine();
|
|
29
33
|
}
|
|
@@ -151,6 +155,9 @@ const getFieldType = (field: EntityField, dateLibrary: DateLibrary, input?: bool
|
|
|
151
155
|
if (field.type === 'DateTime') {
|
|
152
156
|
return (input ? `(${DATE_CLASS[dateLibrary]} | string)` : DATE_CLASS[dateLibrary]) + (field.list ? '[]' : '');
|
|
153
157
|
}
|
|
158
|
+
if (field.type === 'Time') {
|
|
159
|
+
return `Time${field.list ? '[]' : ''}`;
|
|
160
|
+
}
|
|
154
161
|
|
|
155
162
|
return get(PRIMITIVE_TYPES, field.type) + (field.list ? '[]' : '');
|
|
156
163
|
default: {
|
|
@@ -1,39 +1,10 @@
|
|
|
1
1
|
import { GraphQLScalarType, Kind } from 'graphql';
|
|
2
2
|
import { Models } from '../models/models';
|
|
3
3
|
import { and, isCreatable, isRootModel, isUpdatable, merge, not, typeToField } from '../models/utils';
|
|
4
|
+
import { parseTime, serializeTime } from '../utils/time';
|
|
4
5
|
import { mutationResolver } from './mutations';
|
|
5
6
|
import { queryResolver } from './resolver';
|
|
6
7
|
|
|
7
|
-
const normalizeTimeToHHmmForSerialize = (value: unknown): string => {
|
|
8
|
-
if (typeof value !== 'string') {
|
|
9
|
-
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value}`);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Postgres `time` columns may serialize to `HH:mm:ss`.
|
|
13
|
-
// Be permissive here and just extract the leading `HH:mm`.
|
|
14
|
-
const match = value.match(/^(\d{2}:\d{2})/);
|
|
15
|
-
if (!match) {
|
|
16
|
-
throw new Error(`Invalid Time value "${value}". Expected HH:mm.`);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return match[1];
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const normalizeTimeToHHmmForParse = (value: unknown): string => {
|
|
23
|
-
if (typeof value !== 'string') {
|
|
24
|
-
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value}`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// For input, we only accept time-without-timezone values.
|
|
28
|
-
// Accept `HH:mm` and `HH:mm:ss[.fraction]`, but explicitly reject `Z` and `+/-HH:mm`.
|
|
29
|
-
const match = value.match(/^(\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?$/);
|
|
30
|
-
if (!match) {
|
|
31
|
-
throw new Error(`Invalid Time value "${value}". Expected HH:mm.`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return `${match[1]}:${match[2]}`;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
8
|
export const getResolvers = (models: Models) => {
|
|
38
9
|
const resolvers: Record<string, any> = {
|
|
39
10
|
Query: merge([
|
|
@@ -59,14 +30,14 @@ export const getResolvers = (models: Models) => {
|
|
|
59
30
|
Time: new GraphQLScalarType({
|
|
60
31
|
name: 'Time',
|
|
61
32
|
description: 'Time without date and timezone (HH:mm)',
|
|
62
|
-
serialize: (value) => (value == null ? value :
|
|
63
|
-
parseValue: (value) =>
|
|
33
|
+
serialize: (value) => (value == null ? value : serializeTime(value)),
|
|
34
|
+
parseValue: (value) => parseTime(value),
|
|
64
35
|
parseLiteral: (ast) => {
|
|
65
36
|
if (ast.kind !== Kind.STRING) {
|
|
66
37
|
throw new Error(`Invalid literal for Time scalar. Expected STRING, got ${ast.kind}.`);
|
|
67
38
|
}
|
|
68
39
|
|
|
69
|
-
return
|
|
40
|
+
return parseTime(ast.value);
|
|
70
41
|
},
|
|
71
42
|
}),
|
|
72
43
|
};
|
package/src/utils/index.ts
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
|
|
2
|
+
type Hour = `0${Digit}` | `1${Digit}` | `2${'0' | '1' | '2' | '3'}`;
|
|
3
|
+
type Minute = `${'0' | '1' | '2' | '3' | '4' | '5'}${Digit}`;
|
|
4
|
+
|
|
5
|
+
export type Time = `${Hour}:${Minute}`;
|
|
6
|
+
|
|
7
|
+
const PARSE_TIME_RE = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
|
8
|
+
const SERIALIZE_TIME_RE = /^([01]\d|2[0-3]):([0-5]\d)(?::[0-5]\d(?:\.\d+)?)?$/;
|
|
9
|
+
|
|
10
|
+
export const parseTime = (value: unknown): Time => {
|
|
11
|
+
if (typeof value !== 'string') {
|
|
12
|
+
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value}`);
|
|
13
|
+
}
|
|
14
|
+
const match = value.match(PARSE_TIME_RE);
|
|
15
|
+
if (!match) {
|
|
16
|
+
throw new Error(`Invalid Time value "${value}". Expected HH:mm in 24-hour format.`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return `${match[1]}:${match[2]}` as Time;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const serializeTime = (value: unknown): Time => {
|
|
23
|
+
if (typeof value !== 'string') {
|
|
24
|
+
throw new Error(`Time must be a string in HH:mm format. Received: ${typeof value}`);
|
|
25
|
+
}
|
|
26
|
+
const match = value.match(SERIALIZE_TIME_RE);
|
|
27
|
+
if (!match) {
|
|
28
|
+
throw new Error(`Invalid Time value "${value}". Expected HH:mm or HH:mm:ss.`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return `${match[1]}:${match[2]}` as Time;
|
|
32
|
+
};
|