Skip to content

Commit

Permalink
Consolidate schema polling config (#842)
Browse files Browse the repository at this point in the history
* move all schema polling things into config.watchSchema

* update docs

* fix documented watchSchema params

* update init command

* more doc updates

* clean up examples

* changeset
  • Loading branch information
AlecAivazis authored Jan 24, 2023
1 parent 55e750c commit d468143
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 56 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-mirrors-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'houdini': major
---

Grouped `apiUrl`, `schemaPollHeaders`, and `schemaPollInterval` together
1 change: 0 additions & 1 deletion e2e/sveltekit/houdini.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
/** @type {import('houdini').ConfigFile} */
const config = {
schemaPath: '../_api/*.graphql',
defaultCachePolicy: 'CacheOrNetwork',
defaultPartial: true,
scalars: {
DateTime: {
Expand Down
8 changes: 4 additions & 4 deletions example/houdini.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/** @type {import('houdini').ConfigFile} */
const config = {
apiUrl: 'http://localhost:4000/graphql',
watchSchema: {
url: 'http://localhost:4000/graphql',
},
scalars: {
DateTime: {
type: 'Date',
Expand All @@ -13,9 +15,7 @@ const config = {
},
},
plugins: {
'houdini-svelte': {
client: './src/client.ts',
},
'houdini-svelte': {},
},
}

Expand Down
6 changes: 4 additions & 2 deletions packages/houdini/src/cmd/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,9 @@ const writeConfigFile = async ({

// if we have no url, we are using a local schema
if (url !== null) {
config.apiUrl = url
config.watchSchema = {
url,
}
}

// if it's different for defaults, write it down
Expand Down Expand Up @@ -563,7 +565,7 @@ async function detectTools(cwd: string): Promise<DetectedTools> {

const hasDependency = (dep: string) => Boolean(devDependencies?.[dep] || dependencies?.[dep])

let framework: ConfigFile['framework'] = 'svelte'
let framework: 'svelte' | 'kit' = 'svelte'
if (hasDependency('@sveltejs/kit')) {
framework = 'kit'
}
Expand Down
12 changes: 6 additions & 6 deletions packages/houdini/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ export class Config {
types = {},
logLevel,
defaultFragmentMasking = 'enable',
schemaPollInterval = 2000,
schemaPollHeaders = {},
watchSchema,
projectDir,
} = this.configFile

Expand Down Expand Up @@ -136,8 +135,8 @@ export class Config {
this.logLevel = ((logLevel as LogLevel) || LogLevel.Summary).toLowerCase() as LogLevel
this.defaultFragmentMasking = defaultFragmentMasking
this.routesDir = path.join(this.projectRoot, 'src', 'routes')
this.schemaPollInterval = schemaPollInterval
this.schemaPollHeaders = schemaPollHeaders
this.schemaPollInterval = watchSchema?.interval ?? 2000
this.schemaPollHeaders = watchSchema?.headers ?? {}
this.rootDir = path.join(this.projectRoot, '$houdini')

// hold onto the key config
Expand All @@ -153,12 +152,13 @@ export class Config {
}

async apiURL() {
if (!this.configFile.apiUrl) {
const apiURL = this.configFile.watchSchema?.url
if (!apiURL) {
return ''
}

const env = await this.getEnv()
return this.processEnvValues(env, this.configFile.apiUrl)
return this.processEnvValues(env, apiURL)
}

get include() {
Expand Down
53 changes: 26 additions & 27 deletions packages/houdini/src/runtime/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,6 @@ export type ConfigFile = {
*/
schema?: string | GraphQLSchema

/**
* A url to use to pull the schema. For more information: https://www.houdinigraphql.com/api/cli#generate
*/
apiUrl?: string | ((env: Record<string, string | undefined>) => string)

/**
* An object describing custom scalars for your project. For more information: https://www.houdinigraphql.com/api/config#custom-scalars
*/
Expand All @@ -99,12 +94,6 @@ export type ConfigFile = {
*/
definitionsPath?: string

/**
* One of "kit" or "svelte". Used to tell the preprocessor what kind of loading paradigm to generate for you. (default: `kit`)
* @deprecated please follow the steps here: http://www.houdinigraphql.com/guides/release-notes#0170
*/
framework?: 'kit' | 'svelte'

/**
* One of "esm" or "commonjs". Tells the artifact generator what kind of modules to create. (default: `esm`)
*/
Expand Down Expand Up @@ -158,23 +147,9 @@ export type ConfigFile = {
defaultFragmentMasking?: 'enable' | 'disable'

/**
* Configures the houdini plugin's schema polling behavior. By default, houdini will poll your APIs
* during development in order to keep it's definition of your schema up to date. The schemaPollingInterval
* config value sets the amount of time between each request in milliseconds (default 2 seconds).
* To limit the schema introspection to just on the start of the server, set schemaPollingInterval to 0.
* To disable the schema introspection, set schemaPollingInterval to null.
* Configure the dev environment to watch a remote schema for changes
*/
schemaPollInterval?: number | null

/**
* An object containing the environment variables you want passed onto the api when polling for a new schema.
* The keys dictate the header names. If the value is a string, the corresponding environment variable will be used
* directly. If the value is a function, the current environment will be passed to your function so you can perform any
* logic you need
*/
schemaPollHeaders?:
| Record<string, string | ((env: Record<string, string | undefined>) => string)>
| ((env: Record<string, string | undefined>) => Record<string, string>)
watchSchema?: WatchSchemaConfig

/**
* An object describing the plugins enabled for the project
Expand Down Expand Up @@ -206,6 +181,30 @@ export type TypeConfig = {
}
}

export type WatchSchemaConfig = {
/**
* A url to use to pull the schema. For more information: https://www.houdinigraphql.com/api/cli#generate
*/
url: string | ((env: Record<string, string | undefined>) => string)

/**
* sets the amount of time between each request in milliseconds (default 2 seconds).
* To limit the schema introspection to just on the start of the server, set interval to 0.
* To disable the schema introspection, set interval to null.
*/
interval?: number | null

/**
* An object containing the environment variables you want passed onto the api when polling for a new schema.
* The keys dictate the header names. If the value is a string, the corresponding environment variable will be used
* directly. If the value is a function, the current environment will be passed to your function so you can perform any
* logic you need
*/
headers?:
| Record<string, string | ((env: Record<string, string | undefined>) => string)>
| ((env: Record<string, string | undefined>) => Record<string, string>)
}

export type ScalarSpec = {
// the type to use at runtime
type: string
Expand Down
1 change: 0 additions & 1 deletion packages/houdini/src/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ export function testConfigFile({ plugins, ...config }: Partial<ConfigFile> = {})
},
},
},
framework: 'kit',
types: {
Ghost: {
keys: ['name', 'aka'],
Expand Down
70 changes: 55 additions & 15 deletions site/src/routes/api/config/+page.svx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,21 @@ description: A description of every valid configuration value for Houdini.
All configuration for your houdini application is defined in a single file that is imported by both the runtime and the command-line tool (called `houdini.config.js`). Because of this, you must make sure that any imports and logic are resolvable in both environments. This means that if you rely on process.env or other node-specifics you will have to use a plugin to replace the expression with something that can run in the browser.

```javascript:title=houdini.config.js
/** @type {import('houdini').ConfigFile} */
export default {
apiUrl: 'http://localhost:4000/graphql',
schemaPollHeaders: {
Authentication(env) {
return `Bearer ${env.AUTH_TOKEN}`
}
watchSchema: {
url: 'http://localhost:4000/graphql',
},
scalars: {
DateTime: {
type: 'Date',
unmarshal(val) {
return new Date(val)
},
marshal(date) {
return date.getTime()
}
}
}
}
```
Expand All @@ -25,7 +34,7 @@ By default, your config file can contain the following values:
- `include` (optional, default: `"src/**/*.{svelte,graphql,gql,ts,js}"`): a pattern (or list of patterns) to identify source code files.
- `exclude` (optional): a pattern (or list of patterns) that filters out files that match the include pattern
- `schemaPath` (optional, default: `"./schema.graphql"`): the path to the static representation of your schema, can be a glob pointing to multiple files
- `apiUrl` (optional, a string or function): Configures the url to use to pull the schema. If you don't pass an `apiUrl`, the kit plugin will not poll for schema changes. If you want to access an environment variable, you can either prefix your string with `env:` or set it to a function that takes the current environment and returns a string. For more information see the [section below](#environment-variables).
- `watchSchema` (optional, an object): configure the development server to poll a remote url for changes in the schema. When a change is detected, the dev serer will automatically regenerate your runtime. For more information see [Schema Polling](#schema-polling).
- `module` (optional, default: `"esm"`): One of `"esm"` or `"commonjs"`. Used to tell the artifact generator what kind of modules to create. (default: `esm`)
- `definitionsPath` (optional, default: `"$houdini/graphql"`): a path that the generator will use to write `schema.graphql` and `documents.gql` files containing all of the internal fragment and directive definitions used in the project.
- `scalars` (optional): An object describing custom scalars for your project (see below).
Expand All @@ -36,8 +45,6 @@ By default, your config file can contain the following values:
- `types` (optional): an object that customizes the resolution behavior for a specific type. For more information see the [Caching Guide](/guides/caching-data#custom-ids).
- `logLevel` (optional, default: `"summary"`): Specifies the style of logging houdini will use when generating your file. One of "quiet", "full", "summary", or "short-summary".
- `defaultFragmentMasking` (optional, default: `enable`): `"enable"` to mask fragment and use collocated data requirement as best or `"disable"` to access fragment data directly in operation. Can be overridden individually at fragment level.
- `schemaPollHeaders` (optional): An object specifying the headers to use when pulling your schema. Keys of the object are header names and its values can be either a strings or a function that takes the current `process.env` and returns the the value to use. If you want to access an environment variable, prefix your string with `env:`, ie `env:API_KEY`. For more information see the [section below](#environment-variables).
- `schemaPollInterval` (optional, default: `2000`): Configures the schema polling behavior for the kit plugin. If its value is greater than `0`, the plugin will poll the set number of milliseconds. If set to `0`, the plugin will only pull the schema when you first run `dev`. If you set to `null`, the plugin will never look for schema changes. You can see use the [pull-schema command](/api/cli#pull-schema) to get updates.
- `defaultListTarget` (optional): Can be set to `all` for all list operations to ignore parent ID and affect all lists with the name.
- `defaultListPosition` (optional, default: "first"): One of `"first"` or `"last"` to indicate the default location for list operations.
- `plugins` (optional): An object containing the set of plugins you want to add to your houdini application. The keys are plugin names, the values are plugin-specific configuration. The actual plugin API is undocumented and considered unstable while we try out various things internally. For an overview of your framework plugin's specific configuration, see below.
Expand All @@ -47,6 +54,9 @@ By default, your config file can contain the following values:
Configuring the svelte plugin is done inside of the `plugins` key in your config file:

```javascript:title=houdini.config.js
/// <references types="houdini-svelte">

/** @type {import('houdini').ConfigFile} */
export default {
// ...
plugins: {
Expand Down Expand Up @@ -89,16 +99,43 @@ export default {
}
```

## Environment Variables
## Schema Polling

You can configure your development server to poll a remote URL for changes in your schema using the `watchSchema`
argument:

```typescript
export default {
watchSchema: {
url: 'http://localhost:4000/graphql',
headers: {
Authentication(env) {
return `Bearer ${env.AUTH_TOKEN}`
}
}
}
}
```

You can pass the following parameters to `watchSchema`:

There are a few different options for using environment variables in your `apiUrl` and `schemaPollHeaders`
- `url` (a string or function): Configures the url to use to pull the schema. If you don't pass an `apiUrl`, the kit plugin will not poll for schema changes. If you want to access an environment variable, you can either prefix your string with `env:` or set it to a function that takes the current environment and returns a string. For more information see the [section below](#environment-variables).
- `headers` (optional): An object specifying the headers to use when pulling your schema. Keys of the object are header names and its values can be either a strings or a function that takes the current `process.env` and returns the the value to use. If you want to access an environment variable, prefix your string with `env:`, ie `env:API_KEY`. For more information see the [section below](#environment-variables).
- `interval` (optional, default: `2000`): Configures the schema polling behavior for the kit plugin. If its value is greater than `0`, the plugin will poll the set number of milliseconds. If set to `0`, the plugin will only pull the schema when you first run `dev`. If you set to `null`, the plugin will never look for schema changes. You can see use the [pull-schema command](/api/cli#pull-schema) to get updates.

### Environment Variables

There are a few different options for using environment variables in your `url` and `headers`
config values. Keep in mind that Houdini will look for `.env` and `.env.local` files for environment variables.
For simple cases, you can just prepend `env:` to the value:

```javascript
export default {
schemaPollHeaders: {
Authentication: 'env:AUTH_TOKEN'
watchSchema: {
url: '...',
headers: {
Authentication: 'env:AUTH_TOKEN'
}
}
}
```
Expand All @@ -109,9 +146,12 @@ environment variables:

```javascript
export default {
schemaPollHeaders: {
Authentication: function (env) {
return `Bearer ${env.AUTH_TOKEN}`
watchSchema: {
url: '...',
headers: {
Authentication(env) {
return `Bearer ${env.AUTH_TOKEN}`
}
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions site/src/routes/guides/release-notes/+page.svx
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,29 @@ need to pass a new config to your client:

</DeepDive>

### Grouped `apiUrl`, `schemaPollHeaders`, and `schemaPollInterval` together

In order to clarify the difference between the `apiUrl` config value and the
value passed to `HoudiniClient`, we moved all of the schema polling related
config values into a single `watchSchema` object:

```diff
export default {
- apiUrl: "http://my.awesome.app.com,
- schemaPollInterval: 6000,
- schemaPollHeaders: {
- Authorization: (env) => `Bearer ${env.TOKEN}`,
- },
+ watchSchema {
+ url: "http://my.awesome.app.com,
+ interval: 6000,
+ headers: {
+ Authorization: (env) => `Bearer ${env.TOKEN}`,
+ }
+ },
}
```

### Imperative Cache Reworked

We removed all of that `setFieldType` complexity and now you can read and write data by passing
Expand Down

0 comments on commit d468143

Please sign in to comment.