Skip to content

Commit

Permalink
feat(fetchText): add fetchText API for fetch text response (#23)
Browse files Browse the repository at this point in the history
* test: create test case for fetchText

* feat(fetchText): add fetchText API for produce fetch for text response
  • Loading branch information
r17x committed Oct 2, 2022
1 parent 55aa5bb commit 814d36e
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 45 deletions.
43 changes: 41 additions & 2 deletions README.md
@@ -1,6 +1,13 @@
<div align="center">
<h1>fetch.macro</h1>
<h1 id="toc">fetch.macro</h1>
<p>Allows you to build fetcher function by URL at compile-time.</p>

<p align="center">
<a href="#usage">Usage</a> •
<a href="#api">API</a> •
<a href="#contributors">Contributors</a>
</p>

</div>

---
Expand All @@ -20,8 +27,12 @@

## Usage

[[Back to the Table of Contents]](#toc)

Simply install and configure [`babel-plugin-macros`](https://github.com/kentcdodds/babel-plugin-macros) and then use `fetch.macro`.

> Some project that build with `create-react-app` doesn't need extra setup for `babel-plugin-macros`.
### Vite

To be able to use these macros in your [Vite](https://vitejs.dev/) project, you only need install [`vite-plugin-babel-macros`](https://github.com/itsMapleLeaf/vite-plugin-babel-macros) and add some configuration in `vite.config.js`. And it just work.
Expand All @@ -47,11 +58,13 @@ export default {
#### Basic

Run one of the following command inside your project directory to install the package:

```
$ npm i fetch.macro
or
$ yarn add fetch.macro
$ yarn add fetch.macro
```

Given the following `Input`:

```javascript
Expand Down Expand Up @@ -90,8 +103,34 @@ const fetchProject = ({ id, projectId, others, ...opts }) =>
fetch(`/api/v1/user/${id}/project/${projectId}/${others}`, opts);
```

## API

[[Back to the Table of Contents]](#toc)

### Default

It will be produce a code for fetch function with URL by input and return response that need to be manual handle the response.

```
import f from 'fetch.macro'
const fetchByUrl = f("/api/v1/ping");
```

### fetchText

It will be produce a code for fetch function with URL by input and return [**response text**](https://webidl.spec.whatwg.org/#idl-USVString).

```
import { fetchText } from 'fetch.macro'
const fetchLicense = fetchText("https://raw.githubusercontent.com/r17x/fetch.macro/main/LICENSE");
```

## Contributors

[[Back to the Table of Contents]](#toc)

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
Expand Down
128 changes: 85 additions & 43 deletions src/fetch.macro.js
Expand Up @@ -9,47 +9,89 @@ const getValue = (path) =>

const isValueHaveArgs = (val) => /:\w+/g.test(val);

module.exports = createMacro(({ babel: { types: t, template }, references: { default: paths } }) => {
paths.forEach(({ parentPath }) => {
const value = getValue(parentPath);
const memberExpressionTemplate = (ref) =>
({
[true]: "",
[ref === "default"]: "",
[ref === "fetchText"]: ".then(r => r.text())",
/**
* @todo {https://github.com/r17x/fetch.macro/issues/22}
* - [ ] fetchJson
* - [ ] fetchBlob
* - [ ] fetchArrayBuffer
* - [ ] fetchFormData
*/
}.true);

module.exports = createMacro(
({
babel: { types: t, template },
references: {
default: paths,
fetchText,
/**
* @todo {https://github.com/r17x/fetch.macro/issues/22}
* - [ ] fetchJson
* - [ ] fetchBlob
* - [ ] fetchArrayBuffer
* - [ ] fetchFormData
*/
},
}) => {
const transform =
(reference) =>
({ parentPath }) => {
const value = getValue(parentPath);
const memberExpression = memberExpressionTemplate(reference);

if (value) {
if (isValueHaveArgs(value)) {
const buildFetch = template(`(PARAM) => fetch(URI, opts)`.concat(memberExpression));
parentPath.replaceWithMultiple(
buildFetch({
PARAM: t.objectPattern(
value
.split("/")
.filter((v) => v.startsWith(":"))
.map((p) => {
const id = t.identifier(p.replace(":", ""));
return t.objectProperty(id, id, false, true);
})
.concat([t.restElement(t.identifier("opts"))]),
),
URI: t.templateLiteral(
value
.replace(/:\w+/g, "::::")
.split("::::")
.map((v, i, a) => t.templateElement({ raw: v, cooked: v }, i + 1 === a.length)),
value
.split("/")
.filter((v) => v.startsWith(":"))
.map((v) => t.identifier(v.replace(":", ""))),
),
}),
);
} else {
const buildFetch = template(`(opts) => fetch(URI, opts)`.concat(memberExpression));
parentPath.replaceWithMultiple(
buildFetch({
URI: t.stringLiteral(value),
}),
);
}
} else {
parentPath.parentPath.remove();
}
};

if (value) {
if (isValueHaveArgs(value)) {
const buildFetch = template(`(PARAM) => fetch(URI, opts)`);
parentPath.replaceWithMultiple(
buildFetch({
PARAM: t.objectPattern(
value
.split("/")
.filter((v) => v.startsWith(":"))
.map((p) => {
const id = t.identifier(p.replace(":", ""));
return t.objectProperty(id, id, false, true);
})
.concat([t.restElement(t.identifier("opts"))]),
),
URI: t.templateLiteral(
value
.replace(/:\w+/g, "::::")
.split("::::")
.map((v, i, a) => t.templateElement({ raw: v, cooked: v }, i + 1 === a.length)),
value
.split("/")
.filter((v) => v.startsWith(":"))
.map((v) => t.identifier(v.replace(":", ""))),
),
}),
);
} else {
const buildFetch = template(`(opts) => fetch(URI, opts)`);
parentPath.replaceWithMultiple(
buildFetch({
URI: t.stringLiteral(value),
}),
);
}
} else {
parentPath.parentPath.remove();
}
});
});
(paths || []).forEach(transform("default"));
(fetchText || []).forEach(transform("fetchText"));
/**
* @todo {https://github.com/r17x/fetch.macro/issues/22}
* - [ ] fetchJson
* - [ ] fetchBlob
* - [ ] fetchArrayBuffer
* - [ ] fetchFormData
*/
},
);
12 changes: 12 additions & 0 deletions tests/fetch.js
Expand Up @@ -68,4 +68,16 @@ createTests("fetch", [
`,
output: "",
},
// fetchText
{
title: "fetchText with url params",
code: `
import {fetchText} from '../src/fetch.macro'
const fetchProject = fetchText\`/api/v1/user/:id/project/:projectId/:others\`;
`,
output: `
const fetchProject = ({ id, projectId, others, ...opts }) =>
fetch(\`/api/v1/user/\${id}/project/\${projectId}/\${others}\`, opts).then((r) => r.text());
`,
},
]);

0 comments on commit 814d36e

Please sign in to comment.