appflare 0.2.42 → 0.2.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Documentation.md +36 -0
- package/cli/schema-compiler.ts +4 -1
- package/cli/templates/core/client/handlers/index.ts +8 -0
- package/cli/templates/core/client/types.ts +1 -0
- package/dist/cli/index.js +8 -2
- package/dist/cli/index.mjs +8 -2
- package/dist/react/index.d.mts +2 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +1 -1
- package/dist/react/index.mjs +1 -1
- package/package.json +1 -1
- package/react/use-infinite-query.ts +5 -2
- package/react/use-query.ts +5 -2
package/Documentation.md
CHANGED
|
@@ -478,6 +478,42 @@ Inside handlers, you commonly use:
|
|
|
478
478
|
- `upsert` supports `target` (conflict columns) and `set` (on-conflict update columns)
|
|
479
479
|
- `ctx.error(status, message, details)` for typed failures
|
|
480
480
|
|
|
481
|
+
#### Updating manyToMany relations
|
|
482
|
+
|
|
483
|
+
The `update` operation supports managing manyToMany relations via the `set` payload. Each manyToMany relation field accepts an object with `items` and optional `mode`:
|
|
484
|
+
|
|
485
|
+
```ts
|
|
486
|
+
// Merge mode (default) — adds new links, keeps existing ones
|
|
487
|
+
await ctx.db.family.update({
|
|
488
|
+
where: { primaryUserId: userId },
|
|
489
|
+
set: {
|
|
490
|
+
members: {
|
|
491
|
+
items: [
|
|
492
|
+
"existing-user-id", // link by ID
|
|
493
|
+
{ id: "another-user-id" }, // link by ID (object form)
|
|
494
|
+
{ name: "New User", email: "..." }, // create new user, then link
|
|
495
|
+
],
|
|
496
|
+
mode: "merge",
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// Overwrite mode — deletes all existing links, keeps only new ones
|
|
502
|
+
await ctx.db.family.update({
|
|
503
|
+
where: { primaryUserId: userId },
|
|
504
|
+
set: {
|
|
505
|
+
members: {
|
|
506
|
+
items: ["user-id-1", "user-id-2"],
|
|
507
|
+
mode: "overwrite",
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
});
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
- `items` — array of IDs (string/number) or partial objects. Objects without an `id` field are created in the target table before linking.
|
|
514
|
+
- `mode` — `"merge"` (default) keeps existing links and adds new ones; `"overwrite"` deletes all existing links for the parent record before inserting new ones.
|
|
515
|
+
- All relation updates run inside a transaction when present.
|
|
516
|
+
|
|
481
517
|
See real examples in:
|
|
482
518
|
|
|
483
519
|
- `packages/backend/src/queries/db-features.ts`
|
package/cli/schema-compiler.ts
CHANGED
|
@@ -66,8 +66,11 @@ function toSqlLiteral(value: unknown): string {
|
|
|
66
66
|
if (value instanceof Date) {
|
|
67
67
|
return quote(value.toISOString());
|
|
68
68
|
}
|
|
69
|
+
if (typeof value === "object" && value !== null) {
|
|
70
|
+
return JSON.stringify(value);
|
|
71
|
+
}
|
|
69
72
|
throw new Error(
|
|
70
|
-
`Unsupported SQL default value '${String(value)}'. Use string, number, boolean, null, or
|
|
73
|
+
`Unsupported SQL default value '${String(value)}'. Use string, number, boolean, null, Date, array, or object.`,
|
|
71
74
|
);
|
|
72
75
|
}
|
|
73
76
|
|
|
@@ -88,6 +88,9 @@ function renderTreeObject(node: TreeNode, indentLevel = 1): string {
|
|
|
88
88
|
lines.push(
|
|
89
89
|
`${childIndent}subscribe: ${node.operation.alias}Route(runtime).subscribe,`,
|
|
90
90
|
);
|
|
91
|
+
lines.push(
|
|
92
|
+
`${childIndent}queryKey: ${node.operation.alias}Route(runtime).queryKey,`,
|
|
93
|
+
);
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
lines.push(`${indent}}`);
|
|
@@ -300,10 +303,15 @@ function renderRouteFactory(operation: HttpOperation): string {
|
|
|
300
303
|
};
|
|
301
304
|
};
|
|
302
305
|
|
|
306
|
+
const queryKey = (args?: ${inputType}): [string, string, string, ${inputType}] => {
|
|
307
|
+
return ["appflare", "query", ${JSON.stringify(operation.routePath)}, (args ?? {}) as ${inputType}];
|
|
308
|
+
};
|
|
309
|
+
|
|
303
310
|
return {
|
|
304
311
|
schema: ${schemaType},
|
|
305
312
|
run,
|
|
306
313
|
subscribe,
|
|
314
|
+
queryKey,
|
|
307
315
|
};
|
|
308
316
|
};`;
|
|
309
317
|
}
|
|
@@ -107,6 +107,7 @@ export type AppflareQueryRouteClient<
|
|
|
107
107
|
subscribe: (
|
|
108
108
|
options: AppflareQuerySubscribeOptions<import("zod").input<TSchema>, TOutput>,
|
|
109
109
|
) => AppflareRealtimeSubscription;
|
|
110
|
+
queryKey: (args?: import("zod").input<TSchema>) => [string, string, string, import("zod").input<TSchema>];
|
|
110
111
|
};
|
|
111
112
|
|
|
112
113
|
export type InferRouteSchema<TRoute> = TRoute extends {
|
package/dist/cli/index.js
CHANGED
|
@@ -166,7 +166,7 @@ export function createAppflare<Options extends BetterAuthClientOptions = Inferre
|
|
|
166
166
|
): Appflare<Options> {
|
|
167
167
|
return new Appflare(options);
|
|
168
168
|
}
|
|
169
|
-
`}function rr(e){let n=e.replace(/[^A-Za-z0-9_]/g,"_");return /^[0-9]/.test(n)?`_${n}`:n||"_route"}function ve(e){return e.split(/[^A-Za-z0-9]+/).filter(Boolean).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function ar(e){return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}function Re(e){let n={children:new Map};for(let t of e){let r=n;for(let a of t.segments){let o=r.children.get(a);o||(o={children:new Map},r.children.set(a,o)),r=o;}r.operation=t;}return n}function J(e,n=1){let t=" ".repeat(n),r=" ".repeat(n+1),a=Array.from(e.children.entries()).sort(([i],[s])=>i.localeCompare(s));if(a.length===0)return e.operation?`${e.operation.alias}Route(runtime)`:"{}";let o=["{"];for(let[i,s]of a)o.push(`${r}${ar(i)}: ${J(s,n+1)},`);return e.operation&&(o.push(`${r}run: ${e.operation.alias}Route(runtime).run,`),o.push(`${r}schema: ${e.operation.alias}Route(runtime).schema,`),e.operation.kind==="query"&&o.push(`${r}subscribe: ${e.operation.alias}Route(runtime).subscribe,`)),o.push(`${t}}`),o.join(`
|
|
169
|
+
`}function rr(e){let n=e.replace(/[^A-Za-z0-9_]/g,"_");return /^[0-9]/.test(n)?`_${n}`:n||"_route"}function ve(e){return e.split(/[^A-Za-z0-9]+/).filter(Boolean).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function ar(e){return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}function Re(e){let n={children:new Map};for(let t of e){let r=n;for(let a of t.segments){let o=r.children.get(a);o||(o={children:new Map},r.children.set(a,o)),r=o;}r.operation=t;}return n}function J(e,n=1){let t=" ".repeat(n),r=" ".repeat(n+1),a=Array.from(e.children.entries()).sort(([i],[s])=>i.localeCompare(s));if(a.length===0)return e.operation?`${e.operation.alias}Route(runtime)`:"{}";let o=["{"];for(let[i,s]of a)o.push(`${r}${ar(i)}: ${J(s,n+1)},`);return e.operation&&(o.push(`${r}run: ${e.operation.alias}Route(runtime).run,`),o.push(`${r}schema: ${e.operation.alias}Route(runtime).schema,`),e.operation.kind==="query"&&(o.push(`${r}subscribe: ${e.operation.alias}Route(runtime).subscribe,`),o.push(`${r}queryKey: ${e.operation.alias}Route(runtime).queryKey,`))),o.push(`${t}}`),o.join(`
|
|
170
170
|
`)}function or(e,n){if(e.kind!=="query"&&e.kind!=="mutation")return null;let t=e.clientSegments&&e.clientSegments.length>0?e.clientSegments:e.routePath.replace(/^\//,"").split("/").filter(Boolean).slice(1);if(t.length>=2&&t[t.length-1]===t[t.length-2]&&t.pop(),t.length===0)return null;let r=rr(`op_${n}_${e.kind}_${t.join("_")}`);return {kind:e.kind,routePath:e.routePath,queryName:e.handlerName??t.join("/"),segments:t,importPath:e.clientImportPath,exportName:e.exportName,alias:r,schemaConst:`${r}Schema`,typeBase:`${ve(e.kind)}${ve(t.join("_"))}`}}function ir(e){let n=`${e.typeBase}Input`,t=`${e.typeBase}Output`,r=`${e.typeBase}Schema`,a=e.kind==="query"?"GET":"POST";return e.kind==="query"?`const ${e.alias}Route = (
|
|
171
171
|
runtime: RequestRuntime,
|
|
172
172
|
): AppflareQueryRouteClient<typeof ${e.schemaConst}, ${t}> => {
|
|
@@ -322,10 +322,15 @@ export function createAppflare<Options extends BetterAuthClientOptions = Inferre
|
|
|
322
322
|
};
|
|
323
323
|
};
|
|
324
324
|
|
|
325
|
+
const queryKey = (args?: ${n}): [string, string, string, ${n}] => {
|
|
326
|
+
return ["appflare", "query", ${JSON.stringify(e.routePath)}, (args ?? {}) as ${n}];
|
|
327
|
+
};
|
|
328
|
+
|
|
325
329
|
return {
|
|
326
330
|
schema: ${r},
|
|
327
331
|
run,
|
|
328
332
|
subscribe,
|
|
333
|
+
queryKey,
|
|
329
334
|
};
|
|
330
335
|
};`:`const ${e.alias}Route = (
|
|
331
336
|
runtime: RequestRuntime,
|
|
@@ -1041,6 +1046,7 @@ export type AppflareQueryRouteClient<
|
|
|
1041
1046
|
subscribe: (
|
|
1042
1047
|
options: AppflareQuerySubscribeOptions<import("zod").input<TSchema>, TOutput>,
|
|
1043
1048
|
) => AppflareRealtimeSubscription;
|
|
1049
|
+
queryKey: (args?: import("zod").input<TSchema>) => [string, string, string, import("zod").input<TSchema>];
|
|
1044
1050
|
};
|
|
1045
1051
|
|
|
1046
1052
|
export type InferRouteSchema<TRoute> = TRoute extends {
|
|
@@ -9461,7 +9467,7 @@ ${p}
|
|
|
9461
9467
|
app.route('/admin', adminApp);
|
|
9462
9468
|
app.get('/admin/', (c) => c.redirect('/admin'));
|
|
9463
9469
|
}
|
|
9464
|
-
`}function oe(e){if(typeof e!="object"||e===null)return false;let n=e;return n.kind==="schema"&&typeof n.tables=="object"&&(typeof n.enums=="object"||n.enums===void 0)}function j(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toLowerCase()}function F(e){return e.replace(/[_-]+/g," ").replace(/\s+(.)/g,(n,t)=>t.toUpperCase()).replace(/\s/g,"").replace(/^(.)/,(n,t)=>t.toUpperCase())}function le(e){return e.endsWith("ies")?`${e.slice(0,-3)}y`:e.endsWith("ses")?e.slice(0,-2):e.endsWith("s")&&e.length>1?e.slice(0,-1):e}function f(e){return JSON.stringify(e)}function Er(e){if(typeof e=="string")return f(e);if(typeof e=="number"||typeof e=="boolean")return String(e);if(e===null)return "null";if(e instanceof Date)return f(e.toISOString());throw new Error(`Unsupported SQL default value '${String(e)}'. Use string, number, boolean, null, or
|
|
9470
|
+
`}function oe(e){if(typeof e!="object"||e===null)return false;let n=e;return n.kind==="schema"&&typeof n.tables=="object"&&(typeof n.enums=="object"||n.enums===void 0)}function j(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toLowerCase()}function F(e){return e.replace(/[_-]+/g," ").replace(/\s+(.)/g,(n,t)=>t.toUpperCase()).replace(/\s/g,"").replace(/^(.)/,(n,t)=>t.toUpperCase())}function le(e){return e.endsWith("ies")?`${e.slice(0,-3)}y`:e.endsWith("ses")?e.slice(0,-2):e.endsWith("s")&&e.length>1?e.slice(0,-1):e}function f(e){return JSON.stringify(e)}function Er(e){if(typeof e=="string")return f(e);if(typeof e=="number"||typeof e=="boolean")return String(e);if(e===null)return "null";if(e instanceof Date)return f(e.toISOString());if(typeof e=="object"&&e!==null)return JSON.stringify(e);throw new Error(`Unsupported SQL default value '${String(e)}'. Use string, number, boolean, null, Date, array, or object.`)}function Pr(e){return {kind:"schema",tables:Object.fromEntries(Object.entries(e.tables).map(([n,t])=>[n,{kind:"table",sqlName:t.sqlName,columns:Object.fromEntries(Object.entries(t.columns).map(([r,a])=>[r,{...a}])),relations:Object.fromEntries(Object.entries(t.relations).map(([r,a])=>[r,{...a}]))}])),enums:Object.fromEntries(Object.entries(e.enums??{}).map(([n,t])=>[n,{...t}]))}}function H(e,n,t){let r=e.tables[n];return r?r.columns[t]?.type:void 0}function mn(e,n,t,r,a,o,i){let s=n.columns[t];if(s){if(s.references&&(s.references.table!==r||s.references.column!==a))throw new Error(`Inferred relation '${e}.${t}' conflicts with explicit references(${s.references.table}.${s.references.column}).`);n.columns[t]={...s,notNull:s.notNull??(s.nullable===true?false:o.notNull),nullable:s.nullable??(o.notNull===false?true:void 0),references:{table:r,column:a,onDelete:s.references?.onDelete??o.onDelete,onUpdate:s.references?.onUpdate??o.onUpdate}};return}n.columns[t]={kind:"column",type:o.fkType??i,sqlName:o.sqlName,notNull:o.notNull??true,nullable:o.notNull===false?true:void 0,references:{table:r,column:a,onDelete:o.onDelete,onUpdate:o.onUpdate}};}function fn(e,n,t){if(n.notNull===true&&n.nullable===true)throw new Error(`Invalid nullable configuration on '${e}': cannot set both notNull and nullable to true.`);return n.notNull===true?true:n.nullable===true||n.notNull===false?false:t}function gn(e,n){return `${e}:${n}`}function jr(e,n,t,r){let a=gn(e,n),o=gn(t,r);return a<=o?{key:`${a}|${o}`,leftTable:e,leftReferenceField:n,rightTable:t,rightReferenceField:r,sourceIsLeft:true}:{key:`${o}|${a}`,leftTable:t,leftReferenceField:r,rightTable:e,rightReferenceField:n,sourceIsLeft:false}}function Or(e,n){return `${e}${F(n)}Links`}function hn(e,n,t){let r=le(e),a=le(n);return r===a?`${t}${F(r)}Id`:`${r}Id`}function Dr(e,n,t){if(e.junctionTable!==n.junctionTable)throw new Error(`manyToMany pair '${t}' has conflicting junctionTable values ('${e.junctionTable}' vs '${n.junctionTable}').`);if(e.leftField!==n.leftField)throw new Error(`manyToMany pair '${t}' has conflicting left field values ('${e.leftField}' vs '${n.leftField}').`);if(e.rightField!==n.rightField)throw new Error(`manyToMany pair '${t}' has conflicting right field values ('${e.rightField}' vs '${n.rightField}').`);if(e.leftSqlName!==n.leftSqlName)throw new Error(`manyToMany pair '${t}' has conflicting left sql name values ('${e.leftSqlName}' vs '${n.leftSqlName}').`);if(e.rightSqlName!==n.rightSqlName)throw new Error(`manyToMany pair '${t}' has conflicting right sql name values ('${e.rightSqlName}' vs '${n.rightSqlName}').`);if(e.onDelete!==n.onDelete)throw new Error(`manyToMany pair '${t}' has conflicting onDelete values ('${e.onDelete}' vs '${n.onDelete}').`);if(e.onUpdate!==n.onUpdate)throw new Error(`manyToMany pair '${t}' has conflicting onUpdate values ('${e.onUpdate}' vs '${n.onUpdate}').`);return e}function Vr(e){let n=new Map;for(let[t,r]of Object.entries(e.tables))for(let a of Object.values(r.relations)){if(a.relation!=="manyToMany")continue;let o=a.referenceField??"id",i=a.targetReferenceField??"id",s=jr(t,o,a.targetTable,i),u=hn(s.leftTable,s.rightTable,"source"),l=hn(s.rightTable,s.leftTable,"target"),c={leftTable:s.leftTable,leftReferenceField:s.leftReferenceField,rightTable:s.rightTable,rightReferenceField:s.rightReferenceField,junctionTable:a.junctionTable??Or(s.leftTable,s.rightTable),leftField:s.sourceIsLeft?a.sourceField??u:a.targetField??u,rightField:s.sourceIsLeft?a.targetField??l:a.sourceField??l,leftSqlName:s.sourceIsLeft?a.sourceSqlName:a.targetSqlName,rightSqlName:s.sourceIsLeft?a.targetSqlName:a.sourceSqlName,onDelete:a.onDelete,onUpdate:a.onUpdate};if(c.leftField===c.rightField)throw new Error(`manyToMany pair '${s.key}' resolves to duplicate junction fields '${c.leftField}'. Set sourceField/targetField explicitly.`);let p=n.get(s.key);p?Dr(p,c,s.key):n.set(s.key,c),a.referenceField=o,a.targetReferenceField=i,a.junctionTable=c.junctionTable,a.sourceField=s.sourceIsLeft?c.leftField:c.rightField,a.targetField=s.sourceIsLeft?c.rightField:c.leftField,a.sourceSqlName=s.sourceIsLeft?c.leftSqlName:c.rightSqlName,a.targetSqlName=s.sourceIsLeft?c.rightSqlName:c.leftSqlName;}for(let t of n.values()){if(t.junctionTable in e.tables)throw new Error(`manyToMany auto junction table '${t.junctionTable}' conflicts with an existing table. Set a different junctionTable name.`);let r=H(e,t.leftTable,t.leftReferenceField)??"string",a=H(e,t.rightTable,t.rightReferenceField)??"string";e.tables[t.junctionTable]={kind:"table",columns:{[t.leftField]:{kind:"column",type:r,sqlName:t.leftSqlName,notNull:true,nullable:false,references:{table:t.leftTable,column:t.leftReferenceField,onDelete:t.onDelete,onUpdate:t.onUpdate},index:true},[t.rightField]:{kind:"column",type:a,sqlName:t.rightSqlName,notNull:true,nullable:false,references:{table:t.rightTable,column:t.rightReferenceField,onDelete:t.onDelete,onUpdate:t.onUpdate},index:true}},relations:{[t.leftTable]:{kind:"relation",relation:"one",targetTable:t.leftTable,field:t.leftField,referenceField:t.leftReferenceField},[t.rightTable]:{kind:"relation",relation:"one",targetTable:t.rightTable,field:t.rightField,referenceField:t.rightReferenceField}}};}}function Br(e){for(let[n,t]of Object.entries(e.tables)){for(let[r,a]of Object.entries(t.columns))if(a.notNull===true&&a.nullable===true)throw new Error(`Invalid nullable configuration on '${n}.${r}': cannot set both notNull and nullable to true.`);for(let[r,a]of Object.entries(t.relations))if(a.relation!=="manyToMany"&&a.notNull===true&&a.nullable===true)throw new Error(`Invalid nullable configuration on '${n}.${r}': cannot set both notNull and nullable to true.`)}}function Wr(e){Br(e);let n=Pr(e);for(let[t,r]of Object.entries(n.tables))for(let[a,o]of Object.entries(r.relations)){if(o.relation!=="one")continue;let i=o.referenceField??"id",s=o.field??`${a}Id`;o.field=s;let u=H(n,o.targetTable,i)??o.fkType??"string";mn(t,r,s,o.targetTable,i,{fkType:o.fkType,sqlName:o.sqlName,notNull:fn(`${t}.${a}`,o,true),onDelete:o.onDelete,onUpdate:o.onUpdate},u);}for(let[t,r]of Object.entries(n.tables))for(let a of Object.values(r.relations)){if(a.relation!=="many")continue;let o=n.tables[a.targetTable];if(!o)continue;let i=a.referenceField??"id",s=a.field??`${le(t)}Id`;a.field=s;let u=H(n,t,i)??a.fkType??"string";mn(a.targetTable,o,s,t,i,{fkType:a.fkType,sqlName:a.sqlName,notNull:fn(`${t}.${a.targetTable}`,a,true),onDelete:a.onDelete,onUpdate:a.onUpdate},u);}return Vr(n),n}function bn(e){return e.primaryKey===true||e.notNull!==true||e.autoIncrement===true||e.sqlDefault!==void 0||e.runtimeDefaultFn!==void 0}function O(e){return e.notNull!==true}function Hr(e,n,t){let r=n.sqlName??j(e),a=r!==e;if(n.type==="int")return a?`t.int(${f(r)})`:"t.int()";if(n.type==="string")return n.length!==void 0?a?`t.text(${f(r)}, { length: ${n.length} })`:`t.text({ length: ${n.length} })`:a?`t.text(${f(r)})`:"t.text()";if(n.type==="boolean")return a?`t.int(${f(r)}, { mode: "boolean" })`:'t.int({ mode: "boolean" })';if(n.type==="date")return a?`t.int(${f(r)}, { mode: "timestamp_ms" })`:'t.int({ mode: "timestamp_ms" })';if(n.type==="enum"&&n.enumValues&&n.enumValues.length>0)return n.isArray?a?`t.text(${f(r)}).array()`:"t.text().array()":a?`t.text(${f(r)})`:"t.text()";if(n.type==="json"&&n.jsonShape){let o=L(n.jsonShape);return `${a?`t.text(${f(r)}, { mode: "json" })`:'t.text({ mode: "json" })'}.$type<${o}>()`}return t==="camelToSnake"&&a?`t.text(${f(r)})`:"t.text()"}function Lr(e,n,t){let r=t.field,a=t.referenceField??"id";if(!r)throw new Error(`Relation on '${e}' targeting '${t.targetTable}' is missing a local field.`);if(!(r in n.columns))throw new Error(`Relation '${e}.${r}' references missing local field '${r}'.`);return {sourceField:r,targetField:a}}function zr(e){return e.size===0?"":`import { ${Array.from(e).sort().join(", ")} } from "./auth.schema";
|
|
9465
9471
|
`}function Ur(e){return Object.values(e.relations).filter(n=>n.relation==="one").map(n=>n.targetTable)}function Qr(e,n,t){if(n.references)return {tableName:n.references.table,fieldName:n.references.column};let r=Object.values(t.relations).find(a=>a.relation==="one"&&a.field===e);if(r)return {tableName:r.targetTable,fieldName:r.referenceField??"id"}}function _r(e){let n=[];for(let[t,r]of Object.entries(e.tables)){let a=[];for(let[o,i]of Object.entries(r.columns)){if(i.type!=="json"||!i.jsonShape)continue;let s=ue(i.jsonShape);a.push(`${f(o)}: { shape: ${s} },`);}a.length!==0&&n.push(`${f(t)}: {
|
|
9466
9472
|
${a.map(o=>` ${o}`).join(`
|
|
9467
9473
|
`)}
|
package/dist/cli/index.mjs
CHANGED
|
@@ -166,7 +166,7 @@ export function createAppflare<Options extends BetterAuthClientOptions = Inferre
|
|
|
166
166
|
): Appflare<Options> {
|
|
167
167
|
return new Appflare(options);
|
|
168
168
|
}
|
|
169
|
-
`}function rr(e){let n=e.replace(/[^A-Za-z0-9_]/g,"_");return /^[0-9]/.test(n)?`_${n}`:n||"_route"}function ve(e){return e.split(/[^A-Za-z0-9]+/).filter(Boolean).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function ar(e){return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}function Re(e){let n={children:new Map};for(let t of e){let r=n;for(let a of t.segments){let o=r.children.get(a);o||(o={children:new Map},r.children.set(a,o)),r=o;}r.operation=t;}return n}function J(e,n=1){let t=" ".repeat(n),r=" ".repeat(n+1),a=Array.from(e.children.entries()).sort(([i],[s])=>i.localeCompare(s));if(a.length===0)return e.operation?`${e.operation.alias}Route(runtime)`:"{}";let o=["{"];for(let[i,s]of a)o.push(`${r}${ar(i)}: ${J(s,n+1)},`);return e.operation&&(o.push(`${r}run: ${e.operation.alias}Route(runtime).run,`),o.push(`${r}schema: ${e.operation.alias}Route(runtime).schema,`),e.operation.kind==="query"&&o.push(`${r}subscribe: ${e.operation.alias}Route(runtime).subscribe,`)),o.push(`${t}}`),o.join(`
|
|
169
|
+
`}function rr(e){let n=e.replace(/[^A-Za-z0-9_]/g,"_");return /^[0-9]/.test(n)?`_${n}`:n||"_route"}function ve(e){return e.split(/[^A-Za-z0-9]+/).filter(Boolean).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("")}function ar(e){return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}function Re(e){let n={children:new Map};for(let t of e){let r=n;for(let a of t.segments){let o=r.children.get(a);o||(o={children:new Map},r.children.set(a,o)),r=o;}r.operation=t;}return n}function J(e,n=1){let t=" ".repeat(n),r=" ".repeat(n+1),a=Array.from(e.children.entries()).sort(([i],[s])=>i.localeCompare(s));if(a.length===0)return e.operation?`${e.operation.alias}Route(runtime)`:"{}";let o=["{"];for(let[i,s]of a)o.push(`${r}${ar(i)}: ${J(s,n+1)},`);return e.operation&&(o.push(`${r}run: ${e.operation.alias}Route(runtime).run,`),o.push(`${r}schema: ${e.operation.alias}Route(runtime).schema,`),e.operation.kind==="query"&&(o.push(`${r}subscribe: ${e.operation.alias}Route(runtime).subscribe,`),o.push(`${r}queryKey: ${e.operation.alias}Route(runtime).queryKey,`))),o.push(`${t}}`),o.join(`
|
|
170
170
|
`)}function or(e,n){if(e.kind!=="query"&&e.kind!=="mutation")return null;let t=e.clientSegments&&e.clientSegments.length>0?e.clientSegments:e.routePath.replace(/^\//,"").split("/").filter(Boolean).slice(1);if(t.length>=2&&t[t.length-1]===t[t.length-2]&&t.pop(),t.length===0)return null;let r=rr(`op_${n}_${e.kind}_${t.join("_")}`);return {kind:e.kind,routePath:e.routePath,queryName:e.handlerName??t.join("/"),segments:t,importPath:e.clientImportPath,exportName:e.exportName,alias:r,schemaConst:`${r}Schema`,typeBase:`${ve(e.kind)}${ve(t.join("_"))}`}}function ir(e){let n=`${e.typeBase}Input`,t=`${e.typeBase}Output`,r=`${e.typeBase}Schema`,a=e.kind==="query"?"GET":"POST";return e.kind==="query"?`const ${e.alias}Route = (
|
|
171
171
|
runtime: RequestRuntime,
|
|
172
172
|
): AppflareQueryRouteClient<typeof ${e.schemaConst}, ${t}> => {
|
|
@@ -322,10 +322,15 @@ export function createAppflare<Options extends BetterAuthClientOptions = Inferre
|
|
|
322
322
|
};
|
|
323
323
|
};
|
|
324
324
|
|
|
325
|
+
const queryKey = (args?: ${n}): [string, string, string, ${n}] => {
|
|
326
|
+
return ["appflare", "query", ${JSON.stringify(e.routePath)}, (args ?? {}) as ${n}];
|
|
327
|
+
};
|
|
328
|
+
|
|
325
329
|
return {
|
|
326
330
|
schema: ${r},
|
|
327
331
|
run,
|
|
328
332
|
subscribe,
|
|
333
|
+
queryKey,
|
|
329
334
|
};
|
|
330
335
|
};`:`const ${e.alias}Route = (
|
|
331
336
|
runtime: RequestRuntime,
|
|
@@ -1041,6 +1046,7 @@ export type AppflareQueryRouteClient<
|
|
|
1041
1046
|
subscribe: (
|
|
1042
1047
|
options: AppflareQuerySubscribeOptions<import("zod").input<TSchema>, TOutput>,
|
|
1043
1048
|
) => AppflareRealtimeSubscription;
|
|
1049
|
+
queryKey: (args?: import("zod").input<TSchema>) => [string, string, string, import("zod").input<TSchema>];
|
|
1044
1050
|
};
|
|
1045
1051
|
|
|
1046
1052
|
export type InferRouteSchema<TRoute> = TRoute extends {
|
|
@@ -9461,7 +9467,7 @@ ${p}
|
|
|
9461
9467
|
app.route('/admin', adminApp);
|
|
9462
9468
|
app.get('/admin/', (c) => c.redirect('/admin'));
|
|
9463
9469
|
}
|
|
9464
|
-
`}function oe(e){if(typeof e!="object"||e===null)return false;let n=e;return n.kind==="schema"&&typeof n.tables=="object"&&(typeof n.enums=="object"||n.enums===void 0)}function j(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toLowerCase()}function F(e){return e.replace(/[_-]+/g," ").replace(/\s+(.)/g,(n,t)=>t.toUpperCase()).replace(/\s/g,"").replace(/^(.)/,(n,t)=>t.toUpperCase())}function le(e){return e.endsWith("ies")?`${e.slice(0,-3)}y`:e.endsWith("ses")?e.slice(0,-2):e.endsWith("s")&&e.length>1?e.slice(0,-1):e}function f(e){return JSON.stringify(e)}function Er(e){if(typeof e=="string")return f(e);if(typeof e=="number"||typeof e=="boolean")return String(e);if(e===null)return "null";if(e instanceof Date)return f(e.toISOString());throw new Error(`Unsupported SQL default value '${String(e)}'. Use string, number, boolean, null, or
|
|
9470
|
+
`}function oe(e){if(typeof e!="object"||e===null)return false;let n=e;return n.kind==="schema"&&typeof n.tables=="object"&&(typeof n.enums=="object"||n.enums===void 0)}function j(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toLowerCase()}function F(e){return e.replace(/[_-]+/g," ").replace(/\s+(.)/g,(n,t)=>t.toUpperCase()).replace(/\s/g,"").replace(/^(.)/,(n,t)=>t.toUpperCase())}function le(e){return e.endsWith("ies")?`${e.slice(0,-3)}y`:e.endsWith("ses")?e.slice(0,-2):e.endsWith("s")&&e.length>1?e.slice(0,-1):e}function f(e){return JSON.stringify(e)}function Er(e){if(typeof e=="string")return f(e);if(typeof e=="number"||typeof e=="boolean")return String(e);if(e===null)return "null";if(e instanceof Date)return f(e.toISOString());if(typeof e=="object"&&e!==null)return JSON.stringify(e);throw new Error(`Unsupported SQL default value '${String(e)}'. Use string, number, boolean, null, Date, array, or object.`)}function Pr(e){return {kind:"schema",tables:Object.fromEntries(Object.entries(e.tables).map(([n,t])=>[n,{kind:"table",sqlName:t.sqlName,columns:Object.fromEntries(Object.entries(t.columns).map(([r,a])=>[r,{...a}])),relations:Object.fromEntries(Object.entries(t.relations).map(([r,a])=>[r,{...a}]))}])),enums:Object.fromEntries(Object.entries(e.enums??{}).map(([n,t])=>[n,{...t}]))}}function H(e,n,t){let r=e.tables[n];return r?r.columns[t]?.type:void 0}function mn(e,n,t,r,a,o,i){let s=n.columns[t];if(s){if(s.references&&(s.references.table!==r||s.references.column!==a))throw new Error(`Inferred relation '${e}.${t}' conflicts with explicit references(${s.references.table}.${s.references.column}).`);n.columns[t]={...s,notNull:s.notNull??(s.nullable===true?false:o.notNull),nullable:s.nullable??(o.notNull===false?true:void 0),references:{table:r,column:a,onDelete:s.references?.onDelete??o.onDelete,onUpdate:s.references?.onUpdate??o.onUpdate}};return}n.columns[t]={kind:"column",type:o.fkType??i,sqlName:o.sqlName,notNull:o.notNull??true,nullable:o.notNull===false?true:void 0,references:{table:r,column:a,onDelete:o.onDelete,onUpdate:o.onUpdate}};}function fn(e,n,t){if(n.notNull===true&&n.nullable===true)throw new Error(`Invalid nullable configuration on '${e}': cannot set both notNull and nullable to true.`);return n.notNull===true?true:n.nullable===true||n.notNull===false?false:t}function gn(e,n){return `${e}:${n}`}function jr(e,n,t,r){let a=gn(e,n),o=gn(t,r);return a<=o?{key:`${a}|${o}`,leftTable:e,leftReferenceField:n,rightTable:t,rightReferenceField:r,sourceIsLeft:true}:{key:`${o}|${a}`,leftTable:t,leftReferenceField:r,rightTable:e,rightReferenceField:n,sourceIsLeft:false}}function Or(e,n){return `${e}${F(n)}Links`}function hn(e,n,t){let r=le(e),a=le(n);return r===a?`${t}${F(r)}Id`:`${r}Id`}function Dr(e,n,t){if(e.junctionTable!==n.junctionTable)throw new Error(`manyToMany pair '${t}' has conflicting junctionTable values ('${e.junctionTable}' vs '${n.junctionTable}').`);if(e.leftField!==n.leftField)throw new Error(`manyToMany pair '${t}' has conflicting left field values ('${e.leftField}' vs '${n.leftField}').`);if(e.rightField!==n.rightField)throw new Error(`manyToMany pair '${t}' has conflicting right field values ('${e.rightField}' vs '${n.rightField}').`);if(e.leftSqlName!==n.leftSqlName)throw new Error(`manyToMany pair '${t}' has conflicting left sql name values ('${e.leftSqlName}' vs '${n.leftSqlName}').`);if(e.rightSqlName!==n.rightSqlName)throw new Error(`manyToMany pair '${t}' has conflicting right sql name values ('${e.rightSqlName}' vs '${n.rightSqlName}').`);if(e.onDelete!==n.onDelete)throw new Error(`manyToMany pair '${t}' has conflicting onDelete values ('${e.onDelete}' vs '${n.onDelete}').`);if(e.onUpdate!==n.onUpdate)throw new Error(`manyToMany pair '${t}' has conflicting onUpdate values ('${e.onUpdate}' vs '${n.onUpdate}').`);return e}function Vr(e){let n=new Map;for(let[t,r]of Object.entries(e.tables))for(let a of Object.values(r.relations)){if(a.relation!=="manyToMany")continue;let o=a.referenceField??"id",i=a.targetReferenceField??"id",s=jr(t,o,a.targetTable,i),u=hn(s.leftTable,s.rightTable,"source"),l=hn(s.rightTable,s.leftTable,"target"),c={leftTable:s.leftTable,leftReferenceField:s.leftReferenceField,rightTable:s.rightTable,rightReferenceField:s.rightReferenceField,junctionTable:a.junctionTable??Or(s.leftTable,s.rightTable),leftField:s.sourceIsLeft?a.sourceField??u:a.targetField??u,rightField:s.sourceIsLeft?a.targetField??l:a.sourceField??l,leftSqlName:s.sourceIsLeft?a.sourceSqlName:a.targetSqlName,rightSqlName:s.sourceIsLeft?a.targetSqlName:a.sourceSqlName,onDelete:a.onDelete,onUpdate:a.onUpdate};if(c.leftField===c.rightField)throw new Error(`manyToMany pair '${s.key}' resolves to duplicate junction fields '${c.leftField}'. Set sourceField/targetField explicitly.`);let p=n.get(s.key);p?Dr(p,c,s.key):n.set(s.key,c),a.referenceField=o,a.targetReferenceField=i,a.junctionTable=c.junctionTable,a.sourceField=s.sourceIsLeft?c.leftField:c.rightField,a.targetField=s.sourceIsLeft?c.rightField:c.leftField,a.sourceSqlName=s.sourceIsLeft?c.leftSqlName:c.rightSqlName,a.targetSqlName=s.sourceIsLeft?c.rightSqlName:c.leftSqlName;}for(let t of n.values()){if(t.junctionTable in e.tables)throw new Error(`manyToMany auto junction table '${t.junctionTable}' conflicts with an existing table. Set a different junctionTable name.`);let r=H(e,t.leftTable,t.leftReferenceField)??"string",a=H(e,t.rightTable,t.rightReferenceField)??"string";e.tables[t.junctionTable]={kind:"table",columns:{[t.leftField]:{kind:"column",type:r,sqlName:t.leftSqlName,notNull:true,nullable:false,references:{table:t.leftTable,column:t.leftReferenceField,onDelete:t.onDelete,onUpdate:t.onUpdate},index:true},[t.rightField]:{kind:"column",type:a,sqlName:t.rightSqlName,notNull:true,nullable:false,references:{table:t.rightTable,column:t.rightReferenceField,onDelete:t.onDelete,onUpdate:t.onUpdate},index:true}},relations:{[t.leftTable]:{kind:"relation",relation:"one",targetTable:t.leftTable,field:t.leftField,referenceField:t.leftReferenceField},[t.rightTable]:{kind:"relation",relation:"one",targetTable:t.rightTable,field:t.rightField,referenceField:t.rightReferenceField}}};}}function Br(e){for(let[n,t]of Object.entries(e.tables)){for(let[r,a]of Object.entries(t.columns))if(a.notNull===true&&a.nullable===true)throw new Error(`Invalid nullable configuration on '${n}.${r}': cannot set both notNull and nullable to true.`);for(let[r,a]of Object.entries(t.relations))if(a.relation!=="manyToMany"&&a.notNull===true&&a.nullable===true)throw new Error(`Invalid nullable configuration on '${n}.${r}': cannot set both notNull and nullable to true.`)}}function Wr(e){Br(e);let n=Pr(e);for(let[t,r]of Object.entries(n.tables))for(let[a,o]of Object.entries(r.relations)){if(o.relation!=="one")continue;let i=o.referenceField??"id",s=o.field??`${a}Id`;o.field=s;let u=H(n,o.targetTable,i)??o.fkType??"string";mn(t,r,s,o.targetTable,i,{fkType:o.fkType,sqlName:o.sqlName,notNull:fn(`${t}.${a}`,o,true),onDelete:o.onDelete,onUpdate:o.onUpdate},u);}for(let[t,r]of Object.entries(n.tables))for(let a of Object.values(r.relations)){if(a.relation!=="many")continue;let o=n.tables[a.targetTable];if(!o)continue;let i=a.referenceField??"id",s=a.field??`${le(t)}Id`;a.field=s;let u=H(n,t,i)??a.fkType??"string";mn(a.targetTable,o,s,t,i,{fkType:a.fkType,sqlName:a.sqlName,notNull:fn(`${t}.${a.targetTable}`,a,true),onDelete:a.onDelete,onUpdate:a.onUpdate},u);}return Vr(n),n}function bn(e){return e.primaryKey===true||e.notNull!==true||e.autoIncrement===true||e.sqlDefault!==void 0||e.runtimeDefaultFn!==void 0}function O(e){return e.notNull!==true}function Hr(e,n,t){let r=n.sqlName??j(e),a=r!==e;if(n.type==="int")return a?`t.int(${f(r)})`:"t.int()";if(n.type==="string")return n.length!==void 0?a?`t.text(${f(r)}, { length: ${n.length} })`:`t.text({ length: ${n.length} })`:a?`t.text(${f(r)})`:"t.text()";if(n.type==="boolean")return a?`t.int(${f(r)}, { mode: "boolean" })`:'t.int({ mode: "boolean" })';if(n.type==="date")return a?`t.int(${f(r)}, { mode: "timestamp_ms" })`:'t.int({ mode: "timestamp_ms" })';if(n.type==="enum"&&n.enumValues&&n.enumValues.length>0)return n.isArray?a?`t.text(${f(r)}).array()`:"t.text().array()":a?`t.text(${f(r)})`:"t.text()";if(n.type==="json"&&n.jsonShape){let o=L(n.jsonShape);return `${a?`t.text(${f(r)}, { mode: "json" })`:'t.text({ mode: "json" })'}.$type<${o}>()`}return t==="camelToSnake"&&a?`t.text(${f(r)})`:"t.text()"}function Lr(e,n,t){let r=t.field,a=t.referenceField??"id";if(!r)throw new Error(`Relation on '${e}' targeting '${t.targetTable}' is missing a local field.`);if(!(r in n.columns))throw new Error(`Relation '${e}.${r}' references missing local field '${r}'.`);return {sourceField:r,targetField:a}}function zr(e){return e.size===0?"":`import { ${Array.from(e).sort().join(", ")} } from "./auth.schema";
|
|
9465
9471
|
`}function Ur(e){return Object.values(e.relations).filter(n=>n.relation==="one").map(n=>n.targetTable)}function Qr(e,n,t){if(n.references)return {tableName:n.references.table,fieldName:n.references.column};let r=Object.values(t.relations).find(a=>a.relation==="one"&&a.field===e);if(r)return {tableName:r.targetTable,fieldName:r.referenceField??"id"}}function _r(e){let n=[];for(let[t,r]of Object.entries(e.tables)){let a=[];for(let[o,i]of Object.entries(r.columns)){if(i.type!=="json"||!i.jsonShape)continue;let s=ue(i.jsonShape);a.push(`${f(o)}: { shape: ${s} },`);}a.length!==0&&n.push(`${f(t)}: {
|
|
9466
9472
|
${a.map(o=>` ${o}`).join(`
|
|
9467
9473
|
`)}
|
package/dist/react/index.d.mts
CHANGED
|
@@ -36,6 +36,7 @@ type AppflareQueryLike$1<TArgs extends Record<string, unknown>, TData> = {
|
|
|
36
36
|
onChange: (data: TData, update: AppflareRealtimeQueryUpdateLike$1<TData>) => void;
|
|
37
37
|
onError?: (error: unknown) => void;
|
|
38
38
|
}) => AppflareRealtimeSubscriptionLike$1;
|
|
39
|
+
queryKey?: (args?: TArgs) => QueryKey;
|
|
39
40
|
};
|
|
40
41
|
type UseAppflareQueryOptions<TArgs extends Record<string, unknown>, TData, TSelected = TData, TKey extends QueryKey = QueryKey> = {
|
|
41
42
|
realtime?: {
|
|
@@ -95,6 +96,7 @@ type AppflareQueryLike<TArgs extends Record<string, unknown>, TData> = {
|
|
|
95
96
|
onChange: (data: TData, update: AppflareRealtimeQueryUpdateLike<TData>) => void;
|
|
96
97
|
onError?: (error: unknown) => void;
|
|
97
98
|
}) => AppflareRealtimeSubscriptionLike;
|
|
99
|
+
queryKey?: (args?: TArgs) => QueryKey;
|
|
98
100
|
};
|
|
99
101
|
type UseAppflareInfiniteQueryOptions<TArgs extends Record<string, unknown>, TData, TPageParam, TSelected = InfiniteData<TData, TPageParam>, TKey extends QueryKey = QueryKey> = {
|
|
100
102
|
realtime?: {
|
package/dist/react/index.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ type AppflareQueryLike$1<TArgs extends Record<string, unknown>, TData> = {
|
|
|
36
36
|
onChange: (data: TData, update: AppflareRealtimeQueryUpdateLike$1<TData>) => void;
|
|
37
37
|
onError?: (error: unknown) => void;
|
|
38
38
|
}) => AppflareRealtimeSubscriptionLike$1;
|
|
39
|
+
queryKey?: (args?: TArgs) => QueryKey;
|
|
39
40
|
};
|
|
40
41
|
type UseAppflareQueryOptions<TArgs extends Record<string, unknown>, TData, TSelected = TData, TKey extends QueryKey = QueryKey> = {
|
|
41
42
|
realtime?: {
|
|
@@ -95,6 +96,7 @@ type AppflareQueryLike<TArgs extends Record<string, unknown>, TData> = {
|
|
|
95
96
|
onChange: (data: TData, update: AppflareRealtimeQueryUpdateLike<TData>) => void;
|
|
96
97
|
onError?: (error: unknown) => void;
|
|
97
98
|
}) => AppflareRealtimeSubscriptionLike;
|
|
99
|
+
queryKey?: (args?: TArgs) => QueryKey;
|
|
98
100
|
};
|
|
99
101
|
type UseAppflareInfiniteQueryOptions<TArgs extends Record<string, unknown>, TData, TPageParam, TSelected = InfiniteData<TData, TPageParam>, TKey extends QueryKey = QueryKey> = {
|
|
100
102
|
realtime?: {
|
package/dist/react/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var reactQuery=require('@tanstack/react-query'),react=require('react');function O(r){let
|
|
1
|
+
'use strict';var reactQuery=require('@tanstack/react-query'),react=require('react');function O(r){let a=new Error(r.message);return r.status!==void 0&&(a.status=r.status),a}function b(r,...a){let t=a[0]??{},e=a[1],o=reactQuery.useQueryClient(),i=react.useRef(e?.realtime?.onChange),p=react.useRef(e?.realtime?.onError);react.useEffect(()=>{i.current=e?.realtime?.onChange,p.current=e?.realtime?.onError;},[e?.realtime?.onChange,e?.realtime?.onError]);let u=react.useMemo(()=>e?.queryOptions?.queryKey??(r.queryKey?r.queryKey(t):["appflare","query",r,t]),[t,e?.queryOptions?.queryKey,r]),d=react.useMemo(()=>reactQuery.hashKey(u),[u]),f=react.useMemo(()=>reactQuery.hashKey([t]),[t]),A=react.useMemo(()=>reactQuery.hashKey([e?.realtime?.requestOptions]),[e?.realtime?.requestOptions]),m=reactQuery.useQuery({...e?.queryOptions,queryKey:u,queryFn:async()=>{let s=await r.run(t,e?.requestOptions);if(s.error)throw O(s.error);return s.data}});return react.useEffect(()=>{if(e?.realtime?.enabled===false||!r.subscribe)return;let s=new AbortController,y=r.subscribe({args:t,authToken:e?.realtime?.authToken,requestOptions:e?.realtime?.requestOptions,signal:s.signal,onChange:(n,c)=>{o.setQueryData(u,n),i.current?.(n,c);},onError:n=>{p.current?.(n);}});return ()=>{s.abort(),y.remove();}},[f,e?.realtime?.authToken,e?.realtime?.enabled,A,r.subscribe,o,d]),m}function h(r){let a=new Error(r.message);return r.status!==void 0&&(a.status=r.status),a}function P(r,...a){let t=a[0]??{},e=a[1],o=reactQuery.useQueryClient(),i=react.useRef(e?.realtime?.onChange),p=react.useRef(e?.realtime?.onError);react.useEffect(()=>{i.current=e?.realtime?.onChange,p.current=e?.realtime?.onError;},[e?.realtime?.onChange,e?.realtime?.onError]);let u=react.useMemo(()=>e?.queryOptions?.queryKey??(r.queryKey?r.queryKey(t):["appflare","infinite-query",r,t]),[t,e?.queryOptions?.queryKey,r]),d=react.useMemo(()=>reactQuery.hashKey(u),[u]),f=react.useMemo(()=>reactQuery.hashKey([t]),[t]),A=react.useMemo(()=>reactQuery.hashKey([e?.realtime?.requestOptions]),[e?.realtime?.requestOptions]),m=reactQuery.useInfiniteQuery({...e?.queryOptions,queryKey:u,queryFn:async({pageParam:s})=>{let y=s===void 0||!e?.pageParamToArgs?t:e.pageParamToArgs(t,s),n=await r.run(y,e?.requestOptions);if(n.error)throw h(n.error);return n.data}});return react.useEffect(()=>{if(e?.realtime?.enabled===false||!r.subscribe)return;let s=new AbortController,y=r.subscribe({args:t,authToken:e?.realtime?.authToken,requestOptions:e?.realtime?.requestOptions,signal:s.signal,onChange:(n,c)=>{o.setQueryData(u,T=>!T||T.pages.length===0?T:{...T,pages:[n,...T.pages.slice(1)]}),i.current?.(n,c);},onError:n=>{p.current?.(n);}});return ()=>{s.abort(),y.remove();}},[f,e?.realtime?.authToken,e?.realtime?.enabled,A,r.subscribe,o,d]),m}function L(r){let a=new Error(r.message);return r.status!==void 0&&(a.status=r.status),a}function C(r,a){return reactQuery.useMutation({...a,mutationFn:async t=>{let e=await r.run(t??{});if(e.error)throw L(e.error);return e.data}})}exports.useInfiniteQuery=P;exports.useMutation=C;exports.useQuery=b;
|
package/dist/react/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {useQueryClient,hashKey,useQuery,useInfiniteQuery,useMutation}from'@tanstack/react-query';import {useRef,useEffect,useMemo}from'react';function O(r){let
|
|
1
|
+
import {useQueryClient,hashKey,useQuery,useInfiniteQuery,useMutation}from'@tanstack/react-query';import {useRef,useEffect,useMemo}from'react';function O(r){let a=new Error(r.message);return r.status!==void 0&&(a.status=r.status),a}function b(r,...a){let t=a[0]??{},e=a[1],o=useQueryClient(),i=useRef(e?.realtime?.onChange),p=useRef(e?.realtime?.onError);useEffect(()=>{i.current=e?.realtime?.onChange,p.current=e?.realtime?.onError;},[e?.realtime?.onChange,e?.realtime?.onError]);let u=useMemo(()=>e?.queryOptions?.queryKey??(r.queryKey?r.queryKey(t):["appflare","query",r,t]),[t,e?.queryOptions?.queryKey,r]),d=useMemo(()=>hashKey(u),[u]),f=useMemo(()=>hashKey([t]),[t]),A=useMemo(()=>hashKey([e?.realtime?.requestOptions]),[e?.realtime?.requestOptions]),m=useQuery({...e?.queryOptions,queryKey:u,queryFn:async()=>{let s=await r.run(t,e?.requestOptions);if(s.error)throw O(s.error);return s.data}});return useEffect(()=>{if(e?.realtime?.enabled===false||!r.subscribe)return;let s=new AbortController,y=r.subscribe({args:t,authToken:e?.realtime?.authToken,requestOptions:e?.realtime?.requestOptions,signal:s.signal,onChange:(n,c)=>{o.setQueryData(u,n),i.current?.(n,c);},onError:n=>{p.current?.(n);}});return ()=>{s.abort(),y.remove();}},[f,e?.realtime?.authToken,e?.realtime?.enabled,A,r.subscribe,o,d]),m}function h(r){let a=new Error(r.message);return r.status!==void 0&&(a.status=r.status),a}function P(r,...a){let t=a[0]??{},e=a[1],o=useQueryClient(),i=useRef(e?.realtime?.onChange),p=useRef(e?.realtime?.onError);useEffect(()=>{i.current=e?.realtime?.onChange,p.current=e?.realtime?.onError;},[e?.realtime?.onChange,e?.realtime?.onError]);let u=useMemo(()=>e?.queryOptions?.queryKey??(r.queryKey?r.queryKey(t):["appflare","infinite-query",r,t]),[t,e?.queryOptions?.queryKey,r]),d=useMemo(()=>hashKey(u),[u]),f=useMemo(()=>hashKey([t]),[t]),A=useMemo(()=>hashKey([e?.realtime?.requestOptions]),[e?.realtime?.requestOptions]),m=useInfiniteQuery({...e?.queryOptions,queryKey:u,queryFn:async({pageParam:s})=>{let y=s===void 0||!e?.pageParamToArgs?t:e.pageParamToArgs(t,s),n=await r.run(y,e?.requestOptions);if(n.error)throw h(n.error);return n.data}});return useEffect(()=>{if(e?.realtime?.enabled===false||!r.subscribe)return;let s=new AbortController,y=r.subscribe({args:t,authToken:e?.realtime?.authToken,requestOptions:e?.realtime?.requestOptions,signal:s.signal,onChange:(n,c)=>{o.setQueryData(u,T=>!T||T.pages.length===0?T:{...T,pages:[n,...T.pages.slice(1)]}),i.current?.(n,c);},onError:n=>{p.current?.(n);}});return ()=>{s.abort(),y.remove();}},[f,e?.realtime?.authToken,e?.realtime?.enabled,A,r.subscribe,o,d]),m}function L(r){let a=new Error(r.message);return r.status!==void 0&&(a.status=r.status),a}function C(r,a){return useMutation({...a,mutationFn:async t=>{let e=await r.run(t??{});if(e.error)throw L(e.error);return e.data}})}export{P as useInfiniteQuery,C as useMutation,b as useQuery};
|
package/package.json
CHANGED
|
@@ -62,6 +62,7 @@ type AppflareQueryLike<TArgs extends Record<string, unknown>, TData> = {
|
|
|
62
62
|
) => void;
|
|
63
63
|
onError?: (error: unknown) => void;
|
|
64
64
|
}) => AppflareRealtimeSubscriptionLike;
|
|
65
|
+
queryKey?: (args?: TArgs) => QueryKey;
|
|
65
66
|
};
|
|
66
67
|
|
|
67
68
|
export type UseAppflareInfiniteQueryOptions<
|
|
@@ -158,8 +159,10 @@ export function useInfiniteQuery<
|
|
|
158
159
|
const resolvedQueryKey = useMemo(() => {
|
|
159
160
|
return (
|
|
160
161
|
options?.queryOptions?.queryKey ??
|
|
161
|
-
(
|
|
162
|
-
|
|
162
|
+
(query.queryKey
|
|
163
|
+
? query.queryKey(args)
|
|
164
|
+
: (["appflare", "infinite-query", query, args] as unknown as TKey))
|
|
165
|
+
) as TKey
|
|
163
166
|
}, [args, options?.queryOptions?.queryKey, query]);
|
|
164
167
|
|
|
165
168
|
const resolvedQueryKeyHash = useMemo(
|
package/react/use-query.ts
CHANGED
|
@@ -61,6 +61,7 @@ type AppflareQueryLike<TArgs extends Record<string, unknown>, TData> = {
|
|
|
61
61
|
) => void;
|
|
62
62
|
onError?: (error: unknown) => void;
|
|
63
63
|
}) => AppflareRealtimeSubscriptionLike;
|
|
64
|
+
queryKey?: (args?: TArgs) => QueryKey;
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
export type UseAppflareQueryOptions<
|
|
@@ -135,8 +136,10 @@ export function useQuery<
|
|
|
135
136
|
const resolvedQueryKey = useMemo(() => {
|
|
136
137
|
return (
|
|
137
138
|
options?.queryOptions?.queryKey ??
|
|
138
|
-
(
|
|
139
|
-
|
|
139
|
+
(query.queryKey
|
|
140
|
+
? query.queryKey(args)
|
|
141
|
+
: (["appflare", "query", query, args] as unknown as TKey))
|
|
142
|
+
) as TKey
|
|
140
143
|
}, [args, options?.queryOptions?.queryKey, query]);
|
|
141
144
|
|
|
142
145
|
const resolvedQueryKeyHash = useMemo(
|