appflare 0.2.12 → 0.2.14

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/dist/index.d.mts CHANGED
@@ -83,10 +83,6 @@ type LoadedAppflareConfig = {
83
83
  config: NormalizedAppflareConfig;
84
84
  };
85
85
 
86
- declare function loadConfig(configPathArg?: string): Promise<LoadedAppflareConfig>;
87
-
88
- declare function generateArtifacts(loadedConfig: LoadedAppflareConfig): Promise<void>;
89
-
90
86
  type ColumnType = "int" | "string" | "boolean" | "date";
91
87
  type ColumnBuilderOptions = {
92
88
  sqlName?: string;
@@ -95,12 +91,16 @@ type ColumnBuilderOptions = {
95
91
  type PrimaryKeyOptions = {
96
92
  autoIncrement?: boolean;
97
93
  };
94
+ type ForeignKeyAction = "cascade" | "set null" | "set default" | "restrict" | "no action";
98
95
  type RelationOneOptions = {
99
96
  referenceField?: string;
100
97
  field?: string;
101
98
  fkType?: ColumnType;
102
99
  sqlName?: string;
103
100
  notNull?: boolean;
101
+ nullable?: boolean;
102
+ onDelete?: ForeignKeyAction;
103
+ onUpdate?: ForeignKeyAction;
104
104
  };
105
105
  type RelationManyOptions = {
106
106
  referenceField?: string;
@@ -108,6 +108,9 @@ type RelationManyOptions = {
108
108
  fkType?: ColumnType;
109
109
  sqlName?: string;
110
110
  notNull?: boolean;
111
+ nullable?: boolean;
112
+ onDelete?: ForeignKeyAction;
113
+ onUpdate?: ForeignKeyAction;
111
114
  };
112
115
  type ColumnReference = {
113
116
  table: string;
@@ -119,8 +122,11 @@ type ColumnDefinition = {
119
122
  sqlName?: string;
120
123
  length?: number;
121
124
  notNull?: boolean;
125
+ nullable?: boolean;
122
126
  primaryKey?: boolean;
123
127
  autoIncrement?: boolean;
128
+ /** When true the column stores a UUID generated at runtime (string type). */
129
+ uuidPrimaryKey?: boolean;
124
130
  unique?: true | {
125
131
  name?: string;
126
132
  };
@@ -128,6 +134,8 @@ type ColumnDefinition = {
128
134
  name?: string;
129
135
  };
130
136
  sqlDefault?: unknown;
137
+ /** When true, the SQL column gets DEFAULT CURRENT_TIMESTAMP and runtime inserts use `new Date()`. */
138
+ nowDefault?: boolean;
131
139
  runtimeDefaultFn?: () => unknown;
132
140
  references?: ColumnReference;
133
141
  };
@@ -140,6 +148,9 @@ type OneRelationDefinition = {
140
148
  fkType?: ColumnType;
141
149
  sqlName?: string;
142
150
  notNull?: boolean;
151
+ nullable?: boolean;
152
+ onDelete?: ForeignKeyAction;
153
+ onUpdate?: ForeignKeyAction;
143
154
  };
144
155
  type ManyRelationDefinition = {
145
156
  kind: "relation";
@@ -150,6 +161,9 @@ type ManyRelationDefinition = {
150
161
  fkType?: ColumnType;
151
162
  sqlName?: string;
152
163
  notNull?: boolean;
164
+ nullable?: boolean;
165
+ onDelete?: ForeignKeyAction;
166
+ onUpdate?: ForeignKeyAction;
153
167
  };
154
168
  type RelationDefinition = OneRelationDefinition | ManyRelationDefinition;
155
169
  type TableOptions = {
@@ -172,11 +186,18 @@ declare class ColumnBuilder {
172
186
  private with;
173
187
  sql(name: string): ColumnBuilder;
174
188
  notNull(): ColumnBuilder;
189
+ nullable(): ColumnBuilder;
175
190
  primaryKey(options?: PrimaryKeyOptions): ColumnBuilder;
176
191
  unique(name?: string): ColumnBuilder;
177
192
  index(name?: string): ColumnBuilder;
178
193
  default(value: unknown): ColumnBuilder;
179
194
  defaultFn(fn: () => unknown): ColumnBuilder;
195
+ /**
196
+ * Shorthand for date columns that should default to the current timestamp.
197
+ * Sets SQL `DEFAULT CURRENT_TIMESTAMP` (via `nowDefault`) and
198
+ * a runtime default of `new Date()`.
199
+ */
200
+ defaultNow(): ColumnBuilder;
180
201
  references(table: string, column?: string): ColumnBuilder;
181
202
  toDefinition(): ColumnDefinition;
182
203
  }
@@ -188,8 +209,14 @@ declare const v: {
188
209
  string: (options?: ColumnBuilderOptions) => ColumnBuilder;
189
210
  boolean: (options?: ColumnBuilderOptions) => ColumnBuilder;
190
211
  date: (options?: ColumnBuilderOptions) => ColumnBuilder;
212
+ /**
213
+ * UUID primary key column.
214
+ * Stored as a string, marked as primary key and auto-populated with
215
+ * `crypto.randomUUID()` at runtime (no SQL sequence).
216
+ */
217
+ uuid: (options?: ColumnBuilderOptions) => ColumnBuilder;
191
218
  one: (targetTable: string, fieldOrOptions?: string | RelationOneOptions, options?: RelationOneOptions) => OneRelationDefinition;
192
219
  many: (targetTable: string, fieldOrOptions?: string | RelationManyOptions, options?: RelationManyOptions) => ManyRelationDefinition;
193
220
  };
194
221
 
195
- export { type AppflareConfig, type AppflareDatabaseBinding, type AppflareKVNamespace, type AppflareR2Bucket, type ColumnDefinition, type LoadedAppflareConfig, type NormalizedAppflareConfig, type RelationDefinition, type SchemaDefinition, type TableDefinition, generateArtifacts, isSchemaDefinition, loadConfig, schema, table, v };
222
+ export { type AppflareConfig, type AppflareDatabaseBinding, type AppflareKVNamespace, type AppflareR2Bucket, type ColumnDefinition, type LoadedAppflareConfig, type NormalizedAppflareConfig, type RelationDefinition, type SchemaDefinition, type TableDefinition, isSchemaDefinition, schema, table, v };
package/dist/index.d.ts CHANGED
@@ -83,10 +83,6 @@ type LoadedAppflareConfig = {
83
83
  config: NormalizedAppflareConfig;
84
84
  };
85
85
 
86
- declare function loadConfig(configPathArg?: string): Promise<LoadedAppflareConfig>;
87
-
88
- declare function generateArtifacts(loadedConfig: LoadedAppflareConfig): Promise<void>;
89
-
90
86
  type ColumnType = "int" | "string" | "boolean" | "date";
91
87
  type ColumnBuilderOptions = {
92
88
  sqlName?: string;
@@ -95,12 +91,16 @@ type ColumnBuilderOptions = {
95
91
  type PrimaryKeyOptions = {
96
92
  autoIncrement?: boolean;
97
93
  };
94
+ type ForeignKeyAction = "cascade" | "set null" | "set default" | "restrict" | "no action";
98
95
  type RelationOneOptions = {
99
96
  referenceField?: string;
100
97
  field?: string;
101
98
  fkType?: ColumnType;
102
99
  sqlName?: string;
103
100
  notNull?: boolean;
101
+ nullable?: boolean;
102
+ onDelete?: ForeignKeyAction;
103
+ onUpdate?: ForeignKeyAction;
104
104
  };
105
105
  type RelationManyOptions = {
106
106
  referenceField?: string;
@@ -108,6 +108,9 @@ type RelationManyOptions = {
108
108
  fkType?: ColumnType;
109
109
  sqlName?: string;
110
110
  notNull?: boolean;
111
+ nullable?: boolean;
112
+ onDelete?: ForeignKeyAction;
113
+ onUpdate?: ForeignKeyAction;
111
114
  };
112
115
  type ColumnReference = {
113
116
  table: string;
@@ -119,8 +122,11 @@ type ColumnDefinition = {
119
122
  sqlName?: string;
120
123
  length?: number;
121
124
  notNull?: boolean;
125
+ nullable?: boolean;
122
126
  primaryKey?: boolean;
123
127
  autoIncrement?: boolean;
128
+ /** When true the column stores a UUID generated at runtime (string type). */
129
+ uuidPrimaryKey?: boolean;
124
130
  unique?: true | {
125
131
  name?: string;
126
132
  };
@@ -128,6 +134,8 @@ type ColumnDefinition = {
128
134
  name?: string;
129
135
  };
130
136
  sqlDefault?: unknown;
137
+ /** When true, the SQL column gets DEFAULT CURRENT_TIMESTAMP and runtime inserts use `new Date()`. */
138
+ nowDefault?: boolean;
131
139
  runtimeDefaultFn?: () => unknown;
132
140
  references?: ColumnReference;
133
141
  };
@@ -140,6 +148,9 @@ type OneRelationDefinition = {
140
148
  fkType?: ColumnType;
141
149
  sqlName?: string;
142
150
  notNull?: boolean;
151
+ nullable?: boolean;
152
+ onDelete?: ForeignKeyAction;
153
+ onUpdate?: ForeignKeyAction;
143
154
  };
144
155
  type ManyRelationDefinition = {
145
156
  kind: "relation";
@@ -150,6 +161,9 @@ type ManyRelationDefinition = {
150
161
  fkType?: ColumnType;
151
162
  sqlName?: string;
152
163
  notNull?: boolean;
164
+ nullable?: boolean;
165
+ onDelete?: ForeignKeyAction;
166
+ onUpdate?: ForeignKeyAction;
153
167
  };
154
168
  type RelationDefinition = OneRelationDefinition | ManyRelationDefinition;
155
169
  type TableOptions = {
@@ -172,11 +186,18 @@ declare class ColumnBuilder {
172
186
  private with;
173
187
  sql(name: string): ColumnBuilder;
174
188
  notNull(): ColumnBuilder;
189
+ nullable(): ColumnBuilder;
175
190
  primaryKey(options?: PrimaryKeyOptions): ColumnBuilder;
176
191
  unique(name?: string): ColumnBuilder;
177
192
  index(name?: string): ColumnBuilder;
178
193
  default(value: unknown): ColumnBuilder;
179
194
  defaultFn(fn: () => unknown): ColumnBuilder;
195
+ /**
196
+ * Shorthand for date columns that should default to the current timestamp.
197
+ * Sets SQL `DEFAULT CURRENT_TIMESTAMP` (via `nowDefault`) and
198
+ * a runtime default of `new Date()`.
199
+ */
200
+ defaultNow(): ColumnBuilder;
180
201
  references(table: string, column?: string): ColumnBuilder;
181
202
  toDefinition(): ColumnDefinition;
182
203
  }
@@ -188,8 +209,14 @@ declare const v: {
188
209
  string: (options?: ColumnBuilderOptions) => ColumnBuilder;
189
210
  boolean: (options?: ColumnBuilderOptions) => ColumnBuilder;
190
211
  date: (options?: ColumnBuilderOptions) => ColumnBuilder;
212
+ /**
213
+ * UUID primary key column.
214
+ * Stored as a string, marked as primary key and auto-populated with
215
+ * `crypto.randomUUID()` at runtime (no SQL sequence).
216
+ */
217
+ uuid: (options?: ColumnBuilderOptions) => ColumnBuilder;
191
218
  one: (targetTable: string, fieldOrOptions?: string | RelationOneOptions, options?: RelationOneOptions) => OneRelationDefinition;
192
219
  many: (targetTable: string, fieldOrOptions?: string | RelationManyOptions, options?: RelationManyOptions) => ManyRelationDefinition;
193
220
  };
194
221
 
195
- export { type AppflareConfig, type AppflareDatabaseBinding, type AppflareKVNamespace, type AppflareR2Bucket, type ColumnDefinition, type LoadedAppflareConfig, type NormalizedAppflareConfig, type RelationDefinition, type SchemaDefinition, type TableDefinition, generateArtifacts, isSchemaDefinition, loadConfig, schema, table, v };
222
+ export { type AppflareConfig, type AppflareDatabaseBinding, type AppflareKVNamespace, type AppflareR2Bucket, type ColumnDefinition, type LoadedAppflareConfig, type NormalizedAppflareConfig, type RelationDefinition, type SchemaDefinition, type TableDefinition, isSchemaDefinition, schema, table, v };
package/dist/index.js CHANGED
@@ -1,2 +1 @@
1
- #!/usr/bin/env node
2
- 'use strict';var chunkNKSCHJ57_js=require('./chunk-NKSCHJ57.js');require('./chunk-XVWH6PJQ.js');Object.defineProperty(exports,"generateArtifacts",{enumerable:true,get:function(){return chunkNKSCHJ57_js.f}});Object.defineProperty(exports,"isSchemaDefinition",{enumerable:true,get:function(){return chunkNKSCHJ57_js.d}});Object.defineProperty(exports,"loadConfig",{enumerable:true,get:function(){return chunkNKSCHJ57_js.a}});Object.defineProperty(exports,"schema",{enumerable:true,get:function(){return chunkNKSCHJ57_js.c}});Object.defineProperty(exports,"table",{enumerable:true,get:function(){return chunkNKSCHJ57_js.b}});Object.defineProperty(exports,"v",{enumerable:true,get:function(){return chunkNKSCHJ57_js.e}});
1
+ 'use strict';var o=class n{definition;constructor(e,t={}){if(typeof e=="string"){this.definition={kind:"column",type:e,sqlName:t.sqlName,length:t.length};return}this.definition={...e};}with(e){return new n({...this.definition,...e})}sql(e){return this.with({sqlName:e})}notNull(){return this.with({notNull:true,nullable:false})}nullable(){return this.with({nullable:true,notNull:false})}primaryKey(e={}){return this.with({primaryKey:true,autoIncrement:e.autoIncrement??this.definition.autoIncrement})}unique(e){return this.with({unique:e?{name:e}:true})}index(e){return this.with({index:e?{name:e}:true})}default(e){return this.with({sqlDefault:e})}defaultFn(e){return this.with({runtimeDefaultFn:e})}defaultNow(){return this.with({nowDefault:true,runtimeDefaultFn:()=>new Date})}references(e,t="id"){return this.with({references:{table:e,column:t}})}toDefinition(){return {...this.definition}}};function a(n,e={}){let t={},l={};for(let[i,r]of Object.entries(n)){if(r instanceof o){t[i]=r.toDefinition();continue}if(r.kind==="relation"){l[i]=r;continue}throw new Error(`Invalid table field '${i}'. Use column builders or relation helpers.`)}return {kind:"table",sqlName:e.sqlName,columns:t,relations:l}}function u(n){return {kind:"schema",tables:n}}function s(n){if(typeof n!="object"||n===null)return false;let e=n;return e.kind==="schema"&&typeof e.tables=="object"}function p(n,e,t={}){let l=typeof e=="string"?e:void 0,i=typeof e=="string"?t:e??t;return {kind:"relation",relation:"one",targetTable:n,field:i.field??l,referenceField:i.referenceField,fkType:i.fkType,sqlName:i.sqlName,notNull:i.notNull,nullable:i.nullable,onDelete:i.onDelete,onUpdate:i.onUpdate}}function f(n,e,t={}){let l=typeof e=="string"?e:void 0,i=typeof e=="string"?t:e??t;return {kind:"relation",relation:"many",targetTable:n,field:i.field??l,referenceField:i.referenceField,fkType:i.fkType,sqlName:i.sqlName,notNull:i.notNull,nullable:i.nullable,onDelete:i.onDelete,onUpdate:i.onUpdate}}var m={int:(n={})=>new o("int",n),string:(n={})=>new o("string",n),boolean:(n={})=>new o("boolean",n),date:(n={})=>new o("date",n),uuid:(n={})=>new o({kind:"column",type:"string",sqlName:n.sqlName,length:n.length??36,primaryKey:true,uuidPrimaryKey:true,runtimeDefaultFn:()=>crypto.randomUUID()}),one:(n,e,t={})=>p(n,e,t),many:(n,e,t={})=>f(n,e,t)};exports.isSchemaDefinition=s;exports.schema=u;exports.table=a;exports.v=m;
package/dist/index.mjs CHANGED
@@ -1,2 +1 @@
1
- #!/usr/bin/env node
2
- export{f as generateArtifacts,d as isSchemaDefinition,a as loadConfig,c as schema,b as table,e as v}from'./chunk-6BUT7DXS.mjs';import'./chunk-4JK3AKWC.mjs';
1
+ var o=class n{definition;constructor(e,t={}){if(typeof e=="string"){this.definition={kind:"column",type:e,sqlName:t.sqlName,length:t.length};return}this.definition={...e};}with(e){return new n({...this.definition,...e})}sql(e){return this.with({sqlName:e})}notNull(){return this.with({notNull:true,nullable:false})}nullable(){return this.with({nullable:true,notNull:false})}primaryKey(e={}){return this.with({primaryKey:true,autoIncrement:e.autoIncrement??this.definition.autoIncrement})}unique(e){return this.with({unique:e?{name:e}:true})}index(e){return this.with({index:e?{name:e}:true})}default(e){return this.with({sqlDefault:e})}defaultFn(e){return this.with({runtimeDefaultFn:e})}defaultNow(){return this.with({nowDefault:true,runtimeDefaultFn:()=>new Date})}references(e,t="id"){return this.with({references:{table:e,column:t}})}toDefinition(){return {...this.definition}}};function a(n,e={}){let t={},l={};for(let[i,r]of Object.entries(n)){if(r instanceof o){t[i]=r.toDefinition();continue}if(r.kind==="relation"){l[i]=r;continue}throw new Error(`Invalid table field '${i}'. Use column builders or relation helpers.`)}return {kind:"table",sqlName:e.sqlName,columns:t,relations:l}}function u(n){return {kind:"schema",tables:n}}function s(n){if(typeof n!="object"||n===null)return false;let e=n;return e.kind==="schema"&&typeof e.tables=="object"}function p(n,e,t={}){let l=typeof e=="string"?e:void 0,i=typeof e=="string"?t:e??t;return {kind:"relation",relation:"one",targetTable:n,field:i.field??l,referenceField:i.referenceField,fkType:i.fkType,sqlName:i.sqlName,notNull:i.notNull,nullable:i.nullable,onDelete:i.onDelete,onUpdate:i.onUpdate}}function f(n,e,t={}){let l=typeof e=="string"?e:void 0,i=typeof e=="string"?t:e??t;return {kind:"relation",relation:"many",targetTable:n,field:i.field??l,referenceField:i.referenceField,fkType:i.fkType,sqlName:i.sqlName,notNull:i.notNull,nullable:i.nullable,onDelete:i.onDelete,onUpdate:i.onUpdate}}var m={int:(n={})=>new o("int",n),string:(n={})=>new o("string",n),boolean:(n={})=>new o("boolean",n),date:(n={})=>new o("date",n),uuid:(n={})=>new o({kind:"column",type:"string",sqlName:n.sqlName,length:n.length??36,primaryKey:true,uuidPrimaryKey:true,runtimeDefaultFn:()=>crypto.randomUUID()}),one:(n,e,t={})=>p(n,e,t),many:(n,e,t={})=>f(n,e,t)};export{s as isSchemaDefinition,u as schema,a as table,m as v};
@@ -1,2 +1 @@
1
- #!/usr/bin/env node
2
- 'use strict';require('../chunk-XVWH6PJQ.js');var reactQuery=require('@tanstack/react-query'),react=require('react');function O(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function b(r,...t){let a=t[0]??{},e=t[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??["appflare","query",r,a],[a,e?.queryOptions?.queryKey,r]),g=react.useMemo(()=>reactQuery.hashKey(u),[u]),f=react.useMemo(()=>reactQuery.hashKey([a]),[a]),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(a,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:a,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,g]),m}function h(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function P(r,...t){let a=t[0]??{},e=t[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??["appflare","infinite-query",r,a],[a,e?.queryOptions?.queryKey,r]),g=react.useMemo(()=>reactQuery.hashKey(u),[u]),f=react.useMemo(()=>reactQuery.hashKey([a]),[a]),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?a:e.pageParamToArgs(a,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:a,authToken:e.realtime?.authToken,requestOptions:e.realtime?.requestOptions,signal:s.signal,onChange:(n,c)=>{o.setQueryData(u,l=>!l||l.pages.length===0?l:{...l,pages:[n,...l.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,g]),m}function L(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function C(r,t){return reactQuery.useMutation({...t,mutationFn:async a=>{let e=await r.run(a??{});if(e.error)throw L(e.error);return e.data}})}exports.useInfiniteQuery=P;exports.useMutation=C;exports.useQuery=b;
1
+ 'use strict';var reactQuery=require('@tanstack/react-query'),react=require('react');function O(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function b(r,...t){let a=t[0]??{},e=t[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??["appflare","query",r,a],[a,e?.queryOptions?.queryKey,r]),g=react.useMemo(()=>reactQuery.hashKey(u),[u]),f=react.useMemo(()=>reactQuery.hashKey([a]),[a]),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(a,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:a,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,g]),m}function h(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function P(r,...t){let a=t[0]??{},e=t[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??["appflare","infinite-query",r,a],[a,e?.queryOptions?.queryKey,r]),g=react.useMemo(()=>reactQuery.hashKey(u),[u]),f=react.useMemo(()=>reactQuery.hashKey([a]),[a]),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?a:e.pageParamToArgs(a,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:a,authToken:e.realtime?.authToken,requestOptions:e.realtime?.requestOptions,signal:s.signal,onChange:(n,c)=>{o.setQueryData(u,l=>!l||l.pages.length===0?l:{...l,pages:[n,...l.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,g]),m}function L(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function C(r,t){return reactQuery.useMutation({...t,mutationFn:async a=>{let e=await r.run(a??{});if(e.error)throw L(e.error);return e.data}})}exports.useInfiniteQuery=P;exports.useMutation=C;exports.useQuery=b;
@@ -1,2 +1 @@
1
- #!/usr/bin/env node
2
- import'../chunk-4JK3AKWC.mjs';import {useQueryClient,hashKey,useQuery,useInfiniteQuery,useMutation}from'@tanstack/react-query';import {useRef,useEffect,useMemo}from'react';function O(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function b(r,...t){let a=t[0]??{},e=t[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??["appflare","query",r,a],[a,e?.queryOptions?.queryKey,r]),g=useMemo(()=>hashKey(u),[u]),f=useMemo(()=>hashKey([a]),[a]),A=useMemo(()=>hashKey([e?.realtime?.requestOptions]),[e?.realtime?.requestOptions]),m=useQuery({...e?.queryOptions,queryKey:u,queryFn:async()=>{let s=await r.run(a,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:a,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,g]),m}function h(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function P(r,...t){let a=t[0]??{},e=t[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??["appflare","infinite-query",r,a],[a,e?.queryOptions?.queryKey,r]),g=useMemo(()=>hashKey(u),[u]),f=useMemo(()=>hashKey([a]),[a]),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?a:e.pageParamToArgs(a,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:a,authToken:e.realtime?.authToken,requestOptions:e.realtime?.requestOptions,signal:s.signal,onChange:(n,c)=>{o.setQueryData(u,l=>!l||l.pages.length===0?l:{...l,pages:[n,...l.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,g]),m}function L(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function C(r,t){return useMutation({...t,mutationFn:async a=>{let e=await r.run(a??{});if(e.error)throw L(e.error);return e.data}})}export{P as useInfiniteQuery,C as useMutation,b as useQuery};
1
+ import {useQueryClient,hashKey,useQuery,useInfiniteQuery,useMutation}from'@tanstack/react-query';import {useRef,useEffect,useMemo}from'react';function O(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function b(r,...t){let a=t[0]??{},e=t[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??["appflare","query",r,a],[a,e?.queryOptions?.queryKey,r]),g=useMemo(()=>hashKey(u),[u]),f=useMemo(()=>hashKey([a]),[a]),A=useMemo(()=>hashKey([e?.realtime?.requestOptions]),[e?.realtime?.requestOptions]),m=useQuery({...e?.queryOptions,queryKey:u,queryFn:async()=>{let s=await r.run(a,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:a,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,g]),m}function h(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function P(r,...t){let a=t[0]??{},e=t[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??["appflare","infinite-query",r,a],[a,e?.queryOptions?.queryKey,r]),g=useMemo(()=>hashKey(u),[u]),f=useMemo(()=>hashKey([a]),[a]),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?a:e.pageParamToArgs(a,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:a,authToken:e.realtime?.authToken,requestOptions:e.realtime?.requestOptions,signal:s.signal,onChange:(n,c)=>{o.setQueryData(u,l=>!l||l.pages.length===0?l:{...l,pages:[n,...l.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,g]),m}function L(r){let t=new Error(r.message);return r.status!==void 0&&(t.status=r.status),t}function C(r,t){return useMutation({...t,mutationFn:async a=>{let e=await r.run(a??{});if(e.error)throw L(e.error);return e.data}})}export{P as useInfiniteQuery,C as useMutation,b as useQuery};
package/index.ts CHANGED
@@ -6,8 +6,6 @@ export type {
6
6
  LoadedAppflareConfig,
7
7
  NormalizedAppflareConfig,
8
8
  } from "./cli/types";
9
- export { loadConfig } from "./cli/load-config";
10
- export { generateArtifacts } from "./cli/generate";
11
9
  export {
12
10
  schema,
13
11
  table,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appflare",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -37,7 +37,6 @@
37
37
  "@types/bun": "^1.3.9",
38
38
  "@types/node": "^25.3.0",
39
39
  "npm-check-updates": "^19.4.0",
40
- "typescript": "^5.9.3",
41
40
  "tsup": "^8.3.6"
42
41
  },
43
42
  "dependencies": {
@@ -53,6 +52,7 @@
53
52
  "drizzle-orm": "0.45.1",
54
53
  "hono": "4.12.0",
55
54
  "wrangler": "4.67.0",
56
- "zod": "4.3.6"
55
+ "zod": "4.3.6",
56
+ "typescript": "^5.9.3"
57
57
  }
58
58
  }
package/schema.ts CHANGED
@@ -9,12 +9,22 @@ export type PrimaryKeyOptions = {
9
9
  autoIncrement?: boolean;
10
10
  };
11
11
 
12
+ export type ForeignKeyAction =
13
+ | "cascade"
14
+ | "set null"
15
+ | "set default"
16
+ | "restrict"
17
+ | "no action";
18
+
12
19
  export type RelationOneOptions = {
13
20
  referenceField?: string;
14
21
  field?: string;
15
22
  fkType?: ColumnType;
16
23
  sqlName?: string;
17
24
  notNull?: boolean;
25
+ nullable?: boolean;
26
+ onDelete?: ForeignKeyAction;
27
+ onUpdate?: ForeignKeyAction;
18
28
  };
19
29
 
20
30
  export type RelationManyOptions = {
@@ -23,6 +33,9 @@ export type RelationManyOptions = {
23
33
  fkType?: ColumnType;
24
34
  sqlName?: string;
25
35
  notNull?: boolean;
36
+ nullable?: boolean;
37
+ onDelete?: ForeignKeyAction;
38
+ onUpdate?: ForeignKeyAction;
26
39
  };
27
40
 
28
41
  export type ColumnReference = {
@@ -36,11 +49,16 @@ export type ColumnDefinition = {
36
49
  sqlName?: string;
37
50
  length?: number;
38
51
  notNull?: boolean;
52
+ nullable?: boolean;
39
53
  primaryKey?: boolean;
40
54
  autoIncrement?: boolean;
55
+ /** When true the column stores a UUID generated at runtime (string type). */
56
+ uuidPrimaryKey?: boolean;
41
57
  unique?: true | { name?: string };
42
58
  index?: true | { name?: string };
43
59
  sqlDefault?: unknown;
60
+ /** When true, the SQL column gets DEFAULT CURRENT_TIMESTAMP and runtime inserts use `new Date()`. */
61
+ nowDefault?: boolean;
44
62
  runtimeDefaultFn?: () => unknown;
45
63
  references?: ColumnReference;
46
64
  };
@@ -54,6 +72,9 @@ export type OneRelationDefinition = {
54
72
  fkType?: ColumnType;
55
73
  sqlName?: string;
56
74
  notNull?: boolean;
75
+ nullable?: boolean;
76
+ onDelete?: ForeignKeyAction;
77
+ onUpdate?: ForeignKeyAction;
57
78
  };
58
79
 
59
80
  export type ManyRelationDefinition = {
@@ -65,6 +86,9 @@ export type ManyRelationDefinition = {
65
86
  fkType?: ColumnType;
66
87
  sqlName?: string;
67
88
  notNull?: boolean;
89
+ nullable?: boolean;
90
+ onDelete?: ForeignKeyAction;
91
+ onUpdate?: ForeignKeyAction;
68
92
  };
69
93
 
70
94
  export type RelationDefinition = OneRelationDefinition | ManyRelationDefinition;
@@ -121,7 +145,11 @@ export class ColumnBuilder {
121
145
  }
122
146
 
123
147
  public notNull(): ColumnBuilder {
124
- return this.with({ notNull: true });
148
+ return this.with({ notNull: true, nullable: false });
149
+ }
150
+
151
+ public nullable(): ColumnBuilder {
152
+ return this.with({ nullable: true, notNull: false });
125
153
  }
126
154
 
127
155
  public primaryKey(options: PrimaryKeyOptions = {}): ColumnBuilder {
@@ -147,6 +175,18 @@ export class ColumnBuilder {
147
175
  return this.with({ runtimeDefaultFn: fn });
148
176
  }
149
177
 
178
+ /**
179
+ * Shorthand for date columns that should default to the current timestamp.
180
+ * Sets SQL `DEFAULT CURRENT_TIMESTAMP` (via `nowDefault`) and
181
+ * a runtime default of `new Date()`.
182
+ */
183
+ public defaultNow(): ColumnBuilder {
184
+ return this.with({
185
+ nowDefault: true,
186
+ runtimeDefaultFn: () => new Date(),
187
+ });
188
+ }
189
+
150
190
  public references(table: string, column = "id"): ColumnBuilder {
151
191
  return this.with({ references: { table, column } });
152
192
  }
@@ -204,6 +244,62 @@ export function isSchemaDefinition(value: unknown): value is SchemaDefinition {
204
244
  return candidate.kind === "schema" && typeof candidate.tables === "object";
205
245
  }
206
246
 
247
+ // ---------------------------------------------------------------------------
248
+ // Relation builder helpers
249
+ // ---------------------------------------------------------------------------
250
+
251
+ function buildOneRelation(
252
+ targetTable: string,
253
+ fieldOrOptions?: string | RelationOneOptions,
254
+ options: RelationOneOptions = {},
255
+ ): OneRelationDefinition {
256
+ const field = typeof fieldOrOptions === "string" ? fieldOrOptions : undefined;
257
+ const mergedOptions =
258
+ typeof fieldOrOptions === "string" ? options : (fieldOrOptions ?? options);
259
+
260
+ return {
261
+ kind: "relation",
262
+ relation: "one",
263
+ targetTable,
264
+ field: mergedOptions.field ?? field,
265
+ referenceField: mergedOptions.referenceField,
266
+ fkType: mergedOptions.fkType,
267
+ sqlName: mergedOptions.sqlName,
268
+ notNull: mergedOptions.notNull,
269
+ nullable: mergedOptions.nullable,
270
+ onDelete: mergedOptions.onDelete,
271
+ onUpdate: mergedOptions.onUpdate,
272
+ };
273
+ }
274
+
275
+ function buildManyRelation(
276
+ targetTable: string,
277
+ fieldOrOptions?: string | RelationManyOptions,
278
+ options: RelationManyOptions = {},
279
+ ): ManyRelationDefinition {
280
+ const field = typeof fieldOrOptions === "string" ? fieldOrOptions : undefined;
281
+ const mergedOptions =
282
+ typeof fieldOrOptions === "string" ? options : (fieldOrOptions ?? options);
283
+
284
+ return {
285
+ kind: "relation",
286
+ relation: "many",
287
+ targetTable,
288
+ field: mergedOptions.field ?? field,
289
+ referenceField: mergedOptions.referenceField,
290
+ fkType: mergedOptions.fkType,
291
+ sqlName: mergedOptions.sqlName,
292
+ notNull: mergedOptions.notNull,
293
+ nullable: mergedOptions.nullable,
294
+ onDelete: mergedOptions.onDelete,
295
+ onUpdate: mergedOptions.onUpdate,
296
+ };
297
+ }
298
+
299
+ // ---------------------------------------------------------------------------
300
+ // Public API
301
+ // ---------------------------------------------------------------------------
302
+
207
303
  export const v = {
208
304
  int: (options: ColumnBuilderOptions = {}) =>
209
305
  new ColumnBuilder("int", options),
@@ -213,50 +309,34 @@ export const v = {
213
309
  new ColumnBuilder("boolean", options),
214
310
  date: (options: ColumnBuilderOptions = {}) =>
215
311
  new ColumnBuilder("date", options),
312
+
313
+ /**
314
+ * UUID primary key column.
315
+ * Stored as a string, marked as primary key and auto-populated with
316
+ * `crypto.randomUUID()` at runtime (no SQL sequence).
317
+ */
318
+ uuid: (options: ColumnBuilderOptions = {}) =>
319
+ new ColumnBuilder({
320
+ kind: "column",
321
+ type: "string",
322
+ sqlName: options.sqlName,
323
+ length: options.length ?? 36,
324
+ primaryKey: true,
325
+ uuidPrimaryKey: true,
326
+ runtimeDefaultFn: () => crypto.randomUUID(),
327
+ }),
328
+
216
329
  one: (
217
330
  targetTable: string,
218
331
  fieldOrOptions?: string | RelationOneOptions,
219
332
  options: RelationOneOptions = {},
220
- ): OneRelationDefinition => {
221
- const field =
222
- typeof fieldOrOptions === "string" ? fieldOrOptions : undefined;
223
- const mergedOptions =
224
- typeof fieldOrOptions === "string"
225
- ? options
226
- : (fieldOrOptions ?? options);
227
-
228
- return {
229
- kind: "relation",
230
- relation: "one",
231
- targetTable,
232
- field: mergedOptions.field ?? field,
233
- referenceField: mergedOptions.referenceField,
234
- fkType: mergedOptions.fkType,
235
- sqlName: mergedOptions.sqlName,
236
- notNull: mergedOptions.notNull,
237
- };
238
- },
333
+ ): OneRelationDefinition =>
334
+ buildOneRelation(targetTable, fieldOrOptions, options),
335
+
239
336
  many: (
240
337
  targetTable: string,
241
338
  fieldOrOptions?: string | RelationManyOptions,
242
339
  options: RelationManyOptions = {},
243
- ): ManyRelationDefinition => {
244
- const field =
245
- typeof fieldOrOptions === "string" ? fieldOrOptions : undefined;
246
- const mergedOptions =
247
- typeof fieldOrOptions === "string"
248
- ? options
249
- : (fieldOrOptions ?? options);
250
-
251
- return {
252
- kind: "relation",
253
- relation: "many",
254
- targetTable,
255
- field: mergedOptions.field ?? field,
256
- referenceField: mergedOptions.referenceField,
257
- fkType: mergedOptions.fkType,
258
- sqlName: mergedOptions.sqlName,
259
- notNull: mergedOptions.notNull,
260
- };
261
- },
340
+ ): ManyRelationDefinition =>
341
+ buildManyRelation(targetTable, fieldOrOptions, options),
262
342
  };
package/tsup.config.ts CHANGED
@@ -1,32 +1,82 @@
1
1
  import { defineConfig } from "tsup";
2
2
 
3
- export default defineConfig({
4
- entry: ["index.ts", "cli/index.ts", "react/index.ts"],
5
- format: ["esm", "cjs"],
6
- dts: true,
7
- splitting: true,
8
- sourcemap: false,
9
- clean: true,
10
- minify: true,
11
- treeshake: true,
12
- external: [
13
- "better-auth",
14
- "better-auth-cloudflare",
15
- "commander",
16
- "hono",
17
- "zod",
18
- "wrangler",
19
- "drizzle-kit",
20
- "drizzle-orm",
21
- "chokidar",
22
- "bun",
23
- "better-fetch",
24
- "@better-auth/cli",
25
- "@hono/standard-validator",
26
- "react",
27
- "@tanstack/react-query",
28
- ],
29
- banner: {
30
- js: "#!/usr/bin/env node",
3
+ export default defineConfig([
4
+ {
5
+ entry: ["index.ts", "react/index.ts"],
6
+ format: ["esm", "cjs"],
7
+ dts: true,
8
+ splitting: false,
9
+ sourcemap: false,
10
+ clean: true,
11
+ minify: true,
12
+ treeshake: true,
13
+ external: [
14
+ "better-auth",
15
+ "better-auth-cloudflare",
16
+ "hono",
17
+ "zod",
18
+ "wrangler",
19
+ "drizzle-kit",
20
+ "drizzle-orm",
21
+ "bun",
22
+ "better-fetch",
23
+ "react",
24
+ "@tanstack/react-query",
25
+ ],
31
26
  },
32
- });
27
+ {
28
+ entry: {
29
+ "cli/index": "cli/index.ts",
30
+ },
31
+ format: ["esm", "cjs"],
32
+ platform: "neutral",
33
+ target: "node18",
34
+ dts: true,
35
+ splitting: false,
36
+ sourcemap: false,
37
+ clean: false, // Don't clean because the previous task cleaned it
38
+ minify: true,
39
+ treeshake: true,
40
+ external: [
41
+ "better-auth",
42
+ "better-auth-cloudflare",
43
+ "commander",
44
+ "hono",
45
+ "zod",
46
+ "wrangler",
47
+ "drizzle-kit",
48
+ "drizzle-orm",
49
+ "chokidar",
50
+ "bun",
51
+ "better-fetch",
52
+ "@better-auth/cli",
53
+ "@hono/standard-validator",
54
+ "react",
55
+ "@tanstack/react-query",
56
+ "typescript",
57
+ "fs",
58
+ "path",
59
+ "url",
60
+ "crypto",
61
+ "os",
62
+ "process",
63
+ "child_process",
64
+ "node:fs",
65
+ "node:path",
66
+ "node:url",
67
+ "node:crypto",
68
+ "node:os",
69
+ "node:process",
70
+ "node:child_process",
71
+ ],
72
+ banner: {
73
+ js: "#!/usr/bin/env bun",
74
+ },
75
+ esbuildOptions(options) {
76
+ options.define = {
77
+ ...options.define,
78
+ Bun: "Bun",
79
+ };
80
+ },
81
+ },
82
+ ]);
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- var g=Object.create;var f=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty;var m=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(b,c)=>(typeof require<"u"?require:b)[c]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});var n=(a,b)=>()=>(b||a((b={exports:{}}).exports,b),b.exports);var l=(a,b,c,e)=>{if(b&&typeof b=="object"||typeof b=="function")for(let d of i(b))!k.call(a,d)&&d!==c&&f(a,d,{get:()=>b[d],enumerable:!(e=h(b,d))||e.enumerable});return a};var o=(a,b,c)=>(c=a!=null?g(j(a)):{},l(b||!a||!a.__esModule?f(c,"default",{value:a,enumerable:true}):c,a));export{m as a,n as b,o as c};