prisma-guard 1.10.0 → 1.12.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/dist/runtime/index.cjs +275 -4
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.js +275 -4
- package/dist/runtime/index.js.map +1 -1
- package/package.json +1 -1
package/dist/runtime/index.js
CHANGED
|
@@ -1369,8 +1369,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1369
1369
|
enumMap,
|
|
1370
1370
|
scalarBase
|
|
1371
1371
|
);
|
|
1372
|
-
|
|
1373
|
-
fieldSchemas[fieldName] = z4.union([refined, shorthand]).optional();
|
|
1372
|
+
fieldSchemas[fieldName] = z4.union([refined, equalsBase]).optional();
|
|
1374
1373
|
} else {
|
|
1375
1374
|
fieldSchemas[fieldName] = refined.optional();
|
|
1376
1375
|
}
|
|
@@ -2829,6 +2828,19 @@ var VALID_SHAPE_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set(["data", "where
|
|
|
2829
2828
|
var VALID_SHAPE_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
|
|
2830
2829
|
var VALID_SHAPE_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set(["where", "select", "include"]);
|
|
2831
2830
|
var VALID_SHAPE_KEYS_UPSERT = /* @__PURE__ */ new Set(["where", "create", "update", "select", "include"]);
|
|
2831
|
+
var KNOWN_RELATION_WRITE_OPS = /* @__PURE__ */ new Set([
|
|
2832
|
+
"connect",
|
|
2833
|
+
"connectOrCreate",
|
|
2834
|
+
"create",
|
|
2835
|
+
"createMany",
|
|
2836
|
+
"disconnect",
|
|
2837
|
+
"delete",
|
|
2838
|
+
"set",
|
|
2839
|
+
"update",
|
|
2840
|
+
"updateMany",
|
|
2841
|
+
"upsert",
|
|
2842
|
+
"deleteMany"
|
|
2843
|
+
]);
|
|
2832
2844
|
function validateMutationBodyKeys(body, allowed, method) {
|
|
2833
2845
|
for (const key of Object.keys(body)) {
|
|
2834
2846
|
if (!allowed.has(key)) {
|
|
@@ -2853,6 +2865,26 @@ function validateCreateCompleteness(modelName, dataConfig, typeMap, scopeFks, zo
|
|
|
2853
2865
|
return;
|
|
2854
2866
|
const zodDefaultFields = zodDefaults[modelName];
|
|
2855
2867
|
const zodDefaultSet = zodDefaultFields ? new Set(zodDefaultFields) : void 0;
|
|
2868
|
+
const relationFksCoveredByShape = /* @__PURE__ */ new Set();
|
|
2869
|
+
for (const [fieldName, value] of Object.entries(dataConfig)) {
|
|
2870
|
+
const meta = modelFields[fieldName];
|
|
2871
|
+
if (!meta)
|
|
2872
|
+
continue;
|
|
2873
|
+
if (meta.isRelation && isPlainObject(value)) {
|
|
2874
|
+
const relConfig = value;
|
|
2875
|
+
if (relConfig.connect || relConfig.connectOrCreate || relConfig.create) {
|
|
2876
|
+
const fkFields = Object.keys(modelFields).filter((f) => {
|
|
2877
|
+
const fm = modelFields[f];
|
|
2878
|
+
return !fm.isRelation && fieldName !== f;
|
|
2879
|
+
});
|
|
2880
|
+
for (const fk of Object.keys(modelFields)) {
|
|
2881
|
+
const fm = modelFields[fk];
|
|
2882
|
+
if (fm.isRelation)
|
|
2883
|
+
continue;
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2856
2888
|
for (const [fieldName, meta] of Object.entries(modelFields)) {
|
|
2857
2889
|
if (meta.isRelation)
|
|
2858
2890
|
continue;
|
|
@@ -2868,11 +2900,237 @@ function validateCreateCompleteness(modelName, dataConfig, typeMap, scopeFks, zo
|
|
|
2868
2900
|
continue;
|
|
2869
2901
|
if (zodDefaultSet && zodDefaultSet.has(fieldName))
|
|
2870
2902
|
continue;
|
|
2903
|
+
const coveredByRelation = Object.entries(dataConfig).some(([shapeName, shapeVal]) => {
|
|
2904
|
+
const shapeMeta = modelFields[shapeName];
|
|
2905
|
+
if (!shapeMeta || !shapeMeta.isRelation)
|
|
2906
|
+
return false;
|
|
2907
|
+
if (!isPlainObject(shapeVal))
|
|
2908
|
+
return false;
|
|
2909
|
+
const relConfig = shapeVal;
|
|
2910
|
+
return !!(relConfig.connect || relConfig.connectOrCreate || relConfig.create);
|
|
2911
|
+
});
|
|
2912
|
+
if (coveredByRelation)
|
|
2913
|
+
continue;
|
|
2871
2914
|
throw new ShapeError(
|
|
2872
2915
|
`Required field "${fieldName}" on model "${modelName}" is missing from create data shape, has no default, and is not a scope FK`
|
|
2873
2916
|
);
|
|
2874
2917
|
}
|
|
2875
2918
|
}
|
|
2919
|
+
function buildWhereFieldsSchema(model, config, typeMap, schemaBuilder) {
|
|
2920
|
+
const modelFields = typeMap[model];
|
|
2921
|
+
if (!modelFields)
|
|
2922
|
+
throw new ShapeError(`Unknown model: ${model}`);
|
|
2923
|
+
const fieldSchemas = {};
|
|
2924
|
+
for (const [fieldName, value] of Object.entries(config)) {
|
|
2925
|
+
if (value !== true)
|
|
2926
|
+
throw new ShapeError(`Field "${fieldName}" in connect/where config must be true`);
|
|
2927
|
+
const meta = modelFields[fieldName];
|
|
2928
|
+
if (!meta)
|
|
2929
|
+
throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
|
|
2930
|
+
if (meta.isRelation)
|
|
2931
|
+
throw new ShapeError(`Relation field "${fieldName}" cannot be used in connect/where`);
|
|
2932
|
+
fieldSchemas[fieldName] = schemaBuilder.buildFieldSchema(model, fieldName).optional();
|
|
2933
|
+
}
|
|
2934
|
+
return z8.object(fieldSchemas).strict();
|
|
2935
|
+
}
|
|
2936
|
+
function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
|
|
2937
|
+
const modelFields = typeMap[model];
|
|
2938
|
+
if (!modelFields)
|
|
2939
|
+
throw new ShapeError(`Unknown model: ${model}`);
|
|
2940
|
+
const fieldSchemas = {};
|
|
2941
|
+
for (const [fieldName, value] of Object.entries(config)) {
|
|
2942
|
+
if (value !== true)
|
|
2943
|
+
throw new ShapeError(`Field "${fieldName}" in nested data config must be true`);
|
|
2944
|
+
const meta = modelFields[fieldName];
|
|
2945
|
+
if (!meta)
|
|
2946
|
+
throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
|
|
2947
|
+
if (meta.isRelation)
|
|
2948
|
+
throw new ShapeError(`Nested relation writes inside nested data are not supported ("${model}.${fieldName}")`);
|
|
2949
|
+
if (meta.isUpdatedAt)
|
|
2950
|
+
throw new ShapeError(`updatedAt field "${fieldName}" cannot be used in nested data`);
|
|
2951
|
+
let fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
|
|
2952
|
+
if (!meta.isRequired) {
|
|
2953
|
+
fieldSchema = fieldSchema.nullable().optional();
|
|
2954
|
+
} else if (meta.hasDefault) {
|
|
2955
|
+
fieldSchema = fieldSchema.optional();
|
|
2956
|
+
}
|
|
2957
|
+
fieldSchemas[fieldName] = fieldSchema;
|
|
2958
|
+
}
|
|
2959
|
+
return z8.object(fieldSchemas).strict();
|
|
2960
|
+
}
|
|
2961
|
+
function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, config, typeMap, schemaBuilder) {
|
|
2962
|
+
const relatedFields = typeMap[relatedModelName];
|
|
2963
|
+
if (!relatedFields)
|
|
2964
|
+
throw new ShapeError(`Unknown related model "${relatedModelName}" for field "${model}.${fieldName}"`);
|
|
2965
|
+
for (const key of Object.keys(config)) {
|
|
2966
|
+
if (!KNOWN_RELATION_WRITE_OPS.has(key)) {
|
|
2967
|
+
throw new ShapeError(`Unknown relation write operation "${key}" on "${model}.${fieldName}". Allowed: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`);
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
const opSchemas = {};
|
|
2971
|
+
if (config.connect !== void 0) {
|
|
2972
|
+
if (!isPlainObject(config.connect)) {
|
|
2973
|
+
throw new ShapeError(`connect config on "${model}.${fieldName}" must be an object of field names`);
|
|
2974
|
+
}
|
|
2975
|
+
const connectSchema = buildWhereFieldsSchema(relatedModelName, config.connect, typeMap, schemaBuilder);
|
|
2976
|
+
opSchemas["connect"] = isList ? z8.union([connectSchema, z8.preprocess(coerceToArray, z8.array(connectSchema))]).optional() : connectSchema.optional();
|
|
2977
|
+
}
|
|
2978
|
+
if (config.connectOrCreate !== void 0) {
|
|
2979
|
+
if (!isPlainObject(config.connectOrCreate)) {
|
|
2980
|
+
throw new ShapeError(`connectOrCreate config on "${model}.${fieldName}" must be an object with "where" and "create"`);
|
|
2981
|
+
}
|
|
2982
|
+
const coc = config.connectOrCreate;
|
|
2983
|
+
if (!coc.where || !isPlainObject(coc.where)) {
|
|
2984
|
+
throw new ShapeError(`connectOrCreate on "${model}.${fieldName}" requires "where" object`);
|
|
2985
|
+
}
|
|
2986
|
+
if (!coc.create || !isPlainObject(coc.create)) {
|
|
2987
|
+
throw new ShapeError(`connectOrCreate on "${model}.${fieldName}" requires "create" object`);
|
|
2988
|
+
}
|
|
2989
|
+
const whereSchema = buildWhereFieldsSchema(relatedModelName, coc.where, typeMap, schemaBuilder);
|
|
2990
|
+
const createSchema = buildNestedDataSchema(relatedModelName, coc.create, typeMap, schemaBuilder);
|
|
2991
|
+
const cocSchema = z8.object({ where: whereSchema, create: createSchema }).strict();
|
|
2992
|
+
opSchemas["connectOrCreate"] = isList ? z8.union([cocSchema, z8.preprocess(coerceToArray, z8.array(cocSchema))]).optional() : cocSchema.optional();
|
|
2993
|
+
}
|
|
2994
|
+
if (config.create !== void 0) {
|
|
2995
|
+
if (!isPlainObject(config.create)) {
|
|
2996
|
+
throw new ShapeError(`create config on "${model}.${fieldName}" must be an object of field names`);
|
|
2997
|
+
}
|
|
2998
|
+
const createSchema = buildNestedDataSchema(relatedModelName, config.create, typeMap, schemaBuilder);
|
|
2999
|
+
opSchemas["create"] = isList ? z8.union([createSchema, z8.preprocess(coerceToArray, z8.array(createSchema))]).optional() : createSchema.optional();
|
|
3000
|
+
}
|
|
3001
|
+
if (config.createMany !== void 0) {
|
|
3002
|
+
if (!isList) {
|
|
3003
|
+
throw new ShapeError(`createMany is only valid on to-many relations ("${model}.${fieldName}")`);
|
|
3004
|
+
}
|
|
3005
|
+
if (!isPlainObject(config.createMany)) {
|
|
3006
|
+
throw new ShapeError(`createMany config on "${model}.${fieldName}" must be an object`);
|
|
3007
|
+
}
|
|
3008
|
+
const cmConfig = config.createMany;
|
|
3009
|
+
if (!cmConfig.data || !isPlainObject(cmConfig.data)) {
|
|
3010
|
+
throw new ShapeError(`createMany on "${model}.${fieldName}" requires "data" object`);
|
|
3011
|
+
}
|
|
3012
|
+
const dataSchema = buildNestedDataSchema(relatedModelName, cmConfig.data, typeMap, schemaBuilder);
|
|
3013
|
+
const cmSchemaFields = {
|
|
3014
|
+
data: z8.preprocess(coerceToArray, z8.array(dataSchema))
|
|
3015
|
+
};
|
|
3016
|
+
if ("skipDuplicates" in cmConfig) {
|
|
3017
|
+
cmSchemaFields["skipDuplicates"] = z8.boolean().optional();
|
|
3018
|
+
}
|
|
3019
|
+
opSchemas["createMany"] = z8.object(cmSchemaFields).strict().optional();
|
|
3020
|
+
}
|
|
3021
|
+
if (config.disconnect !== void 0) {
|
|
3022
|
+
if (config.disconnect === true) {
|
|
3023
|
+
if (isList) {
|
|
3024
|
+
throw new ShapeError(`disconnect on to-many relation "${model}.${fieldName}" requires field config, not true`);
|
|
3025
|
+
}
|
|
3026
|
+
opSchemas["disconnect"] = z8.literal(true).optional();
|
|
3027
|
+
} else if (isPlainObject(config.disconnect)) {
|
|
3028
|
+
const disconnectSchema = buildWhereFieldsSchema(relatedModelName, config.disconnect, typeMap, schemaBuilder);
|
|
3029
|
+
opSchemas["disconnect"] = isList ? z8.union([disconnectSchema, z8.preprocess(coerceToArray, z8.array(disconnectSchema))]).optional() : disconnectSchema.optional();
|
|
3030
|
+
} else {
|
|
3031
|
+
throw new ShapeError(`disconnect config on "${model}.${fieldName}" must be true (to-one) or an object of field names`);
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
if (config.delete !== void 0) {
|
|
3035
|
+
if (config.delete === true) {
|
|
3036
|
+
if (isList) {
|
|
3037
|
+
throw new ShapeError(`delete on to-many relation "${model}.${fieldName}" requires field config, not true`);
|
|
3038
|
+
}
|
|
3039
|
+
opSchemas["delete"] = z8.literal(true).optional();
|
|
3040
|
+
} else if (isPlainObject(config.delete)) {
|
|
3041
|
+
const deleteSchema = buildWhereFieldsSchema(relatedModelName, config.delete, typeMap, schemaBuilder);
|
|
3042
|
+
opSchemas["delete"] = isList ? z8.union([deleteSchema, z8.preprocess(coerceToArray, z8.array(deleteSchema))]).optional() : deleteSchema.optional();
|
|
3043
|
+
} else {
|
|
3044
|
+
throw new ShapeError(`delete config on "${model}.${fieldName}" must be true (to-one) or an object of field names`);
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
if (config.set !== void 0) {
|
|
3048
|
+
if (!isList) {
|
|
3049
|
+
throw new ShapeError(`set is only valid on to-many relations ("${model}.${fieldName}")`);
|
|
3050
|
+
}
|
|
3051
|
+
if (!isPlainObject(config.set)) {
|
|
3052
|
+
throw new ShapeError(`set config on "${model}.${fieldName}" must be an object of field names`);
|
|
3053
|
+
}
|
|
3054
|
+
const setSchema = buildWhereFieldsSchema(relatedModelName, config.set, typeMap, schemaBuilder);
|
|
3055
|
+
opSchemas["set"] = z8.preprocess(coerceToArray, z8.array(setSchema)).optional();
|
|
3056
|
+
}
|
|
3057
|
+
if (config.update !== void 0) {
|
|
3058
|
+
if (!isPlainObject(config.update)) {
|
|
3059
|
+
throw new ShapeError(`update config on "${model}.${fieldName}" must be an object`);
|
|
3060
|
+
}
|
|
3061
|
+
const updateConfig = config.update;
|
|
3062
|
+
if (isList) {
|
|
3063
|
+
if (!updateConfig.where || !isPlainObject(updateConfig.where)) {
|
|
3064
|
+
throw new ShapeError(`update on to-many "${model}.${fieldName}" requires "where" object`);
|
|
3065
|
+
}
|
|
3066
|
+
if (!updateConfig.data || !isPlainObject(updateConfig.data)) {
|
|
3067
|
+
throw new ShapeError(`update on to-many "${model}.${fieldName}" requires "data" object`);
|
|
3068
|
+
}
|
|
3069
|
+
const whereSchema = buildWhereFieldsSchema(relatedModelName, updateConfig.where, typeMap, schemaBuilder);
|
|
3070
|
+
const dataSchema = buildNestedDataSchema(relatedModelName, updateConfig.data, typeMap, schemaBuilder);
|
|
3071
|
+
const updateSchema = z8.object({ where: whereSchema, data: dataSchema }).strict();
|
|
3072
|
+
opSchemas["update"] = z8.union([updateSchema, z8.preprocess(coerceToArray, z8.array(updateSchema))]).optional();
|
|
3073
|
+
} else {
|
|
3074
|
+
const dataSchema = buildNestedDataSchema(relatedModelName, updateConfig, typeMap, schemaBuilder);
|
|
3075
|
+
opSchemas["update"] = dataSchema.optional();
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
if (config.upsert !== void 0) {
|
|
3079
|
+
if (!isPlainObject(config.upsert)) {
|
|
3080
|
+
throw new ShapeError(`upsert config on "${model}.${fieldName}" must be an object`);
|
|
3081
|
+
}
|
|
3082
|
+
const upsertConfig = config.upsert;
|
|
3083
|
+
if (!upsertConfig.where || !isPlainObject(upsertConfig.where)) {
|
|
3084
|
+
throw new ShapeError(`upsert on "${model}.${fieldName}" requires "where" object`);
|
|
3085
|
+
}
|
|
3086
|
+
if (!upsertConfig.create || !isPlainObject(upsertConfig.create)) {
|
|
3087
|
+
throw new ShapeError(`upsert on "${model}.${fieldName}" requires "create" object`);
|
|
3088
|
+
}
|
|
3089
|
+
if (!upsertConfig.update || !isPlainObject(upsertConfig.update)) {
|
|
3090
|
+
throw new ShapeError(`upsert on "${model}.${fieldName}" requires "update" object`);
|
|
3091
|
+
}
|
|
3092
|
+
const whereSchema = buildWhereFieldsSchema(relatedModelName, upsertConfig.where, typeMap, schemaBuilder);
|
|
3093
|
+
const createSchema = buildNestedDataSchema(relatedModelName, upsertConfig.create, typeMap, schemaBuilder);
|
|
3094
|
+
const updateSchema = buildNestedDataSchema(relatedModelName, upsertConfig.update, typeMap, schemaBuilder);
|
|
3095
|
+
const upsertSchema = z8.object({ where: whereSchema, create: createSchema, update: updateSchema }).strict();
|
|
3096
|
+
opSchemas["upsert"] = isList ? z8.union([upsertSchema, z8.preprocess(coerceToArray, z8.array(upsertSchema))]).optional() : upsertSchema.optional();
|
|
3097
|
+
}
|
|
3098
|
+
if (config.updateMany !== void 0) {
|
|
3099
|
+
if (!isList) {
|
|
3100
|
+
throw new ShapeError(`updateMany is only valid on to-many relations ("${model}.${fieldName}")`);
|
|
3101
|
+
}
|
|
3102
|
+
if (!isPlainObject(config.updateMany)) {
|
|
3103
|
+
throw new ShapeError(`updateMany config on "${model}.${fieldName}" must be an object`);
|
|
3104
|
+
}
|
|
3105
|
+
const umConfig = config.updateMany;
|
|
3106
|
+
if (!umConfig.where || !isPlainObject(umConfig.where)) {
|
|
3107
|
+
throw new ShapeError(`updateMany on "${model}.${fieldName}" requires "where" object`);
|
|
3108
|
+
}
|
|
3109
|
+
if (!umConfig.data || !isPlainObject(umConfig.data)) {
|
|
3110
|
+
throw new ShapeError(`updateMany on "${model}.${fieldName}" requires "data" object`);
|
|
3111
|
+
}
|
|
3112
|
+
const whereSchema = buildWhereFieldsSchema(relatedModelName, umConfig.where, typeMap, schemaBuilder);
|
|
3113
|
+
const dataSchema = buildNestedDataSchema(relatedModelName, umConfig.data, typeMap, schemaBuilder);
|
|
3114
|
+
const umSchema = z8.object({ where: whereSchema, data: dataSchema }).strict();
|
|
3115
|
+
opSchemas["updateMany"] = z8.union([umSchema, z8.preprocess(coerceToArray, z8.array(umSchema))]).optional();
|
|
3116
|
+
}
|
|
3117
|
+
if (config.deleteMany !== void 0) {
|
|
3118
|
+
if (!isList) {
|
|
3119
|
+
throw new ShapeError(`deleteMany is only valid on to-many relations ("${model}.${fieldName}")`);
|
|
3120
|
+
}
|
|
3121
|
+
if (!isPlainObject(config.deleteMany)) {
|
|
3122
|
+
throw new ShapeError(`deleteMany config on "${model}.${fieldName}" must be an object`);
|
|
3123
|
+
}
|
|
3124
|
+
const dmConfig = config.deleteMany;
|
|
3125
|
+
if (!dmConfig.where || !isPlainObject(dmConfig.where)) {
|
|
3126
|
+
throw new ShapeError(`deleteMany on "${model}.${fieldName}" requires "where" object`);
|
|
3127
|
+
}
|
|
3128
|
+
const whereSchema = buildWhereFieldsSchema(relatedModelName, dmConfig.where, typeMap, schemaBuilder);
|
|
3129
|
+
const dmSchema = z8.object({ where: whereSchema }).strict();
|
|
3130
|
+
opSchemas["deleteMany"] = z8.union([dmSchema, z8.preprocess(coerceToArray, z8.array(dmSchema))]).optional();
|
|
3131
|
+
}
|
|
3132
|
+
return z8.object(opSchemas).strict();
|
|
3133
|
+
}
|
|
2876
3134
|
function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDefaults) {
|
|
2877
3135
|
const modelFields = typeMap[model];
|
|
2878
3136
|
if (!modelFields)
|
|
@@ -2885,8 +3143,21 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
|
|
|
2885
3143
|
const fieldMeta = modelFields[fieldName];
|
|
2886
3144
|
if (!fieldMeta)
|
|
2887
3145
|
throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
|
|
2888
|
-
if (fieldMeta.isRelation)
|
|
2889
|
-
|
|
3146
|
+
if (fieldMeta.isRelation) {
|
|
3147
|
+
if (!isPlainObject(value)) {
|
|
3148
|
+
throw new ShapeError(`Relation field "${fieldName}" on model "${model}" requires a relation write config object`);
|
|
3149
|
+
}
|
|
3150
|
+
schemaMap[fieldName] = buildRelationWriteSchema(
|
|
3151
|
+
model,
|
|
3152
|
+
fieldName,
|
|
3153
|
+
fieldMeta.type,
|
|
3154
|
+
fieldMeta.isList,
|
|
3155
|
+
value,
|
|
3156
|
+
typeMap,
|
|
3157
|
+
schemaBuilder
|
|
3158
|
+
).optional();
|
|
3159
|
+
continue;
|
|
3160
|
+
}
|
|
2890
3161
|
if (fieldMeta.isUpdatedAt)
|
|
2891
3162
|
throw new ShapeError(`updatedAt field "${fieldName}" cannot be used in data shape`);
|
|
2892
3163
|
if (typeof value === "function") {
|