Skip to content

Commit

Permalink
Merge pull request #85 from basehub-ai/jb/support-fragmentOf
Browse files Browse the repository at this point in the history
support fragmentOf
  • Loading branch information
julianbenegas authored Apr 5, 2024
2 parents 1ca6261 + 7a85095 commit a122845
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 28 deletions.
48 changes: 48 additions & 0 deletions .changeset/smooth-dots-greet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
"basehub": major
"playground": patch
---

# New `fragmentOn` helper to extract fragments

In this new major version, we're introducing `fragmentOn`, a simpler way to create fragments in the `basehub` SDK.

Previously, in order to reuse a fragment, you'd do something like this:

```ts
// old way 👎
import { LinkComponentGenqlSelection, LinkComponent, FieldsSelection } from 'basehub'

const LinkFragment = {
href: true,
label: true
} satisfies LinkComponentGenqlSelection

// extract the type
type LinkFragment = FieldsSelection<LinkComponent, typeof LinkFragment>
```
Looks simple, but it's a bit hard to understand. You need to know that we're exposing a `LinkComponentGenqlSelection`, and that you should use the `satisfies` so the object's type is constrained but also can be more specific. Then, to extract the type, you'd get `FieldsSelection`, and finally, `LinkComponent`. A lot of types!
Moreover, if you needed to create another fragment, it'd be this same process, over and over again.
This is how it's done in the new version:
```ts
// new way 👍
import { fragmentOn } from 'basehub'

const LinkFragment = fragmentOn("LinkComponent", {
href: true,
label: true
})

// extract the type
type LinkFragment = fragmentOn.infer<typeof LinkFragment>
```
Much simpler!
## Why is this a breaking change
Before this version, we exposed a lot of the internal types from `'basehub'`. We now don't. Some applications might depend on this, and that's why this is a breaking change. If you need those types for some reason that wasn't discussed in this document, feel free to raise an issue and we can see to bring them back.
4 changes: 2 additions & 2 deletions packages/basehub/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
],
"sideEffects": false,
"scripts": {
"dev": "pnpm build --watch",
"dev": "pnpm build --watch --draft",
"build": "pnpm build:bin & pnpm build:client",
"build:bin": "tsup --config tsup-bin.config.ts",
"build:client": "tsup --config tsup-client.config.ts"
Expand All @@ -35,7 +35,7 @@
},
"dependencies": {
"@basehub/mutation-api-helpers": "1.0.0",
"@basehub/genql": "6.3.5",
"@basehub/genql": "7.0.0",
"arg": "5.0.1",
"dotenv-mono": "1.3.10",
"esbuild": "0.19.2",
Expand Down
6 changes: 5 additions & 1 deletion packages/basehub/src/bin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ function help(code: number) {
console.log(`
Usage
$ basehub
$ basehub dev
$ basehub dev # turns on draft and watch mode automatically.
Options
--output, -o Output directory, if you don't want the default behavior.
--env-prefix, -ep Prefix for environment variables.
--banner, -b Add code at the top of each generated file.
--watch, -v Watch for changes and regenerate.
--draft, -v Generate with draft mode enabled.
--version, -v Version number.
--help, -h Display this message.`);
process.exit(code);
Expand All @@ -41,6 +43,7 @@ const args = arg(
"--env-prefix": String,
"--banner": String,
"--version": Boolean,
"--draft": Boolean,
"--help": Boolean,
"--watch": Boolean,
// aliases
Expand All @@ -49,6 +52,7 @@ const args = arg(
"-ep": "--env-prefix",
"-b": "--banner",
"-v": "--version",
"-d": "--draft",
"-h": "--help",
"-w": "--watch",
},
Expand Down
17 changes: 17 additions & 0 deletions packages/basehub/src/bin/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const main = async (args: Args, opts?: { forceDraft?: boolean }) => {
token: args["--token"],
prefix: args["--env-prefix"],
output: args["--output"],
draft: args["--draft"],
...(opts?.forceDraft && { draft: true }),
};

Expand All @@ -36,6 +37,7 @@ export const main = async (args: Args, opts?: { forceDraft?: boolean }) => {
const pathArgs = output
? [output]
: ["node_modules", "basehub", "dist", "generated-client"]; // default output path
const isCustomOutput = !!output;

const basehubOutputPath = path.resolve(process.cwd(), ...pathArgs);

Expand Down Expand Up @@ -183,6 +185,21 @@ export const main = async (args: Args, opts?: { forceDraft?: boolean }) => {

appendGeneratedCodeBanner(basehubOutputPath, args["--banner"]);

if (isCustomOutput) {
// alias react-rich-text and other packages to the generated client for better import experience
["react-rich-text", "api-transaction"].map((pathsToAlias) => {
// create a file in the output directory that aliases the package to the generated client
fs.writeFileSync(
path.join(basehubOutputPath, `${pathsToAlias}.d.ts`),
`export * from "basehub/${pathsToAlias}";`
);
fs.writeFileSync(
path.join(basehubOutputPath, `${pathsToAlias}.js`),
`module.exports = require("basehub/${pathsToAlias}");`
);
});
}

logIfNotSilent(silent, "🪄 Generated `basehub` client");
return { preventedClientGeneration, schemaHash };
}
Expand Down
2 changes: 1 addition & 1 deletion playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"build:analyze": "cross-env ANALYZE=true pnpm build",
"start": "next start",
"lint": "next lint",
"generate": "basehub --watch"
"generate": "basehub"
},
"dependencies": {
"basehub": "workspace:^",
Expand Down
42 changes: 22 additions & 20 deletions playground/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
import { Pump } from "../../.basehub/react-pump";
import { fragmentOn } from "../../.basehub";

const HomepageFragment = fragmentOn("Homepage", {
heroTitle: true,
heroSubtitle: true,
idkAnImage: {
url: true,
},
cta: {
label: true,
href: true,
},
coll: {
items: {
_id: true,
_title: true,
someTextHere: true,
},
},
});

export default async function HomePage() {
return (
<main>
<Pump
queries={[
{
homepage: {
heroTitle: true,
heroSubtitle: true,
idkAnImage: {
url: true,
},
cta: {
label: true,
href: true,
},
coll: {
items: {
_id: true,
_title: true,
someTextHere: true,
},
},
},
homepage: HomepageFragment,
},
]}
cache="no-store"
Expand All @@ -38,7 +41,7 @@ export default async function HomePage() {
<p>{homepage.heroSubtitle}</p>
<a href={homepage.cta.href}>{homepage.cta.label}</a>
<img
src={homepage.idkAnImage.url}
src={homepage.idkAnImage?.url}
alt="something"
width={200}
height={200}
Expand All @@ -48,7 +51,6 @@ export default async function HomePage() {
return (
<div key={item._id}>
<h2>{item._title}</h2>
<p>{item.someTextHere}</p>
</div>
);
})}
Expand Down
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a122845

Please sign in to comment.