Skip to content

Commit

Permalink
[INT-18028] docs(cli): Bring over paging cursor doc changes added in …
Browse files Browse the repository at this point in the history
…visual-builder repo (#701)

Co-authored-by: Raúl Negrón <raul.negron@zapier.com>
  • Loading branch information
rnegron and rnegron committed Sep 13, 2023
1 parent 3b6b011 commit cd7185b
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 160 deletions.
58 changes: 18 additions & 40 deletions docs/index.html
Expand Up @@ -1644,7 +1644,7 @@ <h3 id="oauth2">OAuth2</h3>
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>For OAuth2, <code>authentication.oauth2Config.authorizeUrl</code>, <code>authentication.oauth2Config.getAccessToken</code>, and <code>authentication.oauth2Config.refreshAccessToken</code> have fields like <code>redirect_uri</code> and <code>state</code> in <code>bundle.inputData</code>. After the code is exchanged for an access token and/or refresh token, those tokens are stored in <code>bundle.authData</code> for the connection.</p><p>Also, <code>authentication.oauth2Config.getAccessToken</code> has access to the additional return values in <code>rawRequest</code> and <code>cleanedRequest</code> should you need to extract other values (for example, from the query string).</p><p>If you define <code>fields</code> to collect additional details from the user, please note that <code>client_id</code> and <code>client_secret</code> are reserved keys and cannot be used as keys for input form fields.</p><blockquote>
<p>Note: The OAuth2 <code>state</code> param is a <a href="https://auth0.com/docs/secure/attack-protection/state-parameters">standard security feature</a> that helps ensure that authorization requests are only coming from your servers. Most OAuth clients have support for this and will send back the <code>state</code> query param that the user brings to your app. The Zapier Platform performs this check and this required field cannot be disabled. The state parameter is automatically generated by Zapier in the background, and can be accessed at <code>bundle.inputData.state</code>.
<p>Note: The OAuth2 <code>state</code> param is a <a href="https://auth0.com/docs/secure/attack-protection/state-parameters">standard security feature</a> that helps ensure that authorization requests are only coming from your servers. Most OAuth clients have support for this and will send back the <code>state</code> query param that the user brings to your app. The Zapier Platform performs this check and this required field cannot be disabled. The state parameter is automatically generated by Zapier in the background, and can be accessed at <code>bundle.inputData.state</code>.
Since Zapier uses the <code>state</code> to verify that GET requests to your redirect URL truly come from your app, it needs to be generated by Zapier so that it can be validated later (once the user confirms that they&apos;d like to grant Zapier permission to access their account in your app).</p>
</blockquote>
</div>
Expand Down Expand Up @@ -2890,7 +2890,7 @@ <h3 id="zrequesturl-options"><code>z.request([url], options)</code></h3>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p><code>z.request([url], options)</code> is a promise based HTTP client with some Zapier-specific goodies. See <a href="#making-http-requests">Making HTTP Requests</a>. <code>z.request()</code> will <a href="https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding">percent-encode</a> non-ascii characters and these reserved characters: <code>:$/?#[]@$&amp;+,;=^@`\</code>. Use <a href="https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#requestschema"><code>skipEncodingChars</code></a> to modify this behaviour. </p>
<p><code>z.request([url], options)</code> is a promise based HTTP client with some Zapier-specific goodies. See <a href="#making-http-requests">Making HTTP Requests</a>. <code>z.request()</code> will <a href="https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding">percent-encode</a> non-ascii characters and these reserved characters: <code>:$/?#[]@$&amp;+,;=^@`\</code>. Use <a href="https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#requestschema"><code>skipEncodingChars</code></a> to modify this behaviour.</p>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">

Expand Down Expand Up @@ -5488,54 +5488,32 @@ <h3 id="whats-the-deal-with-pagination-when-is-it-used-and-how-does-it-work">Wha
<p>If your API uses cursor-based paging instead of an offset, you can use <code>z.cursor.get</code> and <code>z.cursor.set</code>:</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-js"><span class="hljs-comment">// the perform method of our trigger</span>
<span class="hljs-comment">// ensure operation.canPaginate is true!</span>

<span class="hljs-keyword">const</span> performWithoutAsync = <span class="hljs-function">(<span class="hljs-params">z, bundle</span>) =&gt;</span> {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">Promise</span>.resolve()
.then(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
<span class="hljs-keyword">if</span> (bundle.meta.page === <span class="hljs-number">0</span>) {
<span class="hljs-comment">// first page, no need to fetch a cursor</span>
<span class="hljs-keyword">return</span> <span class="hljs-built_in">Promise</span>.resolve();
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> z.cursor.get(); <span class="hljs-comment">// Promise&lt;string | null&gt;</span>
}
})
.then(<span class="hljs-function">(<span class="hljs-params">cursor</span>) =&gt;</span> {
<span class="hljs-keyword">return</span> z.request(
<span class="hljs-string">&apos;https://5ae7ad3547436a00143e104d.mockapi.io/api/recipes&apos;</span>,
{
<span class="hljs-attr">params</span>: { cursor }, <span class="hljs-comment">// if cursor is null, it&apos;s ignored here</span>
}
);
})
.then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
<span class="hljs-comment">// need to save the cursor and return a promise, but also need to pass the data along</span>
<span class="hljs-keyword">return</span> <span class="hljs-built_in">Promise</span>.all([response.items, z.cursor.set(response.nextPage)]);
})
.then(<span class="hljs-function">(<span class="hljs-params">[items <span class="hljs-regexp">/* null */</span>]</span>) =&gt;</span> {
<span class="hljs-keyword">return</span> items;
});
};
<pre><code class="lang-js"><span class="hljs-keyword">const</span> perform = <span class="hljs-keyword">async</span> (z, bundle) =&gt; {
<span class="hljs-keyword">let</span> cursor;

<span class="hljs-comment">// ---------------------------------------------------</span>
<span class="hljs-comment">// if fetching a page other than the first (first page is 0),</span>
<span class="hljs-comment">// get the cursor stored after fetching the previous page.</span>
<span class="hljs-keyword">if</span> (bundle.meta.page &gt; <span class="hljs-number">0</span>) {
cursor = <span class="hljs-keyword">await</span> z.cursor.get();

<span class="hljs-keyword">const</span> performWithAsync = <span class="hljs-keyword">async</span> (z, bundle) =&gt; {
<span class="hljs-keyword">let</span> cursor;
<span class="hljs-keyword">if</span> (bundle.meta.page) {
cursor = <span class="hljs-keyword">await</span> z.cursor.get(); <span class="hljs-comment">// string | null</span>
<span class="hljs-comment">// if the previous page was the last one and cursor is empty/null,</span>
<span class="hljs-comment">// return an empty array.</span>
<span class="hljs-keyword">if</span> (!cursor) {
<span class="hljs-keyword">return</span> [];
}
}

<span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> z.request(
<span class="hljs-string">&apos;https://5ae7ad3547436a00143e104d.mockapi.io/api/recipes&apos;</span>,
{
<span class="hljs-comment">// if cursor is null, it&apos;s sent as an empty query</span>
<span class="hljs-comment">// param and should be ignored by the server</span>
<span class="hljs-comment">// cursor typically is a param to pass along to the next request,</span>
<span class="hljs-comment">// or the full URL for the next page of items.</span>
<span class="hljs-attr">params</span>: { cursor },
}
);

<span class="hljs-comment">// we successfully got page 1, should store the cursor in case the user wants page 2</span>
<span class="hljs-comment">// after fetching a page, set the returned cursor for the next page,</span>
<span class="hljs-comment">// or empty/null if this was the last one.</span>
<span class="hljs-keyword">await</span> z.cursor.set(response.nextPage);

<span class="hljs-keyword">return</span> response.items;
Expand All @@ -5547,7 +5525,7 @@ <h3 id="whats-the-deal-with-pagination-when-is-it-used-and-how-does-it-work">Wha
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>Cursors are stored per-zap and last about an hour. Per the above, make sure to only include the cursor if <code>bundle.meta.page !== 0</code>, so you don&apos;t accidentally reuse a cursor from a previous poll.</p><p>Lastly, you need to set <code>canPaginate</code> to <code>true</code> in your polling definition (per the <a href="https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#basicpollingoperationschema">schema</a>) for the <code>z.cursor</code> methods to work as expected.</p><p><a id="dedup"></a></p>
<p>Cursors are stored per-zap and last about an hour. Per the above, make sure to only include the cursor if <code>bundle.meta.page &gt; 0</code>, so you don&apos;t accidentally reuse a cursor from a previous poll.</p><p>Lastly, you need to set <code>canPaginate</code> to <code>true</code> in your polling definition (per the <a href="https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#basicpollingoperationschema">schema</a>) for the <code>z.cursor</code> methods to work as expected.</p><p><a id="dedup"></a></p>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">

Expand Down
6 changes: 3 additions & 3 deletions packages/cli/README-source.md
Expand Up @@ -452,7 +452,7 @@ Also, `authentication.oauth2Config.getAccessToken` has access to the additional
If you define `fields` to collect additional details from the user, please note that `client_id` and `client_secret` are reserved keys and cannot be used as keys for input form fields.
> Note: The OAuth2 `state` param is a [standard security feature](https://auth0.com/docs/secure/attack-protection/state-parameters) that helps ensure that authorization requests are only coming from your servers. Most OAuth clients have support for this and will send back the `state` query param that the user brings to your app. The Zapier Platform performs this check and this required field cannot be disabled. The state parameter is automatically generated by Zapier in the background, and can be accessed at `bundle.inputData.state`.
> Note: The OAuth2 `state` param is a [standard security feature](https://auth0.com/docs/secure/attack-protection/state-parameters) that helps ensure that authorization requests are only coming from your servers. Most OAuth clients have support for this and will send back the `state` query param that the user brings to your app. The Zapier Platform performs this check and this required field cannot be disabled. The state parameter is automatically generated by Zapier in the background, and can be accessed at `bundle.inputData.state`.
Since Zapier uses the `state` to verify that GET requests to your redirect URL truly come from your app, it needs to be generated by Zapier so that it can be validated later (once the user confirms that they'd like to grant Zapier permission to access their account in your app).
Expand Down Expand Up @@ -815,7 +815,7 @@ We provide several methods off of the `z` object, which is provided as the first
### `z.request([url], options)`
`z.request([url], options)` is a promise based HTTP client with some Zapier-specific goodies. See [Making HTTP Requests](#making-http-requests). `z.request()` will [percent-encode](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) non-ascii characters and these reserved characters: ``:$/?#[]@$&+,;=^@`\``. Use [`skipEncodingChars`](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#requestschema) to modify this behaviour.
`z.request([url], options)` is a promise based HTTP client with some Zapier-specific goodies. See [Making HTTP Requests](#making-http-requests). `z.request()` will [percent-encode](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) non-ascii characters and these reserved characters: ``:$/?#[]@$&+,;=^@`\``. Use [`skipEncodingChars`](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#requestschema) to modify this behaviour.
### `z.console`
Expand Down Expand Up @@ -2018,7 +2018,7 @@ If your API uses cursor-based paging instead of an offset, you can use `z.cursor
[insert-file:./snippets/paging-cursor.js]
```
Cursors are stored per-zap and last about an hour. Per the above, make sure to only include the cursor if `bundle.meta.page !== 0`, so you don't accidentally reuse a cursor from a previous poll.
Cursors are stored per-zap and last about an hour. Per the above, make sure to only include the cursor if `bundle.meta.page > 0`, so you don't accidentally reuse a cursor from a previous poll.
Lastly, you need to set `canPaginate` to `true` in your polling definition (per the [schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#basicpollingoperationschema)) for the `z.cursor` methods to work as expected.
Expand Down
58 changes: 18 additions & 40 deletions packages/cli/README.md
Expand Up @@ -872,7 +872,7 @@ Also, `authentication.oauth2Config.getAccessToken` has access to the additional
If you define `fields` to collect additional details from the user, please note that `client_id` and `client_secret` are reserved keys and cannot be used as keys for input form fields.
> Note: The OAuth2 `state` param is a [standard security feature](https://auth0.com/docs/secure/attack-protection/state-parameters) that helps ensure that authorization requests are only coming from your servers. Most OAuth clients have support for this and will send back the `state` query param that the user brings to your app. The Zapier Platform performs this check and this required field cannot be disabled. The state parameter is automatically generated by Zapier in the background, and can be accessed at `bundle.inputData.state`.
> Note: The OAuth2 `state` param is a [standard security feature](https://auth0.com/docs/secure/attack-protection/state-parameters) that helps ensure that authorization requests are only coming from your servers. Most OAuth clients have support for this and will send back the `state` query param that the user brings to your app. The Zapier Platform performs this check and this required field cannot be disabled. The state parameter is automatically generated by Zapier in the background, and can be accessed at `bundle.inputData.state`.
Since Zapier uses the `state` to verify that GET requests to your redirect URL truly come from your app, it needs to be generated by Zapier so that it can be validated later (once the user confirms that they'd like to grant Zapier permission to access their account in your app).
Expand Down Expand Up @@ -1788,7 +1788,7 @@ We provide several methods off of the `z` object, which is provided as the first
### `z.request([url], options)`
`z.request([url], options)` is a promise based HTTP client with some Zapier-specific goodies. See [Making HTTP Requests](#making-http-requests). `z.request()` will [percent-encode](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) non-ascii characters and these reserved characters: ``:$/?#[]@$&+,;=^@`\``. Use [`skipEncodingChars`](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#requestschema) to modify this behaviour.
`z.request([url], options)` is a promise based HTTP client with some Zapier-specific goodies. See [Making HTTP Requests](#making-http-requests). `z.request()` will [percent-encode](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) non-ascii characters and these reserved characters: ``:$/?#[]@$&+,;=^@`\``. Use [`skipEncodingChars`](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#requestschema) to modify this behaviour.
### `z.console`
Expand Down Expand Up @@ -3442,62 +3442,40 @@ const perform = async (z, bundle) => {
If your API uses cursor-based paging instead of an offset, you can use `z.cursor.get` and `z.cursor.set`:
```js
// the perform method of our trigger
// ensure operation.canPaginate is true!
const performWithoutAsync = (z, bundle) => {
return Promise.resolve()
.then(() => {
if (bundle.meta.page === 0) {
// first page, no need to fetch a cursor
return Promise.resolve();
} else {
return z.cursor.get(); // Promise<string | null>
}
})
.then((cursor) => {
return z.request(
'https://5ae7ad3547436a00143e104d.mockapi.io/api/recipes',
{
params: { cursor }, // if cursor is null, it's ignored here
}
);
})
.then((response) => {
// need to save the cursor and return a promise, but also need to pass the data along
return Promise.all([response.items, z.cursor.set(response.nextPage)]);
})
.then(([items /* null */]) => {
return items;
});
};
const perform = async (z, bundle) => {
let cursor;
// ---------------------------------------------------
// if fetching a page other than the first (first page is 0),
// get the cursor stored after fetching the previous page.
if (bundle.meta.page > 0) {
cursor = await z.cursor.get();
const performWithAsync = async (z, bundle) => {
let cursor;
if (bundle.meta.page) {
cursor = await z.cursor.get(); // string | null
// if the previous page was the last one and cursor is empty/null,
// return an empty array.
if (!cursor) {
return [];
}
}
const response = await z.request(
'https://5ae7ad3547436a00143e104d.mockapi.io/api/recipes',
{
// if cursor is null, it's sent as an empty query
// param and should be ignored by the server
// cursor typically is a param to pass along to the next request,
// or the full URL for the next page of items.
params: { cursor },
}
);
// we successfully got page 1, should store the cursor in case the user wants page 2
// after fetching a page, set the returned cursor for the next page,
// or empty/null if this was the last one.
await z.cursor.set(response.nextPage);
return response.items;
};
```
Cursors are stored per-zap and last about an hour. Per the above, make sure to only include the cursor if `bundle.meta.page !== 0`, so you don't accidentally reuse a cursor from a previous poll.
Cursors are stored per-zap and last about an hour. Per the above, make sure to only include the cursor if `bundle.meta.page > 0`, so you don't accidentally reuse a cursor from a previous poll.
Lastly, you need to set `canPaginate` to `true` in your polling definition (per the [schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#basicpollingoperationschema)) for the `z.cursor` methods to work as expected.
Expand Down

0 comments on commit cd7185b

Please sign in to comment.