diff --git a/.changeset/stale-ligers-appear.md b/.changeset/stale-ligers-appear.md
new file mode 100644
index 000000000..5953a671c
--- /dev/null
+++ b/.changeset/stale-ligers-appear.md
@@ -0,0 +1,5 @@
+---
+'houdini': patch
+---
+
+Adding a new directive @allLists to update all lists after a mutation
diff --git a/.graphqlrc.yaml b/.graphqlrc.yaml
index 0a92465f7..d276eb918 100644
--- a/.graphqlrc.yaml
+++ b/.graphqlrc.yaml
@@ -1,9 +1,9 @@
projects:
- default:
+ sveltekit:
# 👇 For vscode-graphql and intellisense
schema:
- - e2e/api/*.graphql
- - e2e/$houdini/graphql/schema.graphql
+ - e2e/_api/*.graphql
+ - e2e/sveltekit/$houdini/graphql/schema.graphql
documents:
- - e2e/src/**/*.gql
- - e2e/$houdini/graphql/documents.gql
+ - e2e/sveltekit/src/**/*.gql
+ - e2e/sveltekit/$houdini/graphql/documents.gql
diff --git a/e2e/_api/graphql.mjs b/e2e/_api/graphql.mjs
index 8ee4c8d86..f5fd58d75 100644
--- a/e2e/_api/graphql.mjs
+++ b/e2e/_api/graphql.mjs
@@ -12,38 +12,46 @@ export const typeDefs = sourceFiles.map((filepath) =>
// Example Cities/Libraries/Books data
// Assume a traditional relational database for storage - each table with unique ID.
-let cityId = 1;
-let libraryId = 1;
-let bookId = 1;
+let cityId = 1
+let libraryId = 1
+let bookId = 1
// Allow the "database" to be persistent and mutable
let cities = [
{
- id: cityId++, name: 'Alexandria', libraries: [
+ id: cityId++,
+ name: 'Alexandria',
+ libraries: [
{
- id: libraryId++, name: 'The Library of Alexandria', books: [
+ id: libraryId++,
+ name: 'The Library of Alexandria',
+ books: [
{ id: bookId++, title: 'Callimachus Pinakes' },
{ id: bookId++, title: 'Kutubkhana-i-lskandriyya' },
- ]
+ ],
},
{
- id: libraryId++, name: 'Bibliotheca Alexandrina', books: [
- { id: bookId++, title: 'Analyze your own personality' },
- ]
+ id: libraryId++,
+ name: 'Bibliotheca Alexandrina',
+ books: [{ id: bookId++, title: 'Analyze your own personality' }],
},
- ]
+ ],
},
{
- id: cityId++, name: 'Istanbul', libraries: [
+ id: cityId++,
+ name: 'Istanbul',
+ libraries: [
{
- id: libraryId++, name: 'The Imperial Library of Constantinople', books: [
+ id: libraryId++,
+ name: 'The Imperial Library of Constantinople',
+ books: [
{ id: bookId++, title: 'Homer' },
{ id: bookId++, title: 'The Hellenistic History' },
- ]
+ ],
},
- ]
+ ],
},
-];
+]
// example data
const data = [
@@ -88,6 +96,13 @@ export const resolvers = {
usersList: (_, args) => {
return [...getSnapshot(args.snapshot)].splice(args.offset || 0, args.limit)
},
+ userNodes: (_, args) => {
+ const allData = [...getSnapshot(args.snapshot)]
+ return {
+ totalCount: allData.length,
+ nodes: allData.splice(args.offset || 0, args.limit),
+ }
+ },
session: (_, args, info) => {
let token = null
info.request.headers.forEach((value, key) => {
@@ -136,7 +151,7 @@ export const resolvers = {
}
},
cities: () => {
- return cities;
+ return cities
},
},
@@ -156,7 +171,7 @@ export const resolvers = {
await sleep(args.delay)
}
const user = {
- id: (list.length + 1).toString(),
+ id: `${args.snapshot}:${list.length + 1}`,
name: args.name,
birthDate: args.birthDate,
enumValue: args.enumValue,
@@ -187,7 +202,7 @@ export const resolvers = {
try {
let data = await processFile(file)
return data
- } catch (e) { }
+ } catch (e) {}
throw new GraphQLYogaError('ERROR', { code: 500 })
},
multipleUpload: async (_, { files }) => {
@@ -209,12 +224,12 @@ export const resolvers = {
libraries: [],
}
- cities.push(city);
- return city;
+ cities.push(city)
+ return city
},
addLibrary: (_, args) => {
- const cityId = Number.parseInt(args.city);
- const city = cities.find((city) => city.id === cityId);
+ const cityId = Number.parseInt(args.city)
+ const city = cities.find((city) => city.id === cityId)
if (!city) {
throw new GraphQLYogaError('City not found', { code: 404 })
}
@@ -224,50 +239,58 @@ export const resolvers = {
name: args.name,
books: [],
}
- city.libraries.push(library);
- return library;
+ city.libraries.push(library)
+ return library
},
addBook: (_, args) => {
- const libraryId = Number.parseInt(args.library);
- const city = cities.find((city) => city.libraries.find((library) => library.id === libraryId));
+ const libraryId = Number.parseInt(args.library)
+ const city = cities.find((city) =>
+ city.libraries.find((library) => library.id === libraryId)
+ )
if (!city) {
throw new GraphQLYogaError('City/Library not found', { code: 404 })
}
- const library = city.libraries.find((library) => library.id === libraryId);
-
+ const library = city.libraries.find((library) => library.id === libraryId)
+
const book = {
id: bookId++,
title: args.title,
}
- library.books.push(book);
- return book;
+ library.books.push(book)
+ return book
},
deleteCity: (_, args) => {
- const cityId = Number.parseInt(args.city);
- const city = cities.find((city) => city.id === cityId);
- cities = cities.filter((city) => city.id !== cityId);
- return city;
+ const cityId = Number.parseInt(args.city)
+ const city = cities.find((city) => city.id === cityId)
+ cities = cities.filter((city) => city.id !== cityId)
+ return city
},
deleteLibrary: (_, args) => {
- const libraryId = Number.parseInt(args.library);
- const city = cities.find((city) => city.libraries.find((library) => library.id === libraryId));
+ const libraryId = Number.parseInt(args.library)
+ const city = cities.find((city) =>
+ city.libraries.find((library) => library.id === libraryId)
+ )
if (!city) {
throw new GraphQLYogaError('City/Library not found', { code: 404 })
}
- const library = city.libraries.find((library) => library.id === libraryId);
- city.libraries = city.libraries.filter((library) => library.id !== libraryId);
- return library;
+ const library = city.libraries.find((library) => library.id === libraryId)
+ city.libraries = city.libraries.filter((library) => library.id !== libraryId)
+ return library
},
deleteBook: (_, args) => {
- const bookId = Number.parseInt(args.book);
- const city = cities.find((city) => city.libraries.find((library) => library.books.find((book) => book.id === bookId)));
+ const bookId = Number.parseInt(args.book)
+ const city = cities.find((city) =>
+ city.libraries.find((library) => library.books.find((book) => book.id === bookId))
+ )
if (!city) {
throw new GraphQLYogaError('City/Library/Book not found', { code: 404 })
}
- const library = city.libraries.find((library) => library.books.find((book) => book.id === bookId));
- const book = library.books.find((book) => book.id === bookId);
- library.books = library.books.filter((book) => book.id !== bookId);
- return book;
+ const library = city.libraries.find((library) =>
+ library.books.find((book) => book.id === bookId)
+ )
+ const book = library.books.find((book) => book.id === bookId)
+ library.books = library.books.filter((book) => book.id !== bookId)
+ return book
},
},
diff --git a/e2e/_api/schema.graphql b/e2e/_api/schema.graphql
index be3609e90..4753c771a 100644
--- a/e2e/_api/schema.graphql
+++ b/e2e/_api/schema.graphql
@@ -57,6 +57,7 @@ type Query {
snapshot: String!
): UserConnection!
usersList(limit: Int = 4, offset: Int, snapshot: String!): [User!]!
+ userNodes(limit: Int = 4, offset: Int, snapshot: String!): UserNodes!
session: String
cities: [City]!
}
@@ -85,6 +86,11 @@ type UserEdge {
node: User
}
+type UserNodes {
+ totalCount: Int
+ nodes: [User!]!
+}
+
type Book {
id: ID!
title: String!
diff --git a/e2e/sveltekit/package.json b/e2e/sveltekit/package.json
index 8bb331be3..8d764b708 100644
--- a/e2e/sveltekit/package.json
+++ b/e2e/sveltekit/package.json
@@ -21,8 +21,8 @@
"devDependencies": {
"@kitql/helper": "^0.5.0",
"@playwright/test": "1.25.0",
- "@sveltejs/adapter-auto": "1.0.0-next.66",
- "@sveltejs/kit": "1.0.0-next.510",
+ "@sveltejs/adapter-auto": "1.0.0-next.88",
+ "@sveltejs/kit": "1.0.0-next.547",
"@typescript-eslint/eslint-plugin": "^5.10.1",
"@typescript-eslint/parser": "^5.10.1",
"concurrently": "7.1.0",
diff --git a/e2e/sveltekit/src/lib/utils/routes.ts b/e2e/sveltekit/src/lib/utils/routes.ts
index 2f5046879..2a60ed2eb 100644
--- a/e2e/sveltekit/src/lib/utils/routes.ts
+++ b/e2e/sveltekit/src/lib/utils/routes.ts
@@ -6,6 +6,7 @@ export const routes = {
Query_param: '/query-param',
isFetching_with_load: '/isFetching/with_load',
isFetching_without_load: '/isFetching/without_load',
+ lists_all: '/lists-all?limit=15',
Stores_SSR: '/stores/ssr',
Stores_Network: '/stores/network',
diff --git a/e2e/sveltekit/src/lib/utils/testsHelper.ts b/e2e/sveltekit/src/lib/utils/testsHelper.ts
index f45c9ed87..f2c021cf9 100644
--- a/e2e/sveltekit/src/lib/utils/testsHelper.ts
+++ b/e2e/sveltekit/src/lib/utils/testsHelper.ts
@@ -39,7 +39,7 @@ export async function expect_n_gql(
page: Page,
selector: string | null,
n: number,
- action: 'click' | 'hover' = 'click'
+ action: 'click' | 'hover' | 'press_ArrowUp' | 'press_ArrowDown' = 'click'
) {
const start = new Date().valueOf();
const timing: number[] = [];
@@ -81,8 +81,14 @@ export async function expect_n_gql(
if (selector) {
if (action === 'click') {
await page.click(selector);
- } else {
+ } else if (action === 'hover') {
await page.hover(selector);
+ } else if (action === 'press_ArrowUp') {
+ await page.locator(selector).press('ArrowUp');
+ } else if (action === 'press_ArrowDown') {
+ page.locator(selector).press('ArrowDown');
+ } else {
+ throw new Error(`action ${action} not implemented`);
}
}
diff --git a/e2e/sveltekit/src/routes/lists-all/+page.gql b/e2e/sveltekit/src/routes/lists-all/+page.gql
new file mode 100644
index 000000000..ec3d271f1
--- /dev/null
+++ b/e2e/sveltekit/src/routes/lists-all/+page.gql
@@ -0,0 +1,9 @@
+query ListAll($limit: Int!) {
+ userNodes(limit: $limit, snapshot: "lists-all") {
+ totalCount
+ nodes @list(name: "List_All") {
+ id
+ name
+ }
+ }
+}
diff --git a/e2e/sveltekit/src/routes/lists-all/+page.svelte b/e2e/sveltekit/src/routes/lists-all/+page.svelte
new file mode 100644
index 000000000..a0b1f3375
--- /dev/null
+++ b/e2e/sveltekit/src/routes/lists-all/+page.svelte
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
List
+
+ {#each $ListAll.data?.userNodes.nodes ?? [] as user}
+
{user?.name}
+ {/each}
+
diff --git a/e2e/sveltekit/src/routes/lists-all/+page.ts b/e2e/sveltekit/src/routes/lists-all/+page.ts
new file mode 100644
index 000000000..1de46ca7b
--- /dev/null
+++ b/e2e/sveltekit/src/routes/lists-all/+page.ts
@@ -0,0 +1,10 @@
+import type { PageLoad } from './$types';
+import { load_ListAll } from '$houdini';
+
+export const load: PageLoad = async (event) => {
+ const limit = parseInt(event.url.searchParams.get('limit') ?? '1', 10);
+
+ return {
+ ...(await load_ListAll({ event, variables: { limit } }))
+ };
+};
diff --git a/e2e/sveltekit/src/routes/lists-all/AddUser.gql b/e2e/sveltekit/src/routes/lists-all/AddUser.gql
new file mode 100644
index 000000000..4988c268b
--- /dev/null
+++ b/e2e/sveltekit/src/routes/lists-all/AddUser.gql
@@ -0,0 +1,5 @@
+mutation ListAll_AddUser {
+ addUser(name: "Omar Sy", birthDate: 254143016000, snapshot: "List_All") {
+ ...List_All_insert @allLists @prepend
+ }
+}
diff --git a/e2e/sveltekit/src/routes/lists-all/spec.ts b/e2e/sveltekit/src/routes/lists-all/spec.ts
new file mode 100644
index 000000000..8b552c7c3
--- /dev/null
+++ b/e2e/sveltekit/src/routes/lists-all/spec.ts
@@ -0,0 +1,44 @@
+import { test } from '@playwright/test';
+import { routes } from '../../lib/utils/routes.js';
+import { expectToBe, expect_n_gql, goto } from '../../lib/utils/testsHelper.js';
+
+test.describe('lists-all', () => {
+ test('With 3 lists to append', async ({ page }) => {
+ await goto(page, routes.lists_all);
+
+ // select the input
+ await page.locator('input[type="number"]').click();
+ // add 1 to the input to load a second list
+ await expect_n_gql(page, 'input[type="number"]', 1, 'press_ArrowUp');
+ // add 1 to the input to load a third list
+ await expect_n_gql(page, 'input[type="number"]', 1, 'press_ArrowUp');
+
+ // expect to have the righ data
+ await expectToBe(
+ page,
+ 'Bruce WillisSamuel JacksonMorgan FreemanTom HanksWill SmithHarrison FordEddie MurphyClint Eastwood'
+ );
+
+ // mutation to add a new actor (Expect to have 1 mutation)
+ await expect_n_gql(page, 'text=Add User', 1);
+
+ // expect to have the data added
+ await expectToBe(
+ page,
+ 'Omar SyBruce WillisSamuel JacksonMorgan FreemanTom HanksWill SmithHarrison FordEddie MurphyClint Eastwood'
+ );
+
+ // select the input
+ await page.locator('input[type="number"]').click();
+ // go back 1 list, expect no graphql request (from cache!)
+ await expect_n_gql(page, 'input[type="number"]', 0, 'press_ArrowDown');
+ // go back 1 list, expect no graphql request (from cache!)
+ await expect_n_gql(page, 'input[type="number"]', 0, 'press_ArrowDown');
+
+ // expect the data to still contain the new actor
+ await expectToBe(
+ page,
+ 'Omar SyBruce WillisSamuel JacksonMorgan FreemanTom HanksWill SmithHarrison FordEddie MurphyClint Eastwood'
+ );
+ });
+});
diff --git a/example/package.json b/example/package.json
index d2378ae63..dca63892c 100644
--- a/example/package.json
+++ b/example/package.json
@@ -13,7 +13,7 @@
"devDependencies": {
"@graphql-yoga/node": "^2.8.0",
"@kitql/vite-plugin-watch-and-run": "^0.4.0",
- "@sveltejs/kit": "1.0.0-next.510",
+ "@sveltejs/kit": "1.0.0-next.547",
"concurrently": "^6.2.1",
"graphql": "^15.8.0",
"houdini": "workspace:^",
diff --git a/packages/houdini-svelte/package.json b/packages/houdini-svelte/package.json
index b973a9675..5c0eaebff 100644
--- a/packages/houdini-svelte/package.json
+++ b/packages/houdini-svelte/package.json
@@ -10,7 +10,7 @@
},
"dependencies": {
"@kitql/helper": "^0.5.0",
- "@sveltejs/kit": "1.0.0-next.505",
+ "@sveltejs/kit": "1.0.0-next.547",
"ast-types": "^0.15.1",
"estree-walker": "^3.0.1",
"graphql": "^15.8.0",
diff --git a/packages/houdini-svelte/src/runtime/session.ts b/packages/houdini-svelte/src/runtime/session.ts
index 18c80ecb4..7df88c34d 100644
--- a/packages/houdini-svelte/src/runtime/session.ts
+++ b/packages/houdini-svelte/src/runtime/session.ts
@@ -27,7 +27,7 @@ export class RequestContext {
throw error(status, typeof message === 'string' ? message : message.message)
}
- redirect(status: number, location: string): any {
+ redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308, location: string): any {
throw redirect(status, location)
}
diff --git a/packages/houdini/src/codegen/generators/artifacts/artifacts.test.ts b/packages/houdini/src/codegen/generators/artifacts/artifacts.test.ts
index 81f42bdc3..8f02da52c 100644
--- a/packages/houdini/src/codegen/generators/artifacts/artifacts.test.ts
+++ b/packages/houdini/src/codegen/generators/artifacts/artifacts.test.ts
@@ -869,6 +869,274 @@ describe('mutation artifacts', function () {
`)
})
+ test('insert operation allList', async function () {
+ const mutationDocs = [
+ mockCollectedDoc(
+ `mutation A {
+ addFriend {
+ friend {
+ ...All_Users_insert @allLists
+ }
+ }
+ }`
+ ),
+ mockCollectedDoc(
+ `query TestQuery {
+ users(stringValue: "foo") @list(name: "All_Users") {
+ firstName
+ }
+ }`
+ ),
+ ]
+
+ // execute the generator
+ await runPipeline(config, mutationDocs)
+
+ expect(mutationDocs[0]).toMatchInlineSnapshot(`
+ export default {
+ name: "A",
+ kind: "HoudiniMutation",
+ hash: "7cc5c23ffd19603e2c7c727d1ac2726d4d87ee6b0470ced7d28c7f0ed88a05c2",
+
+ raw: \`mutation A {
+ addFriend {
+ friend {
+ ...All_Users_insert
+ id
+ }
+ }
+ }
+
+ fragment All_Users_insert on User {
+ firstName
+ id
+ }
+ \`,
+
+ rootType: "Mutation",
+
+ selection: {
+ addFriend: {
+ type: "AddFriendOutput",
+ keyRaw: "addFriend",
+
+ fields: {
+ friend: {
+ type: "User",
+ keyRaw: "friend",
+
+ operations: [{
+ action: "insert",
+ list: "All_Users",
+ position: "last",
+ target: "all"
+ }],
+
+ fields: {
+ firstName: {
+ type: "String",
+ keyRaw: "firstName"
+ },
+
+ id: {
+ type: "ID",
+ keyRaw: "id"
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+
+ "HoudiniHash=90d93ca64a69bec0880925b8af471b0da1cf76964df0b6b6c3af30b6fd877217";
+ `)
+ })
+
+ test('insert operation allList by default in config', async function () {
+ const mutationDocs = [
+ mockCollectedDoc(
+ `mutation A {
+ addFriend {
+ friend {
+ ...All_Users_insert
+ }
+ }
+ }`
+ ),
+ mockCollectedDoc(
+ `query TestQuery {
+ users(stringValue: "foo") @list(name: "All_Users") {
+ firstName
+ }
+ }`
+ ),
+ ]
+
+ let configUpdate = testConfig()
+ configUpdate.defaultListTarget = 'all'
+
+ // execute the generator
+ await runPipeline(configUpdate, mutationDocs)
+
+ // verify contents
+ expect(mutationDocs[0]).toMatchInlineSnapshot(`
+ export default {
+ name: "A",
+ kind: "HoudiniMutation",
+ hash: "7cc5c23ffd19603e2c7c727d1ac2726d4d87ee6b0470ced7d28c7f0ed88a05c2",
+
+ raw: \`mutation A {
+ addFriend {
+ friend {
+ ...All_Users_insert
+ id
+ }
+ }
+ }
+
+ fragment All_Users_insert on User {
+ firstName
+ id
+ }
+ \`,
+
+ rootType: "Mutation",
+
+ selection: {
+ addFriend: {
+ type: "AddFriendOutput",
+ keyRaw: "addFriend",
+
+ fields: {
+ friend: {
+ type: "User",
+ keyRaw: "friend",
+
+ operations: [{
+ action: "insert",
+ list: "All_Users",
+ position: "last",
+ target: "all"
+ }],
+
+ fields: {
+ firstName: {
+ type: "String",
+ keyRaw: "firstName"
+ },
+
+ id: {
+ type: "ID",
+ keyRaw: "id"
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+
+ "HoudiniHash=c2cee63cc2dfd5eabad47ed394b64c91f6e19378bbf018b80c6e3391c3a56e5b";
+ `)
+ })
+
+ test('insert operation cosition first by default in config', async function () {
+ const mutationDocs = [
+ mockCollectedDoc(
+ `mutation A {
+ addFriend {
+ friend {
+ ...All_Users_insert
+ }
+ }
+ }`
+ ),
+ mockCollectedDoc(
+ `query TestQuery {
+ users(stringValue: "foo") @list(name: "All_Users") {
+ firstName
+ }
+ }`
+ ),
+ ]
+
+ let configUpdate = testConfig()
+ configUpdate.internalListPosition = 'first'
+
+ // execute the generator
+ await runPipeline(configUpdate, mutationDocs)
+
+ // load the contents of the file
+ const queryContents = await fs.readFile(
+ path.join(configUpdate.artifactPath(mutationDocs[0].document))
+ )
+ expect(queryContents).toBeTruthy()
+ // parse the contents
+ const parsedQuery: ProgramKind = recast.parse(queryContents!, {
+ parser: typeScriptParser,
+ }).program
+ // verify contents
+ expect(parsedQuery).toMatchInlineSnapshot(`
+ export default {
+ name: "A",
+ kind: "HoudiniMutation",
+ hash: "7cc5c23ffd19603e2c7c727d1ac2726d4d87ee6b0470ced7d28c7f0ed88a05c2",
+
+ raw: \`mutation A {
+ addFriend {
+ friend {
+ ...All_Users_insert
+ id
+ }
+ }
+ }
+
+ fragment All_Users_insert on User {
+ firstName
+ id
+ }
+ \`,
+
+ rootType: "Mutation",
+
+ selection: {
+ addFriend: {
+ type: "AddFriendOutput",
+ keyRaw: "addFriend",
+
+ fields: {
+ friend: {
+ type: "User",
+ keyRaw: "friend",
+
+ operations: [{
+ action: "insert",
+ list: "All_Users",
+ position: "first"
+ }],
+
+ fields: {
+ firstName: {
+ type: "String",
+ keyRaw: "firstName"
+ },
+
+ id: {
+ type: "ID",
+ keyRaw: "id"
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+
+ "HoudiniHash=c2cee63cc2dfd5eabad47ed394b64c91f6e19378bbf018b80c6e3391c3a56e5b";
+ `)
+ })
+
test('toggle operation', async function () {
const mutationDocs = [
mockCollectedDoc(
diff --git a/packages/houdini/src/codegen/generators/artifacts/operations.ts b/packages/houdini/src/codegen/generators/artifacts/operations.ts
index 9480bcfe1..02a3a2d03 100644
--- a/packages/houdini/src/codegen/generators/artifacts/operations.ts
+++ b/packages/houdini/src/codegen/generators/artifacts/operations.ts
@@ -1,6 +1,6 @@
import * as graphql from 'graphql'
-import { Config, HoudiniError, parentTypeFromAncestors } from '../../../lib'
+import { Config, parentTypeFromAncestors } from '../../../lib'
import { MutationOperation } from '../../../runtime/lib/types'
import { convertValue } from './utils'
@@ -98,7 +98,8 @@ function operationObject({
let parentID
let parentKind: 'Variable' | 'String' = 'String'
- let position: MutationOperation['position'] = 'last'
+ let position: MutationOperation['position'] = config.internalListPosition
+ let allLists: MutationOperation['target'] = config.defaultListTarget ?? undefined
let operationWhen: MutationOperation['when'] | undefined
const internalDirectives = selection.directives?.filter((directive) =>
@@ -113,20 +114,32 @@ function operationObject({
const append = internalDirectives.find(
({ name }) => name.value === config.listAppendDirective
)
- // is when applied?
- const when = internalDirectives.find(({ name }) => name.value === 'when')
- // is when_not applied?
- const when_not = internalDirectives.find(({ name }) => name.value === 'when_not')
+
+ // if both are applied, there's a problem, this should never happen has it's checked in validation step
+ if (append) {
+ position = 'last'
+ }
+ if (prepend) {
+ position = 'first'
+ }
+
+ // is allLists applied?
+ const allListsDirective = internalDirectives.find(
+ ({ name }) => name.value === config.listAllListsDirective
+ )
+
// look for the parentID directive
let parent = internalDirectives.find(
({ name }) => name.value === config.listParentDirective
)
- // if both are applied, there's a problem
- if (append && prepend) {
- throw new HoudiniError({ filepath, message: 'you have both applied' })
- }
- position = prepend ? 'first' : 'last'
+ // if both are applied, there's a problem, this should never happen has it's checked in validation step
+ allLists = allListsDirective ? 'all' : undefined
+
+ // is when applied?
+ const when = internalDirectives.find(({ name }) => name.value === 'when')
+ // is when_not applied?
+ const when_not = internalDirectives.find(({ name }) => name.value === 'when_not')
// the parent ID can be provided a few ways, either as an argument to the prepend
// and append directives or with the parentID directive.
@@ -220,9 +233,14 @@ function operationObject({
operation.type = type
}
- // only add the position argument if we are inserting something
+ // only add the position argument if we are inserting or toggling something
if (operationKind === 'insert' || operationKind === 'toggle') {
- operation.position = position || 'last'
+ operation.position = position
+ }
+
+ // only add the position argument if we are inserting something
+ if (operationKind === 'insert' && allLists) {
+ operation.target = 'all'
}
// if there is a parent id
diff --git a/packages/houdini/src/codegen/generators/definitions/schema.test.ts b/packages/houdini/src/codegen/generators/definitions/schema.test.ts
index 1fe9b7ce5..0896d5477 100644
--- a/packages/houdini/src/codegen/generators/definitions/schema.test.ts
+++ b/packages/houdini/src/codegen/generators/definitions/schema.test.ts
@@ -45,6 +45,9 @@ test('adds internal documents to schema', async function () {
"""@append is used to tell the runtime to add the result to the start of the list"""
directive @append(parentID: ID) on FRAGMENT_SPREAD
+ """@allLists is used to tell the runtime to add the result to all list"""
+ directive @allLists on FRAGMENT_SPREAD
+
"""
@parentID is used to provide a parentID without specifying position or in situations
where it doesn't make sense (eg when deleting a node.)
@@ -112,6 +115,9 @@ test('list operations are included', async function () {
"""@append is used to tell the runtime to add the result to the start of the list"""
directive @append(parentID: ID) on FRAGMENT_SPREAD
+ """@allLists is used to tell the runtime to add the result to all list"""
+ directive @allLists on FRAGMENT_SPREAD
+
"""
@parentID is used to provide a parentID without specifying position or in situations
where it doesn't make sense (eg when deleting a node.)
@@ -198,6 +204,9 @@ test("writing twice doesn't duplicate definitions", async function () {
"""@append is used to tell the runtime to add the result to the start of the list"""
directive @append(parentID: ID) on FRAGMENT_SPREAD
+ """@allLists is used to tell the runtime to add the result to all list"""
+ directive @allLists on FRAGMENT_SPREAD
+
"""
@parentID is used to provide a parentID without specifying position or in situations
where it doesn't make sense (eg when deleting a node.)
diff --git a/packages/houdini/src/codegen/transforms/list.ts b/packages/houdini/src/codegen/transforms/list.ts
index ce5ada5db..3361f97d4 100644
--- a/packages/houdini/src/codegen/transforms/list.ts
+++ b/packages/houdini/src/codegen/transforms/list.ts
@@ -27,7 +27,6 @@ export default async function addListFragments(
} = {}
const errors: Error[] = []
-
// look at every document
for (const doc of documents) {
doc.document = graphql.visit(doc.document, {
diff --git a/packages/houdini/src/codegen/transforms/paginate.test.ts b/packages/houdini/src/codegen/transforms/paginate.test.ts
index 16094156c..0595ca560 100644
--- a/packages/houdini/src/codegen/transforms/paginate.test.ts
+++ b/packages/houdini/src/codegen/transforms/paginate.test.ts
@@ -851,6 +851,53 @@ test('query with forwards cursor paginate', async function () {
`)
})
+test('query with custom first args', async function () {
+ const docs = [
+ mockCollectedDoc(
+ `
+ query Users ($limit: Int!){
+ usersByForwardsCursor(first: $limit) @paginate {
+ edges {
+ node {
+ id
+ }
+ }
+ }
+ }
+ `
+ ),
+ ]
+
+ // run the pipeline
+ const config = testConfig()
+ await runPipeline(config, docs)
+
+ // load the contents of the file
+ expect(docs[0]?.document).toMatchInlineSnapshot(`
+ query Users($limit: Int!, $after: String) {
+ usersByForwardsCursor(first: $limit, after: $after) @paginate {
+ edges {
+ node {
+ id
+ }
+ }
+ edges {
+ cursor
+ node {
+ __typename
+ }
+ }
+ pageInfo {
+ hasPreviousPage
+ hasNextPage
+ startCursor
+ endCursor
+ }
+ }
+ }
+ `)
+})
+
test('query with backwards cursor paginate', async function () {
const docs = [
mockCollectedDoc(
diff --git a/packages/houdini/src/codegen/transforms/paginate.ts b/packages/houdini/src/codegen/transforms/paginate.ts
index c0a61d92d..839db085c 100644
--- a/packages/houdini/src/codegen/transforms/paginate.ts
+++ b/packages/houdini/src/codegen/transforms/paginate.ts
@@ -21,7 +21,12 @@ import { unwrapType, wrapType } from '../utils'
// - generate the query with the fragment embedded using @with to pass query variables through
type PaginationFlags = {
- [fieldName: string]: { enabled: boolean; type: string; defaultValue?: any }
+ [fieldName: string]: {
+ enabled: boolean
+ type: string
+ defaultValue?: any
+ variableName?: string
+ }
}
// paginate transform adds the necessary fields for a paginated field
@@ -199,13 +204,18 @@ export default async function paginate(
let newVariables: Record =
Object.fromEntries(
Object.entries(flags)
- .filter(([, spec]) => spec.enabled)
+ .filter(
+ ([, spec]) =>
+ // let's tale the spec enabled AND where we don't have a dedicated variable for it
+ spec.enabled && spec.variableName === undefined
+ )
.map(([fieldName, spec]) => [
fieldName,
staticVariableDefinition(
fieldName,
spec.type,
- spec.defaultValue
+ spec.defaultValue,
+ spec.variableName
),
])
)
@@ -543,10 +553,15 @@ function replaceArgumentsWithVariables(
flags[arg.name.value].defaultValue = spec.type === 'Int' ? parseInt(oldValue) : oldValue
}
+ // if we have a variable
+ if (arg.value.kind === 'Variable') {
+ flags[arg.name.value].variableName = arg.value.name.value
+ }
+
seenArgs[arg.name.value] = true
// turn the field into a variable
- return variableAsArgument(arg.name.value)
+ return variableAsArgument(arg.name.value, flags[arg.name.value].variableName)
})
// any fields that are enabled but don't have values need to have variable references add
@@ -575,7 +590,7 @@ function replaceArgumentsWithVariables(
return newArgs
}
-function variableAsArgument(name: string): graphql.ArgumentNode {
+function variableAsArgument(name: string, variable?: string): graphql.ArgumentNode {
return {
kind: graphql.Kind.ARGUMENT,
name: {
@@ -586,13 +601,18 @@ function variableAsArgument(name: string): graphql.ArgumentNode {
kind: graphql.Kind.VARIABLE,
name: {
kind: graphql.Kind.NAME,
- value: name,
+ value: variable ?? name,
},
},
}
}
-function staticVariableDefinition(name: string, type: string, defaultValue?: string) {
+function staticVariableDefinition(
+ name: string,
+ type: string,
+ defaultValue?: string,
+ variableName?: string
+) {
return {
kind: graphql.Kind.VARIABLE_DEFINITION,
type: {
@@ -606,7 +626,7 @@ function staticVariableDefinition(name: string, type: string, defaultValue?: str
kind: graphql.Kind.VARIABLE,
name: {
kind: graphql.Kind.NAME,
- value: name,
+ value: variableName ?? name,
},
},
defaultValue: !defaultValue
diff --git a/packages/houdini/src/codegen/transforms/schema.ts b/packages/houdini/src/codegen/transforms/schema.ts
index 5429d0ebf..a8c6e81c9 100644
--- a/packages/houdini/src/codegen/transforms/schema.ts
+++ b/packages/houdini/src/codegen/transforms/schema.ts
@@ -43,6 +43,11 @@ directive @${config.listPrependDirective}(
"""
directive @${config.listAppendDirective}(${config.listDirectiveParentIDArg}: ID) on FRAGMENT_SPREAD
+"""
+ @${config.listAllListsDirective} is used to tell the runtime to add the result to all list
+"""
+directive @${config.listAllListsDirective} on FRAGMENT_SPREAD
+
"""
@${
config.listParentDirective
diff --git a/packages/houdini/src/codegen/validators/typeCheck.test.ts b/packages/houdini/src/codegen/validators/typeCheck.test.ts
index 939ff1d04..68631fb00 100755
--- a/packages/houdini/src/codegen/validators/typeCheck.test.ts
+++ b/packages/houdini/src/codegen/validators/typeCheck.test.ts
@@ -139,6 +139,56 @@ const table: Row[] = [
`,
],
},
+ {
+ title: '@prepend & @append on _insert',
+ pass: false,
+ documents: [
+ `query TestQuery {
+ user {
+ friends {
+ friends @list(name: "Friends") {
+ id
+ }
+ }
+ }
+ }`,
+ `mutation MutationM1 {
+ addFriend {
+ ...Friends_insert @prepend @append @allLists
+ }
+ }`,
+ `mutation MutationM2 {
+ addFriend {
+ ...Friends_insert @prepend @append @allLists
+ }
+ }`,
+ ],
+ },
+ {
+ title: '@parentID @allLists on _insert',
+ pass: false,
+ documents: [
+ `query TestQuery {
+ user {
+ friends {
+ friends @list(name: "Friends") {
+ id
+ }
+ }
+ }
+ }`,
+ `mutation MutationM1 {
+ addFriend {
+ ...Friends_insert @parentID @allLists
+ }
+ }`,
+ `mutation MutationM2 {
+ addFriend {
+ ...Friends_insert @parentID @allLists
+ }
+ }`,
+ ],
+ },
{
title: '@list name must be unique',
pass: false,
@@ -894,6 +944,12 @@ for (const { title, pass, documents, check } of table) {
? undefined
: check ||
function (e: Error | Error[]) {
+ if (title === '@prepend & @append on _insert') {
+ console.log(`e`, e)
+ }
+
+ // We want to check that all errors are grouped into 1 throw
+ // having an array or errors.
expect(e).toHaveLength(2)
}
)
diff --git a/packages/houdini/src/codegen/validators/typeCheck.ts b/packages/houdini/src/codegen/validators/typeCheck.ts
index c2e049382..f55a60765 100755
--- a/packages/houdini/src/codegen/validators/typeCheck.ts
+++ b/packages/houdini/src/codegen/validators/typeCheck.ts
@@ -320,6 +320,8 @@ export default async function typeCheck(
listTypes,
fragments,
}),
+ // checkMutationOperation
+ checkMutationOperation(config),
// pagination directive can only show up on nodes or the query type
nodeDirectives(config, [config.paginateDirective]),
// this replaces KnownArgumentNamesRule
@@ -415,29 +417,43 @@ const validateLists = ({
return
}
+ // Do we have the parentId another way?
+ let parentIdFound = false
// look for one of the list directives
directive = node.directives?.find(({ name }) => [
[config.listPrependDirective, config.listAppendDirective].includes(name.value),
])
- // if there is no directive
- if (!directive) {
- ctx.reportError(
- new graphql.GraphQLError('parentID is required for this list fragment')
+ if (directive) {
+ // find the argument holding the parent ID
+ let parentArg = directive.arguments?.find(
+ (arg) => arg.name.value === config.listDirectiveParentIDArg
)
+ if (parentArg) {
+ parentIdFound = true
+ }
+ }
+
+ if (parentIdFound) {
+ // parentId was found, so we're good to go
return
}
- // find the argument holding the parent ID
- let parentArg = directive.arguments?.find(
- (arg) => arg.name.value === config.listDirectiveParentIDArg
+ // look for allLists directive
+ const allLists = node.directives?.find(
+ ({ name }) => config.listAllListsDirective === name.value
)
- if (!parentArg) {
- ctx.reportError(
- new graphql.GraphQLError('parentID is required for this list fragment')
- )
+ // if there is the directive or it's
+ if (allLists || config.defaultListTarget === 'all') {
return
}
+
+ ctx.reportError(
+ new graphql.GraphQLError(
+ `For this list fragment, you need to add or @${config.listParentDirective} or @${config.listAllListsDirective} directive to specify the behavior`
+ )
+ )
+ return
},
// if we run into a directive that points to a list, make sure that list exists
Directive(node) {
@@ -925,6 +941,45 @@ function nodeDirectives(config: Config, directives: string[]) {
}
}
+function checkMutationOperation(config: Config) {
+ return function (ctx: graphql.ValidationContext): graphql.ASTVisitor {
+ return {
+ FragmentSpread(node, _, __, ___, ancestors) {
+ const append = node.directives?.find(
+ (c) => c.name.value === config.listAppendDirective
+ )
+
+ const prepend = node.directives?.find(
+ (c) => c.name.value === config.listPrependDirective
+ )
+ if (append && prepend) {
+ ctx.reportError(
+ new graphql.GraphQLError(
+ `You can't apply both @${config.listPrependDirective} and @${config.listAppendDirective} at the same time`
+ )
+ )
+ return
+ }
+
+ const parentId = node.directives?.find(
+ (c) => c.name.value === config.listParentDirective
+ )
+ const allLists = node.directives?.find(
+ (c) => c.name.value === config.listAllListsDirective
+ )
+ if (parentId && allLists) {
+ ctx.reportError(
+ new graphql.GraphQLError(
+ `You can't apply both @${config.listParentDirective} and @${config.listAllListsDirective} at the same time`
+ )
+ )
+ return
+ }
+ },
+ }
+ }
+}
+
export function getAndVerifyNodeInterface(config: Config): graphql.GraphQLInterfaceType | null {
const { schema } = config
diff --git a/packages/houdini/src/lib/config.ts b/packages/houdini/src/lib/config.ts
index 8afce405e..30022fb0b 100644
--- a/packages/houdini/src/lib/config.ts
+++ b/packages/houdini/src/lib/config.ts
@@ -38,6 +38,8 @@ export class Config {
cacheBufferSize?: number
defaultCachePolicy: CachePolicy
defaultPartial: boolean
+ internalListPosition: 'first' | 'last'
+ defaultListTarget: 'all' | null = null
definitionsFolder?: string
newSchema: string = ''
newDocuments: string = ''
@@ -77,6 +79,8 @@ export class Config {
definitionsPath,
defaultCachePolicy = CachePolicy.CacheOrNetwork,
defaultPartial = false,
+ defaultListPosition = 'append',
+ defaultListTarget = null,
defaultKeys,
types = {},
logLevel,
@@ -116,6 +120,8 @@ export class Config {
this.cacheBufferSize = cacheBufferSize
this.defaultCachePolicy = defaultCachePolicy
this.defaultPartial = defaultPartial
+ this.internalListPosition = defaultListPosition === 'append' ? 'last' : 'first'
+ this.defaultListTarget == defaultListTarget
this.definitionsFolder = definitionsPath
this.logLevel = ((logLevel as LogLevel) || LogLevel.Summary).toLowerCase() as LogLevel
this.disableMasking = disableMasking
@@ -470,6 +476,10 @@ export class Config {
return 'parentID'
}
+ get listAllListsDirective() {
+ return 'allLists'
+ }
+
get listNameArg() {
return 'name'
}
@@ -578,6 +588,7 @@ export class Config {
this.listPrependDirective,
this.listAppendDirective,
this.listDirectiveParentIDArg,
+ this.listAllListsDirective,
this.whenDirective,
this.whenNotDirective,
this.argumentsDirective,
diff --git a/packages/houdini/src/runtime/cache/cache.ts b/packages/houdini/src/runtime/cache/cache.ts
index 561f35259..ee87d095a 100644
--- a/packages/houdini/src/runtime/cache/cache.ts
+++ b/packages/houdini/src/runtime/cache/cache.ts
@@ -110,8 +110,8 @@ export class Cache {
}
// return the list handler to mutate a named list in the cache
- list(name: string, parentID?: string | {}): ListCollection {
- const handler = this._internal_unstable.lists.get(name, parentID)
+ list(name: string, parentID?: string, allLists?: boolean): ListCollection {
+ const handler = this._internal_unstable.lists.get(name, parentID, allLists)
if (!handler) {
throw new Error(
`Cannot find list with name: ${name}${
@@ -570,7 +570,10 @@ class CacheInternal {
}
// if the necessary list doesn't exist, don't do anything
- if (operation.list && !this.lists.get(operation.list, parentID)) {
+ if (
+ operation.list &&
+ !this.lists.get(operation.list, parentID, operation.target === 'all')
+ ) {
continue
}
@@ -585,7 +588,7 @@ class CacheInternal {
operation.list
) {
this.cache
- .list(operation.list, parentID)
+ .list(operation.list, parentID, operation.target === 'all')
.when(operation.when)
.addToList(fields, target, variables, operation.position || 'last')
}
@@ -598,7 +601,7 @@ class CacheInternal {
operation.list
) {
this.cache
- .list(operation.list, parentID)
+ .list(operation.list, parentID, operation.target === 'all')
.when(operation.when)
.remove(target, variables)
}
@@ -624,7 +627,7 @@ class CacheInternal {
operation.list
) {
this.cache
- .list(operation.list, parentID)
+ .list(operation.list, parentID, operation.target === 'all')
.when(operation.when)
.toggleElement(fields, target, variables, operation.position || 'last')
}
diff --git a/packages/houdini/src/runtime/cache/lists.ts b/packages/houdini/src/runtime/cache/lists.ts
index 8d09d39b2..0c036863e 100644
--- a/packages/houdini/src/runtime/cache/lists.ts
+++ b/packages/houdini/src/runtime/cache/lists.ts
@@ -16,7 +16,7 @@ export class ListManager {
private listsByField: Map> = new Map()
- get(listName: string, id?: string | {}) {
+ get(listName: string, id?: string, allLists?: boolean) {
const matches = this.lists.get(listName)
// if we don't have a list by that name, we're done
@@ -24,11 +24,29 @@ export class ListManager {
return null
}
+ // if we want to update all list, return all matches
+ if (allLists) {
+ return new ListCollection(
+ Array.from(matches, ([key, value]) => [...value.lists]).flat()
+ )
+ }
+
const head = [...matches.values()][0]
+ // the provided id won't match the cache's ID so we have to compute the internal ID, using
+ // one of the matches to figure out the type of the list element
+ const { recordType } = head.lists[0]
+ const parentID = id ? this.cache._internal_unstable.id(recordType || '', id)! : this.rootID
+
// if there is only one list with that name, return it
if (matches?.size === 1) {
- return head
+ // if there is no provided id, just use the first one
+ if (!id) {
+ return head
+ }
+
+ // otherwise we're only safe to use the head if it matches the parentID
+ return parentID === Array.from(matches.keys())[0] ? head : null
}
// there are multiple versions of the list so the user must
@@ -36,17 +54,13 @@ export class ListManager {
// it would have been caught in the size === 1 check above since
// root's ID is fixed
if (!id) {
- throw new Error(
- `Found multiple instances of "${listName}". Please provide a ` +
- `parentID that corresponds to the object containing the field marked with @list or @paginate.`
+ console.error(
+ `Found multiple instances of "${listName}". Please provide one of @parentID or @allLists directives to ` +
+ `help identify which list you want modify. For more information, visit this guide: https://www.houdinigraphql.com/api/graphql#parentidvalue-string `
)
+ return null
}
- // the provided id won't match the cache's ID so we have to compute the internal ID, using
- // one of the matches to figure out the type of the list element
- const { recordType } = head.lists[0]
- const parentID = id ? this.cache._internal_unstable.id(recordType || '', id)! : this.rootID
-
// return the list pointing to the correct parent
return this.lists.get(listName)?.get(parentID)
}
diff --git a/packages/houdini/src/runtime/cache/tests/list.test.ts b/packages/houdini/src/runtime/cache/tests/list.test.ts
index ca81f9fb0..47cfaedb7 100644
--- a/packages/houdini/src/runtime/cache/tests/list.test.ts
+++ b/packages/houdini/src/runtime/cache/tests/list.test.ts
@@ -1624,10 +1624,6 @@ test('append operation', function () {
{
action: 'insert',
list: 'All_Users',
- parentID: {
- kind: 'String',
- value: cache._internal_unstable.id('User', '1')!,
- },
},
],
fields: {
@@ -1646,7 +1642,7 @@ test('append operation', function () {
})
// make sure we just added to the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toHaveLength(1)
+ expect([...cache.list('All_Users', '1')]).toHaveLength(1)
})
test('append from list', function () {
@@ -1716,10 +1712,6 @@ test('append from list', function () {
{
action: 'insert',
list: 'All_Users',
- parentID: {
- kind: 'String',
- value: cache._internal_unstable.id('User', '1')!,
- },
},
],
fields: {
@@ -1736,7 +1728,7 @@ test('append from list', function () {
})
// make sure we just added to the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toHaveLength(2)
+ expect([...cache.list('All_Users', '1')]).toHaveLength(2)
})
test('toggle list', function () {
@@ -1823,10 +1815,6 @@ test('toggle list', function () {
{
action: 'toggle',
list: 'All_Users',
- parentID: {
- kind: 'String',
- value: cache._internal_unstable.id('User', '1')!,
- },
},
],
fields: {
@@ -1841,23 +1829,15 @@ test('toggle list', function () {
// write some data to a different location with a new user
// that should be added to the list
cache.write({ selection: toggleSelection, data: { newUser: { id: '3' } } })
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toEqual([
- 'User:5',
- 'User:3',
- ])
+ expect([...cache.list('All_Users', '1')]).toEqual(['User:5', 'User:3'])
// toggle the user again to remove the user
cache.write({ selection: toggleSelection, data: { newUser: { id: '3' } } })
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toEqual([
- 'User:5',
- ])
+ expect([...cache.list('All_Users', '1')]).toEqual(['User:5'])
// toggle the user again to add the user back
cache.write({ selection: toggleSelection, data: { newUser: { id: '3' } } })
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toEqual([
- 'User:5',
- 'User:3',
- ])
+ expect([...cache.list('All_Users', '1')]).toEqual(['User:5', 'User:3'])
})
test('append when operation', function () {
@@ -1933,10 +1913,6 @@ test('append when operation', function () {
{
action: 'insert',
list: 'All_Users',
- parentID: {
- kind: 'String',
- value: cache._internal_unstable.id('User', '1')!,
- },
when: {
must: {
value: 'not-foo',
@@ -1960,7 +1936,7 @@ test('append when operation', function () {
})
// make sure we just added to the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toHaveLength(0)
+ expect([...cache.list('All_Users', '1')]).toHaveLength(0)
})
test('prepend when operation', function () {
@@ -2036,10 +2012,6 @@ test('prepend when operation', function () {
{
action: 'insert',
list: 'All_Users',
- parentID: {
- kind: 'String',
- value: cache._internal_unstable.id('User', '1')!,
- },
position: 'first',
when: {
must: {
@@ -2064,7 +2036,7 @@ test('prepend when operation', function () {
})
// make sure we just added to the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toHaveLength(0)
+ expect([...cache.list('All_Users', '1')]).toHaveLength(0)
})
test('prepend operation', function () {
@@ -2154,10 +2126,6 @@ test('prepend operation', function () {
{
action: 'insert',
list: 'All_Users',
- parentID: {
- kind: 'String',
- value: cache._internal_unstable.id('User', '1')!,
- },
position: 'first',
},
],
@@ -2177,10 +2145,7 @@ test('prepend operation', function () {
})
// make sure we just added to the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toEqual([
- 'User:3',
- 'User:2',
- ])
+ expect([...cache.list('All_Users', '1')]).toEqual(['User:3', 'User:2'])
})
test('remove operation', function () {
@@ -2265,10 +2230,6 @@ test('remove operation', function () {
{
action: 'remove',
list: 'All_Users',
- parentID: {
- kind: 'String',
- value: cache._internal_unstable.id('User', '1')!,
- },
},
],
fields: {
@@ -2287,7 +2248,7 @@ test('remove operation', function () {
})
// make sure we removed the element from the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toHaveLength(0)
+ expect([...cache.list('All_Users', '1')]).toHaveLength(0)
})
test('remove operation from list', function () {
@@ -2375,10 +2336,6 @@ test('remove operation from list', function () {
{
action: 'remove',
list: 'All_Users',
- parentID: {
- kind: 'String',
- value: cache._internal_unstable.id('User', '1')!,
- },
},
],
fields: {
@@ -2395,7 +2352,7 @@ test('remove operation from list', function () {
})
// make sure we removed the element from the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toHaveLength(0)
+ expect([...cache.list('All_Users', '1')]).toHaveLength(0)
})
test('delete operation', function () {
@@ -2498,7 +2455,7 @@ test('delete operation', function () {
})
// make sure we removed the element from the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toHaveLength(0)
+ expect([...cache.list('All_Users', '1')]).toHaveLength(0)
expect(cache._internal_unstable.storage.topLayer.operations['User:2'].deleted).toBeTruthy()
})
@@ -2606,7 +2563,7 @@ test('delete operation from list', function () {
})
// make sure we removed the element from the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toHaveLength(0)
+ expect([...cache.list('All_Users', '1')]).toHaveLength(0)
expect(cache._internal_unstable.storage.topLayer.operations['User:2'].deleted).toBeTruthy()
expect(cache._internal_unstable.storage.topLayer.operations['User:3'].deleted).toBeTruthy()
@@ -2753,7 +2710,7 @@ test('delete operation from connection', function () {
})
// make sure we removed the element from the list
- expect([...cache.list('All_Users', cache._internal_unstable.id('User', '1')!)]).toHaveLength(0)
+ expect([...cache.list('All_Users', '1')]).toHaveLength(0)
expect(cache._internal_unstable.storage.topLayer.operations['User:2'].deleted).toBeTruthy()
})
@@ -3225,10 +3182,6 @@ test('list operations fail silently', function () {
{
action: 'insert',
list: 'All_Users',
- parentID: {
- kind: 'String',
- value: cache._internal_unstable.id('User', '1')!,
- },
},
],
fields: {
@@ -3399,7 +3352,7 @@ test('parentID must be passed if there are multiple instances of a list handler'
// instantiate a cache
const cache = new Cache(config)
- const friendsSelection = {
+ const friendsSelection: SubscriptionSelection = {
friends: {
type: 'User',
keyRaw: 'friends',
@@ -3471,11 +3424,73 @@ test('parentID must be passed if there are multiple instances of a list handler'
{}
)
- // looking up the list without a parent id should fail
- expect(() => cache.list('All_Users')).toThrow()
- expect(cache.list('All_Users', '1')!.lists[0].recordID).toEqual(
- cache._internal_unstable.id('User', '1')
- )
+ // append a value to the store
+ const writeSelectionNoParentID: SubscriptionSelection = {
+ user: {
+ type: 'User',
+ keyRaw: 'user',
+ operations: [
+ {
+ action: 'insert',
+ list: 'All_Users',
+ },
+ ],
+ fields: {
+ id: {
+ type: 'ID',
+ keyRaw: 'id',
+ },
+ firstName: {
+ type: 'String',
+ keyRaw: 'firstName',
+ },
+ },
+ },
+ }
+ const writeSelectionWithParentID: SubscriptionSelection = {
+ user: {
+ type: 'User',
+ keyRaw: 'user',
+ operations: [
+ {
+ action: 'insert',
+ list: 'All_Users',
+ parentID: {
+ kind: 'String',
+ value: '1',
+ },
+ },
+ ],
+ fields: {
+ id: {
+ type: 'ID',
+ keyRaw: 'id',
+ },
+ firstName: {
+ type: 'String',
+ keyRaw: 'firstName',
+ },
+ },
+ },
+ }
+
+ // write the value without a parent ID
+ cache.write({
+ selection: writeSelectionNoParentID,
+ data: { user: { id: '2', firstName: 'test' } },
+ })
+ // make sure we didn't modify the lists
+ expect([...cache.list('All_Users', '1')]).toHaveLength(1)
+ expect([...cache.list('All_Users', '2')]).toHaveLength(0)
+
+ // write the value with a parent ID
+ cache.write({
+ selection: writeSelectionWithParentID,
+ data: { user: { id: '2', firstName: 'test' } },
+ })
+ // make sure we modified the correct list
+ expect([...cache.list('All_Users', '1')]).toHaveLength(2)
+ expect([...cache.list('All_Users', '2')]).toHaveLength(0)
})
test('append in abstract list', function () {
@@ -3745,3 +3760,95 @@ test('list operations on interface fields without a well defined parent update t
},
})
})
+
+test("parentID ignores single lists that don't match", function () {
+ // instantiate a cache
+ const cache = new Cache(config)
+
+ // create a list we will add to
+ cache.write({
+ selection: {
+ viewer: {
+ type: 'User',
+ keyRaw: 'viewer',
+ fields: {
+ id: {
+ type: 'ID',
+ keyRaw: 'id',
+ },
+ },
+ },
+ },
+ data: {
+ viewer: {
+ id: '1',
+ },
+ },
+ })
+
+ // subscribe to the data to register the list
+ cache.subscribe(
+ {
+ rootType: 'User',
+ selection: {
+ friends: {
+ type: 'User',
+ keyRaw: 'friends',
+ list: {
+ name: 'All_Users',
+ connection: false,
+ type: 'User',
+ },
+ fields: {
+ id: {
+ type: 'ID',
+ keyRaw: 'id',
+ },
+ firstName: {
+ type: 'String',
+ keyRaw: 'firstName',
+ },
+ },
+ },
+ },
+ parentID: cache._internal_unstable.id('User', '1')!,
+ set: vi.fn(),
+ },
+ {}
+ )
+
+ // write some data to a different location with a new user
+ // that should be added to the list
+ cache.write({
+ selection: {
+ newUser: {
+ type: 'User',
+ keyRaw: 'newUser',
+ operations: [
+ {
+ action: 'insert',
+ list: 'All_Users',
+ parentID: {
+ kind: 'String',
+ value: '2',
+ },
+ },
+ ],
+ fields: {
+ id: {
+ type: 'ID',
+ keyRaw: 'id',
+ },
+ },
+ },
+ },
+ data: {
+ newUser: {
+ id: '3',
+ },
+ },
+ })
+
+ // make sure we just added to the list
+ expect([...cache.list('All_Users', '1')]).toHaveLength(0)
+})
diff --git a/packages/houdini/src/runtime/lib/config.ts b/packages/houdini/src/runtime/lib/config.ts
index a2e07f52d..67b36acf9 100644
--- a/packages/houdini/src/runtime/lib/config.ts
+++ b/packages/houdini/src/runtime/lib/config.ts
@@ -100,13 +100,13 @@ 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)
+ * 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)
+ * One of "esm" or "commonjs". Tells the artifact generator what kind of modules to create. (default: `esm`)
*/
module?: 'esm' | 'commonjs'
@@ -125,6 +125,16 @@ export type ConfigFile = {
*/
defaultPartial?: boolean
+ /**
+ * Specifies whether mutations should append or prepend list. For more information: https://www.houdinigraphql.com/api/graphql (default: `append`)
+ */
+ defaultListPosition?: 'append' | 'prepend'
+
+ /**
+ * Specifies whether mutation should apply a specific target list. When you set `all`, it's like adding the directive `@allLists` to all _insert fragment (default: `null`)
+ */
+ defaultListTarget?: 'all' | null
+
/**
* A list of fields to use when computing a record’s id. The default value is ['id']. For more information: https://www.houdinigraphql.com/guides/caching-data#custom-ids
*/
diff --git a/packages/houdini/src/runtime/lib/types.ts b/packages/houdini/src/runtime/lib/types.ts
index 30dd824e9..90d9150af 100644
--- a/packages/houdini/src/runtime/lib/types.ts
+++ b/packages/houdini/src/runtime/lib/types.ts
@@ -121,6 +121,7 @@ export type MutationOperation = {
value: string
}
position?: 'first' | 'last'
+ target?: 'all'
when?: ListWhen
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index aea38677d..c5a94074c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: 5.4
+lockfileVersion: 5.4
importers:
@@ -57,32 +57,6 @@ importers:
graphql-ws: 5.11.2_graphql@15.8.0
ws: 8.8.1
- e2e/my-app:
- specifiers:
- '@sveltejs/adapter-auto': next
- '@sveltejs/kit': next
- graphql: ^15.8.0
- houdini: ^0.17.5
- houdini-svelte: ^0.17.5
- svelte: ^3.44.0
- svelte-check: ^2.7.1
- svelte-preprocess: ^4.10.6
- tslib: ^2.3.1
- typescript: ^4.7.4
- vite: ^3.1.0
- devDependencies:
- '@sveltejs/adapter-auto': 1.0.0-next.87
- '@sveltejs/kit': 1.0.0-next.539_svelte@3.52.0+vite@3.1.6
- graphql: 15.8.0
- houdini: link:../../packages/houdini
- houdini-svelte: link:../../packages/houdini-svelte
- svelte: 3.52.0
- svelte-check: 2.8.1_svelte@3.52.0
- svelte-preprocess: 4.10.7_besnmoibwkhwtentvwuriss7pa
- tslib: 2.4.0
- typescript: 4.8.4
- vite: 3.1.6
-
e2e/next:
specifiers:
'@types/node': ^18.7.23
@@ -116,8 +90,8 @@ importers:
specifiers:
'@kitql/helper': ^0.5.0
'@playwright/test': 1.25.0
- '@sveltejs/adapter-auto': 1.0.0-next.66
- '@sveltejs/kit': 1.0.0-next.510
+ '@sveltejs/adapter-auto': 1.0.0-next.88
+ '@sveltejs/kit': 1.0.0-next.547
'@typescript-eslint/eslint-plugin': ^5.10.1
'@typescript-eslint/parser': ^5.10.1
concurrently: 7.1.0
@@ -139,8 +113,8 @@ importers:
devDependencies:
'@kitql/helper': 0.5.0
'@playwright/test': 1.25.0
- '@sveltejs/adapter-auto': 1.0.0-next.66
- '@sveltejs/kit': 1.0.0-next.510_svelte@3.52.0+vite@3.1.4
+ '@sveltejs/adapter-auto': 1.0.0-next.88
+ '@sveltejs/kit': 1.0.0-next.547_svelte@3.52.0+vite@3.1.4
'@typescript-eslint/eslint-plugin': 5.35.1_hy4by47wjjtoupqk2r7jy5xf2e
'@typescript-eslint/parser': 5.35.1_pyvvhc3zqdua4akflcggygkl44
concurrently: 7.1.0
@@ -164,7 +138,7 @@ importers:
specifiers:
'@graphql-yoga/node': ^2.8.0
'@kitql/vite-plugin-watch-and-run': ^0.4.0
- '@sveltejs/kit': 1.0.0-next.510
+ '@sveltejs/kit': 1.0.0-next.547
concurrently: ^6.2.1
graphql: ^15.8.0
graphql-relay: 0.10.0
@@ -185,7 +159,7 @@ importers:
devDependencies:
'@graphql-yoga/node': 2.13.13_graphql@15.8.0
'@kitql/vite-plugin-watch-and-run': 0.4.2
- '@sveltejs/kit': 1.0.0-next.510_svelte@3.50.1+vite@3.1.4
+ '@sveltejs/kit': 1.0.0-next.547_svelte@3.50.1+vite@3.1.4
concurrently: 6.5.1
graphql: 15.8.0
houdini: link:../packages/houdini
@@ -312,7 +286,7 @@ importers:
packages/houdini-svelte:
specifiers:
'@kitql/helper': ^0.5.0
- '@sveltejs/kit': 1.0.0-next.505
+ '@sveltejs/kit': 1.0.0-next.547
'@types/minimatch': ^5.1.2
ast-types: ^0.15.1
estree-walker: ^3.0.1
@@ -325,7 +299,7 @@ importers:
vitest: ^0.23.4
dependencies:
'@kitql/helper': 0.5.0
- '@sveltejs/kit': 1.0.0-next.505_svelte@3.52.0+vite@3.1.6
+ '@sveltejs/kit': 1.0.0-next.547_svelte@3.52.0+vite@3.2.4
ast-types: 0.15.2
estree-walker: 3.0.1
graphql: 15.8.0
@@ -1134,10 +1108,7 @@ packages:
/@cloudflare/workers-types/3.14.1:
resolution: {integrity: sha512-B1/plF62pt+H2IJHvApK8fdOJAVsvojvacuac8x8s+JIyqbropMyqNqHTKLm3YD8ZFLGwYeFTudU+PQ7vGvBdA==}
-
- /@cloudflare/workers-types/3.18.0:
- resolution: {integrity: sha512-ehKOJVLMeR+tZkYhWEaLYQxl0TaIZu/kE86HF3/RidR8Xv5LuQxpbh+XXAoKVqsaphWLhIgBhgnlN5HGdheXSQ==}
- dev: true
+ dev: false
/@envelop/core/2.5.0_graphql@15.8.0:
resolution: {integrity: sha512-nlDC9q75bjvS/ajbkkVlwGPSYlWhZOQ6StxMTEjvUVefL4o49NpMlGgxfN2mJ64y1CJ3MI/bIemZ3jOHmiv3Og==}
@@ -1196,6 +1167,7 @@ packages:
cpu: [loong64]
os: [linux]
requiresBuild: true
+ dev: false
optional: true
/@esbuild/linux-loong64/0.15.10:
@@ -1334,6 +1306,7 @@ packages:
/@iarna/toml/2.2.5:
resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==}
+ dev: false
/@istanbuljs/load-nyc-config/1.1.0:
resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==}
@@ -1482,6 +1455,7 @@ packages:
transitivePeerDependencies:
- encoding
- supports-color
+ dev: false
/@mdx-js/util/1.6.22:
resolution: {integrity: sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==}
@@ -1663,6 +1637,7 @@ packages:
dependencies:
estree-walker: 2.0.2
picomatch: 2.3.1
+ dev: false
/@rushstack/eslint-patch/1.2.0:
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==}
@@ -1682,26 +1657,10 @@ packages:
- supports-color
dev: false
- /@sveltejs/adapter-auto/1.0.0-next.66:
- resolution: {integrity: sha512-p78AQaSDHkLS5EFGqCF2xrLHMjKxx6wTLUvnP26cu2llh/VV4NihQ0rheVNgPWL+tGZpVznhrUG8fWmJxPciug==}
- dependencies:
- '@sveltejs/adapter-cloudflare': 1.0.0-next.32
- '@sveltejs/adapter-netlify': 1.0.0-next.72
- '@sveltejs/adapter-vercel': 1.0.0-next.68
- transitivePeerDependencies:
- - encoding
- - supports-color
- dev: true
-
- /@sveltejs/adapter-auto/1.0.0-next.87:
- resolution: {integrity: sha512-0MPCKo3aY1i3oESI6ZZikOB+MDV89WlWj4ot+/WEsP1J2uDA2HSirCZYWDnLB5i00HDHzqwBOfDDwHJ00pPC4w==}
+ /@sveltejs/adapter-auto/1.0.0-next.88:
+ resolution: {integrity: sha512-WcbELnu0Dz/72T1gbhDHxmNevVMEnQeNVi2IYrEj/uEKSMet4LOIrPv3DAAl8NETgBfzNJbMQpE7r9yL67CMTA==}
dependencies:
- '@sveltejs/adapter-cloudflare': 1.0.0-next.40
- '@sveltejs/adapter-netlify': 1.0.0-next.84
- '@sveltejs/adapter-vercel': 1.0.0-next.81
- transitivePeerDependencies:
- - encoding
- - supports-color
+ import-meta-resolve: 2.1.0
dev: true
/@sveltejs/adapter-cloudflare/1.0.0-next.31:
@@ -1712,22 +1671,6 @@ packages:
worktop: 0.8.0-next.14
dev: false
- /@sveltejs/adapter-cloudflare/1.0.0-next.32:
- resolution: {integrity: sha512-tzkUsdQlBk9xUjcGUOBYos4HKaeaXvz9v4TQ1QS2yIHEtL5xvMEDPZ94/DB2gPL4LZCnYbdY2lsy5HCsoN0hkQ==}
- dependencies:
- '@cloudflare/workers-types': 3.14.1
- esbuild: 0.14.54
- worktop: 0.8.0-next.14
- dev: true
-
- /@sveltejs/adapter-cloudflare/1.0.0-next.40:
- resolution: {integrity: sha512-KT4TK40T9pl24nPFWHgw1QwAv9AjOkUymjFpS07Ro2zeBHJVgga1Jl0OA1bsiyEiLNRivNRwaWHFySlZ2JJpxQ==}
- dependencies:
- '@cloudflare/workers-types': 3.18.0
- esbuild: 0.15.13
- worktop: 0.8.0-next.14
- dev: true
-
/@sveltejs/adapter-netlify/1.0.0-next.71:
resolution: {integrity: sha512-la1CGtWO1xul1L3zEoFAoc4EX2uxZjrZcOMS3tkKB8drxhbQsNbnTE6fmSSMFiZXhxaikczrBgQwqIaDkLTmZg==}
dependencies:
@@ -1737,23 +1680,6 @@ packages:
tiny-glob: 0.2.9
dev: false
- /@sveltejs/adapter-netlify/1.0.0-next.72:
- resolution: {integrity: sha512-g570hYAMkgrJfo/TRg3DZFmlR7bNFHECFPOMgc8R+f28ROap/nXA8ICbiSBF7+zJ5JXvJbqHGjERSsyhEq+59g==}
- dependencies:
- '@iarna/toml': 2.2.5
- esbuild: 0.14.54
- set-cookie-parser: 2.5.1
- tiny-glob: 0.2.9
- dev: true
-
- /@sveltejs/adapter-netlify/1.0.0-next.84:
- resolution: {integrity: sha512-i4vf3to0sV/iI39UPPhlVjOP+jZCZ048M4oHkqDM1FfJwACwgXaysdF2t4X0DV3loLmrkfarwbatjbGIECA9uQ==}
- dependencies:
- '@iarna/toml': 2.2.5
- esbuild: 0.15.13
- set-cookie-parser: 2.5.1
- dev: true
-
/@sveltejs/adapter-vercel/1.0.0-next.67:
resolution: {integrity: sha512-xg85d/vlivbTaZu70zmaPNkrY1YZhDrcxljuwVWO0LCzA4DACIA7CnXI9klUiXM5SPpsB8BhY6dS8sW5cDYWzw==}
dependencies:
@@ -1764,26 +1690,6 @@ packages:
- supports-color
dev: false
- /@sveltejs/adapter-vercel/1.0.0-next.68:
- resolution: {integrity: sha512-ImM+fDwGkVaf920Wzh284nfAfu/WoPXCpMwog0kveIODVgCozbpJY55fO860LccqdS0YDyeFqOUrZJCqcYNx4w==}
- dependencies:
- '@vercel/nft': 0.21.0
- esbuild: 0.14.54
- transitivePeerDependencies:
- - encoding
- - supports-color
- dev: true
-
- /@sveltejs/adapter-vercel/1.0.0-next.81:
- resolution: {integrity: sha512-cuNolQSqabSs97J2hn9bnRDOscihIO+VEYltsc+POLU/ecv7pbUm1qdRakeG3+ehK1mfZ9dub6vEVuLKhm+Qng==}
- dependencies:
- '@vercel/nft': 0.22.1
- esbuild: 0.15.13
- transitivePeerDependencies:
- - encoding
- - supports-color
- dev: true
-
/@sveltejs/kit/1.0.0-next.405_svelte@3.49.0+vite@3.0.9:
resolution: {integrity: sha512-jHSa74F7k+hC+0fof75g/xm/+1M5sM66Qt6v8eLLMSgjkp36Lb5xOioBhbl6w0NYoE5xysLsBWuu+yHytfvCBA==}
engines: {node: '>=16.9'}
@@ -1804,93 +1710,64 @@ packages:
- supports-color
dev: false
- /@sveltejs/kit/1.0.0-next.505_svelte@3.52.0+vite@3.1.6:
- resolution: {integrity: sha512-vg2WvWiUB7useJZOKbdM8WOXv10WD7SVDER74IXd1t/TWb/uXHzwMQ/ZAsXZFdxQsz1cDGFub3iC76PW+j58Pg==}
+ /@sveltejs/kit/1.0.0-next.547_svelte@3.50.1+vite@3.1.4:
+ resolution: {integrity: sha512-QhmoRt0nHISyl+0KRUoo/lod79eBSBgBqxb3E1hWLQLKF7vX5bCkXcZ84WReQtDwHkqvPrmJK2IBcF6za5nhjw==}
engines: {node: '>=16.14'}
hasBin: true
requiresBuild: true
peerDependencies:
svelte: ^3.44.0
- vite: ^3.1.0
- dependencies:
- '@sveltejs/vite-plugin-svelte': 1.0.5_svelte@3.52.0+vite@3.1.6
- '@types/cookie': 0.5.1
- cookie: 0.5.0
- devalue: 3.1.3
- kleur: 4.1.5
- magic-string: 0.26.3
- mime: 3.0.0
- node-fetch: 3.2.10
- sade: 1.8.1
- set-cookie-parser: 2.5.1
- sirv: 2.0.2
- svelte: 3.52.0
- tiny-glob: 0.2.9
- undici: 5.11.0
- vite: 3.1.6
- transitivePeerDependencies:
- - diff-match-patch
- - supports-color
- dev: false
-
- /@sveltejs/kit/1.0.0-next.510_svelte@3.50.1+vite@3.1.4:
- resolution: {integrity: sha512-i96sRqEzNP1dOaQQ2aR38H6emdQJhc1qr5KqNyjqi3Wb0sDAG49cQxMRUOdydkVKZkG/o7PvC5qdyblVfalAdA==}
- engines: {node: '>=16.14'}
- hasBin: true
- requiresBuild: true
- peerDependencies:
- svelte: ^3.44.0
- vite: ^3.1.0
+ vite: ^3.2.0
dependencies:
- '@sveltejs/vite-plugin-svelte': 1.0.5_svelte@3.50.1+vite@3.1.4
+ '@sveltejs/vite-plugin-svelte': 1.2.0_svelte@3.50.1+vite@3.1.4
'@types/cookie': 0.5.1
cookie: 0.5.0
- devalue: 4.0.0
+ devalue: 4.2.0
kleur: 4.1.5
- magic-string: 0.26.3
+ magic-string: 0.26.7
mime: 3.0.0
sade: 1.8.1
set-cookie-parser: 2.5.1
sirv: 2.0.2
svelte: 3.50.1
tiny-glob: 0.2.9
- undici: 5.11.0
+ undici: 5.12.0
vite: 3.1.4
transitivePeerDependencies:
- diff-match-patch
- supports-color
dev: true
- /@sveltejs/kit/1.0.0-next.510_svelte@3.52.0+vite@3.1.4:
- resolution: {integrity: sha512-i96sRqEzNP1dOaQQ2aR38H6emdQJhc1qr5KqNyjqi3Wb0sDAG49cQxMRUOdydkVKZkG/o7PvC5qdyblVfalAdA==}
+ /@sveltejs/kit/1.0.0-next.547_svelte@3.52.0+vite@3.1.4:
+ resolution: {integrity: sha512-QhmoRt0nHISyl+0KRUoo/lod79eBSBgBqxb3E1hWLQLKF7vX5bCkXcZ84WReQtDwHkqvPrmJK2IBcF6za5nhjw==}
engines: {node: '>=16.14'}
hasBin: true
requiresBuild: true
peerDependencies:
svelte: ^3.44.0
- vite: ^3.1.0
+ vite: ^3.2.0
dependencies:
- '@sveltejs/vite-plugin-svelte': 1.0.5_svelte@3.52.0+vite@3.1.4
+ '@sveltejs/vite-plugin-svelte': 1.2.0_svelte@3.52.0+vite@3.1.4
'@types/cookie': 0.5.1
cookie: 0.5.0
- devalue: 4.0.0
+ devalue: 4.2.0
kleur: 4.1.5
- magic-string: 0.26.3
+ magic-string: 0.26.7
mime: 3.0.0
sade: 1.8.1
set-cookie-parser: 2.5.1
sirv: 2.0.2
svelte: 3.52.0
tiny-glob: 0.2.9
- undici: 5.11.0
+ undici: 5.12.0
vite: 3.1.4
transitivePeerDependencies:
- diff-match-patch
- supports-color
dev: true
- /@sveltejs/kit/1.0.0-next.539_svelte@3.52.0+vite@3.1.6:
- resolution: {integrity: sha512-BCD9lMiNoz1S5k1R+4s0pkyMwiqtut5kAXgC7qo3WaJnzXxBJziJfkyJZT0fM6mrEHlcdJ/o5hBkswyVHsxqtA==}
+ /@sveltejs/kit/1.0.0-next.547_svelte@3.52.0+vite@3.2.4:
+ resolution: {integrity: sha512-QhmoRt0nHISyl+0KRUoo/lod79eBSBgBqxb3E1hWLQLKF7vX5bCkXcZ84WReQtDwHkqvPrmJK2IBcF6za5nhjw==}
engines: {node: '>=16.14'}
hasBin: true
requiresBuild: true
@@ -1898,7 +1775,7 @@ packages:
svelte: ^3.44.0
vite: ^3.2.0
dependencies:
- '@sveltejs/vite-plugin-svelte': 1.1.0_svelte@3.52.0+vite@3.1.6
+ '@sveltejs/vite-plugin-svelte': 1.2.0_svelte@3.52.0+vite@3.2.4
'@types/cookie': 0.5.1
cookie: 0.5.0
devalue: 4.2.0
@@ -1911,11 +1788,11 @@ packages:
svelte: 3.52.0
tiny-glob: 0.2.9
undici: 5.12.0
- vite: 3.1.6
+ vite: 3.2.4
transitivePeerDependencies:
- diff-match-patch
- supports-color
- dev: true
+ dev: false
/@sveltejs/vite-plugin-svelte/1.0.1_svelte@3.49.0+vite@3.0.9:
resolution: {integrity: sha512-PorCgUounn0VXcpeJu+hOweZODKmGuLHsLomwqSj+p26IwjjGffmYQfVHtiTWq+NqaUuuHWWG7vPge6UFw4Aeg==}
@@ -1932,7 +1809,7 @@ packages:
debug: 4.3.4
deepmerge: 4.2.2
kleur: 4.1.5
- magic-string: 0.26.3
+ magic-string: 0.26.7
svelte: 3.49.0
svelte-hmr: 0.14.12_svelte@3.49.0
vite: 3.0.9
@@ -1940,8 +1817,8 @@ packages:
- supports-color
dev: false
- /@sveltejs/vite-plugin-svelte/1.0.5_svelte@3.50.1+vite@3.1.4:
- resolution: {integrity: sha512-CmSdSow0Dr5ua1A11BQMtreWnE0JZmkVIcRU/yG3PKbycKUpXjNdgYTWFSbStLB0vdlGnBbm2+Y4sBVj+C+TIw==}
+ /@sveltejs/vite-plugin-svelte/1.2.0_svelte@3.50.1+vite@3.1.4:
+ resolution: {integrity: sha512-DT2oUkWAloH1tO7X5cQ4uDxQofaIS76skyFMElKtoqT6HJao+D82LI5i+0jPaSSmO7ex3Pa6jGYMlWy9ZJ1cdQ==}
engines: {node: ^14.18.0 || >= 16}
peerDependencies:
diff-match-patch: ^1.0.5
@@ -1951,20 +1828,20 @@ packages:
diff-match-patch:
optional: true
dependencies:
- '@rollup/pluginutils': 4.2.1
debug: 4.3.4
deepmerge: 4.2.2
kleur: 4.1.5
- magic-string: 0.26.3
+ magic-string: 0.26.7
svelte: 3.50.1
- svelte-hmr: 0.14.12_svelte@3.50.1
+ svelte-hmr: 0.15.1_svelte@3.50.1
vite: 3.1.4
+ vitefu: 0.2.1_vite@3.1.4
transitivePeerDependencies:
- supports-color
dev: true
- /@sveltejs/vite-plugin-svelte/1.0.5_svelte@3.52.0+vite@3.1.4:
- resolution: {integrity: sha512-CmSdSow0Dr5ua1A11BQMtreWnE0JZmkVIcRU/yG3PKbycKUpXjNdgYTWFSbStLB0vdlGnBbm2+Y4sBVj+C+TIw==}
+ /@sveltejs/vite-plugin-svelte/1.2.0_svelte@3.52.0+vite@3.1.4:
+ resolution: {integrity: sha512-DT2oUkWAloH1tO7X5cQ4uDxQofaIS76skyFMElKtoqT6HJao+D82LI5i+0jPaSSmO7ex3Pa6jGYMlWy9ZJ1cdQ==}
engines: {node: ^14.18.0 || >= 16}
peerDependencies:
diff-match-patch: ^1.0.5
@@ -1974,43 +1851,20 @@ packages:
diff-match-patch:
optional: true
dependencies:
- '@rollup/pluginutils': 4.2.1
debug: 4.3.4
deepmerge: 4.2.2
kleur: 4.1.5
- magic-string: 0.26.3
+ magic-string: 0.26.7
svelte: 3.52.0
- svelte-hmr: 0.14.12_svelte@3.52.0
+ svelte-hmr: 0.15.1_svelte@3.52.0
vite: 3.1.4
+ vitefu: 0.2.1_vite@3.1.4
transitivePeerDependencies:
- supports-color
dev: true
- /@sveltejs/vite-plugin-svelte/1.0.5_svelte@3.52.0+vite@3.1.6:
- resolution: {integrity: sha512-CmSdSow0Dr5ua1A11BQMtreWnE0JZmkVIcRU/yG3PKbycKUpXjNdgYTWFSbStLB0vdlGnBbm2+Y4sBVj+C+TIw==}
- engines: {node: ^14.18.0 || >= 16}
- peerDependencies:
- diff-match-patch: ^1.0.5
- svelte: ^3.44.0
- vite: ^3.0.0
- peerDependenciesMeta:
- diff-match-patch:
- optional: true
- dependencies:
- '@rollup/pluginutils': 4.2.1
- debug: 4.3.4
- deepmerge: 4.2.2
- kleur: 4.1.5
- magic-string: 0.26.3
- svelte: 3.52.0
- svelte-hmr: 0.14.12_svelte@3.52.0
- vite: 3.1.6
- transitivePeerDependencies:
- - supports-color
- dev: false
-
- /@sveltejs/vite-plugin-svelte/1.1.0_svelte@3.52.0+vite@3.1.6:
- resolution: {integrity: sha512-cFRfEdztubtj1c/rYh7ArK7XCfFJn6wG6+J8/e9amFsKtEJILovoBrK0/mxt1AjPQg0vaX+fHPKvhx+q8mTPaQ==}
+ /@sveltejs/vite-plugin-svelte/1.2.0_svelte@3.52.0+vite@3.2.4:
+ resolution: {integrity: sha512-DT2oUkWAloH1tO7X5cQ4uDxQofaIS76skyFMElKtoqT6HJao+D82LI5i+0jPaSSmO7ex3Pa6jGYMlWy9ZJ1cdQ==}
engines: {node: ^14.18.0 || >= 16}
peerDependencies:
diff-match-patch: ^1.0.5
@@ -2025,11 +1879,12 @@ packages:
kleur: 4.1.5
magic-string: 0.26.7
svelte: 3.52.0
- svelte-hmr: 0.15.0_svelte@3.52.0
- vite: 3.1.6
+ svelte-hmr: 0.15.1_svelte@3.52.0
+ vite: 3.2.4
+ vitefu: 0.2.1_vite@3.2.4
transitivePeerDependencies:
- supports-color
- dev: true
+ dev: false
/@swc/helpers/0.4.11:
resolution: {integrity: sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==}
@@ -2642,26 +2497,7 @@ packages:
transitivePeerDependencies:
- encoding
- supports-color
-
- /@vercel/nft/0.22.1:
- resolution: {integrity: sha512-lYYZIoxRurqDOSoVIdBicGnpUIpfyaS5qVjdPq+EfI285WqtZK3NK/dyCkiyBul+X2U2OEhRyeMdXPCHGJbohw==}
- hasBin: true
- dependencies:
- '@mapbox/node-pre-gyp': 1.0.9
- acorn: 8.8.0
- async-sema: 3.1.1
- bindings: 1.5.0
- estree-walker: 2.0.2
- glob: 7.2.3
- graceful-fs: 4.2.10
- micromatch: 4.0.5
- node-gyp-build: 4.5.0
- resolve-from: 5.0.0
- rollup-pluginutils: 2.8.2
- transitivePeerDependencies:
- - encoding
- - supports-color
- dev: true
+ dev: false
/@whatwg-node/fetch/0.3.2:
resolution: {integrity: sha512-Bs5zAWQs0tXsLa4mRmLw7Psps1EN78vPtgcLpw3qPY8s6UYPUM67zFZ9cy+7tZ64PXhfwzxJn+m7RH2Lq48RNQ==}
@@ -2673,13 +2509,14 @@ packages:
form-data-encoder: 1.7.2
formdata-node: 4.3.3
node-fetch: 2.6.7
- undici: 5.11.0
+ undici: 5.12.0
web-streams-polyfill: 3.2.1
transitivePeerDependencies:
- encoding
/abbrev/1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
+ dev: false
/abort-controller/3.0.0:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
@@ -2706,6 +2543,7 @@ packages:
debug: 4.3.4
transitivePeerDependencies:
- supports-color
+ dev: false
/aggregate-error/3.1.0:
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
@@ -2775,6 +2613,7 @@ packages:
/aproba/2.0.0:
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
+ dev: false
/are-we-there-yet/2.0.0:
resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
@@ -2782,6 +2621,7 @@ packages:
dependencies:
delegates: 1.0.0
readable-stream: 3.6.0
+ dev: false
/argparse/1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
@@ -2864,6 +2704,7 @@ packages:
/async-sema/3.1.1:
resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==}
+ dev: false
/axe-core/4.4.3:
resolution: {integrity: sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==}
@@ -2932,6 +2773,7 @@ packages:
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
dependencies:
file-uri-to-path: 1.0.0
+ dev: false
/boolbase/1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
@@ -3101,6 +2943,7 @@ packages:
/chownr/2.0.0:
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
engines: {node: '>=10'}
+ dev: false
/ci-info/3.4.0:
resolution: {integrity: sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==}
@@ -3202,6 +3045,7 @@ packages:
/color-support/1.1.3:
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
hasBin: true
+ dev: false
/colorette/2.0.19:
resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==}
@@ -3250,6 +3094,7 @@ packages:
/console-control-strings/1.1.0:
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
+ dev: false
/convert-source-map/1.8.0:
resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==}
@@ -3448,6 +3293,7 @@ packages:
/delegates/1.0.0:
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
+ dev: false
/detect-indent/6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
@@ -3456,18 +3302,10 @@ packages:
/detect-libc/2.0.1:
resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==}
engines: {node: '>=8'}
-
- /devalue/3.1.3:
- resolution: {integrity: sha512-9KO89Cb+qjzf2CqdrH+NuLaqdk9GhDP5EhR4zlkR51dvuIaiqtlkDkGzLMShDemwUy21raSMdu+kpX8Enw3yGQ==}
dev: false
- /devalue/4.0.0:
- resolution: {integrity: sha512-w25siwXyuMUqMr7jPlEjyNCp1vn0Jzj/fNg3qVt/r/Dpe8HjESh2V92L0jmh3uq4iJt0BvjH+Azk1pQzkcnDWA==}
- dev: true
-
/devalue/4.2.0:
resolution: {integrity: sha512-mbjoAaCL2qogBKgeFxFPOXAUsZchircF+B/79LD4sHH0+NHfYm8gZpQrskKDn5gENGt35+5OI1GUF7hLVnkPDw==}
- dev: true
/diff-sequences/29.0.0:
resolution: {integrity: sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==}
@@ -3609,6 +3447,7 @@ packages:
cpu: [x64]
os: [android]
requiresBuild: true
+ dev: false
optional: true
/esbuild-android-64/0.15.10:
@@ -3633,6 +3472,7 @@ packages:
cpu: [arm64]
os: [android]
requiresBuild: true
+ dev: false
optional: true
/esbuild-android-arm64/0.15.10:
@@ -3657,6 +3497,7 @@ packages:
cpu: [x64]
os: [darwin]
requiresBuild: true
+ dev: false
optional: true
/esbuild-darwin-64/0.15.10:
@@ -3681,6 +3522,7 @@ packages:
cpu: [arm64]
os: [darwin]
requiresBuild: true
+ dev: false
optional: true
/esbuild-darwin-arm64/0.15.10:
@@ -3705,6 +3547,7 @@ packages:
cpu: [x64]
os: [freebsd]
requiresBuild: true
+ dev: false
optional: true
/esbuild-freebsd-64/0.15.10:
@@ -3729,6 +3572,7 @@ packages:
cpu: [arm64]
os: [freebsd]
requiresBuild: true
+ dev: false
optional: true
/esbuild-freebsd-arm64/0.15.10:
@@ -3753,6 +3597,7 @@ packages:
cpu: [ia32]
os: [linux]
requiresBuild: true
+ dev: false
optional: true
/esbuild-linux-32/0.15.10:
@@ -3777,6 +3622,7 @@ packages:
cpu: [x64]
os: [linux]
requiresBuild: true
+ dev: false
optional: true
/esbuild-linux-64/0.15.10:
@@ -3801,6 +3647,7 @@ packages:
cpu: [arm]
os: [linux]
requiresBuild: true
+ dev: false
optional: true
/esbuild-linux-arm/0.15.10:
@@ -3825,6 +3672,7 @@ packages:
cpu: [arm64]
os: [linux]
requiresBuild: true
+ dev: false
optional: true
/esbuild-linux-arm64/0.15.10:
@@ -3849,6 +3697,7 @@ packages:
cpu: [mips64el]
os: [linux]
requiresBuild: true
+ dev: false
optional: true
/esbuild-linux-mips64le/0.15.10:
@@ -3873,6 +3722,7 @@ packages:
cpu: [ppc64]
os: [linux]
requiresBuild: true
+ dev: false
optional: true
/esbuild-linux-ppc64le/0.15.10:
@@ -3897,6 +3747,7 @@ packages:
cpu: [riscv64]
os: [linux]
requiresBuild: true
+ dev: false
optional: true
/esbuild-linux-riscv64/0.15.10:
@@ -3921,6 +3772,7 @@ packages:
cpu: [s390x]
os: [linux]
requiresBuild: true
+ dev: false
optional: true
/esbuild-linux-s390x/0.15.10:
@@ -3945,6 +3797,7 @@ packages:
cpu: [x64]
os: [netbsd]
requiresBuild: true
+ dev: false
optional: true
/esbuild-netbsd-64/0.15.10:
@@ -3969,6 +3822,7 @@ packages:
cpu: [x64]
os: [openbsd]
requiresBuild: true
+ dev: false
optional: true
/esbuild-openbsd-64/0.15.10:
@@ -4003,6 +3857,7 @@ packages:
cpu: [x64]
os: [sunos]
requiresBuild: true
+ dev: false
optional: true
/esbuild-sunos-64/0.15.10:
@@ -4027,6 +3882,7 @@ packages:
cpu: [ia32]
os: [win32]
requiresBuild: true
+ dev: false
optional: true
/esbuild-windows-32/0.15.10:
@@ -4051,6 +3907,7 @@ packages:
cpu: [x64]
os: [win32]
requiresBuild: true
+ dev: false
optional: true
/esbuild-windows-64/0.15.10:
@@ -4075,6 +3932,7 @@ packages:
cpu: [arm64]
os: [win32]
requiresBuild: true
+ dev: false
optional: true
/esbuild-windows-arm64/0.15.10:
@@ -4120,6 +3978,7 @@ packages:
esbuild-windows-32: 0.14.54
esbuild-windows-64: 0.14.54
esbuild-windows-arm64: 0.14.54
+ dev: false
/esbuild/0.15.10:
resolution: {integrity: sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==}
@@ -4672,9 +4531,11 @@ packages:
/estree-walker/0.6.1:
resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==}
+ dev: false
/estree-walker/2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+ dev: false
/estree-walker/3.0.1:
resolution: {integrity: sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g==}
@@ -4801,6 +4662,7 @@ packages:
/file-uri-to-path/1.0.0:
resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
+ dev: false
/fill-range/7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
@@ -4901,6 +4763,7 @@ packages:
engines: {node: '>= 8'}
dependencies:
minipass: 3.3.4
+ dev: false
/fs-monkey/1.0.3:
resolution: {integrity: sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==}
@@ -4947,6 +4810,7 @@ packages:
string-width: 4.2.3
strip-ansi: 6.0.1
wide-align: 1.1.5
+ dev: false
/gensync/1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
@@ -5130,6 +4994,7 @@ packages:
/has-unicode/2.0.1:
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
+ dev: false
/has/1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
@@ -5177,6 +5042,7 @@ packages:
debug: 4.3.4
transitivePeerDependencies:
- supports-color
+ dev: false
/human-id/1.0.2:
resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==}
@@ -5216,6 +5082,10 @@ packages:
parent-module: 1.0.1
resolve-from: 4.0.0
+ /import-meta-resolve/2.1.0:
+ resolution: {integrity: sha512-yG9pxkWJVTy4cmRsNWE3ztFdtFuYIV8G4N+cbCkO8b+qngkLyIUhxQFuZ0qJm67+0nUOxjMPT7nfksPKza1v2g==}
+ dev: true
+
/imurmurhash/0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
@@ -5804,24 +5674,18 @@ packages:
dependencies:
sourcemap-codec: 1.4.8
- /magic-string/0.26.3:
- resolution: {integrity: sha512-u1Po0NDyFcwdg2nzHT88wSK0+Rih0N1M+Ph1Sp08k8yvFFU3KR72wryS7e1qMPJypt99WB7fIFVCA92mQrMjrg==}
- engines: {node: '>=12'}
- dependencies:
- sourcemap-codec: 1.4.8
-
/magic-string/0.26.7:
resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==}
engines: {node: '>=12'}
dependencies:
sourcemap-codec: 1.4.8
- dev: true
/make-dir/3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
engines: {node: '>=8'}
dependencies:
semver: 6.3.0
+ dev: false
/makeerror/1.0.12:
resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==}
@@ -5984,6 +5848,7 @@ packages:
engines: {node: '>=8'}
dependencies:
yallist: 4.0.0
+ dev: false
/minizlib/2.1.2:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
@@ -5991,6 +5856,7 @@ packages:
dependencies:
minipass: 3.3.4
yallist: 4.0.0
+ dev: false
/mixme/0.5.4:
resolution: {integrity: sha512-3KYa4m4Vlqx98GPdOHghxSdNtTvcP8E0kkaJ5Dlh+h2DRzF7zpuVVcA8B0QpKd11YJeP9QQ7ASkKzOeu195Wzw==}
@@ -6007,6 +5873,7 @@ packages:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
hasBin: true
+ dev: false
/mri/1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
@@ -6104,6 +5971,7 @@ packages:
/node-gyp-build/4.5.0:
resolution: {integrity: sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==}
hasBin: true
+ dev: false
/node-html-parser/5.4.1:
resolution: {integrity: sha512-xy/O2wOEBJsIRLs4avwa1lVY7tIpXXOoHHUJLa0GvnoPPqMG1hgBVl1tNI3GHOwRktTVZy+Y6rjghk4B9/NLyg==}
@@ -6125,6 +5993,7 @@ packages:
hasBin: true
dependencies:
abbrev: 1.1.1
+ dev: false
/normalize-package-data/2.5.0:
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
@@ -6160,6 +6029,7 @@ packages:
console-control-strings: 1.1.0
gauge: 3.0.2
set-blocking: 2.0.0
+ dev: false
/npx-import/1.1.3:
resolution: {integrity: sha512-zy6249FJ81OtPsvz2y0+rgis31EN5wbdwBG2umtEh65W/4onYArHuoUSZ+W+T7BQYK7YF+h9G4CuGPusMCcLOw==}
@@ -6428,6 +6298,15 @@ packages:
picocolors: 1.0.0
source-map-js: 1.0.2
+ /postcss/8.4.19:
+ resolution: {integrity: sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.4
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: false
+
/preferred-pm/3.0.3:
resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==}
engines: {node: '>=10'}
@@ -6588,6 +6467,7 @@ packages:
inherits: 2.0.4
string_decoder: 1.3.0
util-deprecate: 1.0.2
+ dev: false
/readdirp/3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
@@ -6632,6 +6512,7 @@ packages:
/regexparam/2.0.1:
resolution: {integrity: sha512-zRgSaYemnNYxUv+/5SeoHI0eJIgTL/A2pUtXUPLHQxUldagouJ9p+K6IbIZ/JiQuCEv2E2B1O11SjVQy3aMCkw==}
engines: {node: '>=8'}
+ dev: false
/regexpp/3.2.0:
resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==}
@@ -6805,6 +6686,7 @@ packages:
resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
dependencies:
estree-walker: 0.6.1
+ dev: false
/rollup/2.77.3:
resolution: {integrity: sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==}
@@ -6820,6 +6702,7 @@ packages:
hasBin: true
optionalDependencies:
fsevents: 2.3.2
+ dev: true
/rollup/2.79.1:
resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==}
@@ -6857,6 +6740,7 @@ packages:
/safe-buffer/5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+ dev: false
/safe-regex-test/1.0.0:
resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==}
@@ -7133,6 +7017,7 @@ packages:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
dependencies:
safe-buffer: 5.2.1
+ dev: false
/stringify-entities/3.1.0:
resolution: {integrity: sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg==}
@@ -7294,8 +7179,8 @@ packages:
svelte: 3.49.0
dev: false
- /svelte-hmr/0.14.12_svelte@3.50.1:
- resolution: {integrity: sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==}
+ /svelte-hmr/0.15.1_svelte@3.50.1:
+ resolution: {integrity: sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==}
engines: {node: ^12.20 || ^14.13.1 || >= 16}
peerDependencies:
svelte: '>=3.19.0'
@@ -7303,22 +7188,13 @@ packages:
svelte: 3.50.1
dev: true
- /svelte-hmr/0.14.12_svelte@3.52.0:
- resolution: {integrity: sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==}
- engines: {node: ^12.20 || ^14.13.1 || >= 16}
- peerDependencies:
- svelte: '>=3.19.0'
- dependencies:
- svelte: 3.52.0
-
- /svelte-hmr/0.15.0_svelte@3.52.0:
- resolution: {integrity: sha512-Aw21SsyoohyVn4yiKXWPNCSW2DQNH/76kvUnE9kpt4h9hcg9tfyQc6xshx9hzgMfGF0kVx0EGD8oBMWSnATeOg==}
+ /svelte-hmr/0.15.1_svelte@3.52.0:
+ resolution: {integrity: sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==}
engines: {node: ^12.20 || ^14.13.1 || >= 16}
peerDependencies:
svelte: '>=3.19.0'
dependencies:
svelte: 3.52.0
- dev: true
/svelte-kit-cookie-session/3.0.6:
resolution: {integrity: sha512-8HmnhTxLgf2nqNTW22FwzzXHepdN7gLXH5mBU1zhZX93JXyq/OOLsgbWhX9Hv9JNUlYknwq/ZE54iMrEFaH5BA==}
@@ -7613,6 +7489,7 @@ packages:
minizlib: 2.1.2
mkdirp: 1.0.4
yallist: 4.0.0
+ dev: false
/term-size/2.2.1:
resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
@@ -7889,18 +7766,11 @@ packages:
has-symbols: 1.0.3
which-boxed-primitive: 1.0.2
- /undici/5.11.0:
- resolution: {integrity: sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw==}
- engines: {node: '>=12.18'}
- dependencies:
- busboy: 1.6.0
-
/undici/5.12.0:
resolution: {integrity: sha512-zMLamCG62PGjd9HHMpo05bSLvvwWOZgGeiWlN/vlqu3+lRo3elxktVGEyLMX+IO7c2eflLjcW74AlkhEZm15mg==}
engines: {node: '>=12.18'}
dependencies:
busboy: 1.6.0
- dev: true
/unherit/1.1.3:
resolution: {integrity: sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==}
@@ -8041,6 +7911,7 @@ packages:
/util-deprecate/1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ dev: false
/uuid/8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
@@ -8197,6 +8068,62 @@ packages:
rollup: 2.78.1
optionalDependencies:
fsevents: 2.3.2
+ dev: true
+
+ /vite/3.2.4:
+ resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': '>= 14'
+ less: '*'
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ esbuild: 0.15.13
+ postcss: 8.4.19
+ resolve: 1.22.1
+ rollup: 2.79.1
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: false
+
+ /vitefu/0.2.1_vite@3.1.4:
+ resolution: {integrity: sha512-clkvXTAeUf+XQKm3bhWUhT4pye+3acm6YCTGaWhxxIvZZ/QjnA3JA8Zud+z/mO5y5XYvJJhevs5Sjkv/FI8nRw==}
+ peerDependencies:
+ vite: ^3.0.0
+ peerDependenciesMeta:
+ vite:
+ optional: true
+ dependencies:
+ vite: 3.1.4
+ dev: true
+
+ /vitefu/0.2.1_vite@3.2.4:
+ resolution: {integrity: sha512-clkvXTAeUf+XQKm3bhWUhT4pye+3acm6YCTGaWhxxIvZZ/QjnA3JA8Zud+z/mO5y5XYvJJhevs5Sjkv/FI8nRw==}
+ peerDependencies:
+ vite: ^3.0.0
+ peerDependenciesMeta:
+ vite:
+ optional: true
+ dependencies:
+ vite: 3.2.4
+ dev: false
/vitest/0.23.4:
resolution: {integrity: sha512-iukBNWqQAv8EKDBUNntspLp9SfpaVFbmzmM0sNcnTxASQZMzRw3PsM6DMlsHiI+I6GeO5/sYDg3ecpC+SNFLrQ==}
@@ -8316,6 +8243,7 @@ packages:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
dependencies:
string-width: 4.2.3
+ dev: false
/word-wrap/1.2.3:
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
@@ -8327,6 +8255,7 @@ packages:
dependencies:
mrmime: 1.0.1
regexparam: 2.0.1
+ dev: false
/wrap-ansi/6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
diff --git a/site/src/routes/api/config.svx b/site/src/routes/api/config.svx
index cbdd8379b..03c167518 100644
--- a/site/src/routes/api/config.svx
+++ b/site/src/routes/api/config.svx
@@ -38,6 +38,8 @@ By default, your config file can contain the following values:
- `disableMasking` (optional, default: `false`): A boolean indicating whether fields from referenced fragments should be included in a document's selection set (can be overridden individually)
- `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`.
- `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.
## Svelte Plugin
diff --git a/site/src/routes/api/graphql.svx b/site/src/routes/api/graphql.svx
index b4ee361b5..a0ae7bd7b 100644
--- a/site/src/routes/api/graphql.svx
+++ b/site/src/routes/api/graphql.svx
@@ -41,6 +41,10 @@ For more information on using these fragments, head over to the [mutation docs](
`@append` is used in conjunction with the [list operation fragments](#list-operations) to tell the runtime to add the element at the end of the list. Can be used with both `_insert` and `_toggle` fragments. If the list is a member of a fragment, you will have to pass a value for the `parentID` so the correct list can be updated, otherwise the argument should be omitted.
+### `@allLists`
+
+`@allLists` is used in conjunction with the [list operation fragments](#list-operations) to tell the runtime to add the element to all lists. Can be used with both `_insert` and `_toggle` fragments. You can't have `parentID` at the same time.
+
### `@when`
`@when` provides a conditional under which the [list operation](#list-operations) should be executed. It takes arguments that match the arguments of the field tagged with `@list` or `@paginate`. For more information, check out the [mutation docs](/api/mutation#lists).