Skip to content

Commit

Permalink
flesh out usage in readme
Browse files Browse the repository at this point in the history
  • Loading branch information
angusfretwell committed Feb 29, 2024
1 parent 18d38f9 commit 6337252
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 17 deletions.
161 changes: 149 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,185 @@ npm install civicrm-api

## Usage

> [!NOTE]
> Usage documentation is a work in progress.
### Create a client

```ts
import { createClient } from "civicrm-api";

const client = createClient({
baseUrl: "https://example.com/civicrm",
apiKey: "your-api-key",
entities: { contact: "Contact" },
});

const contactRequest = client
.contact()
.get({ where: { id: 1 } })
.one();
```

## API

### `createClient(options: ClientOptions): Client`

Configure a CiviCRM API client.

#### options.baseUrl

The base URL of the CiviCRM installation.

#### options.apiKey

The [API key](https://docs.civicrm.org/sysadmin/en/latest/setup/api-keys/) to
use for authentication.

#### options.entities

An object containing entities the client will be used to make requests for. Keys
will be
used to reference the entity within the client, and values should match the
entity in CiviCRM:

```ts
const client = createClient({
entities: {
contact: "Contact",
activity: "Activity",
},
});
```

### Make a request
### `client.<entity>(requestOptions?: RequestInit): RequestBuilder`

Create a request builder for a configured entity.

#### requestOptions

Accepts
the [same options as `fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options).

Headers will be merged with the default headers.

```ts
client.contact({
headers: {
"X-Custom-Header": "value",
},
cache: "no-cache",
});
```

### Request builder

Request builders are used to build and execute requests.

Methods can be chained, and the request is executed by
calling `.then()` or starting a chain with `await`.

```ts
// Using .then()
client
.contact()
.get({ where: { id: 1 } })
.one()
.then((contact) => {
//
});

// Using await
const contact = await client
.contact()
.get({ where: { id: 1 } })
.one();
```

## Development
#### `get(params?: Params): RequestBuilder`

#### `create(params?: Params): RequestBuilder`

#### `update(params?: Params): RequestBuilder`

#### `save(params?: Params): RequestBuilder`

#### `delete(params?: Params): RequestBuilder`

#### `getChecksum(params?: Params): RequestBuilder`

Set the action for the request to the method name, and optionally set request
parameters.

##### params

An object accepting parameters accepted by CiviCRM
including `select`, `where`, `having`, `join`,
`groupBy`, `orderBy`, `limit`, `offset` and `values`.

> [!NOTE]
> Development documentation is a work in progress.
Alternatively accepts a key-value object for methods like `getChecksum`.

### Setup
#### `one(): RequestBuilder`

Return a single record (i.e. set the index of the request to 0).

#### `chain(label: string, requestBuilder: RequestBuilder): RequestBuilder`

[Chain a request](https://docs.civicrm.org/dev/en/latest/api/v4/chaining/#apiv4-chaining)
for another entity within the current API call.

```ts
const contact = await client
.contact()
.get({ where: { id: 1 } })
.chain(
"activity",
client.activity().get({ where: { target_contact_id: "$id" } }),
)
.one();

console.log(contact);
// => { id: 1, activity: [{ target_contact_id: 1, ... }], ... }
```

#### label

The label for the chained request, which will be used access the result of the
chained request within the response.

#### requestBuilder

A request builder for the chained request.

## Development

### Install dependencies

```sh
npm install
```

### Testing
### Run tests

```sh
npm test
```

### Building
### Build the package

```sh
npm run build
```

### Releasing

1. Increment the version number and create a tag:

```sh
npm version <major|minor|patch|prerelease>
```

2. Push the tag to GitHub:

```sh
git push --tags
```

3. [Create a release](https://github.com/socialistalternative/civicrm-api/releases/new)
on GitHub. The package will be built and published to npm automatically by
GitHub Actions.
9 changes: 6 additions & 3 deletions src/request-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import {
Params,
RequestFn,
RequestParams,
Response,
} from "./types";

export class RequestBuilder<T = any> implements PromiseLike<T> {
export class RequestBuilder<T = Response | Response[]>
implements PromiseLike<T>
{
private readonly entity: Entity;
private readonly request: RequestFn<T>;
private innerPromise: Promise<T>;
Expand Down Expand Up @@ -83,8 +86,8 @@ export class RequestBuilder<T = any> implements PromiseLike<T> {
return this;
}

chain(name: string, req: RequestBuilder) {
this.chains[name] = req;
chain(label: string, requestBuilder: RequestBuilder) {
this.chains[label] = requestBuilder;

return this;
}
Expand Down
4 changes: 2 additions & 2 deletions src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export async function request(
apiKey: string;
},
[entity, action, params, index]: RequestParams,
{ headers, ...requestInit }: RequestInit = {},
{ headers, ...requestOptions }: RequestInit = {},
) {
const requestId = crypto.randomUUID();

Expand All @@ -33,7 +33,7 @@ export async function request(
"X-Request-ID": requestId,
...headers,
},
...requestInit,
...requestOptions,
});

if (!res.ok) {
Expand Down
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,7 @@ export type Index = number;

export type RequestParams = [Entity, Action, Params?, Index?];
export type RequestFn<T> = (params: RequestParams) => Promise<T>;

export interface Response {
[key: string]: Value | Response;
}

0 comments on commit 6337252

Please sign in to comment.