mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-17 12:31:52 +03:00
8726236a9d
26 Commits
Author | SHA1 | Message | Date | |
---|---|---|---|---|
Samir Talwar
|
342391f39d |
Upgrade Ormolu to v0.5.
This upgrades the version of Ormolu required by the HGE repository to v0.5.0.1, and reformats all code accordingly. Ormolu v0.5 reformats code that uses infix operators. This is mostly useful, adding newlines and indentation to make it clear which operators are applied first, but in some cases, it's unpleasant. To make this easier on the eyes, I had to do the following: * Add a few fixity declarations (search for `infix`) * Add parentheses to make precedence clear, allowing Ormolu to keep everything on one line * Rename `relevantEq` to `(==~)` in #6651 and set it to `infix 4` * Add a few _.ormolu_ files (thanks to @hallettj for helping me get started), mostly for Autodocodec operators that don't have explicit fixity declarations In general, I think these changes are quite reasonable. They mostly affect indentation. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6675 GitOrigin-RevId: cd47d87f1d089fb0bc9dcbbe7798dbceedcd7d83 |
||
Vamshi Surabhi
|
c2a1d30765 |
simplify type collection for introspection
No user facing changes. Minor cleanup. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6519 GitOrigin-RevId: 7d9b6077a609175642059895800e9c540cf62790 |
||
Samir Talwar
|
f01c7f4ee6 |
server: Remove QErr and Code dependencies from the schema parsers.
In the process of decoupling the schema parsers from the GraphQL Engine, we need to remove dependencies on `Hasura.Base.Error`. First of all, we have avoided using `QErr` in schema parsers code, instead returning a more appropriate data type which can be converted to a `Hasura.Base.Error.QErr` later. Secondly, we create a new `ParseErrorCode` type to represent parse failure types, which are then converted to a `Hasura.Base.Error.Code` later. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5181 GitOrigin-RevId: 8655e26adb1e7d5e3d552c77a8a403f987b53467 |
||
paritosh-08
|
95adde4ce2 |
server: support for Apollo federation
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4584 Co-authored-by: Auke Booij <164426+abooij@users.noreply.github.com> GitOrigin-RevId: 0f60c263efb5fbaa25620dd8159e8cfda25a61b2 |
||
Samir Talwar
|
33b19c327c |
Replace Data.Text.Extended with ErrorMessage in a few more places.
Mostly in the schema parsers code, to reduce its exposure to the rest of the codebase. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5088 GitOrigin-RevId: 752fcc10b4748b601e2e5313db326fe7f84febb4 |
||
Auke Booij
|
8ccf7724ce |
server: Metadata origin for definitions (type parameter version v2)
The code that builds the GraphQL schema, and `buildGQLContext` in particular, is partial: not every value of `(ServerConfigCtx, GraphQLQueryType, SourceCache, HashMap RemoteSchemaName (RemoteSchemaCtx, MetadataObject), ActionCache, AnnotatedCustomTypes)` results in a valid GraphQL schema. When it fails, we want to be able to return better error messages than we currently do. The key thing that is missing is a way to trace back GraphQL type information to their origin from the Hasura metadata. Currently, we have a number of correctness checks of our GraphQL schema. But these correctness checks only have access to pure GraphQL type information, and hence can only report errors in terms of that. Possibly the worst is the "conflicting definitions" error, which, in practice, can only be debugged by Hasura engineers. This is terrible DX for customers. This PR allows us to print better error messages, by adding a field to the `Definition` type that traces the GraphQL type to its origin in the metadata. So the idea is simple: just add `MetadataObjId`, or `Maybe` that, or some other sum type of that, to `Definition`. However, we want to avoid having to import a `Hasura.RQL` module from `Hasura.GraphQL.Parser`. So we instead define this additional field of `Definition` through a new type parameter, which is threaded through in `Hasura.GraphQL.Parser`. We then define type synonyms in `Hasura.GraphQL.Schema.Parser` that fill in this type parameter, so that it is not visible for the majority of the codebase. The idea of associating metadata information to `Definition`s really comes to fruition when combined with hasura/graphql-engine-mono#4517. Their combination would allow us to use the API of fatal errors (just like the current `MonadError QErr`) to report _inconsistencies_ in the metadata. Such inconsistencies are then _automatically_ ignored. So no ad-hoc decisions need to be made on how to cut out inconsistent metadata from the GraphQL schema. This will allow us to report much better errors, as well as improve the likelihood of a successful HGE startup. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4770 Co-authored-by: Samir Talwar <47582+SamirTalwar@users.noreply.github.com> GitOrigin-RevId: 728402b0cae83ae8e83463a826ceeb609001acae |
||
Samir Talwar
|
8db9b77c77 |
server: Reorganize quasi-quoted names.
Pretty much all quasi-quoted names in the server code base have ended up in `Hasura.GraphQL.Parser.Constants`. I'm now finding this unpleasant for two reasons: 1. I would like to factor out the parser code into its own Cabal package, and I don't want to have to expose all these names. 2. Most of them really have nothing to do with the parsers. In order to remedy this, I have: 1. moved the names used by parser code to `Hasura.GraphQL.Parser.DirectiveName`, as they're all related to directives; 2. moved `Hasura.GraphQL.Parser.Constants` to `Hasura.Name`, changing the qualified import name from `G` to `Name`; 3. moved names only used in tests to the appropriate test case; 4. removed unused items from `Hasura.Name`; and 5. grouped related names. Most of the changes are simply changing `G` to `Name`, which I find much more meaningful. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4777 GitOrigin-RevId: a77aa0aee137b2b5e6faec94495d3a9fbfa1348b |
||
Daniel Harvey
|
0f97c27115 |
Replace ParseT with Parse
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4724 GitOrigin-RevId: d742bc876ca11dbbe7e3f02bbdf9bf9c2440cbe6 |
||
Antoine Leblanc
|
3cbcbd9291 |
Remove RQL/Types.hs
## Description This PR removes `RQL.Types`, which was now only re-exporting a bunch of unrelated modules. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4363 GitOrigin-RevId: 894f29a19bff70b3dad8abc5d9858434d5065417 |
||
Solomon
|
c945b2d391 |
Replaces litName splices with name quasiquotes
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4267 GitOrigin-RevId: 2d93c35a7e34dbada3b72aabcae5fc2858bbfc29 |
||
jkachmar
|
647231b685 |
Yeet some default-extensions
Manually enables: * EmptyCase * ExistentialQuantification * QuantifiedConstraints * QuasiQuotes * TemplateHaskell * TypeFamilyDependencies ...in the following components: * 'graphql-engine' library * 'graphql-engine' 'src-test' * 'graphql-engine' 'tests/integration' * 'graphql-engine' tests-hspec' Additionally, performs some light refactoring and documentation. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3991 GitOrigin-RevId: 514477d3466b01f60eca8935d0fef60dd0756838 |
||
kodiakhq[bot]
|
1181625173 |
server: optimize collectTypeDefinitions and refactor
Numbers from CI for the new (currently noisy) `replace_metadata` adhoc benchmark: chinook: 0.19s -> 0.16 huge_schema: 36.98s -> 29.89 PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3685 GitOrigin-RevId: be79b666858b03e8407c0d89765e9aac0af8d40a |
||
Auke Booij
|
7547786b2b |
Build introspection Schema ad-hoc at parsing time
In order to respond to GraphQL queries that make use of the introspection fields `__type` or `__schema`, we need two things: - an overview of the relevant GraphQL type information, stored in a `Schema` object, and - to have included the `__type` and `__schema` fields in the `query_root` that we generate. It used to be necessary to do the above items in that order, since the `__type` and `__schema` fields (i.e. the respective `FieldParser`s) were generated _from_ a `Schema` object. Thanks to recent refactorings in `Hasura.GraphQL.Schema.Introspect` (see hasura/graphql-engine-mono#2835 or hasura/graphql-engine@5760d9289c), the introspection fields _themselves_ are now `Schema`-agnostic, and simply return a function that takes a `Schema` object after parsing. For instance, the type of `schema`, corresponding to the `__schema` field, has literally changed as follows: ```diff -schema :: MonadParse n => Schema -> FieldParser n ( J.Value) +schema :: MonadParse n => FieldParser n (Schema -> J.Value) ``` This means that the introspection fields can be included in the GraphQL schema *before* we have generated a `Schema` object. In particular, rather than the current architecture of generating `Schema` at startup time for every role, we can instead generate `Schema` ad-hoc at query parsing time, only for those queries that make use of the introspection fields. This avoids us storing a `Schema` for every role for the lifetime of the server. However: this introduces a functional change, as the code that generates the `Schema` object, and in particular the `accumulateTypeDefinitions` method, also does certain correctness checks, to prevent exposing a spec-incompliant GraphQL schema. If these correctness checks are being done at parsing time rather than startup time, then we catch certain errors only later on. For this reason, this PR adds an explicit run of this type accumulation at startup time. For efficiency reasons, and since this correctness check is not essential for correct operation of HGE, this is done for the admin role only. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3231 GitOrigin-RevId: 23701c548b785929b28667025436b6ce60bfe1cd |
||
Antoine Leblanc
|
a023a3259d |
Prevent uses of unsafeMkName whenever possible.
### Description This PR is the result of a discussion in #3363. Namely, we would like to remove all uses of `unsafeMkName`, or at the very least document every single one of them, to avoid similar issues. To do so, this PR does the following: - it adds a hlint suggestion not to use that function: - suggestions don't mark the PR as failed, but will be shown at review time - it is possible to disable that hint with `{- HLINT ignore myFunction "unsafe" -}` - wherever possible, it removes uses of `unsafeMkName` in favour of `mkName` - it adds a comment with a tracking issue for the two remaining uses: - #3478 - #3479 ### Remaining work - discuss whether this hint should make the linter step fail, since the linter step isn't required to merge anyway, and there is a way to disable the hint wherever we think the use of that function is acceptable - check that none of those uses were load-bearing and result in errors now PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3480 GitOrigin-RevId: 0a7e3e9d1a48185764c04ab61e34b58273af347c |
||
Swann Moreau
|
5760d9289c |
server: introspection cleanups
this pr modifies the representation chosen for introspection parsers, "pushing down" the `Schema` input so it is not required to build the parser anymore. instead, the value produced when the parser is evaluated becomes a function that consumes a schema: ```diff -schema :: MonadParse n => Schema -> FieldParser n ( J.Value) +schema :: MonadParse n => FieldParser n (Schema -> J.Value) ``` this addresses points (1) and (2) of #2833 and is intended to make #2799 easier: we will need to enforce permissions when generating introspection objects, hiding fields the user is not allowed to see, so if we can pass the schema _later_, we can build this parser once, evaluate it once to (morally) obtain a function `Schema -> Value`, and simply run that single `Schema -> Value` function on different role-based schemas. (we really need some terminology to be fixed here: "parser" is already not the best name, and then we have parser vs value/function "returned" by parser vs...) however, we have immediate benefits: we no longer _need_ a `Schema` object to build the introspection parsers! this means we can remove the bogus "degenerate case" schema that is currently constructed in `emptyIntrospection` (and indeed we remove that binding altogether). (fun fact: the diff for this pull request has a negative line count despite adding a lot of comments. @abooij says i have bragging rights in perpetuity now, à la @nicuveo) changes: - internal changes to the operation of the server, invisible outside of a small number of `GraphQL.Schema.*` modules - no user-facing changes PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2835 Co-authored-by: Auke Booij <164426+abooij@users.noreply.github.com> Co-authored-by: Brandon Simmons <210815+jberryman@users.noreply.github.com> GitOrigin-RevId: 9990f53b8f5c733424c4d71a24d94c13dee842ba |
||
Auke Booij
|
e805fc01f3 |
Avoid NonNullableType
This refactors the AST of GraphQL types so that we don't need `NonNullableType`. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3178 GitOrigin-RevId: 6513c8ea0a3cf4ad3ca7d8ef9ca996912fd5eedc |
||
Auke Booij
|
2c3277e0a7 |
Refactor InputFieldInfo
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3143 GitOrigin-RevId: a374e07216f3f7d7dee61b222a2758d3ebeb98bb |
||
Auke Booij
|
caf9957aca |
Remove Unique from Definition
GraphQL types can refer to each other in a circular way. The PDV framework used to use values of type `Unique` to recognize two fragments of GraphQL schema as being the same instance. Internally, this is based on `Data.Unique` from the `base` package, which simply increases a counter on every creation of a `Unique` object. **NB**: The `Unique` values are _not_ used for knot tying the schema combinators themselves (i.e. `Parser`s). The knot tying for `Parser`s is purely based on keys provided to `memoizeOn`. The `Unique` values are _only_ used to recognize two pieces of GraphQL _schema_ as being identical. Originally, the idea was that this would help us with a perfectly correct identification of GraphQL types. But this fully correct equality checking of GraphQL types was never implemented, and does not seem to be necessary to prevent bugs. Specifically, these `Unique` values are stored as part of `data Definition a`, which specifies a part of our internal abstract syntax tree for the GraphQL types that we expose. The `Unique` values get initialized by the `SchemaT` effect. In #2894 and #2895, we are experimenting with how (parts of) the GraphQL types can be hidden behind certain permission predicates. This would allow a single GraphQL schema in memory to serve all roles, implementing #2711. The permission predicates get evaluated at query parsing time when we know what role is doing a certain request, thus outputting the correct GraphQL types for that role. If the approach of #2895 is followed, then the `Definition` objects, and thus the `Unique` values, would be hidden behind the permission predicates. Since the permission predicates are evaluated only after the schema is already supposed to be built, this means that the permission predicates would prevent us from initializing the `Unique` values, rendering them useless. The simplest remedy to this is to remove our usage of `Unique` altogether from the GraphQL schema and schema combinators. It doesn't serve a functional purpose, doesn't prevent bugs, and requires extra bookkeeping. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2980 GitOrigin-RevId: 50d3f9e0b9fbf578ac49c8fc773ba64a94b1f43d |
||
Auke Booij
|
29158900d8 |
Refactor type name customization
Source typename customization (hasura/graphql-engine@aac64f2c81) introduced a mechanism to change certain names in the GraphQL schema that is exposed. In particular it allows last-minute modification of: 1. the names of some types, and 2. the names of some root fields. The above two items are assigned distinct customization algorithms, and at times both algorithms are in scope. So a need to distinguish them is needed. In the original design, this was addressed by introducing a newtype wrapper `Typename` around GraphQL `Name`s, dedicated to the names of types. However, in the majority of the codebase, type names are also represented by `Name`. For this reason, it was unavoidable to allow for easy conversion. This was supported by a `HasName Typename` instance, as well as by publishing the constructors of `Typename`. This means that the type safety that newtypes can add is lost. In particular, it is now very easy to confuse type name customization with root field name customization. This refactors the above design by instead introducing newtypes around the customization operations: ```haskell newtype MkTypename = MkTypename {runMkTypename :: Name -> Name} deriving (Semigroup, Monoid) via (Endo Name) newtype MkRootFieldName = MkRootFieldName {runMkRootFieldName :: Name -> Name} deriving (Semigroup, Monoid) via (Endo Name) ``` The `Monoid` instance allows easy composition of customization operations, piggybacking off of the type of `Endo`maps. This design allows safe co-existence of the two customization algorithms, while avoiding the syntactic overhead of packing and unpacking newtypes. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2989 GitOrigin-RevId: da3a353a9b003ee40c8d0a1e02872e99d2edd3ca |
||
Brandon Simmons
|
b167120f96 |
server: add explicit export lists in OSS server and enforce with warning
We'll see if this improves compile times at all, but I think it's worth doing as at least the most minimal form of module documentation. This was accomplished by first compiling everything with -ddump-minimal-imports, and then a bunch of scripting (with help from ormolu) **EDIT** it doesn't seem to improve CI compile times but the noise floor is high as it looks like we're not caching library dependencies anymore PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2730 GitOrigin-RevId: 667eb8de1e0f1af70420cbec90402922b8b84cb4 |
||
David Overton
|
aac64f2c81 |
Source typename customization (close graphql-engine#6974)
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/1616 GitOrigin-RevId: f7eefd2367929209aa77895ea585e96a99a78d47 |
||
Robert
|
11a454c2d6 |
server, pro: actually reformat the code-base using ormolu
This commit applies ormolu to the whole Haskell code base by running `make format`. For in-flight branches, simply merging changes from `main` will result in merge conflicts. To avoid this, update your branch using the following instructions. Replace `<format-commit>` by the hash of *this* commit. $ git checkout my-feature-branch $ git merge <format-commit>^ # and resolve conflicts normally $ make format $ git commit -a -m "reformat with ormolu" $ git merge -s ours post-ormolu https://github.com/hasura/graphql-engine-mono/pull/2404 GitOrigin-RevId: 75049f5c12f430c615eafb4c6b8e83e371e01c8e |
||
Robert
|
bdacf1bd23 |
server: remove ApplicativeDo from default extensions
I spent half the day reducing a weird compile failure here https://github.com/hasura/graphql-engine-mono/pull/1593/files#r713102990 to this https://gitlab.haskell.org/ghc/ghc/-/issues/17768#note_378004. Seems ApplicativeDo makes a mess of non-applicative monadic do in some cases. Given our rather localized use of ApplicativeDo, seemed a good idea to remove it from the list of default extensions. It appears that ApplicativeDo also buries some unused return value warnings, so this PR also silences those. We should check that none of those warnings were warranted though. https://github.com/hasura/graphql-engine-mono/pull/2413 GitOrigin-RevId: 1874c1a82230431849265755b1407beebc947041 |
||
Antoine Leblanc
|
dfbdfca144 |
server: fix order of fields in introspection output
GitOrigin-RevId: edd6af755d46c3d13c8b7b5504f8d89701a3250f |
||
Auke Booij
|
0540b279db
|
server: make more use of hlint (#6059)
https://github.com/hasura/graphql-engine/pull/6059 |
||
Alexis King
|
7e970177c1
|
Rewrite GraphQL schema generation and query parsing (close #2801) (#4111)
Aka “the PDV refactor.” History is preserved on the branch 2801-graphql-schema-parser-refactor. * [skip ci] remove stale benchmark commit from commit_diff * [skip ci] Check for root field name conflicts between remotes * [skip ci] Additionally check for conflicts between remotes and DB * [skip ci] Check for conflicts in schema when tracking a table * [skip ci] Fix equality checking in GraphQL AST * server: fix mishandling of GeoJSON inputs in subscriptions (fix #3239) (#4551) * Add support for multiple top-level fields in a subscription to improve testability of subscriptions * Add an internal flag to enable multiple subscriptions * Add missing call to withConstructorFn in live queries (fix #3239) Co-authored-by: Alexis King <lexi.lambda@gmail.com> * Scheduled triggers (close #1914) (#3553) server: add scheduled triggers Co-authored-by: Alexis King <lexi.lambda@gmail.com> Co-authored-by: Marion Schleifer <marion@hasura.io> Co-authored-by: Karthikeyan Chinnakonda <karthikeyan@hasura.io> Co-authored-by: Aleksandra Sikora <ola.zxcvbnm@gmail.com> * dev.sh: bump version due to addition of croniter python dependency * server: fix an introspection query caching issue (fix #4547) (#4661) Introspection queries accept variables, but we need to make sure to also touch the variables that we ignore, so that an introspection query is marked not reusable if we are not able to build a correct query plan for it. A better solution here would be to deal with such unused variables correctly, so that more introspection queries become reusable. An even better solution would be to type-safely track *how* to reuse which variables, rather than to split the reusage marking from the planning. Co-authored-by: Tirumarai Selvan <tiru@hasura.io> * flush log buffer on exception in mkWaiApp ( fix #4772 ) (#4801) * flush log buffer on exception in mkWaiApp * add comment to explain the introduced change * add changelog * allow logging details of a live query polling thread (#4959) * changes for poller-log add various multiplexed query info in poller-log * minor cleanup, also fixes a bug which will return duplicate data * Live query poller stats can now be logged This also removes in-memory stats that are collected about batched query execution as the log lines when piped into an monitoring tool will give us better insights. * allow poller-log to be configurable * log minimal information in the livequery-poller-log Other information can be retrieved from /dev/subscriptions/extended * fix few review comments * avoid marshalling and unmarshalling from ByteString to EncJSON * separate out SubscriberId and SubscriberMetadata Co-authored-by: Anon Ray <rayanon004@gmail.com> * Don't compile in developer APIs by default * Tighten up handling of admin secret, more docs Store the admin secret only as a hash to prevent leaking the secret inadvertently, and to prevent timing attacks on the secret. NOTE: best practice for stored user passwords is a function with a tunable cost like bcrypt, but our threat model is quite different (even if we thought we could reasonably protect the secret from an attacker who could read arbitrary regions of memory), and bcrypt is far too slow (by design) to perform on each request. We'd have to rely on our (technically savvy) users to choose high entropy passwords in any case. Referencing #4736 * server/docs: add instructions to fix loss of float precision in PostgreSQL <= 11 (#5187) This adds a server flag, --pg-connection-options, that can be used to set a PostgreSQL connection parameter, extra_float_digits, that needs to be used to avoid loss of data on older versions of PostgreSQL, which have odd default behavior when returning float values. (fixes #5092) * [skip ci] Add new commits from master to the commit diff * [skip ci] serve default directives (skip & include) over introspection * [skip ci] Update non-Haskell assets with the version on master * server: refactor GQL execution check and config API (#5094) Co-authored-by: Vamshi Surabhi <vamshi@hasura.io> Co-authored-by: Vamshi Surabhi <0x777@users.noreply.github.com> * [skip ci] fix js issues in tests by pinning dependencies version * [skip ci] bump graphql version * [skip ci] Add note about memory usage * generalize query execution logic on Postgres (#5110) * generalize PGExecCtx to support specialized functions for various operations * fix tests compilation * allow customising PGExecCtx when starting the web server * server: changes catalog initialization and logging for pro customization (#5139) * new typeclass to abstract the logic of QueryLog-ing * abstract the logic of logging websocket-server logs introduce a MonadWSLog typeclass * move catalog initialization to init step expose a helper function to migrate catalog create schema cache in initialiseCtx * expose various modules and functions for pro * [skip ci] cosmetic change * [skip ci] fix test calling a mutation that does not exist * [skip ci] minor text change * [skip ci] refactored input values * [skip ci] remove VString Origin * server: fix updating of headers behaviour in the update cron trigger API and create future events immediately (#5151) * server: fix bug to update headers in an existing cron trigger and create future events Co-authored-by: Tirumarai Selvan <tiru@hasura.io> * Lower stack chunk size in RTS to reduce thread STACK memory (closes #5190) This reduces memory consumption for new idle subscriptions significantly (see linked ticket). The hypothesis is: we fork a lot of threads per websocket, and some of these use slightly more than the initial 1K stack size, so the first overflow balloons to 32K, when significantly less is required. However: running with `+RTS -K1K -xc` did not seem to show evidence of any overflows! So it's a mystery why this improves things. GHC should probably also be doubling the stack buffer at each overflow or doing something even smarter; the knobs we have aren't so helpful. * [skip ci] fix todo and schema generation for aggregate fields * 5087 libpq pool leak (#5089) Shrink libpq buffers to 1MB before returning connection to pool. Closes #5087 See: https://github.com/hasura/pg-client-hs/pull/19 Also related: #3388 #4077 * bump pg-client-hs version (fixes a build issue on some environments) (#5267) * do not use prepared statements for mutations * server: unlock scheduled events on graceful shutdown (#4928) * Fix buggy parsing of new --conn-lifetime flag in |