import { z } from "zod"; const mfs = {} as any; /* Add a Zod type for ref. This should only support to-one relationships. to-many need * to be implemented using formulas or rel-tables. * * All refs have the type `Other | pending | notFound | deleted`. The exists function * should be able to filter fort these. */ const pending = Symbol.for("pending"); const notFound = Symbol.for("notFound"); const deleted = Symbol.for("deleted"); const a = { get a() { return 1; }, get b() { return this.a + 2; }, }; /* Replace classes with this. */ type Delivery = typeof Delivery.TsType; const Delivery = mfs.table({ path: `deliveries`, /* Define firebase security rules here. */ securityRules: {}, // paths: [{ // path: `deliveries`, // pathSpecificRules: {}, // }], // Use Zod for this schema: {}, /* We no longer cache by reference, instead we only cache based on this query. */ cacheOfflineIf: (query) => query .where("status", "==", "delivered") /* The query can reference local reactive variables. If a team has a value of * pending then the cache won't load it yet, but also won't flush it. */ .where( "team", "==", mfs.signedInUsers.flatMap((user) => user.teams), ) /* This works with reactive values, so as liveTime changes the query will be * updated. */ .where("scheduledDay", ">=", liveTime.daysSinceEpoch - 30), }); /* We should build a draft system into tables that allows drafting and then creating * rows. */ const draftDelivery = Delivery.newDraft(); /* Provides the current time in a reactive format. These values will update as time * progresses. By default these should update every second. */ const liveTime = { /* The current number of days since the epoch. */ daysSinceEpoch: 0, /* The current number of minutes since the epoch. */ minutesSinceEpoch: 0, /* The current number of seconds since the epoch. */ secondsSinceEpoch: 0, }; const joinTeam = mfs .cloudFunction() .args(/* Put Zod-like param type here */ {}) .config( /* Extra config can go here. */ { accessibleViaHttpsApi: true, }, ) .implement((params, env) => { /* Can access basic utility code and mfs tables here and the CLI will do it's best * to compile them all into a working cloud function. If it can't it will log * errors. */ const someDeliveries = Delivery.query(); env.auth; }); // const myTable = z.object({ // firstName: z.string(), // lastName: z.string(), // prefix: z.string(), // }).accessors((self) => ({ // get fullName() { // return `${self.firstName} ${self.lastName}`; // }, // get title() { // return `${self.prefix} ${this.fullName}`; // }, // })); function table(config: T): T extends (getSelf: any) => void ? { create: (args: CreateParamsFor>) => InstOf>; default: (val?: InstOf>) => { create: (args: CreateParamsFor>) => InstOf>; isRequiredForCreate: false; }; nullable: () => { create: (args: CreateParamsFor>) => InstOf>; isRequiredForCreate: false; }; TsType: InstOf>; isRequiredForCreate: true; } : never { return {} as any; } type InstOf = { [K in keyof T]: T[K] extends { create: (...args: any[]) => infer U } ? InstOf : T[K]; }; type CreateParamsFor = { [K in Exclude /* T[K] extends Function ? never : */]: T[K] extends { isRequiredForCreate: true } ? T[K] : T[K] extends { isRequiredForCreate: false } ? T[K] | undefined : // TODO `: T[K]` should be never T[K]; }; type A = typeof A.TsType; const A = table(() => ({ b: B.nullable(), get bName(): string { return this.b.name; }, })); type B = typeof B.TsType; const B = table((self: () => B) => ({ name: Str.default(`Unnamed`), _a: A, get a() { return self()._a; }, myFunc: () => { return self().name; }, })); type Str = string; const Str = { create: () => "a", default: (val = "a") => val, }; const aInst = A.create({ b: undefined, bName: "a", }); aInst.b.name; const bInst = B.create({ name: "a", a: aInst, myFunc: () => "a", }); aInst.bName; bInst.a.b.name;