diff --git a/src/common/src/typegraph/runtimes/deno.rs b/src/common/src/typegraph/runtimes/deno.rs index c370c06d7..53f4e1daf 100644 --- a/src/common/src/typegraph/runtimes/deno.rs +++ b/src/common/src/typegraph/runtimes/deno.rs @@ -1,6 +1,7 @@ // Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. // SPDX-License-Identifier: MPL-2.0 +use anyhow::{anyhow, Context, Result}; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -11,6 +12,44 @@ pub struct FunctionMatData { pub script: String, } +#[derive(Serialize, Deserialize, Clone, Debug, Hash, PartialEq, Eq)] +#[serde(tag = "type", content = "value")] +#[serde(rename_all = "snake_case")] +pub enum ContextCheckX { + NonNull, + Value(String), + Pattern(String), +} + +#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "snake_case")] +#[serde(tag = "name", content = "param")] +pub enum PredefinedFunctionMatData { + Identity, + True, + False, + InternalPolicy, + ContextCheck { key: String, value: ContextCheckX }, +} + +#[derive(Serialize)] +struct PredefinedFunctionMatDataRaw { + name: String, + param: Option, +} + +impl PredefinedFunctionMatData { + pub fn from_raw(name: String, param: Option) -> Result { + let param = param + .map(|p| serde_json::from_str(&p)) + .transpose() + .context("invalid predefined function materializer parameter")?; + let value = serde_json::to_value(&PredefinedFunctionMatDataRaw { name, param })?; + serde_json::from_value(value) + .map_err(|e| anyhow!("invalid predefined function materializer: {e:?}")) + } +} + #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] pub struct ModuleMatData { diff --git a/src/typegate/src/runtimes/deno/deno.ts b/src/typegate/src/runtimes/deno/deno.ts index d05392b5e..9bd8173d2 100644 --- a/src/typegate/src/runtimes/deno/deno.ts +++ b/src/typegate/src/runtimes/deno/deno.ts @@ -29,11 +29,39 @@ import { getLogger } from "../../log.ts"; const logger = getLogger(import.meta); -const predefinedFuncs: Record>> = { - identity: ({ _, ...args }) => args, - true: () => true, - false: () => false, - internal_policy: ({ _: { context } }) => context.provider === "internal", +const predefinedFuncs: Record< + string, + (param: any) => Resolver> +> = { + identity: () => ({ _, ...args }) => args, + true: () => () => true, + false: () => () => false, + internal_policy: () => ({ _: { context } }) => + context.provider === "internal", + context_check: ({ key, value }) => { + let check: (value: any) => boolean; + switch (value.type) { + case "not_null": + check = (v) => v != null; + break; + case "value": + check = (v) => v === value.value; + break; + case "pattern": + check = (v) => new RegExp(value.value).test(v); + break; + default: + throw new Error("unreachable"); + } + const path = key.split("."); + return ({ _: { context } }) => { + let value: any = context; + for (const segment of path) { + value = value?.[segment]; + } + return check(value); + }; + }, }; export class DenoRuntime extends Runtime { @@ -237,7 +265,7 @@ export class DenoRuntime extends Runtime { if (!func) { throw new Error(`predefined function ${mat.data.name} not found`); } - return func; + return func(mat.data.param); } if (mat.name === "static") { diff --git a/src/typegate/src/typegraphs/introspection.json b/src/typegate/src/typegraphs/introspection.json index eeabf338f..3ce0afb4f 100644 --- a/src/typegate/src/typegraphs/introspection.json +++ b/src/typegate/src/typegraphs/introspection.json @@ -6,7 +6,7 @@ "policies": [], "properties": { "__type": 1, - "__schema": 45 + "__schema": 26 }, "id": [], "required": [ @@ -22,7 +22,6 @@ ], "input": 2, "output": 4, - "injections": {}, "runtimeConfig": null, "materializer": 0, "rate_weight": null, @@ -57,14 +56,14 @@ "properties": { "kind": 6, "name": 7, - "description": 8, - "specifiedByURL": 9, - "fields": 10, - "interfaces": 27, - "possibleTypes": 29, - "enumValues": 31, - "inputFields": 39, - "ofType": 44 + "description": 7, + "specifiedByURL": 7, + "fields": 8, + "interfaces": 18, + "possibleTypes": 18, + "enumValues": 20, + "inputFields": 24, + "ofType": 4 }, "id": [], "required": [] @@ -91,27 +90,12 @@ "item": 3, "default_value": null }, - { - "type": "optional", - "title": "type_description_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, - { - "type": "optional", - "title": "type_specifiedByURL_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "function", "title": "type_fields_fn", "policies": [], - "input": 11, - "output": 14, - "injections": {}, + "input": 9, + "output": 12, "runtimeConfig": null, "materializer": 1, "rate_weight": null, @@ -122,7 +106,7 @@ "title": "type_fields_fn_input", "policies": [], "properties": { - "includeDeprecated": 12 + "includeDeprecated": 10 }, "id": [], "required": [] @@ -131,7 +115,7 @@ "type": "optional", "title": "type_fields_fn_input_includeDeprecated_type_fields_fn_input_includeDeprecated_boolean_optional", "policies": [], - "item": 13, + "item": 11, "default_value": null }, { @@ -143,14 +127,14 @@ "type": "optional", "title": "type_fields_fn_output", "policies": [], - "item": 15, + "item": 13, "default_value": null }, { "type": "list", "title": "type_fields_fn_output", "policies": [], - "items": 16 + "items": 14 }, { "type": "object", @@ -158,56 +142,31 @@ "policies": [], "properties": { "name": 3, - "description": 17, - "args": 18, + "description": 7, + "args": 15, "type": 5, - "isDeprecated": 13, - "deprecationReason": 26 + "isDeprecated": 11, + "deprecationReason": 7 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "field_description_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "function", "title": "field_args_fn", "policies": [], - "input": 19, - "output": 21, - "injections": {}, + "input": 9, + "output": 16, "runtimeConfig": null, "materializer": 1, "rate_weight": null, "rate_calls": false }, - { - "type": "object", - "title": "field_args_fn_input", - "policies": [], - "properties": { - "includeDeprecated": 20 - }, - "id": [], - "required": [] - }, - { - "type": "optional", - "title": "field_args_fn_input_includeDeprecated_type_fields_fn_input_includeDeprecated_boolean_optional", - "policies": [], - "item": 13, - "default_value": null - }, { "type": "list", "title": "field_args_fn_output", "policies": [], - "items": 22 + "items": 17 }, { "type": "object", @@ -215,48 +174,20 @@ "policies": [], "properties": { "name": 3, - "description": 23, + "description": 7, "type": 5, - "defaultValue": 24, - "isDeprecated": 13, - "deprecationReason": 25 + "defaultValue": 7, + "isDeprecated": 11, + "deprecationReason": 7 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "input_value_description_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, - { - "type": "optional", - "title": "input_value_defaultValue_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, - { - "type": "optional", - "title": "input_value_deprecationReason_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, - { - "type": "optional", - "title": "field_deprecationReason_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "optional", "title": "type_interfaces_type_interfaces_type_list_optional", "policies": [], - "item": 28, + "item": 19, "default_value": null }, { @@ -265,60 +196,29 @@ "policies": [], "items": 5 }, - { - "type": "optional", - "title": "type_possibleTypes_type_possibleTypes_type_list_optional", - "policies": [], - "item": 30, - "default_value": null - }, - { - "type": "list", - "title": "type_possibleTypes_type_list", - "policies": [], - "items": 5 - }, { "type": "function", "title": "type_enumValues_fn", "policies": [], - "input": 32, - "output": 34, - "injections": {}, + "input": 9, + "output": 21, "runtimeConfig": null, "materializer": 1, "rate_weight": null, "rate_calls": false }, - { - "type": "object", - "title": "type_enumValues_fn_input", - "policies": [], - "properties": { - "includeDeprecated": 33 - }, - "id": [], - "required": [] - }, - { - "type": "optional", - "title": "type_enumValues_fn_input_includeDeprecated_type_fields_fn_input_includeDeprecated_boolean_optional", - "policies": [], - "item": 13, - "default_value": null - }, { "type": "optional", "title": "type_enumValues_fn_output", "policies": [], - "item": 35, + "item": 22, "default_value": null }, { "type": "list", "title": "type_enumValues_fn_output", "policies": [], - "items": 36 + "items": 23 }, { "type": "object", @@ -326,74 +226,29 @@ "policies": [], "properties": { "name": 3, - "description": 37, - "isDeprecated": 13, - "deprecationReason": 38 + "description": 7, + "isDeprecated": 11, + "deprecationReason": 7 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "enum_value_description_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, - { - "type": "optional", - "title": "enum_value_deprecationReason_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "function", "title": "type_inputFields_fn", "policies": [], - "input": 40, - "output": 42, - "injections": {}, + "input": 9, + "output": 25, "runtimeConfig": null, "materializer": 1, "rate_weight": null, "rate_calls": false }, - { - "type": "object", - "title": "type_inputFields_fn_input", - "policies": [], - "properties": { - "includeDeprecated": 41 - }, - "id": [], - "required": [] - }, - { - "type": "optional", - "title": "type_inputFields_fn_input_includeDeprecated_type_fields_fn_input_includeDeprecated_boolean_optional", - "policies": [], - "item": 13, - "default_value": null - }, { "type": "optional", "title": "type_inputFields_fn_output", "policies": [], - "item": 43, - "default_value": null - }, - { - "type": "list", - "title": "type_inputFields_fn_output", - "policies": [], - "items": 22 - }, - { - "type": "optional", - "title": "type_ofType_type_optional", - "policies": [], - "item": 5, + "item": 16, "default_value": null }, { @@ -402,9 +257,8 @@ "policies": [ 0 ], - "input": 46, - "output": 47, - "injections": {}, + "input": 27, + "output": 28, "runtimeConfig": null, "materializer": 3, "rate_weight": null, @@ -423,48 +277,21 @@ "title": "schema", "policies": [], "properties": { - "description": 48, - "types": 49, + "description": 7, + "types": 19, "queryType": 5, - "mutationType": 50, - "subscriptionType": 51, - "directives": 52 + "mutationType": 4, + "subscriptionType": 4, + "directives": 29 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "schema_description_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, - { - "type": "list", - "title": "schema_types_type_list", - "policies": [], - "items": 5 - }, - { - "type": "optional", - "title": "schema_mutationType_type_optional", - "policies": [], - "item": 5, - "default_value": null - }, - { - "type": "optional", - "title": "schema_subscriptionType_type_optional", - "policies": [], - "item": 5, - "default_value": null - }, { "type": "list", "title": "schema_directives_directive_list", "policies": [], - "items": 53 + "items": 30 }, { "type": "object", @@ -472,26 +299,19 @@ "policies": [], "properties": { "name": 3, - "description": 54, - "isRepeatable": 13, - "locations": 55, - "args": 57 + "description": 7, + "isRepeatable": 11, + "locations": 31, + "args": 15 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "directive_description_root___type_fn_input_name_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "list", "title": "directive_locations_directive_location_list", "policies": [], - "items": 56 + "items": 32 }, { "type": "string", @@ -518,41 +338,6 @@ "\"INPUT_OBJECT\"", "\"INPUT_FIELD_DEFINITION\"" ] - }, - { - "type": "function", - "title": "directive_args_fn", - "policies": [], - "input": 58, - "output": 60, - "injections": {}, - "runtimeConfig": null, - "materializer": 1, - "rate_weight": null, - "rate_calls": false - }, - { - "type": "object", - "title": "directive_args_fn_input", - "policies": [], - "properties": { - "includeDeprecated": 59 - }, - "id": [], - "required": [] - }, - { - "type": "optional", - "title": "directive_args_fn_input_includeDeprecated_type_fields_fn_input_includeDeprecated_boolean_optional", - "policies": [], - "item": 13, - "default_value": null - }, - { - "type": "list", - "title": "directive_args_fn_output", - "policies": [], - "items": 22 } ], "materializers": [ @@ -635,4 +420,4 @@ "randomSeed": null, "artifacts": {} } -} +} \ No newline at end of file diff --git a/src/typegate/src/typegraphs/prisma_migration.json b/src/typegate/src/typegraphs/prisma_migration.json index 6d5d98040..3fe31a2a2 100644 --- a/src/typegate/src/typegraphs/prisma_migration.json +++ b/src/typegate/src/typegraphs/prisma_migration.json @@ -6,10 +6,10 @@ "policies": [], "properties": { "diff": 1, - "apply": 8, - "create": 14, - "deploy": 21, - "reset": 27 + "apply": 7, + "create": 11, + "deploy": 14, + "reset": 18 }, "id": [], "required": [ @@ -28,7 +28,6 @@ ], "input": 2, "output": 6, - "injections": {}, "runtimeConfig": null, "materializer": 0, "rate_weight": null, @@ -68,28 +67,20 @@ "title": "root_diff_fn_output", "policies": [], "properties": { - "diff": 7, + "diff": 4, "runtimeName": 3 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "root_diff_fn_output_diff_root_diff_fn_input_typegraph_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "function", "title": "root_apply_fn", "policies": [ 0 ], - "input": 9, - "output": 12, - "injections": {}, + "input": 8, + "output": 9, "runtimeConfig": null, "materializer": 2, "rate_weight": null, @@ -101,34 +92,20 @@ "policies": [], "properties": { "typegraph": 3, - "runtime": 10, - "migrations": 11, + "runtime": 4, + "migrations": 4, "resetDatabase": 5 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "root_apply_fn_input_runtime_root_diff_fn_input_typegraph_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, - { - "type": "optional", - "title": "root_apply_fn_input_migrations_root_diff_fn_input_typegraph_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "object", "title": "root_apply_fn_output", "policies": [], "properties": { "databaseReset": 5, - "appliedMigrations": 13 + "appliedMigrations": 10 }, "id": [], "required": [] @@ -145,9 +122,8 @@ "policies": [ 0 ], - "input": 15, - "output": 18, - "injections": {}, + "input": 12, + "output": 13, "runtimeConfig": null, "materializer": 3, "rate_weight": null, @@ -159,64 +135,35 @@ "policies": [], "properties": { "typegraph": 3, - "runtime": 16, + "runtime": 4, "name": 3, "apply": 5, - "migrations": 17 + "migrations": 4 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "root_create_fn_input_runtime_root_diff_fn_input_typegraph_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, - { - "type": "optional", - "title": "root_create_fn_input_migrations_root_diff_fn_input_typegraph_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "object", "title": "root_create_fn_output", "policies": [], "properties": { "createdMigrationName": 3, - "applyError": 19, - "migrations": 20, + "applyError": 4, + "migrations": 4, "runtimeName": 3 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "root_create_fn_output_applyError_root_diff_fn_input_typegraph_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, - { - "type": "optional", - "title": "root_create_fn_output_migrations_root_diff_fn_input_typegraph_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "function", "title": "root_deploy_fn", "policies": [ 0 ], - "input": 22, - "output": 24, - "injections": {}, + "input": 15, + "output": 16, "runtimeConfig": null, "materializer": 4, "rate_weight": null, @@ -228,26 +175,19 @@ "policies": [], "properties": { "typegraph": 3, - "runtime": 23, + "runtime": 4, "migrations": 3 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "root_deploy_fn_input_runtime_root_diff_fn_input_typegraph_string_optional", - "policies": [], - "item": 3, - "default_value": null - }, { "type": "object", "title": "root_deploy_fn_output", "policies": [], "properties": { - "migrationCount": 25, - "appliedMigrations": 26 + "migrationCount": 17, + "appliedMigrations": 10 }, "id": [], "required": [] @@ -257,21 +197,14 @@ "title": "root_deploy_fn_output_migrationCount_integer", "policies": [] }, - { - "type": "list", - "title": "root_deploy_fn_output_appliedMigrations_root_diff_fn_input_typegraph_string_list", - "policies": [], - "items": 3 - }, { "type": "function", "title": "root_reset_fn", "policies": [ 0 ], - "input": 28, + "input": 19, "output": 5, - "injections": {}, "runtimeConfig": null, "materializer": 5, "rate_weight": null, @@ -283,17 +216,10 @@ "policies": [], "properties": { "typegraph": 3, - "runtime": 29 + "runtime": 4 }, "id": [], "required": [] - }, - { - "type": "optional", - "title": "root_reset_fn_input_runtime_root_diff_fn_input_typegraph_string_optional", - "policies": [], - "item": 3, - "default_value": null } ], "materializers": [ @@ -411,4 +337,4 @@ "randomSeed": null, "artifacts": {} } -} +} \ No newline at end of file diff --git a/src/typegate/src/typegraphs/typegate.json b/src/typegate/src/typegraphs/typegate.json index 391ec404f..4493070de 100644 --- a/src/typegate/src/typegraphs/typegate.json +++ b/src/typegate/src/typegraphs/typegate.json @@ -10,13 +10,13 @@ "addTypegraph": 12, "removeTypegraphs": 22, "argInfoByPath": 26, - "findAvailableOperations": 40, - "findPrismaModels": 48, - "execRawPrismaRead": 54, - "execRawPrismaCreate": 66, - "execRawPrismaUpdate": 67, - "execRawPrismaDelete": 68, - "queryPrismaModel": 69 + "findAvailableOperations": 37, + "findPrismaModels": 45, + "execRawPrismaRead": 51, + "execRawPrismaCreate": 62, + "execRawPrismaUpdate": 63, + "execRawPrismaDelete": 64, + "queryPrismaModel": 65 }, "id": [], "required": [ @@ -42,7 +42,6 @@ ], "input": 2, "output": 3, - "injections": {}, "runtimeConfig": null, "materializer": 0, "rate_weight": null, @@ -92,7 +91,6 @@ ], "input": 8, "output": 9, - "injections": {}, "runtimeConfig": null, "materializer": 2, "rate_weight": null, @@ -133,7 +131,6 @@ "policies": [], "input": 2, "output": 5, - "injections": {}, "runtimeConfig": null, "materializer": 3, "rate_weight": null, @@ -147,7 +144,6 @@ ], "input": 13, "output": 15, - "injections": {}, "runtimeConfig": null, "materializer": 4, "rate_weight": null, @@ -243,7 +239,6 @@ ], "input": 23, "output": 25, - "injections": {}, "runtimeConfig": null, "materializer": 5, "rate_weight": null, @@ -277,8 +272,7 @@ 0 ], "input": 27, - "output": 30, - "injections": {}, + "output": 29, "runtimeConfig": null, "materializer": 6, "rate_weight": null, @@ -299,21 +293,15 @@ }, { "type": "list", - "title": "root_argInfoByPath_fn_input_argPaths_root_argInfoByPath_fn_input_argPaths_Typegraph_name_string_list_list", + "title": "root_argInfoByPath_fn_input_argPaths_root_removeTypegraphs_fn_input_names_Typegraph_name_string_list_list", "policies": [], - "items": 29 - }, - { - "type": "list", - "title": "root_argInfoByPath_fn_input_argPaths_Typegraph_name_string_list", - "policies": [], - "items": 5 + "items": 24 }, { "type": "list", "title": "root_argInfoByPath_fn_output", "policies": [], - "items": 31 + "items": 30 }, { "type": "object", @@ -323,11 +311,11 @@ "optional": 25, "title": 5, "type": 5, - "enum": 32, - "default": 34, - "format": 35, - "policies": 36, - "fields": 37 + "enum": 31, + "default": 21, + "format": 33, + "policies": 24, + "fields": 34 }, "id": [], "required": [] @@ -336,7 +324,7 @@ "type": "optional", "title": "TypeInfo_enum_TypeInfo_enum_root_addTypegraph_fn_input_fromString_string_json_list_optional", "policies": [], - "item": 33, + "item": 32, "default_value": null }, { @@ -345,13 +333,6 @@ "policies": [], "items": 14 }, - { - "type": "optional", - "title": "TypeInfo_default_root_addTypegraph_fn_input_fromString_string_json_optional", - "policies": [], - "item": 14, - "default_value": null - }, { "type": "optional", "title": "TypeInfo_format_Typegraph_name_string_optional", @@ -359,32 +340,26 @@ "item": 5, "default_value": null }, - { - "type": "list", - "title": "TypeInfo_policies_Typegraph_name_string_list", - "policies": [], - "items": 5 - }, { "type": "optional", "title": "TypeInfo_fields_TypeInfo_fields_TypeInfo_fields_struct_list_optional", "policies": [], - "item": 38, + "item": 35, "default_value": null }, { "type": "list", "title": "TypeInfo_fields_TypeInfo_fields_struct_list", "policies": [], - "items": 39 + "items": 36 }, { "type": "object", "title": "TypeInfo_fields_struct", "policies": [], "properties": { - "subPath": 29, - "termNode": 31 + "subPath": 24, + "termNode": 30 }, "id": [], "required": [] @@ -395,9 +370,8 @@ "policies": [ 0 ], - "input": 41, - "output": 42, - "injections": {}, + "input": 38, + "output": 39, "runtimeConfig": null, "materializer": 7, "rate_weight": null, @@ -417,7 +391,7 @@ "type": "list", "title": "root_findAvailableOperations_fn_output", "policies": [], - "items": 43 + "items": 40 }, { "type": "object", @@ -425,10 +399,10 @@ "policies": [], "properties": { "name": 5, - "type": 44, - "inputs": 45, - "output": 31, - "outputItem": 47 + "type": 41, + "inputs": 42, + "output": 30, + "outputItem": 44 }, "id": [], "required": [] @@ -446,7 +420,7 @@ "type": "list", "title": "OperationInfo_inputs_OperationInfo_inputs_struct_list", "policies": [], - "items": 46 + "items": 43 }, { "type": "object", @@ -454,7 +428,7 @@ "policies": [], "properties": { "name": 5, - "type": 31 + "type": 30 }, "id": [], "required": [] @@ -463,7 +437,7 @@ "type": "optional", "title": "OperationInfo_outputItem_TypeInfo_optional", "policies": [], - "item": 31, + "item": 30, "default_value": null }, { @@ -472,9 +446,8 @@ "policies": [ 0 ], - "input": 41, - "output": 49, - "injections": {}, + "input": 38, + "output": 46, "runtimeConfig": null, "materializer": 8, "rate_weight": null, @@ -484,7 +457,7 @@ "type": "list", "title": "root_findPrismaModels_fn_output", "policies": [], - "items": 50 + "items": 47 }, { "type": "object", @@ -493,7 +466,7 @@ "properties": { "name": 5, "runtime": 5, - "fields": 51 + "fields": 48 }, "id": [], "required": [] @@ -502,7 +475,7 @@ "type": "list", "title": "PrismaModelInfo_fields_PrismaModelInfo_fields_struct_list", "policies": [], - "items": 52 + "items": 49 }, { "type": "object", @@ -511,7 +484,7 @@ "properties": { "name": 5, "as_id": 25, - "type": 53 + "type": 50 }, "id": [], "required": [] @@ -524,10 +497,10 @@ "optional": 25, "title": 5, "type": 5, - "enum": 32, - "default": 34, - "format": 35, - "policies": 36 + "enum": 31, + "default": 21, + "format": 33, + "policies": 24 }, "id": [], "required": [] @@ -538,9 +511,8 @@ "policies": [ 0 ], - "input": 55, + "input": 52, "output": 14, - "injections": {}, "runtimeConfig": null, "materializer": 9, "rate_weight": null, @@ -553,7 +525,7 @@ "properties": { "typegraph": 5, "runtime": 5, - "query": 56 + "query": 53 }, "id": [], "required": [] @@ -563,8 +535,8 @@ "title": "PrismaQuery", "policies": [], "oneOf": [ - 57, - 60 + 54, + 56 ] }, { @@ -572,20 +544,13 @@ "title": "PrismaSingleQuery", "policies": [], "properties": { - "modelName": 58, - "action": 59, + "modelName": 33, + "action": 55, "query": 14 }, "id": [], "required": [] }, - { - "type": "optional", - "title": "PrismaSingleQuery_modelName_Typegraph_name_string_optional", - "policies": [], - "item": 5, - "default_value": null - }, { "type": "string", "title": "PrismaQueryTag", @@ -616,8 +581,8 @@ "title": "PrismaBatchQuery", "policies": [], "properties": { - "batch": 61, - "transaction": 62 + "batch": 57, + "transaction": 58 }, "id": [], "required": [] @@ -626,13 +591,13 @@ "type": "list", "title": "PrismaBatchQuery_batch_PrismaSingleQuery_list", "policies": [], - "items": 57 + "items": 54 }, { "type": "optional", "title": "PrismaBatchQuery_transaction_PrismaBatchQuery_transaction_struct_optional", "policies": [], - "item": 63, + "item": 59, "default_value": null }, { @@ -640,7 +605,7 @@ "title": "PrismaBatchQuery_transaction_struct", "policies": [], "properties": { - "isolationLevel": 64 + "isolationLevel": 60 }, "id": [], "required": [] @@ -649,7 +614,7 @@ "type": "optional", "title": "PrismaBatchQuery_transaction_struct_isolationLevel_PrismaBatchQuery_transaction_struct_isolationLevel_string_enum_optional", "policies": [], - "item": 65, + "item": 61, "default_value": null }, { @@ -673,9 +638,8 @@ "policies": [ 0 ], - "input": 55, + "input": 52, "output": 14, - "injections": {}, "runtimeConfig": null, "materializer": 10, "rate_weight": null, @@ -687,9 +651,8 @@ "policies": [ 0 ], - "input": 55, + "input": 52, "output": 14, - "injections": {}, "runtimeConfig": null, "materializer": 11, "rate_weight": null, @@ -701,9 +664,8 @@ "policies": [ 0 ], - "input": 55, + "input": 52, "output": 14, - "injections": {}, "runtimeConfig": null, "materializer": 12, "rate_weight": null, @@ -715,9 +677,8 @@ "policies": [ 0 ], - "input": 70, - "output": 72, - "injections": {}, + "input": 66, + "output": 68, "runtimeConfig": null, "materializer": 13, "rate_weight": null, @@ -731,8 +692,8 @@ "typegraph": 5, "runtime": 5, "model": 5, - "offset": 71, - "limit": 71 + "offset": 67, + "limit": 67 }, "id": [], "required": [] @@ -747,24 +708,12 @@ "title": "root_queryPrismaModel_fn_output", "policies": [], "properties": { - "fields": 73, - "rowCount": 71, - "data": 74 + "fields": 48, + "rowCount": 67, + "data": 32 }, "id": [], "required": [] - }, - { - "type": "list", - "title": "root_queryPrismaModel_fn_output_fields_PrismaModelInfo_fields_struct_list", - "policies": [], - "items": 52 - }, - { - "type": "list", - "title": "root_queryPrismaModel_fn_output_data_root_addTypegraph_fn_input_fromString_string_json_list", - "policies": [], - "items": 14 } ], "materializers": [ @@ -778,15 +727,21 @@ "data": {} }, { - "name": "function", + "name": "predefined_function", "runtime": 0, "effect": { "effect": "read", "idempotent": true }, "data": { - "script": "var _my_lambda = (_args, { context }) => context.username === 'admin'", - "secrets": [] + "name": "context_check", + "param": { + "key": "username", + "value": { + "type": "value", + "value": "admin" + } + } } }, { @@ -913,7 +868,7 @@ ], "policies": [ { - "name": "admin_only", + "name": "__ctx_username_admin", "materializer": 1 } ], @@ -956,4 +911,4 @@ "randomSeed": null, "artifacts": {} } -} +} \ No newline at end of file diff --git a/src/typegate/src/typegraphs/typegate.py b/src/typegate/src/typegraphs/typegate.py index 2b6552783..daaa3e7fd 100644 --- a/src/typegate/src/typegraphs/typegate.py +++ b/src/typegate/src/typegraphs/typegate.py @@ -1,12 +1,11 @@ # Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. # SPDX-License-Identifier: MPL-2.0 -from typegraph import Graph, fx, t, typegraph +from typegraph import Graph, fx, t, typegraph, Policy from typegraph.gen.exports.runtimes import TypegateOperation from typegraph.gen.types import Err from typegraph.graph.params import Auth, Cors, Rate from typegraph.runtimes.base import Materializer -from typegraph.runtimes.deno import DenoRuntime from typegraph.wit import runtimes, store ### Prisma query (Json protocol): @@ -95,10 +94,7 @@ ), ) def typegate(g: Graph): - deno = DenoRuntime() - admin_only = deno.policy( - "admin_only", code="(_args, { context }) => context.username === 'admin'" - ) + admin_only = Policy.context("username", "admin") g.auth(Auth.basic(["admin"])) diff --git a/src/typegraph/core/src/conversion/runtimes.rs b/src/typegraph/core/src/conversion/runtimes.rs index 76c7dc89e..537bd4e7d 100644 --- a/src/typegraph/core/src/conversion/runtimes.rs +++ b/src/typegraph/core/src/conversion/runtimes.rs @@ -128,10 +128,7 @@ impl MaterializerConverter for DenoMaterializer { ("import_function".to_string(), data) } Predefined(predef) => { - let data = serde_json::from_value(json!({ - "name": predef.name, - })) - .unwrap(); + let data = serde_json::from_value(serde_json::to_value(predef).unwrap()).unwrap(); ("predefined_function".to_string(), data) } }; diff --git a/src/typegraph/core/src/errors.rs b/src/typegraph/core/src/errors.rs index ef33a1421..0f8804b1f 100644 --- a/src/typegraph/core/src/errors.rs +++ b/src/typegraph/core/src/errors.rs @@ -143,10 +143,6 @@ pub fn object_not_found(kind: &str, id: u32) -> TgError { // .into() // } -pub fn unknown_predefined_function(name: &str, runtime: &str) -> TgError { - format!("unknown predefined function {name} for runtime {runtime}").into() -} - pub fn duplicate_policy_name(name: &str) -> TgError { format!("duplicate policy name '{name}'").into() } diff --git a/src/typegraph/core/src/global_store.rs b/src/typegraph/core/src/global_store.rs index e318e6d09..7d3431359 100644 --- a/src/typegraph/core/src/global_store.rs +++ b/src/typegraph/core/src/global_store.rs @@ -14,6 +14,7 @@ use crate::wit::utils::Auth as WitAuth; #[allow(unused)] use crate::wit::runtimes::{Effect, MaterializerDenoPredefined, MaterializerId}; +use common::typegraph::runtimes::deno::PredefinedFunctionMatData; use graphql_parser::parse_query; use indexmap::IndexMap; use std::rc::Rc; @@ -55,7 +56,7 @@ pub struct Store { pub policies: Vec, deno_runtime: RuntimeId, - predefined_deno_functions: HashMap, + predefined_deno_functions: HashMap, deno_modules: IndexMap, public_policy_id: PolicyId, @@ -88,9 +89,7 @@ impl Store { runtime_id: deno_runtime, effect: Effect::Read, data: MaterializerData::Deno(Rc::new(DenoMaterializer::Predefined( - crate::wit::runtimes::MaterializerDenoPredefined { - name: "true".to_string(), - }, + PredefinedFunctionMatData::True, ))), }], @@ -104,8 +103,6 @@ impl Store { } } -const PREDEFINED_DENO_FUNCTIONS: &[&str] = &["identity", "true"]; - thread_local! { pub static STORE: RefCell = RefCell::new(Store::new()); pub static SDK_VERSION: String = "0.5.0-rc.8".to_owned(); @@ -350,25 +347,24 @@ impl Store { with_store(|s| s.public_policy_id) } - pub fn get_predefined_deno_function(name: String) -> Result { - if let Some(mat) = with_store(|s| s.predefined_deno_functions.get(&name).cloned()) { - Ok(mat) - } else if !PREDEFINED_DENO_FUNCTIONS.iter().any(|n| n == &name) { - Err(errors::unknown_predefined_function(&name, "deno")) + pub fn get_predefined_deno_function( + name: String, + param: Option, + ) -> Result { + let mat = PredefinedFunctionMatData::from_raw(name, param)?; + if let Some(mat_id) = with_store(|s| s.predefined_deno_functions.get(&mat).cloned()) { + Ok(mat_id) } else { let runtime_id = Store::get_deno_runtime(); - let mat = Store::register_materializer(Materializer { + let mat_id = Store::register_materializer(Materializer { runtime_id, effect: Effect::Read, - data: Rc::new(DenoMaterializer::Predefined(MaterializerDenoPredefined { - name: name.clone(), - })) - .into(), + data: Rc::new(DenoMaterializer::Predefined(mat.clone())).into(), }); with_store_mut(|s| { - s.predefined_deno_functions.insert(name, mat); + s.predefined_deno_functions.insert(mat, mat_id); }); - Ok(mat) + Ok(mat_id) } } diff --git a/src/typegraph/core/src/lib.rs b/src/typegraph/core/src/lib.rs index 37f912657..ad44a5543 100644 --- a/src/typegraph/core/src/lib.rs +++ b/src/typegraph/core/src/lib.rs @@ -19,10 +19,10 @@ mod test_utils; use std::collections::HashSet; +use common::typegraph::runtimes::deno::{ContextCheckX, PredefinedFunctionMatData}; use common::typegraph::Injection; use errors::{Result, TgError}; use global_store::Store; -use indoc::formatdoc; use params::apply; use regex::Regex; use runtimes::{DenoMaterializer, Materializer}; @@ -38,7 +38,7 @@ use wit::core::{ TypeEither, TypeFile, TypeFloat, TypeFunc, TypeId as CoreTypeId, TypeInteger, TypeList, TypeOptional, TypeString, TypeStruct, TypeUnion, TypegraphInitParams, }; -use wit::runtimes::{Guest, MaterializerDenoFunc}; +use wit::runtimes::{Guest, MaterializerDenoPredefined}; pub mod wit { wit_bindgen::generate!({ @@ -52,6 +52,16 @@ pub mod wit { pub struct Lib {} +impl From for ContextCheckX { + fn from(check: ContextCheck) -> Self { + match check { + ContextCheck::NotNull => ContextCheckX::NonNull, + ContextCheck::Value(v) => ContextCheckX::Value(v), + ContextCheck::Pattern(p) => ContextCheckX::Pattern(p), + } + } +} + impl wit::core::Guest for Lib { fn init_typegraph(params: TypegraphInitParams) -> Result<()> { typegraph::init(params) @@ -185,9 +195,7 @@ impl wit::core::Guest for Lib { } fn get_internal_policy() -> Result<(PolicyId, String)> { - let deno_mat = DenoMaterializer::Predefined(wit::runtimes::MaterializerDenoPredefined { - name: "internal_policy".to_string(), - }); + let deno_mat = DenoMaterializer::Predefined(PredefinedFunctionMatData::InternalPolicy); let mat = Materializer::deno(deno_mat, crate::wit::runtimes::Effect::Read); let policy_id = Store::register_policy( Policy { @@ -213,39 +221,19 @@ impl wit::core::Guest for Lib { .replace_all(&name, "_") .to_string(); - let check = match check { - ContextCheck::NotNull => "value != null".to_string(), - ContextCheck::Value(val) => { - format!("value === {}", serde_json::to_string(&val).unwrap()) - } - ContextCheck::Pattern(pattern) => { - format!( - "new RegExp({}).test(value)", - serde_json::to_string(&pattern).unwrap() - ) - } - }; + let check: ContextCheckX = check.into(); + let check = serde_json::json!({ + "key": key, + "value": check, + }); - let key = serde_json::to_string(&key).unwrap(); - - let code = formatdoc! {r#" - (_, {{ context }}) => {{ - const chunks = {key}.split("."); - let value = context; - for (const chunk of chunks) {{ - value = value?.[chunk]; - }} - return {check}; - }} - "# }; - - let mat_id = Lib::register_deno_func( - MaterializerDenoFunc { - code, - secrets: vec![], - }, - wit::runtimes::Effect::Read, - )?; + let mat_id = Lib::get_predefined_deno_func(MaterializerDenoPredefined { + name: "context_check".to_string(), + param: Some( + serde_json::to_string(&check) + .map_err(|e| format!("Error while serializing context check: {e:?}"))?, + ), + })?; Lib::register_policy(Policy { name: name.clone(), diff --git a/src/typegraph/core/src/runtimes/deno.rs b/src/typegraph/core/src/runtimes/deno.rs index fe34beae5..eb89f6a0f 100644 --- a/src/typegraph/core/src/runtimes/deno.rs +++ b/src/typegraph/core/src/runtimes/deno.rs @@ -1,6 +1,8 @@ // Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. // SPDX-License-Identifier: MPL-2.0 +use common::typegraph::runtimes::deno::PredefinedFunctionMatData; + use crate::wit::runtimes as wit; #[derive(Debug)] @@ -25,7 +27,7 @@ pub struct MaterializerDenoStatic { pub enum DenoMaterializer { Static(MaterializerDenoStatic), Inline(wit::MaterializerDenoFunc), - Predefined(wit::MaterializerDenoPredefined), + Predefined(PredefinedFunctionMatData), Module(MaterializerDenoModule), Import(MaterializerDenoImport), } diff --git a/src/typegraph/core/src/runtimes/mod.rs b/src/typegraph/core/src/runtimes/mod.rs index 704b86296..73606efb2 100644 --- a/src/typegraph/core/src/runtimes/mod.rs +++ b/src/typegraph/core/src/runtimes/mod.rs @@ -295,7 +295,7 @@ impl crate::wit::runtimes::Guest for crate::Lib { fn get_predefined_deno_func( data: wit::MaterializerDenoPredefined, ) -> Result { - Store::get_predefined_deno_function(data.name) + Store::get_predefined_deno_function(data.name, data.param) } fn import_deno_function( diff --git a/src/typegraph/core/src/validation/errors.rs b/src/typegraph/core/src/validation/errors.rs index 41c4467f5..63e11f7a2 100644 --- a/src/typegraph/core/src/validation/errors.rs +++ b/src/typegraph/core/src/validation/errors.rs @@ -17,7 +17,3 @@ pub fn invalid_output_type_predefined(name: &str, expected: &str, got: &str) -> ) .into() } - -pub fn unknown_predefined_function(name: &str) -> Error { - format!("unknown predefined function {}", name).into() -} diff --git a/src/typegraph/core/src/validation/materializers.rs b/src/typegraph/core/src/validation/materializers.rs index 23c3023b4..57c6e0d62 100644 --- a/src/typegraph/core/src/validation/materializers.rs +++ b/src/typegraph/core/src/validation/materializers.rs @@ -1,6 +1,8 @@ // Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. // SPDX-License-Identifier: MPL-2.0 +use common::typegraph::runtimes::deno::PredefinedFunctionMatData; + use crate::runtimes::{DenoMaterializer, MaterializerData, Runtime}; use crate::types::{AsTypeDefEx as _, TypeDef, TypeId}; use crate::wit::core::TypeFunc; @@ -26,31 +28,34 @@ impl Materializer { fn validate_deno_mat(mat_data: &DenoMaterializer, func: &TypeFunc) -> Result<()> { match mat_data { DenoMaterializer::Predefined(predef) => { - match predef.name.as_str() { - "identity" => { + use PredefinedFunctionMatData as P; + match predef { + P::Identity => { if !type_utils::is_equal(func.inp.into(), func.out.into())? { return Err(errors::invalid_output_type_predefined( - &predef.name, + "identity", &TypeId(func.inp).repr()?, &TypeId(func.out).repr()?, )); } } - - "true" | "false" => { + P::True | P::False | P::InternalPolicy | P::ContextCheck { .. } => { if let Ok(xdef) = TypeId(func.out).as_xdef() { let TypeDef::Boolean(_) = xdef.type_def else { return Err(errors::invalid_output_type_predefined( - &predef.name, + match predef { + P::True => "true", + P::False => "false", + P::InternalPolicy => "internal_policy", + P::ContextCheck { .. } => "context_check", + _ => unreachable!(), + }, "bool", &TypeId(func.out).repr()?, )); }; } } - _ => { - return Err(errors::unknown_predefined_function(&predef.name)); - } } Ok(()) } diff --git a/src/typegraph/core/wit/typegraph.wit b/src/typegraph/core/wit/typegraph.wit index cda10f336..c99c057dc 100644 --- a/src/typegraph/core/wit/typegraph.wit +++ b/src/typegraph/core/wit/typegraph.wit @@ -268,6 +268,7 @@ interface runtimes { record materializer-deno-predefined { name: string, + param: option, } record materializer-deno-import { diff --git a/src/typegraph/deno/src/runtimes/deno.ts b/src/typegraph/deno/src/runtimes/deno.ts index 9eb821093..36b2dce64 100644 --- a/src/typegraph/deno/src/runtimes/deno.ts +++ b/src/typegraph/deno/src/runtimes/deno.ts @@ -134,9 +134,9 @@ export class DenoRuntime extends Runtime { fetchContext(outputShape?: C): t.Func { const returnValue = outputShape ? `context` : "JSON.stringify(context)"; return this.func( - t.struct({}), + t.struct({}), outputShape ?? t.json(), - { code: `(_, { context }) => ${returnValue}` } + { code: `(_, { context }) => ${returnValue}` }, ); } diff --git a/src/typegraph/python/typegraph/runtimes/deno.py b/src/typegraph/python/typegraph/runtimes/deno.py index 08dc00512..b223c0e1a 100644 --- a/src/typegraph/python/typegraph/runtimes/deno.py +++ b/src/typegraph/python/typegraph/runtimes/deno.py @@ -118,7 +118,7 @@ def identity(self, inp: "t.struct") -> "t.func": from typegraph import t res = runtimes.get_predefined_deno_func( - store, MaterializerDenoPredefined(name="identity") + store, MaterializerDenoPredefined(name="identity", param=None) ) if isinstance(res, Err): raise Exception(res.value)