type BaseProduct = Schema.Schema.Type<typeof BaseProduct>;
const BaseProduct = Schema.Struct({
id: Resource.ID,
title: Schema.String,
handle: Schema.String,
variants: Schema.Array(BaseVariant),
options: Schema.Array(ProductOption),
tags: Schema.Array(Schema.String),
});
const get = (url: string): Effect.Effect<unknown, Error> =>
Effect.tryPromise({
try: () =>
fetch(url).then((res) => {
if (res.ok) {
return res.json() as Promise<unknown>;
}
throw new Error(String(res.status));
}),
catch: (e) => new Error(String(e)),
});
const cachedGet = (url: string) =>
Effect.gen(function* () {
const cache = yield* Effect.cachedWithTTL(get(url), "60 minutes");
return yield* cache;
});
const Product = Schema.transformOrFail(Schema.String, BaseProduct, {
decode(handle, _, ast) {
return Effect.mapBoth(cachedGet(`/products/${handle}`), {
onFailure: (e) => new ParseResult.Type(ast, handle, e.message),
onSuccess: (product) => product as BaseProduct,
});
},
encode: (product) => ParseResult.succeed(product.handle),
});
type BaseProduct = Schema.Schema.Type<typeof BaseProduct>;
const BaseProduct = Schema.Struct({
id: Resource.ID,
title: Schema.String,
handle: Schema.String,
variants: Schema.Array(BaseVariant),
options: Schema.Array(ProductOption),
tags: Schema.Array(Schema.String),
});
const get = (url: string): Effect.Effect<unknown, Error> =>
Effect.tryPromise({
try: () =>
fetch(url).then((res) => {
if (res.ok) {
return res.json() as Promise<unknown>;
}
throw new Error(String(res.status));
}),
catch: (e) => new Error(String(e)),
});
const cachedGet = (url: string) =>
Effect.gen(function* () {
const cache = yield* Effect.cachedWithTTL(get(url), "60 minutes");
return yield* cache;
});
const Product = Schema.transformOrFail(Schema.String, BaseProduct, {
decode(handle, _, ast) {
return Effect.mapBoth(cachedGet(`/products/${handle}`), {
onFailure: (e) => new ParseResult.Type(ast, handle, e.message),
onSuccess: (product) => product as BaseProduct,
});
},
encode: (product) => ParseResult.succeed(product.handle),
});