Skip to content

Instantly share code, notes, and snippets.

@Swahvay
Created February 2, 2024 16:06
Show Gist options
  • Select an option

  • Save Swahvay/bc91257bdd89371e5b77bf12c7359705 to your computer and use it in GitHub Desktop.

Select an option

Save Swahvay/bc91257bdd89371e5b77bf12c7359705 to your computer and use it in GitHub Desktop.
import { LocationBaseMixin } from './generated/location_base.ts';
type Constructor<T = {}> = new (...args: any[]) => T;
interface ILocation {
isAddressInCalifornia: () => boolean;
}
export function LocationMixin<T extends Constructor>(BaseClass: T) {
return class LocationMixin extends LocationBaseMixin(BaseClass) implements ILocation {
isAddressInCalifornia() {
return this.state === 'CA';
}
}
}
import { Data, Viewer, Ent } from '@snowtop/ent';
import { Country, convertNullableCountry } from '../types';
type Constructor<T = {}> = new (...args: any[]) => T;
export function isLocation(ent: unknown): ent is ILocation {
const o = ent as ILocation;
return (o.isLocation && o.isLocation()) ?? false;
}
interface ILocation extends Ent {
isLocation(): boolean;
address: string | null;
address2: string | null;
city: string | null;
state: string | null;
postalCode: string | null;
country: Country | null;
}
function extractFromArgs<TViewer extends Viewer, TData extends Data>(
args: any[],
): { viewer: TViewer; data: TData } {
if (args.length !== 2) {
throw new Error('args should be length 2');
}
return {
viewer: args[0],
data: args[1],
};
}
export function LocationBaseMixin<T extends Constructor>(BaseClass: T) {
return class LocationBaseMixin extends BaseClass {
readonly address: string | null;
readonly address2: string | null;
readonly city: string | null;
readonly state: string | null;
readonly postalCode: string | null;
readonly country: Country | null;
constructor(...args: any[]) {
super(...args);
const { data } = extractFromArgs(args);
this.address = data.address;
this.address2 = data.address_2;
this.city = data.city;
this.state = data.state;
this.postalCode = data.postal_code;
this.country = convertNullableCountry(data.country);
}
isLocation() {
return true;
}
};
}
@Swahvay
Copy link
Author

Swahvay commented Feb 2, 2024

This would allow you to do things like

getPrivacyPolicy() {
  return {
    rules: [
      {
        apply(v: Viewer, ent?: ILocation) {
          return ent?.isAddressInCalifornia() ? Allow() : Skip()
        }
      }
    ];
  };
}

@lolopinto
Copy link

i think i'm confused. why is there 2 classes?

what's the value of breaking this down into 2 different mixins/classes?

@Swahvay
Copy link
Author

Swahvay commented Feb 3, 2024

The base class is generated while the second class is only generated the first time. It’s the same logic as normal ents. This lets you add custom methods to the pattern that won’t be overwritten if re-generated.

@lolopinto
Copy link

The base class is generated while the second class is only generated the first time. It’s the same logic as normal ents. This lets you add custom methods to the pattern that won’t be overwritten if re-generated.

got it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment