@ts-ghost/core-api
Advanced tools
Comparing version 0.3.2 to 1.0.0
@@ -1122,25 +1122,14 @@ "use strict"; | ||
/** | ||
* Browse function | ||
* @param {} | ||
* @returns | ||
* Browse function that accepts browse params order, filter, page and limit. Will return an instance | ||
* of BrowseFetcher class. | ||
*/ | ||
browse(options) { | ||
let includeFields = []; | ||
if (options?.output?.include) { | ||
const parsedIncludeFields = this.config.include.parse(options.output.include); | ||
includeFields = Object.keys(parsedIncludeFields); | ||
} | ||
return new BrowseFetcher( | ||
{ | ||
schema: this.config.schema, | ||
output: options?.output?.fields && schemaWithPickedFields(this.config.output, options.output.fields) || // this is a hack to get around the fact that I can't figure out how to | ||
// give back the same output as before | ||
this.config.output, | ||
output: this.config.output, | ||
include: this.config.include | ||
}, | ||
{ | ||
browseParams: options && options.input && parseBrowseParams(options.input, this.config.schema) || void 0, | ||
include: includeFields, | ||
fields: options?.output?.fields || void 0, | ||
formats: this.config.formats && options?.output?.formats ? this.config.formats.parse(options.output.formats) : void 0 | ||
browseParams: options && parseBrowseParams(options, this.config.schema) || void 0 | ||
}, | ||
@@ -1151,25 +1140,14 @@ this._api | ||
/** | ||
* Browse function | ||
* @param {} | ||
* @returns | ||
* Read function that accepts Identify fields like id, slug or email. Will return an instance | ||
* of ReadFetcher class. | ||
*/ | ||
read(options) { | ||
let includeFields = []; | ||
if (options?.output?.include) { | ||
const parsedIncludeFields = this.config.include.parse(options.output.include); | ||
includeFields = Object.keys(parsedIncludeFields); | ||
} | ||
return new ReadFetcher( | ||
{ | ||
schema: this.config.schema, | ||
output: options?.output?.fields && schemaWithPickedFields(this.config.output, options.output.fields) || // this is a hack to get around the fact that I can't figure out how to | ||
// give back the same output as before | ||
this.config.output, | ||
output: this.config.output, | ||
include: this.config.include | ||
}, | ||
{ | ||
identity: queryIdentitySchema.parse(options.input), | ||
include: includeFields, | ||
fields: options?.output?.fields || void 0, | ||
formats: this.config.formats && options?.output?.formats ? this.config.formats.parse(options.output.formats) : void 0 | ||
identity: queryIdentitySchema.parse(options) | ||
}, | ||
@@ -1176,0 +1154,0 @@ this._api |
@@ -1122,25 +1122,14 @@ "use strict"; | ||
/** | ||
* Browse function | ||
* @param {} | ||
* @returns | ||
* Browse function that accepts browse params order, filter, page and limit. Will return an instance | ||
* of BrowseFetcher class. | ||
*/ | ||
browse(options) { | ||
let includeFields = []; | ||
if (options?.output?.include) { | ||
const parsedIncludeFields = this.config.include.parse(options.output.include); | ||
includeFields = Object.keys(parsedIncludeFields); | ||
} | ||
return new BrowseFetcher( | ||
{ | ||
schema: this.config.schema, | ||
output: options?.output?.fields && schemaWithPickedFields(this.config.output, options.output.fields) || // this is a hack to get around the fact that I can't figure out how to | ||
// give back the same output as before | ||
this.config.output, | ||
output: this.config.output, | ||
include: this.config.include | ||
}, | ||
{ | ||
browseParams: options && options.input && parseBrowseParams(options.input, this.config.schema) || void 0, | ||
include: includeFields, | ||
fields: options?.output?.fields || void 0, | ||
formats: this.config.formats && options?.output?.formats ? this.config.formats.parse(options.output.formats) : void 0 | ||
browseParams: options && parseBrowseParams(options, this.config.schema) || void 0 | ||
}, | ||
@@ -1151,25 +1140,14 @@ this._api | ||
/** | ||
* Browse function | ||
* @param {} | ||
* @returns | ||
* Read function that accepts Identify fields like id, slug or email. Will return an instance | ||
* of ReadFetcher class. | ||
*/ | ||
read(options) { | ||
let includeFields = []; | ||
if (options?.output?.include) { | ||
const parsedIncludeFields = this.config.include.parse(options.output.include); | ||
includeFields = Object.keys(parsedIncludeFields); | ||
} | ||
return new ReadFetcher( | ||
{ | ||
schema: this.config.schema, | ||
output: options?.output?.fields && schemaWithPickedFields(this.config.output, options.output.fields) || // this is a hack to get around the fact that I can't figure out how to | ||
// give back the same output as before | ||
this.config.output, | ||
output: this.config.output, | ||
include: this.config.include | ||
}, | ||
{ | ||
identity: queryIdentitySchema.parse(options.input), | ||
include: includeFields, | ||
fields: options?.output?.fields || void 0, | ||
formats: this.config.formats && options?.output?.formats ? this.config.formats.parse(options.output.formats) : void 0 | ||
identity: queryIdentitySchema.parse(options) | ||
}, | ||
@@ -1176,0 +1154,0 @@ this._api |
@@ -12,3 +12,3 @@ { | ||
}, | ||
"version": "0.3.2", | ||
"version": "1.0.0", | ||
"main": "./dist/index.js", | ||
@@ -15,0 +15,0 @@ "module": "./dist/index.mjs", |
204
README.md
@@ -96,26 +96,15 @@ <br/> | ||
let query = qb.browse({ | ||
input: { | ||
limit: 5, | ||
order: "title DESC" | ||
// ^? the text here will throw a TypeScript lint error if you use unknown field. | ||
// In that case `title` is correctly defined in the `simplifiedSchema | ||
}, | ||
output: { | ||
include: { | ||
count: true, | ||
// ^? Available inputs here come from the `simplifiedIncludeSchema` | ||
}, | ||
}, | ||
limit: 5, | ||
order: "title DESC" | ||
// ^? the text here will throw a TypeScript lint error if you use unknown field. | ||
// In that case `title` is correctly defined in the `simplifiedSchema | ||
}); | ||
``` | ||
- `input` will accept browse parameters like `page`, `limit`, `order`, `filter`. And read parameters are `id` or `slug`. | ||
- `output` is the same for both methods and let you specify `fields` to output (to not have the full object) and some Schema specific `include`. For example getting the posts including their Authors. | ||
- browse parameters are `page`, `limit`, `order`, `filter`. And read parameters are `id` or `slug`. | ||
*Ghost Content API doesn't work well when you mix `fields` and `include` output, so in most case you shouldn't* | ||
## Method options | ||
## `input` | ||
### `.browse` options | ||
### `.browse` inputs | ||
Input are totally optionals on the `browse` method but they let you filter and order your search. | ||
@@ -131,8 +120,6 @@ | ||
let query = qb.browse({ | ||
input: { | ||
page: 1, | ||
limit: 5, | ||
filter: "title:typescript+slug:-test", | ||
order: "title DESC" | ||
} | ||
page: 1, | ||
limit: 5, | ||
filter: "title:typescript+slug:-test", | ||
order: "title DESC" | ||
}); | ||
@@ -142,6 +129,2 @@ ``` | ||
#### (Deprecated) Type-hint with `as const` | ||
~~You should use `as const` for your input if you are playing with `filter` and `order` so TypeScript can analyse the content of the string statically and TypeCheck it.~~ | ||
This is not needed anymore since TypeScript release 5.0 the generics use const inference. | ||
- `page:number` The current page requested | ||
@@ -154,3 +137,3 @@ - `limit:number` Between 0 and 15 (limitation of the Ghost API) | ||
### `.read` inputs | ||
### `.read` options | ||
Read is meant to be used to fetch 1 object only by `id` or `slug`. | ||
@@ -164,5 +147,3 @@ | ||
let query = qb.read({ | ||
input: { | ||
id: "edHks74hdKqhs34izzahd45" | ||
} | ||
id: "edHks74hdKqhs34izzahd45" | ||
}); | ||
@@ -173,60 +154,8 @@ | ||
let query = qb.read({ | ||
input: { | ||
slug: "typescript-is-awesome-in-2025" | ||
} | ||
slug: "typescript-is-awesome-in-2025" | ||
}); | ||
``` | ||
You can submit **both** `id` and `slug`, but the fetcher will then chose the `id` in priority if present to make the final URL query to the Ghost API. | ||
## `output` | ||
Output is the same for both `browse` and `read` methods and gives you 2 keys to play with | ||
### `fields` | ||
The `fields` key lets you change the output of the result to have only your selected fields, it works by giving the key and the value `true` to the field you want to keep. Under the hood it will use the `zod.pick` method to pick only the fields you want. | ||
```typescript | ||
const qb = new QueryBuilder( | ||
{ schema: simplifiedSchema, output: simplifiedSchema, include: simplifiedIncludeSchema }, | ||
api | ||
); | ||
let result = await qb.read({ | ||
input: { | ||
slug: "typescript-is-cool" | ||
}, | ||
output: { | ||
fields: { | ||
slug: true, | ||
title: true | ||
// ^? available fields come form the `simplifiedSchema` passed in the constructor | ||
} | ||
} | ||
}).fetch(); | ||
if (result.status === 'success') { | ||
const post = result.data; | ||
// ^? type {"slug":string; "title": string} | ||
} | ||
``` | ||
The **output schema** will be modified to only have the fields you selected and TypeScript will pick up on that to warn you if you access non-existing fields. | ||
### `include` | ||
The `include` key lets you include some additionnal data that the Ghost API doesn't give you by default. This `include` key is specific to each resource and is defined in the `Schema` of the resource. You will have to let TypeScript guide you to know what you can include. | ||
```typescript | ||
const qb = new QueryBuilder( | ||
{ schema: simplifiedSchema, output: simplifiedSchema, include: simplifiedIncludeSchema }, | ||
api | ||
); | ||
let result = await qb.read({ | ||
input: { | ||
slug: "phildl" | ||
}, | ||
output: { | ||
include: { | ||
"count": true, | ||
}, | ||
}, | ||
}).fetch(); | ||
``` | ||
## Fetchers | ||
@@ -240,3 +169,3 @@ | ||
These Fetchers are instantiated in a similar way as the QueryBuilder with a `config` containing the same schemas. But also a set of params | ||
Fetchers are instatiated automatically after using `read` or `browse` but these Fetchers can also be instantiated in isolation, in a similar way as the QueryBuilder with a `config` containing the same schemas. But also a set of params | ||
necessary to build the URL to the Ghost API. | ||
@@ -270,3 +199,3 @@ | ||
); | ||
const readFetcher = qb.read({input: {slug: "typescript-is-cool"}}); | ||
const readFetcher = qb.read({ slug: "typescript-is-cool" }); | ||
let result = await readFetcher.fetch(); | ||
@@ -362,6 +291,101 @@ if (result.status === 'success') { | ||
## Modifiying Fetchers output by selecting fields, formats, include | ||
Output can be modified on the `BrowseFetcher` and the `ReadFetcher` through available methods: | ||
- `.fields` | ||
- `.formats` | ||
- `.include` | ||
### `.fields()` | ||
The `fields` methods lets you change the output of the result to have only your selected fields, it works by giving the property key and the value `true` to the field you want to keep. Under the hood it will use the `zod.pick` method to pick only the fields you want. | ||
```typescript | ||
import { BrowseFetcher } from "@ts-ghost/core-api"; | ||
// Example of instantiating a Fetcher, even though you will probably not do it | ||
const browseFetcher = new BrowseFetcher( | ||
{ | ||
schema: simplifiedSchema, | ||
output: simplifiedSchema, | ||
include: simplifiedIncludeSchema, | ||
}, | ||
{ | ||
browseParams: { | ||
limit: 1, | ||
}, | ||
}, | ||
api | ||
); | ||
let result = await browseFetcher.fields({ | ||
slug: true, | ||
title: true | ||
// ^? available fields come form the `simplifiedSchema` passed in the constructor | ||
}).fetch(); | ||
if (result.status === 'success') { | ||
const post = result.data; | ||
// ^? type {"slug":string; "title": string} | ||
} | ||
``` | ||
The **output schema** will be modified to only have the fields you selected and TypeScript will pick up on that to warn you if you access non-existing fields. | ||
### `include` | ||
The `include` method lets you include some additionnal data that the Ghost API doesn't give you by default. This `include` key is specific to each resource and is defined in the `Schema` of the resource. You will have to let TypeScript guide you to know what you can include. | ||
```typescript | ||
const bf = new BrowseFetcher( | ||
{ schema: simplifiedSchema, output: simplifiedSchema, include: simplifiedIncludeSchema }, | ||
{}, | ||
api | ||
); | ||
let result = await bf.include({ | ||
"count": true, | ||
}).fetch(); | ||
``` | ||
The output type will be modified to make the fields you include **non-optionals**. | ||
### `formats` | ||
The `formats` method lets you include some additionnal formats that the Ghost API doesn't give you by default. This is used on the `Post` and `Page` resource to retrieve the content in plaintext, html, or mobiledoc format. The available keys are `html | mobiledoc | plaintext` and the value is a boolean to indicate if you want to include it or not. | ||
```typescript | ||
const bf = new BrowseFetcher( | ||
{ schema: simplifiedSchema, output: simplifiedSchema, include: simplifiedIncludeSchema }, | ||
{}, | ||
api | ||
); | ||
let result = await bf.formats({ | ||
"html": true, | ||
"plaintext": true, | ||
}).fetch(); | ||
``` | ||
The output type will be modified to make the fields `html` and `plaintext` **non-optionals**. | ||
### Chaining methods | ||
You can chain the methods to select the fields, formats, and include you want. | ||
```typescript | ||
const bf = new BrowseFetcher( | ||
{ schema: simplifiedSchema, output: simplifiedSchema, include: simplifiedIncludeSchema }, | ||
{}, | ||
api | ||
); | ||
let result = await bf.fields({ | ||
slug: true, | ||
title: true, | ||
html: true, | ||
plaintext: true, | ||
count: true | ||
}).formats({ | ||
"html": true, | ||
"plaintext": true, | ||
}).include({ | ||
"count": true, | ||
}).fetch(); | ||
``` | ||
## Roadmap | ||
- Write more docs | ||
- Better handling of weird Ghost "include" params in API call | ||
- Handling POST, PUT and DELETE requests. | ||
@@ -368,0 +392,0 @@ ## Contributing |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1
404
416749
6640