From df223f5eaa5e8a80e44d612d0d4ce0ff98a946fd Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 22 Feb 2022 17:29:56 -0800 Subject: [PATCH 01/19] pinsAPI client can get/put --- .mocharc.cjs | 4 + fixtures.js | 9 + generated/fetch/.gitignore | 4 + generated/fetch/.npmignore | 1 + generated/fetch/.openapi-generator-ignore | 23 + generated/fetch/.openapi-generator/FILES | 17 + generated/fetch/.openapi-generator/VERSION | 1 + generated/fetch/README.md | 45 ++ generated/fetch/src/apis/PinsApi.ts | 405 ++++++++++++++++++ generated/fetch/src/apis/index.ts | 3 + generated/fetch/src/index.ts | 5 + generated/fetch/src/models/Failure.ts | 63 +++ generated/fetch/src/models/FailureError.ts | 64 +++ generated/fetch/src/models/Pin.ts | 80 ++++ generated/fetch/src/models/PinResults.ts | 71 +++ generated/fetch/src/models/PinStatus.ts | 109 +++++ generated/fetch/src/models/Status.ts | 38 ++ .../fetch/src/models/TextMatchingStrategy.ts | 38 ++ generated/fetch/src/models/index.ts | 9 + generated/fetch/src/runtime.ts | 320 ++++++++++++++ npm-scripts/postinstall.sh | 10 + package.json | 20 +- patches/aegir+36.1.3.patch | 15 + src/index.ts | 1 + test/MockServer.ts | 154 +++++++ test/PinsApi.spec.ts | 74 ++++ tsconfig.json | 10 +- types/global.d.ts | 3 + types/mock-ipfs-pinning-service.d.ts | 11 - 29 files changed, 1584 insertions(+), 23 deletions(-) create mode 100644 .mocharc.cjs create mode 100644 fixtures.js create mode 100644 generated/fetch/.gitignore create mode 100644 generated/fetch/.npmignore create mode 100644 generated/fetch/.openapi-generator-ignore create mode 100644 generated/fetch/.openapi-generator/FILES create mode 100644 generated/fetch/.openapi-generator/VERSION create mode 100644 generated/fetch/README.md create mode 100644 generated/fetch/src/apis/PinsApi.ts create mode 100644 generated/fetch/src/apis/index.ts create mode 100644 generated/fetch/src/index.ts create mode 100644 generated/fetch/src/models/Failure.ts create mode 100644 generated/fetch/src/models/FailureError.ts create mode 100644 generated/fetch/src/models/Pin.ts create mode 100644 generated/fetch/src/models/PinResults.ts create mode 100644 generated/fetch/src/models/PinStatus.ts create mode 100644 generated/fetch/src/models/Status.ts create mode 100644 generated/fetch/src/models/TextMatchingStrategy.ts create mode 100644 generated/fetch/src/models/index.ts create mode 100644 generated/fetch/src/runtime.ts create mode 100755 npm-scripts/postinstall.sh create mode 100644 patches/aegir+36.1.3.patch create mode 100644 src/index.ts create mode 100644 test/MockServer.ts create mode 100644 test/PinsApi.spec.ts delete mode 100644 types/mock-ipfs-pinning-service.d.ts diff --git a/.mocharc.cjs b/.mocharc.cjs new file mode 100644 index 0000000..0094b57 --- /dev/null +++ b/.mocharc.cjs @@ -0,0 +1,4 @@ +module.exports = { + require: ['./fixtures.js'], + extensions: ['ts', 'tsx'], +} diff --git a/fixtures.js b/fixtures.js new file mode 100644 index 0000000..86a87b4 --- /dev/null +++ b/fixtures.js @@ -0,0 +1,9 @@ + +// @ts-check +export async function mochaGlobalSetup () { + +} + +export async function mochaGlobalTeardown () { + +} diff --git a/generated/fetch/.gitignore b/generated/fetch/.gitignore new file mode 100644 index 0000000..149b576 --- /dev/null +++ b/generated/fetch/.gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist diff --git a/generated/fetch/.npmignore b/generated/fetch/.npmignore new file mode 100644 index 0000000..42061c0 --- /dev/null +++ b/generated/fetch/.npmignore @@ -0,0 +1 @@ +README.md \ No newline at end of file diff --git a/generated/fetch/.openapi-generator-ignore b/generated/fetch/.openapi-generator-ignore new file mode 100644 index 0000000..7484ee5 --- /dev/null +++ b/generated/fetch/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/generated/fetch/.openapi-generator/FILES b/generated/fetch/.openapi-generator/FILES new file mode 100644 index 0000000..5e2cca3 --- /dev/null +++ b/generated/fetch/.openapi-generator/FILES @@ -0,0 +1,17 @@ +.gitignore +.npmignore +README.md +package.json +src/apis/PinsApi.ts +src/apis/index.ts +src/index.ts +src/models/Failure.ts +src/models/FailureError.ts +src/models/Pin.ts +src/models/PinResults.ts +src/models/PinStatus.ts +src/models/Status.ts +src/models/TextMatchingStrategy.ts +src/models/index.ts +src/runtime.ts +tsconfig.json diff --git a/generated/fetch/.openapi-generator/VERSION b/generated/fetch/.openapi-generator/VERSION new file mode 100644 index 0000000..1e20ec3 --- /dev/null +++ b/generated/fetch/.openapi-generator/VERSION @@ -0,0 +1 @@ +5.4.0 \ No newline at end of file diff --git a/generated/fetch/README.md b/generated/fetch/README.md new file mode 100644 index 0000000..a150abe --- /dev/null +++ b/generated/fetch/README.md @@ -0,0 +1,45 @@ +## @ipfs-shipyard/pinning-service-client@1.0.0 + +This generator creates TypeScript/JavaScript client that utilizes [Fetch API](https://fetch.spec.whatwg.org/). The generated Node module can be used in the following environments: + +Environment +* Node.js +* Webpack +* Browserify + +Language level +* ES5 - you must have a Promises/A+ library installed +* ES6 + +Module system +* CommonJS +* ES6 module system + +It can be used in both TypeScript and JavaScript. In TypeScript, the definition should be automatically resolved via `package.json`. ([Reference](http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html)) + +### Building + +To build and compile the typescript sources to javascript use: +``` +npm install +npm run build +``` + +### Publishing + +First build the package then run ```npm publish``` + +### Consuming + +navigate to the folder of your consuming project and run one of the following commands. + +_published:_ + +``` +npm install @ipfs-shipyard/pinning-service-client@1.0.0 --save +``` + +_unPublished (not recommended):_ + +``` +npm install PATH_TO_GENERATED_PACKAGE --save diff --git a/generated/fetch/src/apis/PinsApi.ts b/generated/fetch/src/apis/PinsApi.ts new file mode 100644 index 0000000..0a2f74a --- /dev/null +++ b/generated/fetch/src/apis/PinsApi.ts @@ -0,0 +1,405 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * IPFS Pinning Service API + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import { + Failure, + FailureFromJSON, + FailureToJSON, + Pin, + PinFromJSON, + PinToJSON, + PinResults, + PinResultsFromJSON, + PinResultsToJSON, + PinStatus, + PinStatusFromJSON, + PinStatusToJSON, + Status, + StatusFromJSON, + StatusToJSON, + TextMatchingStrategy, + TextMatchingStrategyFromJSON, + TextMatchingStrategyToJSON, +} from '../models'; + +export interface PinsGetRequest { + cid?: Set; + name?: string; + match?: TextMatchingStrategy; + status?: Set; + before?: Date; + after?: Date; + limit?: number; + meta?: { [key: string]: string; }; +} + +export interface PinsPostRequest { + pin: Pin; +} + +export interface PinsRequestidDeleteRequest { + requestid: string; +} + +export interface PinsRequestidGetRequest { + requestid: string; +} + +export interface PinsRequestidPostRequest { + requestid: string; + pin: Pin; +} + +/** + * PinsApi - interface + * + * @export + * @interface PinsApiInterface + */ +export interface PinsApiInterface { + /** + * List all the pin objects, matching optional filters; when no filter is provided, only successful pins are returned + * @summary List pin objects + * @param {Set} [cid] Return pin objects responsible for pinning the specified CID(s); be aware that using longer hash functions introduces further constraints on the number of CIDs that will fit under the limit of 2000 characters per URL in browser contexts + * @param {string} [name] Return pin objects with specified name (by default a case-sensitive, exact match) + * @param {TextMatchingStrategy} [match] Customize the text matching strategy applied when the name filter is present; exact (the default) is a case-sensitive exact match, partial matches anywhere in the name, iexact and ipartial are case-insensitive versions of the exact and partial strategies + * @param {Set} [status] Return pin objects for pins with the specified status + * @param {Date} [before] Return results created (queued) before provided timestamp + * @param {Date} [after] Return results created (queued) after provided timestamp + * @param {number} [limit] Max records to return + * @param {{ [key: string]: string; }} [meta] Return pin objects that match specified metadata keys passed as a string representation of a JSON object; when implementing a client library, make sure the parameter is URL-encoded to ensure safe transport + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PinsApiInterface + */ + pinsGetRaw(requestParameters: PinsGetRequest, initOverrides?: RequestInit): Promise>; + + /** + * List all the pin objects, matching optional filters; when no filter is provided, only successful pins are returned + * List pin objects + */ + pinsGet(requestParameters: PinsGetRequest, initOverrides?: RequestInit): Promise; + + /** + * Add a new pin object for the current access token + * @summary Add pin object + * @param {Pin} pin + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PinsApiInterface + */ + pinsPostRaw(requestParameters: PinsPostRequest, initOverrides?: RequestInit): Promise>; + + /** + * Add a new pin object for the current access token + * Add pin object + */ + pinsPost(requestParameters: PinsPostRequest, initOverrides?: RequestInit): Promise; + + /** + * Remove a pin object + * @summary Remove pin object + * @param {string} requestid + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PinsApiInterface + */ + pinsRequestidDeleteRaw(requestParameters: PinsRequestidDeleteRequest, initOverrides?: RequestInit): Promise>; + + /** + * Remove a pin object + * Remove pin object + */ + pinsRequestidDelete(requestParameters: PinsRequestidDeleteRequest, initOverrides?: RequestInit): Promise; + + /** + * Get a pin object and its status + * @summary Get pin object + * @param {string} requestid + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PinsApiInterface + */ + pinsRequestidGetRaw(requestParameters: PinsRequestidGetRequest, initOverrides?: RequestInit): Promise>; + + /** + * Get a pin object and its status + * Get pin object + */ + pinsRequestidGet(requestParameters: PinsRequestidGetRequest, initOverrides?: RequestInit): Promise; + + /** + * Replace an existing pin object (shortcut for executing remove and add operations in one step to avoid unnecessary garbage collection of blocks present in both recursive pins) + * @summary Replace pin object + * @param {string} requestid + * @param {Pin} pin + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof PinsApiInterface + */ + pinsRequestidPostRaw(requestParameters: PinsRequestidPostRequest, initOverrides?: RequestInit): Promise>; + + /** + * Replace an existing pin object (shortcut for executing remove and add operations in one step to avoid unnecessary garbage collection of blocks present in both recursive pins) + * Replace pin object + */ + pinsRequestidPost(requestParameters: PinsRequestidPostRequest, initOverrides?: RequestInit): Promise; + +} + +/** + * + */ +export class PinsApi extends runtime.BaseAPI implements PinsApiInterface { + + /** + * List all the pin objects, matching optional filters; when no filter is provided, only successful pins are returned + * List pin objects + */ + async pinsGetRaw(requestParameters: PinsGetRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.cid) { + queryParameters['cid'] = Array.from(requestParameters.cid).join(runtime.COLLECTION_FORMATS["csv"]); + } + + if (requestParameters.name !== undefined) { + queryParameters['name'] = requestParameters.name; + } + + if (requestParameters.match !== undefined) { + queryParameters['match'] = requestParameters.match; + } + + if (requestParameters.status) { + queryParameters['status'] = Array.from(requestParameters.status).join(runtime.COLLECTION_FORMATS["csv"]); + } + + if (requestParameters.before !== undefined) { + queryParameters['before'] = (requestParameters.before as any).toISOString(); + } + + if (requestParameters.after !== undefined) { + queryParameters['after'] = (requestParameters.after as any).toISOString(); + } + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.meta !== undefined) { + queryParameters['meta'] = requestParameters.meta; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("accessToken", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/pins`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => PinResultsFromJSON(jsonValue)); + } + + /** + * List all the pin objects, matching optional filters; when no filter is provided, only successful pins are returned + * List pin objects + */ + async pinsGet(requestParameters: PinsGetRequest = {}, initOverrides?: RequestInit): Promise { + const response = await this.pinsGetRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Add a new pin object for the current access token + * Add pin object + */ + async pinsPostRaw(requestParameters: PinsPostRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.pin === null || requestParameters.pin === undefined) { + throw new runtime.RequiredError('pin','Required parameter requestParameters.pin was null or undefined when calling pinsPost.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("accessToken", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/pins`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: PinToJSON(requestParameters.pin), + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => PinStatusFromJSON(jsonValue)); + } + + /** + * Add a new pin object for the current access token + * Add pin object + */ + async pinsPost(requestParameters: PinsPostRequest, initOverrides?: RequestInit): Promise { + const response = await this.pinsPostRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Remove a pin object + * Remove pin object + */ + async pinsRequestidDeleteRaw(requestParameters: PinsRequestidDeleteRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.requestid === null || requestParameters.requestid === undefined) { + throw new runtime.RequiredError('requestid','Required parameter requestParameters.requestid was null or undefined when calling pinsRequestidDelete.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("accessToken", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/pins/{requestid}`.replace(`{${"requestid"}}`, encodeURIComponent(String(requestParameters.requestid))), + method: 'DELETE', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Remove a pin object + * Remove pin object + */ + async pinsRequestidDelete(requestParameters: PinsRequestidDeleteRequest, initOverrides?: RequestInit): Promise { + await this.pinsRequestidDeleteRaw(requestParameters, initOverrides); + } + + /** + * Get a pin object and its status + * Get pin object + */ + async pinsRequestidGetRaw(requestParameters: PinsRequestidGetRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.requestid === null || requestParameters.requestid === undefined) { + throw new runtime.RequiredError('requestid','Required parameter requestParameters.requestid was null or undefined when calling pinsRequestidGet.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("accessToken", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/pins/{requestid}`.replace(`{${"requestid"}}`, encodeURIComponent(String(requestParameters.requestid))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => PinStatusFromJSON(jsonValue)); + } + + /** + * Get a pin object and its status + * Get pin object + */ + async pinsRequestidGet(requestParameters: PinsRequestidGetRequest, initOverrides?: RequestInit): Promise { + const response = await this.pinsRequestidGetRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Replace an existing pin object (shortcut for executing remove and add operations in one step to avoid unnecessary garbage collection of blocks present in both recursive pins) + * Replace pin object + */ + async pinsRequestidPostRaw(requestParameters: PinsRequestidPostRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.requestid === null || requestParameters.requestid === undefined) { + throw new runtime.RequiredError('requestid','Required parameter requestParameters.requestid was null or undefined when calling pinsRequestidPost.'); + } + + if (requestParameters.pin === null || requestParameters.pin === undefined) { + throw new runtime.RequiredError('pin','Required parameter requestParameters.pin was null or undefined when calling pinsRequestidPost.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("accessToken", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/pins/{requestid}`.replace(`{${"requestid"}}`, encodeURIComponent(String(requestParameters.requestid))), + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: PinToJSON(requestParameters.pin), + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => PinStatusFromJSON(jsonValue)); + } + + /** + * Replace an existing pin object (shortcut for executing remove and add operations in one step to avoid unnecessary garbage collection of blocks present in both recursive pins) + * Replace pin object + */ + async pinsRequestidPost(requestParameters: PinsRequestidPostRequest, initOverrides?: RequestInit): Promise { + const response = await this.pinsRequestidPostRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/generated/fetch/src/apis/index.ts b/generated/fetch/src/apis/index.ts new file mode 100644 index 0000000..9a1d85b --- /dev/null +++ b/generated/fetch/src/apis/index.ts @@ -0,0 +1,3 @@ +/* tslint:disable */ +/* eslint-disable */ +export * from './PinsApi'; diff --git a/generated/fetch/src/index.ts b/generated/fetch/src/index.ts new file mode 100644 index 0000000..be9d1ed --- /dev/null +++ b/generated/fetch/src/index.ts @@ -0,0 +1,5 @@ +/* tslint:disable */ +/* eslint-disable */ +export * from './runtime'; +export * from './apis'; +export * from './models'; diff --git a/generated/fetch/src/models/Failure.ts b/generated/fetch/src/models/Failure.ts new file mode 100644 index 0000000..e2f9961 --- /dev/null +++ b/generated/fetch/src/models/Failure.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * IPFS Pinning Service API + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + FailureError, + FailureErrorFromJSON, + FailureErrorFromJSONTyped, + FailureErrorToJSON, +} from './FailureError'; + +/** + * Response for a failed request + * @export + * @interface Failure + */ +export interface Failure { + /** + * + * @type {FailureError} + * @memberof Failure + */ + error: FailureError; +} + +export function FailureFromJSON(json: any): Failure { + return FailureFromJSONTyped(json, false); +} + +export function FailureFromJSONTyped(json: any, ignoreDiscriminator: boolean): Failure { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'error': FailureErrorFromJSON(json['error']), + }; +} + +export function FailureToJSON(value?: Failure | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'error': FailureErrorToJSON(value.error), + }; +} + diff --git a/generated/fetch/src/models/FailureError.ts b/generated/fetch/src/models/FailureError.ts new file mode 100644 index 0000000..702b151 --- /dev/null +++ b/generated/fetch/src/models/FailureError.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * IPFS Pinning Service API + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface FailureError + */ +export interface FailureError { + /** + * Mandatory string identifying the type of error + * @type {string} + * @memberof FailureError + */ + reason: string; + /** + * Optional, longer description of the error; may include UUID of transaction for support, links to documentation etc + * @type {string} + * @memberof FailureError + */ + details?: string; +} + +export function FailureErrorFromJSON(json: any): FailureError { + return FailureErrorFromJSONTyped(json, false); +} + +export function FailureErrorFromJSONTyped(json: any, ignoreDiscriminator: boolean): FailureError { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'reason': json['reason'], + 'details': !exists(json, 'details') ? undefined : json['details'], + }; +} + +export function FailureErrorToJSON(value?: FailureError | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'reason': value.reason, + 'details': value.details, + }; +} + diff --git a/generated/fetch/src/models/Pin.ts b/generated/fetch/src/models/Pin.ts new file mode 100644 index 0000000..682c980 --- /dev/null +++ b/generated/fetch/src/models/Pin.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * IPFS Pinning Service API + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Pin object + * @export + * @interface Pin + */ +export interface Pin { + /** + * Content Identifier (CID) to be pinned recursively + * @type {string} + * @memberof Pin + */ + cid: string; + /** + * Optional name for pinned data; can be used for lookups later + * @type {string} + * @memberof Pin + */ + name?: string; + /** + * Optional list of multiaddrs known to provide the data + * @type {Set} + * @memberof Pin + */ + origins?: Set; + /** + * Optional metadata for pin object + * @type {{ [key: string]: string; }} + * @memberof Pin + */ + meta?: { [key: string]: string; }; +} + +export function PinFromJSON(json: any): Pin { + return PinFromJSONTyped(json, false); +} + +export function PinFromJSONTyped(json: any, ignoreDiscriminator: boolean): Pin { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'cid': json['cid'], + 'name': !exists(json, 'name') ? undefined : json['name'], + 'origins': !exists(json, 'origins') ? undefined : json['origins'], + 'meta': !exists(json, 'meta') ? undefined : json['meta'], + }; +} + +export function PinToJSON(value?: Pin | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'cid': value.cid, + 'name': value.name, + 'origins': value.origins, + 'meta': value.meta, + }; +} + diff --git a/generated/fetch/src/models/PinResults.ts b/generated/fetch/src/models/PinResults.ts new file mode 100644 index 0000000..1395348 --- /dev/null +++ b/generated/fetch/src/models/PinResults.ts @@ -0,0 +1,71 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * IPFS Pinning Service API + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + PinStatus, + PinStatusFromJSON, + PinStatusFromJSONTyped, + PinStatusToJSON, +} from './PinStatus'; + +/** + * Response used for listing pin objects matching request + * @export + * @interface PinResults + */ +export interface PinResults { + /** + * The total number of pin objects that exist for passed query filters + * @type {number} + * @memberof PinResults + */ + count: number; + /** + * An array of PinStatus results + * @type {Set} + * @memberof PinResults + */ + results: Set; +} + +export function PinResultsFromJSON(json: any): PinResults { + return PinResultsFromJSONTyped(json, false); +} + +export function PinResultsFromJSONTyped(json: any, ignoreDiscriminator: boolean): PinResults { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'count': json['count'], + 'results': (new Set((json['results'] as Array).map(PinStatusFromJSON))), + }; +} + +export function PinResultsToJSON(value?: PinResults | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'count': value.count, + 'results': (Array.from(value.results as Set).map(PinStatusToJSON)), + }; +} + diff --git a/generated/fetch/src/models/PinStatus.ts b/generated/fetch/src/models/PinStatus.ts new file mode 100644 index 0000000..3ae5364 --- /dev/null +++ b/generated/fetch/src/models/PinStatus.ts @@ -0,0 +1,109 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * IPFS Pinning Service API + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + Pin, + PinFromJSON, + PinFromJSONTyped, + PinToJSON, +} from './Pin'; +import { + Status, + StatusFromJSON, + StatusFromJSONTyped, + StatusToJSON, +} from './Status'; + +/** + * Pin object with status + * @export + * @interface PinStatus + */ +export interface PinStatus { + /** + * Globally unique identifier of the pin request; can be used to check the status of ongoing pinning, or pin removal + * @type {string} + * @memberof PinStatus + */ + requestid: string; + /** + * + * @type {Status} + * @memberof PinStatus + */ + status: Status; + /** + * Immutable timestamp indicating when a pin request entered a pinning service; can be used for filtering results and pagination + * @type {Date} + * @memberof PinStatus + */ + created: Date; + /** + * + * @type {Pin} + * @memberof PinStatus + */ + pin: Pin; + /** + * List of multiaddrs designated by pinning service for transferring any new data from external peers + * @type {Set} + * @memberof PinStatus + */ + delegates: Set; + /** + * Optional info for PinStatus response + * @type {{ [key: string]: string; }} + * @memberof PinStatus + */ + info?: { [key: string]: string; }; +} + +export function PinStatusFromJSON(json: any): PinStatus { + return PinStatusFromJSONTyped(json, false); +} + +export function PinStatusFromJSONTyped(json: any, ignoreDiscriminator: boolean): PinStatus { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'requestid': json['requestid'], + 'status': StatusFromJSON(json['status']), + 'created': (new Date(json['created'])), + 'pin': PinFromJSON(json['pin']), + 'delegates': json['delegates'], + 'info': !exists(json, 'info') ? undefined : json['info'], + }; +} + +export function PinStatusToJSON(value?: PinStatus | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'requestid': value.requestid, + 'status': StatusToJSON(value.status), + 'created': (value.created.toISOString()), + 'pin': PinToJSON(value.pin), + 'delegates': value.delegates, + 'info': value.info, + }; +} + diff --git a/generated/fetch/src/models/Status.ts b/generated/fetch/src/models/Status.ts new file mode 100644 index 0000000..32d1ada --- /dev/null +++ b/generated/fetch/src/models/Status.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * IPFS Pinning Service API + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * Status a pin object can have at a pinning service + * @export + * @enum {string} + */ +export enum Status { + Queued = 'queued', + Pinning = 'pinning', + Pinned = 'pinned', + Failed = 'failed' +} + +export function StatusFromJSON(json: any): Status { + return StatusFromJSONTyped(json, false); +} + +export function StatusFromJSONTyped(json: any, ignoreDiscriminator: boolean): Status { + return json as Status; +} + +export function StatusToJSON(value?: Status | null): any { + return value as any; +} + diff --git a/generated/fetch/src/models/TextMatchingStrategy.ts b/generated/fetch/src/models/TextMatchingStrategy.ts new file mode 100644 index 0000000..eb6c76f --- /dev/null +++ b/generated/fetch/src/models/TextMatchingStrategy.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * IPFS Pinning Service API + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * Alternative text matching strategy + * @export + * @enum {string} + */ +export enum TextMatchingStrategy { + Exact = 'exact', + Iexact = 'iexact', + Partial = 'partial', + Ipartial = 'ipartial' +} + +export function TextMatchingStrategyFromJSON(json: any): TextMatchingStrategy { + return TextMatchingStrategyFromJSONTyped(json, false); +} + +export function TextMatchingStrategyFromJSONTyped(json: any, ignoreDiscriminator: boolean): TextMatchingStrategy { + return json as TextMatchingStrategy; +} + +export function TextMatchingStrategyToJSON(value?: TextMatchingStrategy | null): any { + return value as any; +} + diff --git a/generated/fetch/src/models/index.ts b/generated/fetch/src/models/index.ts new file mode 100644 index 0000000..f8f5a52 --- /dev/null +++ b/generated/fetch/src/models/index.ts @@ -0,0 +1,9 @@ +/* tslint:disable */ +/* eslint-disable */ +export * from './Failure'; +export * from './FailureError'; +export * from './Pin'; +export * from './PinResults'; +export * from './PinStatus'; +export * from './Status'; +export * from './TextMatchingStrategy'; diff --git a/generated/fetch/src/runtime.ts b/generated/fetch/src/runtime.ts new file mode 100644 index 0000000..c7a1577 --- /dev/null +++ b/generated/fetch/src/runtime.ts @@ -0,0 +1,320 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * IPFS Pinning Service API + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export const BASE_PATH = "https://pinning-service.example.com".replace(/\/+$/, ""); + +const isBlob = (value: any) => typeof Blob !== 'undefined' && value instanceof Blob; + +/** + * This is the base class for all generated API classes. + */ +export class BaseAPI { + + private middleware: Middleware[]; + + constructor(protected configuration = new Configuration()) { + this.middleware = configuration.middleware; + } + + withMiddleware(this: T, ...middlewares: Middleware[]) { + const next = this.clone(); + next.middleware = next.middleware.concat(...middlewares); + return next; + } + + withPreMiddleware(this: T, ...preMiddlewares: Array) { + const middlewares = preMiddlewares.map((pre) => ({ pre })); + return this.withMiddleware(...middlewares); + } + + withPostMiddleware(this: T, ...postMiddlewares: Array) { + const middlewares = postMiddlewares.map((post) => ({ post })); + return this.withMiddleware(...middlewares); + } + + protected async request(context: RequestOpts, initOverrides?: RequestInit): Promise { + const { url, init } = this.createFetchParams(context, initOverrides); + const response = await this.fetchApi(url, init); + if (response.status >= 200 && response.status < 300) { + return response; + } + throw response; + } + + private createFetchParams(context: RequestOpts, initOverrides?: RequestInit) { + let url = this.configuration.basePath + context.path; + if (context.query !== undefined && Object.keys(context.query).length !== 0) { + // only add the querystring to the URL if there are query parameters. + // this is done to avoid urls ending with a "?" character which buggy webservers + // do not handle correctly sometimes. + url += '?' + this.configuration.queryParamsStringify(context.query); + } + const body = ((typeof FormData !== "undefined" && context.body instanceof FormData) || context.body instanceof URLSearchParams || isBlob(context.body)) + ? context.body + : JSON.stringify(context.body); + + const headers = Object.assign({}, this.configuration.headers, context.headers); + const init = { + method: context.method, + headers: headers, + body, + credentials: this.configuration.credentials, + ...initOverrides + }; + return { url, init }; + } + + private fetchApi = async (url: string, init: RequestInit) => { + let fetchParams = { url, init }; + for (const middleware of this.middleware) { + if (middleware.pre) { + fetchParams = await middleware.pre({ + fetch: this.fetchApi, + ...fetchParams, + }) || fetchParams; + } + } + let response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init); + for (const middleware of this.middleware) { + if (middleware.post) { + response = await middleware.post({ + fetch: this.fetchApi, + url: fetchParams.url, + init: fetchParams.init, + response: response.clone(), + }) || response; + } + } + return response; + } + + /** + * Create a shallow clone of `this` by constructing a new instance + * and then shallow cloning data members. + */ + private clone(this: T): T { + const constructor = this.constructor as any; + const next = new constructor(this.configuration); + next.middleware = this.middleware.slice(); + return next; + } +}; + +export class RequiredError extends Error { + name: "RequiredError" = "RequiredError"; + constructor(public field: string, msg?: string) { + super(msg); + } +} + +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +export type FetchAPI = GlobalFetch['fetch']; + +export interface ConfigurationParameters { + basePath?: string; // override base path + fetchApi?: FetchAPI; // override for fetch implementation + middleware?: Middleware[]; // middleware to apply before/after fetch requests + queryParamsStringify?: (params: HTTPQuery) => string; // stringify function for query strings + username?: string; // parameter for basic security + password?: string; // parameter for basic security + apiKey?: string | ((name: string) => string); // parameter for apiKey security + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string | Promise); // parameter for oauth2 security + headers?: HTTPHeaders; //header params we want to use on every request + credentials?: RequestCredentials; //value for the credentials param we want to use on each request +} + +export class Configuration { + constructor(private configuration: ConfigurationParameters = {}) {} + + get basePath(): string { + return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH; + } + + get fetchApi(): FetchAPI | undefined { + return this.configuration.fetchApi; + } + + get middleware(): Middleware[] { + return this.configuration.middleware || []; + } + + get queryParamsStringify(): (params: HTTPQuery) => string { + return this.configuration.queryParamsStringify || querystring; + } + + get username(): string | undefined { + return this.configuration.username; + } + + get password(): string | undefined { + return this.configuration.password; + } + + get apiKey(): ((name: string) => string) | undefined { + const apiKey = this.configuration.apiKey; + if (apiKey) { + return typeof apiKey === 'function' ? apiKey : () => apiKey; + } + return undefined; + } + + get accessToken(): ((name?: string, scopes?: string[]) => string | Promise) | undefined { + const accessToken = this.configuration.accessToken; + if (accessToken) { + return typeof accessToken === 'function' ? accessToken : async () => accessToken; + } + return undefined; + } + + get headers(): HTTPHeaders | undefined { + return this.configuration.headers; + } + + get credentials(): RequestCredentials | undefined { + return this.configuration.credentials; + } +} + +export type Json = any; +export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD'; +export type HTTPHeaders = { [key: string]: string }; +export type HTTPQuery = { [key: string]: string | number | null | boolean | Array | HTTPQuery }; +export type HTTPBody = Json | FormData | URLSearchParams; +export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original'; + +export interface FetchParams { + url: string; + init: RequestInit; +} + +export interface RequestOpts { + path: string; + method: HTTPMethod; + headers: HTTPHeaders; + query?: HTTPQuery; + body?: HTTPBody; +} + +export function exists(json: any, key: string) { + const value = json[key]; + return value !== null && value !== undefined; +} + +export function querystring(params: HTTPQuery, prefix: string = ''): string { + return Object.keys(params) + .map((key) => { + const fullKey = prefix + (prefix.length ? `[${key}]` : key); + const value = params[key]; + if (value instanceof Array) { + const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue))) + .join(`&${encodeURIComponent(fullKey)}=`); + return `${encodeURIComponent(fullKey)}=${multiValue}`; + } + if (value instanceof Date) { + return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`; + } + if (value instanceof Object) { + return querystring(value as HTTPQuery, fullKey); + } + return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`; + }) + .filter(part => part.length > 0) + .join('&'); +} + +export function mapValues(data: any, fn: (item: any) => any) { + return Object.keys(data).reduce( + (acc, key) => ({ ...acc, [key]: fn(data[key]) }), + {} + ); +} + +export function canConsumeForm(consumes: Consume[]): boolean { + for (const consume of consumes) { + if ('multipart/form-data' === consume.contentType) { + return true; + } + } + return false; +} + +export interface Consume { + contentType: string +} + +export interface RequestContext { + fetch: FetchAPI; + url: string; + init: RequestInit; +} + +export interface ResponseContext { + fetch: FetchAPI; + url: string; + init: RequestInit; + response: Response; +} + +export interface Middleware { + pre?(context: RequestContext): Promise; + post?(context: ResponseContext): Promise; +} + +export interface ApiResponse { + raw: Response; + value(): Promise; +} + +export interface ResponseTransformer { + (json: any): T; +} + +export class JSONApiResponse { + constructor(public raw: Response, private transformer: ResponseTransformer = (jsonValue: any) => jsonValue) {} + + async value(): Promise { + return this.transformer(await this.raw.json()); + } +} + +export class VoidApiResponse { + constructor(public raw: Response) {} + + async value(): Promise { + return undefined; + } +} + +export class BlobApiResponse { + constructor(public raw: Response) {} + + async value(): Promise { + return await this.raw.blob(); + }; +} + +export class TextApiResponse { + constructor(public raw: Response) {} + + async value(): Promise { + return await this.raw.text(); + }; +} diff --git a/npm-scripts/postinstall.sh b/npm-scripts/postinstall.sh new file mode 100755 index 0000000..0226048 --- /dev/null +++ b/npm-scripts/postinstall.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# Generate client code +npm run gen + +patch-package + +# Replace aegir's tsc with tsc-silent so we can ignore errors in generated code +mv node_modules/aegir/node_modules/typescript/bin/tsc node_modules/aegir/node_modules/typescript/bin/tsc-bak +ln -fs $(realpath --relative-to=node_modules/aegir/node_modules/typescript/bin $(npm bin)/tsc-silent) node_modules/aegir/node_modules/typescript/bin/tsc diff --git a/package.json b/package.json index 21aa520..4808de1 100644 --- a/package.json +++ b/package.json @@ -126,37 +126,43 @@ "scripts": { "dep-check": "aegir dep-check src/**/*.ts test/**/*.ts generated/**/*.ts", "fix": "run-s fix:*", + "fix:gen": "./npm-scripts/fix/generated-code.sh", "fix:lint": "aegir lint --fix", "lint": "run-s lint:*", "lint:main": "aegir lint", "lint:project": "check-aegir-project", "release": "aegir release", - "postinstall": "run-s gen", - "build": "aegir build", - "test": "run-s test:*", + "postinstall": "./npm-scripts/postinstall.sh", + "build": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", + "test": "run-p test:*", "test:electron": "aegir test --target electron-main", "test:node": "aegir test --target node --cov && npx nyc report", - "pregen:node": "openapi-generator-cli validate -i https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml", - "gen": "run-p gen:*", + "pregen": "openapi-generator-cli validate -i https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml", + "gen": "run-p gen:fetch", + "postgen": "run-s fix:gen", "gen:fetch": "openapi-generator-cli generate --generator-key fetch", "gen:node": "openapi-generator-cli generate --generator-key node", "gen:ts": "openapi-generator-cli generate --generator-key ts" }, "dependencies": { - "node-fetch": "^3.2.0" + "node-fetch": "^3.2.0", + "patch-package": "^6.4.7" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.4.26", + "@types/collections": "^5.1.2", "@types/express": "^4.17.13", "@types/mocha": "^9.1.0", "@types/node": "^17.0.16", "@types/node-fetch": "^3.0.3", "aegir": "^36.1.3", "check-aegir-project": "^1.0.3", + "collections": "^5.1.13", "dotenvrc": "^1.0.1", "mock-ipfs-pinning-service": "^0.4.0", "npm-run-all": "^4.1.5", - "openapi-typescript": "^5.1.1" + "openapi-typescript": "^5.1.1", + "tsc-silent": "^1.2.1" }, "exports": { ".": { diff --git a/patches/aegir+36.1.3.patch b/patches/aegir+36.1.3.patch new file mode 100644 index 0000000..0a644a4 --- /dev/null +++ b/patches/aegir+36.1.3.patch @@ -0,0 +1,15 @@ +diff --git a/node_modules/aegir/src/build/index.js b/node_modules/aegir/src/build/index.js +index a614f51..e455dfb 100644 +--- a/node_modules/aegir/src/build/index.js ++++ b/node_modules/aegir/src/build/index.js +@@ -130,9 +130,7 @@ const tasks = new Listr([ + */ + task: async (ctx, task) => { + await tsCmd({ +- debug: ctx.debug, +- tsRepo: ctx.tsRepo, +- fileConfig: ctx.fileConfig, ++ ...ctx, + preset: 'types', + include: ctx.fileConfig.ts.include, + copyTo: ctx.fileConfig.ts.copyTo, diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..1b587ff --- /dev/null +++ b/src/index.ts @@ -0,0 +1 @@ +export * from '../generated/fetch/src/index' diff --git a/test/MockServer.ts b/test/MockServer.ts new file mode 100644 index 0000000..92079bf --- /dev/null +++ b/test/MockServer.ts @@ -0,0 +1,154 @@ +import { setup } from 'mock-ipfs-pinning-service' +import type { Application } from 'express' +import type { Server } from 'http' +import portscanner from 'portscanner' +import('dotenvrc') + +export class MockServer { + private _server: Server | undefined = undefined + + private port = Number(process.env.MOCK_PINNING_SERVER_PORT ?? 3000) + private _service: Application | undefined = undefined + + /** + * This set helps us support parallel tests by not attempting to start up multiple MockServer's on the same port + */ + + public basePath: string = '' + + constructor () { + process.on('uncaughtException', MockServer.onEADDRINUSE) + } + + public async start (port = this.port): Promise { + let server + try { + server = await this.server(port) + } catch (err) { + MockServer.error('start error', err) + } + + if (server == null) { + process.exit(1) + } + + // And you'll want to make sure you close the server when your process exits + process.on('beforeExit', this.cleanupSync) + process.on('SIGTERM', this.cleanupSync) + process.on('SIGINT', this.cleanupSync) + process.on('SIGHUP', this.cleanupSync) + + // To prevent duplicated cleanup, remove the process listeners on server close. + server.on('close', () => { + process.off('beforeExit', this.cleanupSync) + process.off('SIGTERM', this.cleanupSync) + process.off('SIGINT', this.cleanupSync) + process.off('SIGHUP', this.cleanupSync) + }) + } + + public async stop (): Promise { + await this.cleanup() + } + + private setBasePath (): void { + this.basePath = `http://127.0.0.1:${this.port}` + } + + /** + * Ensure the port set for this instance is not already in use by another MockServer + */ + private async getAvailablePort (): Promise { + return await new Promise((resolve, reject) => portscanner.findAPortNotInUse(3000, 3099, '127.0.0.1', (error, port) => { + if (error != null) { + return reject(error) + } + this.port = port + this.setBasePath() + resolve(port) + })) + } + + private async service (): Promise { + if (this._service !== undefined) { + return this._service + } + this._service = await setup({ + token: process.env.MOCK_PINNING_SERVER_SECRET + }) + + return this._service + } + + private async server (port = this.port): Promise { + if (this._server !== undefined) { + return this._server + } + if (port !== this.port) { + this.port = port + } + const service = await this.service() + + service.on('error', (err) => { + MockServer.error('service error', err) + }) + this._server = service.listen(await this.getAvailablePort(), () => { + MockServer.debug(`server running on port ${port}`) + }) + + return this._server + } + + private cleanupSync (): void { + void this.cleanup().then(() => { + MockServer.debug('cleaned up') + }) + } + + // Express server cleanup handling. + private async cleanup (): Promise { + const server = await this.server() + server.close((err) => { + if ((err == null) || (err as Error & { code: string })?.code === 'ERR_SERVER_NOT_RUNNING') { + // MockServer.portsInUse.remove(this.port) + MockServer.debug(`server stopped listening on port ${this.port}`) + delete this._server + } + if (err != null) { + MockServer.error(err.name) + MockServer.error(err.message) + MockServer.error(err.stack) + } + }) + } + + private static onEADDRINUSE (err: Error & { code: string }) { + if (err.code === 'EADDRINUSE') { + this.error('Unexpected conflict with port usage') + } else { + this.error('CAUGHT UNKNOWN ERROR') + this.error(err.name) + this.error(err.code) + this.error(err.message) + this.error(err.stack) + } + process.exit(233) + } + + private static debug (...logObjects: unknown[]) { + if (process.env.DEBUG != null) { + MockServer.log('debug', ...logObjects) + } + } + + private static error (...logObjects: unknown[]) { + if (process.env.DEBUG != null) { + MockServer.log('error', ...logObjects) + } + } + + private static log (type: keyof typeof console & 'log' | 'debug' | 'error' | 'warn' | 'info' | 'trace', ...logObjects: unknown[]) { + // eslint-disable-next-line no-console + console[type](...logObjects) + } +} diff --git a/test/PinsApi.spec.ts b/test/PinsApi.spec.ts new file mode 100644 index 0000000..f61ace9 --- /dev/null +++ b/test/PinsApi.spec.ts @@ -0,0 +1,74 @@ + +import { expect } from 'aegir/utils/chai' +import fetch from 'node-fetch' + +import { PinsApi, Configuration, ConfigurationParameters, Pin, Status } from '../src' +import { MockServer } from './MockServer' + +import('dotenvrc') + +const getClientConfigForMockServer = (mockServer: MockServer) => new Configuration({ + basePath: mockServer.basePath, + fetchApi: fetch as GlobalFetch['fetch'], + accessToken: process.env.MOCK_PINNING_SERVER_SECRET +}) + +describe('PinsApi', () => { + describe('Configuration', () => { + it('Can be instantiated', () => { + const configuration: ConfigurationParameters = {} + expect(() => new Configuration(configuration)).not.to.throw() + }) + }) + describe('Client', () => { + const Config = new Configuration({ + basePath: `http://127.0.0.1:${process.env.MOCK_PINNING_SERVER_PORT ?? '3000'}`, + fetchApi: fetch as GlobalFetch['fetch'], + accessToken: process.env.MOCK_PINNING_SERVER_SECRET + }) + + it('Can be instantiated', () => { + expect(() => new PinsApi(Config)).not.to.throw() + }) + + describe('Operations', () => { + let mockServer: MockServer + beforeEach(async () => { + mockServer = new MockServer() + await mockServer.start() + }) + + afterEach(async () => { + await mockServer.stop() + }) + + it('GET: Can get failed Pins', async () => { + const Client = new PinsApi(getClientConfigForMockServer(mockServer)) + const response = await Client.pinsGet({ limit: 1, status: new Set([Status.Failed]) }) + expect(response).to.deep.eq({ count: 0, results: new Set() }) + }) + + it('GET: Can add a Pin successfully', async () => { + const Client = new PinsApi(getClientConfigForMockServer(mockServer)) + const pin: Pin = { + cid: 'abc123', + name: 'pinned-test1' + } + const response = await Client.pinsPost({ pin }) + expect(response).to.deep.includes({ status: Status.Pinned }) + expect(response.pin).to.deep.include({ ...pin }) + }) + + it('POST: Can handle a failed pinning', async () => { + const Client = new PinsApi(getClientConfigForMockServer(mockServer)) + const pin: Pin = { + cid: 'abc123', + name: 'failed-test2' + } + const response = await Client.pinsPost({ pin }) + expect(response).to.deep.includes({ status: Status.Failed }) + expect(response.pin).to.deep.include({ ...pin }) + }) + }) + }) +}) diff --git a/tsconfig.json b/tsconfig.json index 2f1d962..637597f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,14 +6,14 @@ "module": "ES2020", "typeRoots": [ "./types", - "./node_modules/@types", - ], + "./node_modules/@types" + ] }, "include": [ "src", "generated", - "test", + "test/*.ts", "generated", - "types", - ], + "types/*.d.ts" + ] } diff --git a/types/global.d.ts b/types/global.d.ts index 3dd92a5..6335de6 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -1,3 +1,6 @@ declare type GlobalFetch = WindowOrWorkerGlobalScope +declare module 'mock-ipfs-pinning-service' { + export * from 'mock-ipfs-pinning-service/dist/index' +} diff --git a/types/mock-ipfs-pinning-service.d.ts b/types/mock-ipfs-pinning-service.d.ts deleted file mode 100644 index 0f14aaf..0000000 --- a/types/mock-ipfs-pinning-service.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { Application } from 'express'; - -export module 'mock-ipfs-pinning-service' { - declare const MockIpfsPinningService = { - setup: () => Application, - } - export default { - setup: express.application, - }; - export default MockIpfsPinningService; -} From 1ca0cd5baa482552fbe62f5419bc196a5e2db164 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 23 Feb 2022 17:35:21 -0800 Subject: [PATCH 02/19] getting test environments working --- .aegir.cjs | 29 ++++++++++ .envrc | 1 + .gitignore | 2 + fixtures.js | 8 +-- npm-scripts/fix/gen.sh | 40 ++++++++++++++ package.json | 22 ++++++-- test/MockServer.ts | 3 +- test/PinsApi.spec.ts | 74 -------------------------- test/browser-tests/.gitkeep | 0 test/browser.ts | 19 +++++++ test/isomorphic-tests/client.ts | 58 ++++++++++++++++++++ test/isomorphic-tests/configuration.ts | 13 +++++ test/node-tests/.gitkeep | 0 test/node.ts | 23 ++++++++ tsconfig.json | 19 +++++-- 15 files changed, 225 insertions(+), 86 deletions(-) create mode 100755 npm-scripts/fix/gen.sh delete mode 100644 test/PinsApi.spec.ts create mode 100644 test/browser-tests/.gitkeep create mode 100644 test/browser.ts create mode 100644 test/isomorphic-tests/client.ts create mode 100644 test/isomorphic-tests/configuration.ts create mode 100644 test/node-tests/.gitkeep create mode 100644 test/node.ts diff --git a/.aegir.cjs b/.aegir.cjs index b8f6f6f..45bb3fc 100644 --- a/.aegir.cjs +++ b/.aegir.cjs @@ -1,10 +1,39 @@ +// import { MockServer } from './test/MockServer' + +// let mockServer = new MockServer() +require('ts-node').register({ + project: 'tsconfig.json', +}) +const { MockServer } = require('./test/MockServer') + /** @type {import('aegir').PartialOptions} */ module.exports = { + docs: { + publish: true, + entryPoint: './' + }, tsRepo: true, build: { config: { platform: 'node' }, bundlesizeMax: '44KB' + }, + test: { + async before () { + + }, + async beforeEach () { + + // mockServer = new MockServer() + await mockServer.start() + }, + async afterEach () { + + await mockServer.stop() + }, + async after () { + + } } } diff --git a/.envrc b/.envrc index e472052..86e673a 100644 --- a/.envrc +++ b/.envrc @@ -3,3 +3,4 @@ use asdf export PATH=$(npm bin):${PATH} export MOCK_PINNING_SERVER_PORT=3000 export MOCK_PINNING_SERVER_SECRET=secret +export DEBUG=1 diff --git a/.gitignore b/.gitignore index 8eb8cca..81c08c4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ yarn.lock test/ts-use/tsconfig.tsbuildinfo test/tsconfig.tsbuildinfo package-lock.json +*.bak +.swc diff --git a/fixtures.js b/fixtures.js index 86a87b4..2a2d4ec 100644 --- a/fixtures.js +++ b/fixtures.js @@ -1,9 +1,9 @@ // @ts-check -export async function mochaGlobalSetup () { +// export async function mochaGlobalSetup () { -} +// } -export async function mochaGlobalTeardown () { +// export async function mochaGlobalTeardown () { -} +// } diff --git a/npm-scripts/fix/gen.sh b/npm-scripts/fix/gen.sh new file mode 100755 index 0000000..aadf9b3 --- /dev/null +++ b/npm-scripts/fix/gen.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +main() { + # Get all generated files + # local FILES + # FILES=() + local SED_BACKUPS=() + + # remove openapi-generator's package and tsconfig json files + for PKG_JSON in generated/*/package.json; do + rm $PKG_JSON + done + for TSC_JSON in generated/*/tsconfig.json; do + rm $TSC_JSON + done + + for FILES_LIST in $(find generated/*/.openapi-generator/FILES); do + echo FILES_LIST = $FILES_LIST + for FILE in $(cat $FILES_LIST); do + local DIR=$(dirname $(dirname $FILES_LIST)) + local FILE_PATH="${DIR}/${FILE}" + echo "FILE=${FILE_PATH}" + + if test -e $FILE_PATH; then + # Replace all occurrances of "<" with "<" + # Replace all occurrances of ">" with ">" + sed -i .bak -e 's/<\;/\/g' $FILE_PATH + SED_BACKUPS+=( $FILE_PATH.bak ) + fi + done + done + + + echo "SED_BACKUPS = ${SED_BACKUPS[@]}" + # test build.. if build succeeds, remove backup file. + +} + + +main $@ diff --git a/package.json b/package.json index 4808de1..2e4bcc7 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,13 @@ "bugs": { "url": "https://github.com/ipfs-shipyard/js-pinning-service-http-client/issues" }, + "keywords": [ + "dweb", + "ipfs", + "pinning service", + "protocol labs", + "web3" + ], "engines": { "node": ">=16.0.0", "npm": ">=7.0.0" @@ -126,14 +133,17 @@ "scripts": { "dep-check": "aegir dep-check src/**/*.ts test/**/*.ts generated/**/*.ts", "fix": "run-s fix:*", - "fix:gen": "./npm-scripts/fix/generated-code.sh", + "fix:gen": "./npm-scripts/fix/gen.sh", "fix:lint": "aegir lint --fix", "lint": "run-s lint:*", "lint:main": "aegir lint", - "lint:project": "check-aegir-project", + "lint:ts": "aegir ts -p check -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", + "lint-TODO:project": "check-aegir-project # currently broken due to corrupting the repoUrl", "release": "aegir release", "postinstall": "./npm-scripts/postinstall.sh", "build": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", + "build:main": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", + "build:docs": "aegir ts docs", "test": "run-p test:*", "test:electron": "aegir test --target electron-main", "test:node": "aegir test --target node --cov && npx nyc report", @@ -150,18 +160,22 @@ }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.4.26", - "@types/collections": "^5.1.2", + "@swc/core": "^1.2.144", + "@swc/helpers": "^0.3.3", "@types/express": "^4.17.13", "@types/mocha": "^9.1.0", "@types/node": "^17.0.16", "@types/node-fetch": "^3.0.3", + "@types/portscanner": "^2.1.1", "aegir": "^36.1.3", "check-aegir-project": "^1.0.3", - "collections": "^5.1.13", "dotenvrc": "^1.0.1", "mock-ipfs-pinning-service": "^0.4.0", "npm-run-all": "^4.1.5", "openapi-typescript": "^5.1.1", + "portscanner": "^2.2.0", + "regenerator-runtime": "^0.13.9", + "ts-node": "^10.5.0", "tsc-silent": "^1.2.1" }, "exports": { diff --git a/test/MockServer.ts b/test/MockServer.ts index 92079bf..8de8951 100644 --- a/test/MockServer.ts +++ b/test/MockServer.ts @@ -77,7 +77,8 @@ export class MockServer { token: process.env.MOCK_PINNING_SERVER_SECRET }) - return this._service + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + return this._service as Application } private async server (port = this.port): Promise { diff --git a/test/PinsApi.spec.ts b/test/PinsApi.spec.ts deleted file mode 100644 index f61ace9..0000000 --- a/test/PinsApi.spec.ts +++ /dev/null @@ -1,74 +0,0 @@ - -import { expect } from 'aegir/utils/chai' -import fetch from 'node-fetch' - -import { PinsApi, Configuration, ConfigurationParameters, Pin, Status } from '../src' -import { MockServer } from './MockServer' - -import('dotenvrc') - -const getClientConfigForMockServer = (mockServer: MockServer) => new Configuration({ - basePath: mockServer.basePath, - fetchApi: fetch as GlobalFetch['fetch'], - accessToken: process.env.MOCK_PINNING_SERVER_SECRET -}) - -describe('PinsApi', () => { - describe('Configuration', () => { - it('Can be instantiated', () => { - const configuration: ConfigurationParameters = {} - expect(() => new Configuration(configuration)).not.to.throw() - }) - }) - describe('Client', () => { - const Config = new Configuration({ - basePath: `http://127.0.0.1:${process.env.MOCK_PINNING_SERVER_PORT ?? '3000'}`, - fetchApi: fetch as GlobalFetch['fetch'], - accessToken: process.env.MOCK_PINNING_SERVER_SECRET - }) - - it('Can be instantiated', () => { - expect(() => new PinsApi(Config)).not.to.throw() - }) - - describe('Operations', () => { - let mockServer: MockServer - beforeEach(async () => { - mockServer = new MockServer() - await mockServer.start() - }) - - afterEach(async () => { - await mockServer.stop() - }) - - it('GET: Can get failed Pins', async () => { - const Client = new PinsApi(getClientConfigForMockServer(mockServer)) - const response = await Client.pinsGet({ limit: 1, status: new Set([Status.Failed]) }) - expect(response).to.deep.eq({ count: 0, results: new Set() }) - }) - - it('GET: Can add a Pin successfully', async () => { - const Client = new PinsApi(getClientConfigForMockServer(mockServer)) - const pin: Pin = { - cid: 'abc123', - name: 'pinned-test1' - } - const response = await Client.pinsPost({ pin }) - expect(response).to.deep.includes({ status: Status.Pinned }) - expect(response.pin).to.deep.include({ ...pin }) - }) - - it('POST: Can handle a failed pinning', async () => { - const Client = new PinsApi(getClientConfigForMockServer(mockServer)) - const pin: Pin = { - cid: 'abc123', - name: 'failed-test2' - } - const response = await Client.pinsPost({ pin }) - expect(response).to.deep.includes({ status: Status.Failed }) - expect(response.pin).to.deep.include({ ...pin }) - }) - }) - }) -}) diff --git a/test/browser-tests/.gitkeep b/test/browser-tests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/browser.ts b/test/browser.ts new file mode 100644 index 0000000..7f0818c --- /dev/null +++ b/test/browser.ts @@ -0,0 +1,19 @@ +/* eslint-disable no-console */ + +import clientTests from './isomorphic-tests/client' +import configurationTests from './isomorphic-tests/configuration' + + + +const setup = async () => { + return await new Promise((resolve, reject) => { + void resolve() + }) +} + +// eslint-disable-next-line @typescript-eslint/no-misused-promises +describe('browser', async (): Promise => { + console.log(fetch) + await configurationTests(setup) + await clientTests(setup) +}) diff --git a/test/isomorphic-tests/client.ts b/test/isomorphic-tests/client.ts new file mode 100644 index 0000000..b7e7d65 --- /dev/null +++ b/test/isomorphic-tests/client.ts @@ -0,0 +1,58 @@ +/* eslint-env browser, node, mocha */ + +import { expect } from 'aegir/utils/chai' +import { Configuration, PinsApi } from '../../src' + +export default async (setup: () => Promise) => { + describe('Client', () => { + const Config = new Configuration({ + basePath: `http://127.0.0.1:${process.env.MOCK_PINNING_SERVER_PORT ?? '3000'}`, + fetchApi: fetch as GlobalFetch['fetch'], + accessToken: process.env.MOCK_PINNING_SERVER_SECRET + }) + + it('Can be instantiated', () => { + expect(() => new PinsApi(Config)).not.to.throw() + }) + + // describe.skip('Operations', () => { + // let mockServer: MockServer + // beforeEach(async () => { + // mockServer = new MockServer() + // await mockServer.start() + // }) + + // afterEach(async () => { + // await mockServer.stop() + // }) + + // it('GET: Can get failed Pins', async () => { + // const Client = new PinsApi(getClientConfigForMockServer(mockServer)) + // const response = await Client.pinsGet({ limit: 1, status: new Set([Status.Failed]) }) + // expect(response).to.deep.eq({ count: 0, results: new Set() }) + // }) + + // it('GET: Can add a Pin successfully', async () => { + // const Client = new PinsApi(getClientConfigForMockServer(mockServer)) + // const pin: Pin = { + // cid: 'abc123', + // name: 'pinned-test1' + // } + // const response = await Client.pinsPost({ pin }) + // expect(response).to.deep.includes({ status: Status.Pinned }) + // expect(response.pin).to.deep.include({ ...pin }) + // }) + + // it('POST: Can handle a failed pinning', async () => { + // const Client = new PinsApi(getClientConfigForMockServer(mockServer)) + // const pin: Pin = { + // cid: 'abc123', + // name: 'failed-test2' + // } + // const response = await Client.pinsPost({ pin }) + // expect(response).to.deep.includes({ status: Status.Failed }) + // expect(response.pin).to.deep.include({ ...pin }) + // }) + // }) + }) +} diff --git a/test/isomorphic-tests/configuration.ts b/test/isomorphic-tests/configuration.ts new file mode 100644 index 0000000..8bb0e5e --- /dev/null +++ b/test/isomorphic-tests/configuration.ts @@ -0,0 +1,13 @@ +/* eslint-env browser, node, mocha */ + +import { expect } from 'aegir/utils/chai' +import { Configuration, ConfigurationParameters } from '../../src' + +export default async (setup: () => Promise) => { + describe('Configuration', () => { + it('Can be instantiated', () => { + const configuration: ConfigurationParameters = {} + expect(() => new Configuration(configuration)).not.to.throw() + }) + }) +} diff --git a/test/node-tests/.gitkeep b/test/node-tests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/node.ts b/test/node.ts new file mode 100644 index 0000000..230ff61 --- /dev/null +++ b/test/node.ts @@ -0,0 +1,23 @@ +/* eslint-disable no-console */ + +import clientTests from './isomorphic-tests/client' +import configurationTests from './isomorphic-tests/configuration' +import fetch from 'node-fetch' + +const setup = async () => { + return await new Promise((resolve, reject) => { + void resolve() + }) +} +// eslint-disable-next-line @typescript-eslint/no-misused-promises +describe('node', async (): Promise => { + console.log(fetch) + await configurationTests(setup) + await clientTests(setup) +}) + +// const getClientConfigForMockServer = (mockServer: MockServer) => new Configuration({ +// basePath: mockServer.basePath, +// fetchApi: fetch as GlobalFetch['fetch'], +// accessToken: process.env.MOCK_PINNING_SERVER_SECRET +// }) diff --git a/tsconfig.json b/tsconfig.json index 637597f..83cc355 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,8 +12,21 @@ "include": [ "src", "generated", - "test/*.ts", + "test/**/*.ts", "generated", - "types/*.d.ts" - ] + "types/**/*.d.ts" + ], + "ts-node": { + "transpileOnly": true, + "files": true, + "emit": false, + "compiler": "typescript", + "compilerHost": false, + "compilerOptions": { + "module": "CommonJS" + }, + "preferTsExts": true, + "pretty": true, + "swc": true + } } From eb714f54eb3df8bd3cff3e6efcc46d53fa7d4ca1 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 28 Feb 2022 13:19:15 -0800 Subject: [PATCH 03/19] feat: mockservercontroller can spin up mockservers via http --- .aegir.cjs | 25 ++--- test/MockServer.ts => MockServer.ts | 41 ++++--- MockServerController.ts | 138 ++++++++++++++++++++++++ package.json | 12 ++- test/browser.ts | 14 ++- test/configuration.spec.ts | 13 +++ test/isomorphic-tests/client.ts | 108 +++++++++++-------- test/isomorphic-tests/configuration.ts | 13 --- test/node-tests/index.ts | 1 + test/node-tests/mockServerController.ts | 41 +++++++ test/node.ts | 23 ++-- tsconfig.json | 2 +- 12 files changed, 325 insertions(+), 106 deletions(-) rename test/MockServer.ts => MockServer.ts (79%) create mode 100644 MockServerController.ts create mode 100644 test/configuration.spec.ts delete mode 100644 test/isomorphic-tests/configuration.ts create mode 100644 test/node-tests/index.ts create mode 100755 test/node-tests/mockServerController.ts diff --git a/.aegir.cjs b/.aegir.cjs index 45bb3fc..5183901 100644 --- a/.aegir.cjs +++ b/.aegir.cjs @@ -4,7 +4,9 @@ require('ts-node').register({ project: 'tsconfig.json', }) -const { MockServer } = require('./test/MockServer') + +const { MockServerController } = require('./MockServerController') + /** @type {import('aegir').PartialOptions} */ module.exports = { @@ -20,19 +22,18 @@ module.exports = { bundlesizeMax: '44KB' }, test: { + cov: false, async before () { - - }, - async beforeEach () { - - // mockServer = new MockServer() - await mockServer.start() - }, - async afterEach () { - - await mockServer.stop() + return new MockServerController() }, - async after () { + /** + * + * @param {GlobalOptions & TestOptions} _ + * @param {MockServerController} controller + */ + async after (_, controller) { + console.log('test after:') + await controller.shutdown() } } diff --git a/test/MockServer.ts b/MockServer.ts similarity index 79% rename from test/MockServer.ts rename to MockServer.ts index 8de8951..3a20e1b 100644 --- a/test/MockServer.ts +++ b/MockServer.ts @@ -2,6 +2,8 @@ import { setup } from 'mock-ipfs-pinning-service' import type { Application } from 'express' import type { Server } from 'http' import portscanner from 'portscanner' +import cors from 'cors' + import('dotenvrc') export class MockServer { @@ -16,7 +18,7 @@ export class MockServer { public basePath: string = '' - constructor () { + constructor (private readonly config: Parameters[0] = { token: process.env.MOCK_PINNING_SERVER_SECRET }) { process.on('uncaughtException', MockServer.onEADDRINUSE) } @@ -31,19 +33,19 @@ export class MockServer { if (server == null) { process.exit(1) } - + const handler = this.cleanupSync.bind(this) // And you'll want to make sure you close the server when your process exits - process.on('beforeExit', this.cleanupSync) - process.on('SIGTERM', this.cleanupSync) - process.on('SIGINT', this.cleanupSync) - process.on('SIGHUP', this.cleanupSync) + process.on('beforeExit', handler) + process.on('SIGTERM', handler) + process.on('SIGINT', handler) + process.on('SIGHUP', handler) // To prevent duplicated cleanup, remove the process listeners on server close. server.on('close', () => { - process.off('beforeExit', this.cleanupSync) - process.off('SIGTERM', this.cleanupSync) - process.off('SIGINT', this.cleanupSync) - process.off('SIGHUP', this.cleanupSync) + process.off('beforeExit', handler) + process.off('SIGTERM', handler) + process.off('SIGINT', handler) + process.off('SIGHUP', handler) }) } @@ -59,6 +61,11 @@ export class MockServer { * Ensure the port set for this instance is not already in use by another MockServer */ private async getAvailablePort (): Promise { + // this.port = 3000 + + // this.setBasePath() + + // return this.port return await new Promise((resolve, reject) => portscanner.findAPortNotInUse(3000, 3099, '127.0.0.1', (error, port) => { if (error != null) { return reject(error) @@ -73,9 +80,12 @@ export class MockServer { if (this._service !== undefined) { return this._service } - this._service = await setup({ - token: process.env.MOCK_PINNING_SERVER_SECRET - }) + this._service = await setup(this.config) + // this._service = await setup({ + // token: process.env.MOCK_PINNING_SERVER_SECRET, + // loglevel: 'debug' + // }) + this._service.use(cors()) // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion return this._service as Application @@ -94,7 +104,7 @@ export class MockServer { MockServer.error('service error', err) }) this._server = service.listen(await this.getAvailablePort(), () => { - MockServer.debug(`server running on port ${port}`) + MockServer.debug(`${Date.now()}: MockServer running on port ${this.port}`) }) return this._server @@ -109,10 +119,11 @@ export class MockServer { // Express server cleanup handling. private async cleanup (): Promise { const server = await this.server() + const port = this.port server.close((err) => { if ((err == null) || (err as Error & { code: string })?.code === 'ERR_SERVER_NOT_RUNNING') { // MockServer.portsInUse.remove(this.port) - MockServer.debug(`server stopped listening on port ${this.port}`) + MockServer.debug(`${Date.now()}: MockServer stopped listening on port ${port}`) delete this._server } if (err != null) { diff --git a/MockServerController.ts b/MockServerController.ts new file mode 100644 index 0000000..9f9f322 --- /dev/null +++ b/MockServerController.ts @@ -0,0 +1,138 @@ +#!/usr/bin/env ts-node + +/* eslint-disable @typescript-eslint/no-misused-promises */ +/* eslint-disable no-console */ +import express from 'express' +import { MockServer } from './MockServer' +import Router from 'express-promise-router' +import cors from 'cors' + +// const startMockServerController = async () => { +// /** +// * @type {MockServer} +// */ +// const mockServer = null + +// app.get('/stop', (req, res) => { +// res.send('Hello World!') +// }) + +// app.listen(port, () => { +// console.log(`Example app listening on port ${port}`) +// }) +// } + +// type ExpressGetHandler = Parameters>[1] + +class MockServerController { + private readonly mockServers: MockServer[] = [] + private readonly app = express() + private readonly router = Router() + + private readonly port = 3000 + server: import('http').Server + constructor () { + this.router.get<'/start', {port?: string}>('/start', async (req, res, next) => { + const { port } = req.params + + let mockServer: MockServer | null = null + try { + mockServer = await this.startIpfsPinningServer(port) + this.mockServers.push(mockServer) + + /** + * We need to return the basePath and accessToken so the client can call the correct mockServer + */ + res.send({ + success: true, + basePath: mockServer.basePath, + accessToken: process.env.MOCK_PINNING_SERVER_SECRET + }) + } catch (error) { + res.json({ success: false, error }) + next(error) + } + }) + + /** + * A client will request to shut down it's mockServer by port, which it should have received upon calling '/start' + */ + this.router.get<'/stop/:port', {port: string}>('/stop/:port', async (req, res, next) => { + const { port } = req.params + + const mockServer = this.mockServers.find((mockS) => mockS.basePath.includes(port)) + + if (mockServer != null) { + try { + await mockServer.stop() + res.json({ success: true }) + } catch (error) { + res.json({ success: false, error }) + next(error) + } + } else { + console.log('Could not get mockserver') + throw new Error(`MockServer at port ${port} could not be found`) + } + }) + + this.app.use(cors()) + this.app.use(this.router) + + this.server = this.app.listen(this.port, () => { + console.log(`MockServerController listening on port ${this.port}`) + }) + + // And you'll want to make sure you close the server when your process exits + process.on('beforeExit', this.shutdown) + process.on('SIGTERM', this.shutdown) + process.on('SIGINT', this.shutdown) + process.on('SIGHUP', this.shutdown) + + // To prevent duplicated cleanup, remove the process listeners on server close. + this.server.on('close', () => { + process.off('beforeExit', this.shutdown) + process.off('SIGTERM', this.shutdown) + process.off('SIGINT', this.shutdown) + process.off('SIGHUP', this.shutdown) + }) + } + + async shutdown () { + await new Promise((resolve, reject) => { + this.server.close((err) => { + if (err != null) { + console.error('Unexpected error when shutting down the MockServerController') + console.error(err) + } else { + console.log(`MockServerController stopped listening on port ${this.port}`) + } + resolve() + }) + }) + for await (const mockS of this.mockServers) { + try { + await mockS.stop() + } catch (err) { + console.error(`Unexpected error when attempting to shutdown mock server at ${mockS.basePath}`) + console.error(err) + } + } + } + + // async startMockServer (req: {params: { port: number}}, res: {basePath: string, accessToken: string}, next: unknown) { + + // } + + private async startIpfsPinningServer (port?: string) { + const mockServer = new MockServer({ + token: process.env.MOCK_PINNING_SERVER_SECRET + // loglevel: 'info' + }) + await mockServer.start(Number(port)) + + return mockServer + } +} + +export { MockServerController } diff --git a/package.json b/package.json index 2e4bcc7..a1bb8eb 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,7 @@ "build": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", "build:main": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", "build:docs": "aegir ts docs", - "test": "run-p test:*", + "test": "run-s test:*", "test:electron": "aegir test --target electron-main", "test:node": "aegir test --target node --cov && npx nyc report", "pregen": "openapi-generator-cli validate -i https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml", @@ -155,22 +155,28 @@ "gen:ts": "openapi-generator-cli generate --generator-key ts" }, "dependencies": { - "node-fetch": "^3.2.0", "patch-package": "^6.4.7" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.4.26", "@swc/core": "^1.2.144", "@swc/helpers": "^0.3.3", + "@types/cors": "^2.8.12", "@types/express": "^4.17.13", + "@types/express-promise-router": "^3.0.0", "@types/mocha": "^9.1.0", - "@types/node": "^17.0.16", + "@types/node": "^17.0.21", "@types/node-fetch": "^3.0.3", "@types/portscanner": "^2.1.1", "aegir": "^36.1.3", "check-aegir-project": "^1.0.3", + "cors": "^2.8.5", "dotenvrc": "^1.0.1", + "express": "^4.17.3", + "express-promise-router": "^4.1.1", + "fetch-ponyfill": "^7.1.0", "mock-ipfs-pinning-service": "^0.4.0", + "node-fetch": "^2.6.1", "npm-run-all": "^4.1.5", "openapi-typescript": "^5.1.1", "portscanner": "^2.2.0", diff --git a/test/browser.ts b/test/browser.ts index 7f0818c..f8383b7 100644 --- a/test/browser.ts +++ b/test/browser.ts @@ -1,19 +1,17 @@ /* eslint-disable no-console */ import clientTests from './isomorphic-tests/client' -import configurationTests from './isomorphic-tests/configuration' - - +// import configurationTests from './configuration.spec' +import fetchPonyfill from 'fetch-ponyfill' const setup = async () => { - return await new Promise((resolve, reject) => { - void resolve() - }) + return { + fetch: fetchPonyfill().fetch as GlobalFetch['fetch'] + } } // eslint-disable-next-line @typescript-eslint/no-misused-promises describe('browser', async (): Promise => { - console.log(fetch) - await configurationTests(setup) + // await configurationTests(setup) await clientTests(setup) }) diff --git a/test/configuration.spec.ts b/test/configuration.spec.ts new file mode 100644 index 0000000..a2b4587 --- /dev/null +++ b/test/configuration.spec.ts @@ -0,0 +1,13 @@ +/* eslint-env browser, node, mocha */ + +import { expect } from 'aegir/utils/chai' +import { Configuration, ConfigurationParameters } from '../src' + +// export default async (setup: () => Promise) => { +describe('Configuration', () => { + it('Can be instantiated', () => { + const configuration: ConfigurationParameters = {} + expect(() => new Configuration(configuration)).not.to.throw() + }) +}) +// } diff --git a/test/isomorphic-tests/client.ts b/test/isomorphic-tests/client.ts index b7e7d65..b3208b0 100644 --- a/test/isomorphic-tests/client.ts +++ b/test/isomorphic-tests/client.ts @@ -1,58 +1,72 @@ /* eslint-env browser, node, mocha */ import { expect } from 'aegir/utils/chai' -import { Configuration, PinsApi } from '../../src' +import { Configuration, PinsApi, Status } from '../../src' +import type { Pin } from '../../src' -export default async (setup: () => Promise) => { +export default async (setup: () => Promise<{fetch: GlobalFetch['fetch']}>) => { + const { fetch } = await setup() + let Config = new Configuration({ + basePath: `http://127.0.0.1:${process.env.MOCK_PINNING_SERVER_PORT ?? '3000'}`, + fetchApi: fetch, + accessToken: process.env.MOCK_PINNING_SERVER_SECRET + }) describe('Client', () => { - const Config = new Configuration({ - basePath: `http://127.0.0.1:${process.env.MOCK_PINNING_SERVER_PORT ?? '3000'}`, - fetchApi: fetch as GlobalFetch['fetch'], - accessToken: process.env.MOCK_PINNING_SERVER_SECRET - }) - it('Can be instantiated', () => { expect(() => new PinsApi(Config)).not.to.throw() }) - // describe.skip('Operations', () => { - // let mockServer: MockServer - // beforeEach(async () => { - // mockServer = new MockServer() - // await mockServer.start() - // }) - - // afterEach(async () => { - // await mockServer.stop() - // }) - - // it('GET: Can get failed Pins', async () => { - // const Client = new PinsApi(getClientConfigForMockServer(mockServer)) - // const response = await Client.pinsGet({ limit: 1, status: new Set([Status.Failed]) }) - // expect(response).to.deep.eq({ count: 0, results: new Set() }) - // }) - - // it('GET: Can add a Pin successfully', async () => { - // const Client = new PinsApi(getClientConfigForMockServer(mockServer)) - // const pin: Pin = { - // cid: 'abc123', - // name: 'pinned-test1' - // } - // const response = await Client.pinsPost({ pin }) - // expect(response).to.deep.includes({ status: Status.Pinned }) - // expect(response.pin).to.deep.include({ ...pin }) - // }) - - // it('POST: Can handle a failed pinning', async () => { - // const Client = new PinsApi(getClientConfigForMockServer(mockServer)) - // const pin: Pin = { - // cid: 'abc123', - // name: 'failed-test2' - // } - // const response = await Client.pinsPost({ pin }) - // expect(response).to.deep.includes({ status: Status.Failed }) - // expect(response.pin).to.deep.include({ ...pin }) - // }) - // }) + describe('Operations', () => { + // let mockServer: MockServer + // let Config: Configuration + beforeEach(async () => { + const response = await fetch('http://localhost:3000/start') + const { basePath, accessToken } = await response.json() + Config = new Configuration({ + basePath, + accessToken, + fetchApi: fetch + }) + }) + + afterEach(async () => { + const [,,port] = Config.basePath.split(':') + const response = await fetch(`http://localhost:3000/stop/${port}`) + + const { success } = await response.json() + + if (success === false) { + throw new Error(`Unexpected error when attempting to stop the mockServer on port ${port}`) + } + }) + + it('GET: Can get failed Pins', async () => { + const Client = new PinsApi(Config) + const response = await Client.pinsGet({ limit: 1, status: new Set([Status.Failed]) }) + expect(response).to.deep.eq({ count: 0, results: new Set() }) + }) + + it('GET: Can add a Pin successfully', async () => { + const Client = new PinsApi(Config) + const pin: Pin = { + cid: 'abc123', + name: 'pinned-test1' + } + const response = await Client.pinsPost({ pin }) + expect(response).to.deep.includes({ status: Status.Pinned }) + expect(response.pin).to.deep.include({ ...pin }) + }) + + it('POST: Can handle a failed pinning', async () => { + const Client = new PinsApi(Config) + const pin: Pin = { + cid: 'abc123', + name: 'failed-test2' + } + const response = await Client.pinsPost({ pin }) + expect(response).to.deep.includes({ status: Status.Failed }) + expect(response.pin).to.deep.include({ ...pin }) + }) + }) }) } diff --git a/test/isomorphic-tests/configuration.ts b/test/isomorphic-tests/configuration.ts deleted file mode 100644 index 8bb0e5e..0000000 --- a/test/isomorphic-tests/configuration.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env browser, node, mocha */ - -import { expect } from 'aegir/utils/chai' -import { Configuration, ConfigurationParameters } from '../../src' - -export default async (setup: () => Promise) => { - describe('Configuration', () => { - it('Can be instantiated', () => { - const configuration: ConfigurationParameters = {} - expect(() => new Configuration(configuration)).not.to.throw() - }) - }) -} diff --git a/test/node-tests/index.ts b/test/node-tests/index.ts new file mode 100644 index 0000000..83b6c25 --- /dev/null +++ b/test/node-tests/index.ts @@ -0,0 +1 @@ +export * from './mockServerController' diff --git a/test/node-tests/mockServerController.ts b/test/node-tests/mockServerController.ts new file mode 100755 index 0000000..3a74518 --- /dev/null +++ b/test/node-tests/mockServerController.ts @@ -0,0 +1,41 @@ +import { MockServerController } from '../MockServerController' + +import fetchPonyfill from 'fetch-ponyfill' +import { expect } from 'aegir/utils/chai' + +const { fetch } = fetchPonyfill() + +export default async (setup: () => Promise) => { + describe.skip('MockServerController', () => { + it('can start and stop without errors', async () => { + expect(async () => { + const controller = new MockServerController() + await controller.shutdown() + }).not.to.throw() + }) + + it('Can start multiple mockServers', async () => { + const controller = new MockServerController() + const serverConfigs: Array<{basePath: string}> = [] + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for await (const _ of Array(5)) { + const response = await fetch('http://localhost:3000/start') + serverConfigs.push(await response.json()) + } + // it('Can shutdown those mockServers', async () => { + for await (const config of serverConfigs) { + const { basePath } = config + const [,, port] = basePath + + const response = await fetch(`http://localhost:3000/stop/${port}`) + + const { success } = await response.json() + expect(success).to.equal(true) + } + // }) + + await controller.shutdown() + }) + }) +} diff --git a/test/node.ts b/test/node.ts index 230ff61..4c91c87 100644 --- a/test/node.ts +++ b/test/node.ts @@ -1,18 +1,27 @@ /* eslint-disable no-console */ import clientTests from './isomorphic-tests/client' -import configurationTests from './isomorphic-tests/configuration' -import fetch from 'node-fetch' +// import configurationTests from './configuration.spec' +// import mockServerControllerTests from './node-tests' +import fetchPonyfill from 'fetch-ponyfill' const setup = async () => { - return await new Promise((resolve, reject) => { - void resolve() - }) + const { fetch } = fetchPonyfill() + + return { + fetch: fetch as GlobalFetch['fetch'] + } + // return await new Promise<{fetch: GlobalFetch['fetch']}>((resolve, reject) => { + // void resolve({ + // fetch: + // }) + // }) } + // eslint-disable-next-line @typescript-eslint/no-misused-promises describe('node', async (): Promise => { - console.log(fetch) - await configurationTests(setup) + // await mockServerControllerTests(setup) + // await configurationTests(setup) await clientTests(setup) }) diff --git a/tsconfig.json b/tsconfig.json index 83cc355..87f3d6c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,7 @@ "test/**/*.ts", "generated", "types/**/*.d.ts" - ], +, "MockServer.ts" ], "ts-node": { "transpileOnly": true, "files": true, From 7c2188777a4b99d667a8ccd0707e155801fe6e13 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 28 Feb 2022 14:24:39 -0800 Subject: [PATCH 04/19] feat: tests succeed in multiple environemnts --- .envrc | 2 +- CONTRIBUTING.md | 30 +++++++++++++ MockServer.ts | 5 +-- MockServerController.ts | 8 ++-- README.md | 40 ++++++++++-------- package.json | 5 ++- src/index.ts | 16 +++++++ test/browser-tests/.gitkeep | 0 test/browser.ts | 28 ++++++------- test/client.spec.ts | 74 +++++++++++++++++++++++++++++++++ test/isomorphic-tests/client.ts | 72 -------------------------------- test/node.ts | 54 ++++++++++++------------ 12 files changed, 194 insertions(+), 140 deletions(-) create mode 100644 CONTRIBUTING.md delete mode 100644 test/browser-tests/.gitkeep create mode 100644 test/client.spec.ts delete mode 100644 test/isomorphic-tests/client.ts diff --git a/.envrc b/.envrc index 86e673a..75e4876 100644 --- a/.envrc +++ b/.envrc @@ -3,4 +3,4 @@ use asdf export PATH=$(npm bin):${PATH} export MOCK_PINNING_SERVER_PORT=3000 export MOCK_PINNING_SERVER_SECRET=secret -export DEBUG=1 +export DEBUG=0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3146df3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,30 @@ +## @ipfs-shipyard/pinning-service-client@1.0.0 + +This generator creates TypeScript/JavaScript client that utilizes fetch-api. + +### Building + +To build and compile the typescript sources to javascript use: +``` +npm install +npm run build +``` + +### Publishing + +First build the package then run ```npm publish``` + +### Consuming + +navigate to the folder of your consuming project and run one of the following commands. + +_published:_ + +``` +npm install @ipfs-shipyard/pinning-service-client@0.0.0 --save +``` + +_unPublished (not recommended):_ + +``` +npm install PATH_TO_GENERATED_PACKAGE --save diff --git a/MockServer.ts b/MockServer.ts index 3a20e1b..c9ec759 100644 --- a/MockServer.ts +++ b/MockServer.ts @@ -125,8 +125,7 @@ export class MockServer { // MockServer.portsInUse.remove(this.port) MockServer.debug(`${Date.now()}: MockServer stopped listening on port ${port}`) delete this._server - } - if (err != null) { + } else if (err != null) { MockServer.error(err.name) MockServer.error(err.message) MockServer.error(err.stack) @@ -148,7 +147,7 @@ export class MockServer { } private static debug (...logObjects: unknown[]) { - if (process.env.DEBUG != null) { + if (process.env.DEBUG != null && Number(process.env.DEBUG) !== 0) { MockServer.log('debug', ...logObjects) } } diff --git a/MockServerController.ts b/MockServerController.ts index 9f9f322..856380c 100644 --- a/MockServerController.ts +++ b/MockServerController.ts @@ -91,14 +91,14 @@ class MockServerController { // To prevent duplicated cleanup, remove the process listeners on server close. this.server.on('close', () => { - process.off('beforeExit', this.shutdown) - process.off('SIGTERM', this.shutdown) - process.off('SIGINT', this.shutdown) - process.off('SIGHUP', this.shutdown) }) } async shutdown () { + process.off('beforeExit', this.shutdown) + process.off('SIGTERM', this.shutdown) + process.off('SIGINT', this.shutdown) + process.off('SIGHUP', this.shutdown) await new Promise((resolve, reject) => { this.server.close((err) => { if (err != null) { diff --git a/README.md b/README.md index 3146df3..d5d7d04 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,36 @@ ## @ipfs-shipyard/pinning-service-client@1.0.0 -This generator creates TypeScript/JavaScript client that utilizes fetch-api. +This client was generated using [openapi-generator](https://github.com/OpenAPITools/openapi-generator) from the [ipfs pinning services API spec](https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml). -### Building +You can see the commands used to generate the client in the `gen:fetch` npm script. -To build and compile the typescript sources to javascript use: -``` -npm install -npm run build -``` +### Usage -### Publishing +This client only has a programmatic API at the moment (no CLI). You use it like so: -First build the package then run ```npm publish``` +```ts -### Consuming +import { Configuration, PinsApi, Status } from '@ipfs-shipyard/pinning-service-client' +import type { PinsGetRequest, PinResults } from '@ipfs-shipyard/pinning-service-client' -navigate to the folder of your consuming project and run one of the following commands. +const config = new Configuration({ + basePath, // the URI for your pinning provider, e.g. `http://localhost:3000` + accessToken, // the secret token/key given to you by your pinning provider + // fetchApi: fetch, // You can pass your own fetchApi implementation, but we use fetch-ponyfill by default. +}) -_published:_ +const client = new PinsApi(config) -``` -npm install @ipfs-shipyard/pinning-service-client@0.0.0 --save -``` +(async () => { + // Get 10 failed Pins + const pinsGetOptions: PinsGetRequest = { + limit: 10, + status: Status.Failed + } + const {count, results}: PinResults = await client.pinsGet(pinsGetOptions) + + console.log(count, results) -_unPublished (not recommended):_ +})() ``` -npm install PATH_TO_GENERATED_PACKAGE --save diff --git a/package.json b/package.json index a1bb8eb..207de42 100644 --- a/package.json +++ b/package.json @@ -145,6 +145,8 @@ "build:main": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", "build:docs": "aegir ts docs", "test": "run-s test:*", + "test:browser": "aegir test --target browser", + "test:webworker": "aegir test --target webworker", "test:electron": "aegir test --target electron-main", "test:node": "aegir test --target node --cov && npx nyc report", "pregen": "openapi-generator-cli validate -i https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml", @@ -155,6 +157,7 @@ "gen:ts": "openapi-generator-cli generate --generator-key ts" }, "dependencies": { + "fetch-ponyfill": "^7.1.0", "patch-package": "^6.4.7" }, "devDependencies": { @@ -174,9 +177,7 @@ "dotenvrc": "^1.0.1", "express": "^4.17.3", "express-promise-router": "^4.1.1", - "fetch-ponyfill": "^7.1.0", "mock-ipfs-pinning-service": "^0.4.0", - "node-fetch": "^2.6.1", "npm-run-all": "^4.1.5", "openapi-typescript": "^5.1.1", "portscanner": "^2.2.0", diff --git a/src/index.ts b/src/index.ts index 1b587ff..76f16ec 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,17 @@ +import fetchPonyfill from 'fetch-ponyfill' +import { Configuration as GeneratedConfiguration, ConfigurationParameters } from '../generated/fetch/src/index' + +class Configuration extends GeneratedConfiguration { + constructor (options: ConfigurationParameters) { + /** + * Prevent the need for everyone to have to override the fetch API... + */ + if (options.fetchApi == null) { + options.fetchApi = fetchPonyfill().fetch + } + super(options) + } +} + export * from '../generated/fetch/src/index' +export { Configuration } diff --git a/test/browser-tests/.gitkeep b/test/browser-tests/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/test/browser.ts b/test/browser.ts index f8383b7..d30aecb 100644 --- a/test/browser.ts +++ b/test/browser.ts @@ -1,17 +1,17 @@ -/* eslint-disable no-console */ +// /* eslint-disable no-console */ -import clientTests from './isomorphic-tests/client' -// import configurationTests from './configuration.spec' -import fetchPonyfill from 'fetch-ponyfill' +// import clientTests from './isomorphic-tests/client' +// // import configurationTests from './configuration.spec' +// import fetchPonyfill from 'fetch-ponyfill' -const setup = async () => { - return { - fetch: fetchPonyfill().fetch as GlobalFetch['fetch'] - } -} +// const setup = async () => { +// return { +// fetch: fetchPonyfill().fetch as GlobalFetch['fetch'] +// } +// } -// eslint-disable-next-line @typescript-eslint/no-misused-promises -describe('browser', async (): Promise => { - // await configurationTests(setup) - await clientTests(setup) -}) +// // eslint-disable-next-line @typescript-eslint/no-misused-promises +// describe('browser', async (): Promise => { +// // await configurationTests(setup) +// await clientTests(setup) +// }) diff --git a/test/client.spec.ts b/test/client.spec.ts new file mode 100644 index 0000000..02baa27 --- /dev/null +++ b/test/client.spec.ts @@ -0,0 +1,74 @@ +/* eslint-env browser, node, mocha */ + +import { expect } from 'aegir/utils/chai' +import { Configuration, PinsApi, Status } from '../src' +import type { Pin } from '../src' +import fetchPonyfill from 'fetch-ponyfill' + +// export default async (setup: () => Promise<{fetch: GlobalFetch['fetch']}>) => { +const { fetch } = fetchPonyfill() + +let Config = new Configuration({ + basePath: `http://127.0.0.1:${process.env.MOCK_PINNING_SERVER_PORT ?? '3000'}`, + // fetchApi: fetch, + accessToken: process.env.MOCK_PINNING_SERVER_SECRET +}) +describe('Client', () => { + it('Can be instantiated', () => { + expect(() => new PinsApi(Config)).not.to.throw() + }) + + describe('Operations', () => { + // let mockServer: MockServer + // let Config: Configuration + beforeEach(async () => { + const response = await fetch('http://localhost:3000/start') + const { basePath, accessToken } = await response.json() + Config = new Configuration({ + basePath, + accessToken + // fetchApi: fetch + }) + }) + + afterEach(async () => { + const [,,port] = Config.basePath.split(':') + const response = await fetch(`http://localhost:3000/stop/${port}`) + + const { success } = await response.json() + + if (success === false) { + throw new Error(`Unexpected error when attempting to stop the mockServer on port ${port}`) + } + }) + + it('GET: Can get failed Pins', async () => { + const Client = new PinsApi(Config) + const response = await Client.pinsGet({ limit: 1, status: new Set([Status.Failed]) }) + expect(response).to.deep.eq({ count: 0, results: new Set() }) + }) + + it('GET: Can add a Pin successfully', async () => { + const Client = new PinsApi(Config) + const pin: Pin = { + cid: 'abc123', + name: 'pinned-test1' + } + const response = await Client.pinsPost({ pin }) + expect(response).to.deep.includes({ status: Status.Pinned }) + expect(response.pin).to.deep.include({ ...pin }) + }) + + it('POST: Can handle a failed pinning', async () => { + const Client = new PinsApi(Config) + const pin: Pin = { + cid: 'abc123', + name: 'failed-test2' + } + const response = await Client.pinsPost({ pin }) + expect(response).to.deep.includes({ status: Status.Failed }) + expect(response.pin).to.deep.include({ ...pin }) + }) + }) +}) +// } diff --git a/test/isomorphic-tests/client.ts b/test/isomorphic-tests/client.ts deleted file mode 100644 index b3208b0..0000000 --- a/test/isomorphic-tests/client.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* eslint-env browser, node, mocha */ - -import { expect } from 'aegir/utils/chai' -import { Configuration, PinsApi, Status } from '../../src' -import type { Pin } from '../../src' - -export default async (setup: () => Promise<{fetch: GlobalFetch['fetch']}>) => { - const { fetch } = await setup() - let Config = new Configuration({ - basePath: `http://127.0.0.1:${process.env.MOCK_PINNING_SERVER_PORT ?? '3000'}`, - fetchApi: fetch, - accessToken: process.env.MOCK_PINNING_SERVER_SECRET - }) - describe('Client', () => { - it('Can be instantiated', () => { - expect(() => new PinsApi(Config)).not.to.throw() - }) - - describe('Operations', () => { - // let mockServer: MockServer - // let Config: Configuration - beforeEach(async () => { - const response = await fetch('http://localhost:3000/start') - const { basePath, accessToken } = await response.json() - Config = new Configuration({ - basePath, - accessToken, - fetchApi: fetch - }) - }) - - afterEach(async () => { - const [,,port] = Config.basePath.split(':') - const response = await fetch(`http://localhost:3000/stop/${port}`) - - const { success } = await response.json() - - if (success === false) { - throw new Error(`Unexpected error when attempting to stop the mockServer on port ${port}`) - } - }) - - it('GET: Can get failed Pins', async () => { - const Client = new PinsApi(Config) - const response = await Client.pinsGet({ limit: 1, status: new Set([Status.Failed]) }) - expect(response).to.deep.eq({ count: 0, results: new Set() }) - }) - - it('GET: Can add a Pin successfully', async () => { - const Client = new PinsApi(Config) - const pin: Pin = { - cid: 'abc123', - name: 'pinned-test1' - } - const response = await Client.pinsPost({ pin }) - expect(response).to.deep.includes({ status: Status.Pinned }) - expect(response.pin).to.deep.include({ ...pin }) - }) - - it('POST: Can handle a failed pinning', async () => { - const Client = new PinsApi(Config) - const pin: Pin = { - cid: 'abc123', - name: 'failed-test2' - } - const response = await Client.pinsPost({ pin }) - expect(response).to.deep.includes({ status: Status.Failed }) - expect(response.pin).to.deep.include({ ...pin }) - }) - }) - }) -} diff --git a/test/node.ts b/test/node.ts index 4c91c87..45a8315 100644 --- a/test/node.ts +++ b/test/node.ts @@ -1,32 +1,32 @@ -/* eslint-disable no-console */ +// /* eslint-disable no-console */ -import clientTests from './isomorphic-tests/client' -// import configurationTests from './configuration.spec' -// import mockServerControllerTests from './node-tests' -import fetchPonyfill from 'fetch-ponyfill' +// import clientTests from './isomorphic-tests/client' +// // import configurationTests from './configuration.spec' +// // import mockServerControllerTests from './node-tests' +// import fetchPonyfill from 'fetch-ponyfill' -const setup = async () => { - const { fetch } = fetchPonyfill() +// const setup = async () => { +// const { fetch } = fetchPonyfill() - return { - fetch: fetch as GlobalFetch['fetch'] - } - // return await new Promise<{fetch: GlobalFetch['fetch']}>((resolve, reject) => { - // void resolve({ - // fetch: - // }) - // }) -} +// return { +// fetch: fetch as GlobalFetch['fetch'] +// } +// // return await new Promise<{fetch: GlobalFetch['fetch']}>((resolve, reject) => { +// // void resolve({ +// // fetch: +// // }) +// // }) +// } -// eslint-disable-next-line @typescript-eslint/no-misused-promises -describe('node', async (): Promise => { - // await mockServerControllerTests(setup) - // await configurationTests(setup) - await clientTests(setup) -}) - -// const getClientConfigForMockServer = (mockServer: MockServer) => new Configuration({ -// basePath: mockServer.basePath, -// fetchApi: fetch as GlobalFetch['fetch'], -// accessToken: process.env.MOCK_PINNING_SERVER_SECRET +// // eslint-disable-next-line @typescript-eslint/no-misused-promises +// describe('node', async (): Promise => { +// // await mockServerControllerTests(setup) +// // await configurationTests(setup) +// await clientTests(setup) // }) + +// // const getClientConfigForMockServer = (mockServer: MockServer) => new Configuration({ +// // basePath: mockServer.basePath, +// // fetchApi: fetch as GlobalFetch['fetch'], +// // accessToken: process.env.MOCK_PINNING_SERVER_SECRET +// // }) From 937ba7ab1957aaaa09f13a461d52c6cb0432746e Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 28 Feb 2022 16:04:53 -0800 Subject: [PATCH 05/19] cleaning up code --- .aegir.cjs | 2 +- MockServer.ts => test/MockServer.ts | 0 .../MockServerController.ts | 44 +++++++------------ 3 files changed, 17 insertions(+), 29 deletions(-) rename MockServer.ts => test/MockServer.ts (100%) rename MockServerController.ts => test/MockServerController.ts (79%) diff --git a/.aegir.cjs b/.aegir.cjs index 5183901..2537564 100644 --- a/.aegir.cjs +++ b/.aegir.cjs @@ -5,7 +5,7 @@ require('ts-node').register({ project: 'tsconfig.json', }) -const { MockServerController } = require('./MockServerController') +const { MockServerController } = require('./test/MockServerController') /** @type {import('aegir').PartialOptions} */ diff --git a/MockServer.ts b/test/MockServer.ts similarity index 100% rename from MockServer.ts rename to test/MockServer.ts diff --git a/MockServerController.ts b/test/MockServerController.ts similarity index 79% rename from MockServerController.ts rename to test/MockServerController.ts index 856380c..e7f5925 100644 --- a/MockServerController.ts +++ b/test/MockServerController.ts @@ -1,29 +1,11 @@ #!/usr/bin/env ts-node -/* eslint-disable @typescript-eslint/no-misused-promises */ /* eslint-disable no-console */ import express from 'express' import { MockServer } from './MockServer' import Router from 'express-promise-router' import cors from 'cors' -// const startMockServerController = async () => { -// /** -// * @type {MockServer} -// */ -// const mockServer = null - -// app.get('/stop', (req, res) => { -// res.send('Hello World!') -// }) - -// app.listen(port, () => { -// console.log(`Example app listening on port ${port}`) -// }) -// } - -// type ExpressGetHandler = Parameters>[1] - class MockServerController { private readonly mockServers: MockServer[] = [] private readonly app = express() @@ -32,7 +14,7 @@ class MockServerController { private readonly port = 3000 server: import('http').Server constructor () { - this.router.get<'/start', {port?: string}>('/start', async (req, res, next) => { + this.router.get<'/start', {port?: string}>('/start', async (req, res, next) => { // eslint-disable-line @typescript-eslint/no-misused-promises const { port } = req.params let mockServer: MockServer | null = null @@ -57,7 +39,7 @@ class MockServerController { /** * A client will request to shut down it's mockServer by port, which it should have received upon calling '/start' */ - this.router.get<'/stop/:port', {port: string}>('/stop/:port', async (req, res, next) => { + this.router.get<'/stop/:port', {port: string}>('/stop/:port', async (req, res, next) => { // eslint-disable-line @typescript-eslint/no-misused-promises const { port } = req.params const mockServer = this.mockServers.find((mockS) => mockS.basePath.includes(port)) @@ -84,21 +66,27 @@ class MockServerController { }) // And you'll want to make sure you close the server when your process exits - process.on('beforeExit', this.shutdown) - process.on('SIGTERM', this.shutdown) - process.on('SIGINT', this.shutdown) - process.on('SIGHUP', this.shutdown) + process.on('beforeExit', this.shutdownSync) + process.on('SIGTERM', this.shutdownSync) + process.on('SIGINT', this.shutdownSync) + process.on('SIGHUP', this.shutdownSync) // To prevent duplicated cleanup, remove the process listeners on server close. this.server.on('close', () => { }) } + private shutdownSync () { + this.shutdown().catch((err) => { + console.error(err) + }) + } + async shutdown () { - process.off('beforeExit', this.shutdown) - process.off('SIGTERM', this.shutdown) - process.off('SIGINT', this.shutdown) - process.off('SIGHUP', this.shutdown) + process.off('beforeExit', this.shutdownSync) + process.off('SIGTERM', this.shutdownSync) + process.off('SIGINT', this.shutdownSync) + process.off('SIGHUP', this.shutdownSync) await new Promise((resolve, reject) => { this.server.close((err) => { if (err != null) { From f46be5619f1d4d4dd297a77eee3d486f51cc4375 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 28 Feb 2022 16:52:23 -0800 Subject: [PATCH 06/19] feat: ready for release --- .envrc => .envrc-copy | 1 - .gitignore | 1 + npm-scripts/fix/gen.sh | 13 ++++- package.json | 3 +- test/MockServer.ts | 109 ++++++++++++++--------------------- test/MockServerController.ts | 33 +++++------ test/browser.ts | 17 ------ test/client.spec.ts | 3 +- test/logger.ts | 19 ++++++ test/node.ts | 32 ---------- 10 files changed, 91 insertions(+), 140 deletions(-) rename .envrc => .envrc-copy (72%) delete mode 100644 test/browser.ts create mode 100644 test/logger.ts delete mode 100644 test/node.ts diff --git a/.envrc b/.envrc-copy similarity index 72% rename from .envrc rename to .envrc-copy index 75e4876..85be14f 100644 --- a/.envrc +++ b/.envrc-copy @@ -1,6 +1,5 @@ use asdf export PATH=$(npm bin):${PATH} -export MOCK_PINNING_SERVER_PORT=3000 export MOCK_PINNING_SERVER_SECRET=secret export DEBUG=0 diff --git a/.gitignore b/.gitignore index 81c08c4..1da604b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ test/tsconfig.tsbuildinfo package-lock.json *.bak .swc +.envrc diff --git a/npm-scripts/fix/gen.sh b/npm-scripts/fix/gen.sh index aadf9b3..0bb41e5 100755 --- a/npm-scripts/fix/gen.sh +++ b/npm-scripts/fix/gen.sh @@ -5,6 +5,7 @@ main() { # local FILES # FILES=() local SED_BACKUPS=() + local SED_ERROR=0 # remove openapi-generator's package and tsconfig json files for PKG_JSON in generated/*/package.json; do @@ -24,14 +25,22 @@ main() { if test -e $FILE_PATH; then # Replace all occurrances of "<" with "<" # Replace all occurrances of ">" with ">" - sed -i .bak -e 's/<\;/\/g' $FILE_PATH + sed -i .bak -e 's/<\;/\/g' $FILE_PATH || SED_ERROR=1 SED_BACKUPS+=( $FILE_PATH.bak ) fi done done + echo -e "\$SED_ERROR: $SED_ERROR \n" + if ((SED_ERROR)); then + echo "Error when replacing text, not deleting the backup files, please investigate: ${SED_BACKUPS[@]}" + return 1 + else + rm ${SED_BACKUPS[@]} + fi - echo "SED_BACKUPS = ${SED_BACKUPS[@]}" + + # echo "SED_BACKUPS = ${SED_BACKUPS[@]}" # test build.. if build succeeds, remove backup file. } diff --git a/package.json b/package.json index 207de42..bb921a8 100644 --- a/package.json +++ b/package.json @@ -183,7 +183,8 @@ "portscanner": "^2.2.0", "regenerator-runtime": "^0.13.9", "ts-node": "^10.5.0", - "tsc-silent": "^1.2.1" + "tsc-silent": "^1.2.1", + "winston": "^3.6.0" }, "exports": { ".": { diff --git a/test/MockServer.ts b/test/MockServer.ts index c9ec759..d671183 100644 --- a/test/MockServer.ts +++ b/test/MockServer.ts @@ -3,19 +3,16 @@ import type { Application } from 'express' import type { Server } from 'http' import portscanner from 'portscanner' import cors from 'cors' +import { logger } from './logger' import('dotenvrc') export class MockServer { private _server: Server | undefined = undefined - private port = Number(process.env.MOCK_PINNING_SERVER_PORT ?? 3000) + private port: string = '3001' private _service: Application | undefined = undefined - /** - * This set helps us support parallel tests by not attempting to start up multiple MockServer's on the same port - */ - public basePath: string = '' constructor (private readonly config: Parameters[0] = { token: process.env.MOCK_PINNING_SERVER_SECRET }) { @@ -27,7 +24,7 @@ export class MockServer { try { server = await this.server(port) } catch (err) { - MockServer.error('start error', err) + logger.error('start error', err) } if (server == null) { @@ -53,26 +50,39 @@ export class MockServer { await this.cleanup() } - private setBasePath (): void { - this.basePath = `http://127.0.0.1:${this.port}` + private async server (port = this.port): Promise { + if (this._server !== undefined) { + return this._server + } + if (port != null && port !== this.port) { + this.port = port + this.setBasePath() + } else { + port = await this.getAvailablePort() + } + const service = await this.service() + + service.on('error', (err) => { + logger.error('service error', err) + }) + this._server = service.listen(port, () => { + logger.debug(`${Date.now()}: MockServer running on port ${port}`) + }) + + return this._server } /** * Ensure the port set for this instance is not already in use by another MockServer */ - private async getAvailablePort (): Promise { - // this.port = 3000 - - // this.setBasePath() - - // return this.port + private async getAvailablePort (): Promise { return await new Promise((resolve, reject) => portscanner.findAPortNotInUse(3000, 3099, '127.0.0.1', (error, port) => { if (error != null) { return reject(error) } - this.port = port + this.port = port.toString() this.setBasePath() - resolve(port) + resolve(this.port) })) } @@ -81,38 +91,22 @@ export class MockServer { return this._service } this._service = await setup(this.config) - // this._service = await setup({ - // token: process.env.MOCK_PINNING_SERVER_SECRET, - // loglevel: 'debug' - // }) + this._service.use(cors()) - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - return this._service as Application + return this._service } - private async server (port = this.port): Promise { - if (this._server !== undefined) { - return this._server - } - if (port !== this.port) { - this.port = port + private setBasePath (): void { + if (this.port == null) { + throw new Error('Attempted to set basePath before setting this.port.') } - const service = await this.service() - - service.on('error', (err) => { - MockServer.error('service error', err) - }) - this._server = service.listen(await this.getAvailablePort(), () => { - MockServer.debug(`${Date.now()}: MockServer running on port ${this.port}`) - }) - - return this._server + this.basePath = `http://127.0.0.1:${this.port}` } private cleanupSync (): void { void this.cleanup().then(() => { - MockServer.debug('cleaned up') + logger.debug('cleaned up') }) } @@ -123,43 +117,24 @@ export class MockServer { server.close((err) => { if ((err == null) || (err as Error & { code: string })?.code === 'ERR_SERVER_NOT_RUNNING') { // MockServer.portsInUse.remove(this.port) - MockServer.debug(`${Date.now()}: MockServer stopped listening on port ${port}`) + logger.debug(`${Date.now()}: MockServer stopped listening on port ${port}`) delete this._server } else if (err != null) { - MockServer.error(err.name) - MockServer.error(err.message) - MockServer.error(err.stack) + throw err } }) } private static onEADDRINUSE (err: Error & { code: string }) { if (err.code === 'EADDRINUSE') { - this.error('Unexpected conflict with port usage') + logger.error('Unexpected conflict with port usage') } else { - this.error('CAUGHT UNKNOWN ERROR') - this.error(err.name) - this.error(err.code) - this.error(err.message) - this.error(err.stack) - } - process.exit(233) - } - - private static debug (...logObjects: unknown[]) { - if (process.env.DEBUG != null && Number(process.env.DEBUG) !== 0) { - MockServer.log('debug', ...logObjects) + logger.error('CAUGHT UNKNOWN ERROR') + logger.error(err.name) + logger.error(err.code) + logger.error(err.message) + logger.error(err.stack) } - } - - private static error (...logObjects: unknown[]) { - if (process.env.DEBUG != null) { - MockServer.log('error', ...logObjects) - } - } - - private static log (type: keyof typeof console & 'log' | 'debug' | 'error' | 'warn' | 'info' | 'trace', ...logObjects: unknown[]) { - // eslint-disable-next-line no-console - console[type](...logObjects) + process.exit(1) } } diff --git a/test/MockServerController.ts b/test/MockServerController.ts index e7f5925..1544f20 100644 --- a/test/MockServerController.ts +++ b/test/MockServerController.ts @@ -1,11 +1,12 @@ -#!/usr/bin/env ts-node - -/* eslint-disable no-console */ import express from 'express' import { MockServer } from './MockServer' import Router from 'express-promise-router' import cors from 'cors' +import { logger } from './logger' +/** + * MockServerController stands up a server on port 3000 + */ class MockServerController { private readonly mockServers: MockServer[] = [] private readonly app = express() @@ -53,7 +54,7 @@ class MockServerController { next(error) } } else { - console.log('Could not get mockserver') + logger.error('Could not get mockserver') throw new Error(`MockServer at port ${port} could not be found`) } }) @@ -62,7 +63,7 @@ class MockServerController { this.app.use(this.router) this.server = this.app.listen(this.port, () => { - console.log(`MockServerController listening on port ${this.port}`) + logger.debug(`MockServerController listening on port ${this.port}`) }) // And you'll want to make sure you close the server when your process exits @@ -71,18 +72,19 @@ class MockServerController { process.on('SIGINT', this.shutdownSync) process.on('SIGHUP', this.shutdownSync) - // To prevent duplicated cleanup, remove the process listeners on server close. this.server.on('close', () => { + logger.debug(`MockServerController stopped listening on ${this.port}`) }) } private shutdownSync () { this.shutdown().catch((err) => { - console.error(err) + logger.error(err) }) } async shutdown () { + // To prevent duplicated cleanup, remove the process listeners on server close. process.off('beforeExit', this.shutdownSync) process.off('SIGTERM', this.shutdownSync) process.off('SIGINT', this.shutdownSync) @@ -90,10 +92,10 @@ class MockServerController { await new Promise((resolve, reject) => { this.server.close((err) => { if (err != null) { - console.error('Unexpected error when shutting down the MockServerController') - console.error(err) + logger.error('Unexpected error when shutting down the MockServerController') + logger.error(err) } else { - console.log(`MockServerController stopped listening on port ${this.port}`) + logger.debug(`MockServerController stopped listening on port ${this.port}`) } resolve() }) @@ -102,22 +104,17 @@ class MockServerController { try { await mockS.stop() } catch (err) { - console.error(`Unexpected error when attempting to shutdown mock server at ${mockS.basePath}`) - console.error(err) + logger.error(`Unexpected error when attempting to shutdown mock server at ${mockS.basePath}`) + logger.error(err) } } } - // async startMockServer (req: {params: { port: number}}, res: {basePath: string, accessToken: string}, next: unknown) { - - // } - private async startIpfsPinningServer (port?: string) { const mockServer = new MockServer({ token: process.env.MOCK_PINNING_SERVER_SECRET - // loglevel: 'info' }) - await mockServer.start(Number(port)) + await mockServer.start(port) return mockServer } diff --git a/test/browser.ts b/test/browser.ts deleted file mode 100644 index d30aecb..0000000 --- a/test/browser.ts +++ /dev/null @@ -1,17 +0,0 @@ -// /* eslint-disable no-console */ - -// import clientTests from './isomorphic-tests/client' -// // import configurationTests from './configuration.spec' -// import fetchPonyfill from 'fetch-ponyfill' - -// const setup = async () => { -// return { -// fetch: fetchPonyfill().fetch as GlobalFetch['fetch'] -// } -// } - -// // eslint-disable-next-line @typescript-eslint/no-misused-promises -// describe('browser', async (): Promise => { -// // await configurationTests(setup) -// await clientTests(setup) -// }) diff --git a/test/client.spec.ts b/test/client.spec.ts index 02baa27..d6c4fa3 100644 --- a/test/client.spec.ts +++ b/test/client.spec.ts @@ -5,11 +5,10 @@ import { Configuration, PinsApi, Status } from '../src' import type { Pin } from '../src' import fetchPonyfill from 'fetch-ponyfill' -// export default async (setup: () => Promise<{fetch: GlobalFetch['fetch']}>) => { const { fetch } = fetchPonyfill() let Config = new Configuration({ - basePath: `http://127.0.0.1:${process.env.MOCK_PINNING_SERVER_PORT ?? '3000'}`, + basePath: 'http://127.0.0.1:3000', // fetchApi: fetch, accessToken: process.env.MOCK_PINNING_SERVER_SECRET }) diff --git a/test/logger.ts b/test/logger.ts new file mode 100644 index 0000000..fc859b2 --- /dev/null +++ b/test/logger.ts @@ -0,0 +1,19 @@ +import winston from 'winston' + +const logLevel = process.env.LOG_LEVEL ?? 'error' + +const transports = { + console: new winston.transports.Console({ level: logLevel }) +} + +const logger = winston.createLogger({ + transports: [ + transports.console + ] +}) + +if (process.env.LOG_LEVEL == null) { + logger.silent = true +} + +export { logger } diff --git a/test/node.ts b/test/node.ts deleted file mode 100644 index 45a8315..0000000 --- a/test/node.ts +++ /dev/null @@ -1,32 +0,0 @@ -// /* eslint-disable no-console */ - -// import clientTests from './isomorphic-tests/client' -// // import configurationTests from './configuration.spec' -// // import mockServerControllerTests from './node-tests' -// import fetchPonyfill from 'fetch-ponyfill' - -// const setup = async () => { -// const { fetch } = fetchPonyfill() - -// return { -// fetch: fetch as GlobalFetch['fetch'] -// } -// // return await new Promise<{fetch: GlobalFetch['fetch']}>((resolve, reject) => { -// // void resolve({ -// // fetch: -// // }) -// // }) -// } - -// // eslint-disable-next-line @typescript-eslint/no-misused-promises -// describe('node', async (): Promise => { -// // await mockServerControllerTests(setup) -// // await configurationTests(setup) -// await clientTests(setup) -// }) - -// // const getClientConfigForMockServer = (mockServer: MockServer) => new Configuration({ -// // basePath: mockServer.basePath, -// // fetchApi: fetch as GlobalFetch['fetch'], -// // accessToken: process.env.MOCK_PINNING_SERVER_SECRET -// // }) From c48d3b6090d4f2b710f0adceeeba39852a4b43ec Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 28 Feb 2022 17:00:43 -0800 Subject: [PATCH 07/19] fix github action --- .github/workflows/test-and-release.yml | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-and-release.yml b/.github/workflows/test-and-release.yml index 8468485..35f4f5b 100644 --- a/.github/workflows/test-and-release.yml +++ b/.github/workflows/test-and-release.yml @@ -21,7 +21,7 @@ jobs: - name: Run tests run: | npm config set script-shell bash - npm run test:ci + npm run ci:test release: name: Release needs: test diff --git a/package.json b/package.json index bb921a8..0a42f95 100644 --- a/package.json +++ b/package.json @@ -131,6 +131,7 @@ ] }, "scripts": { + "ci:test": "run-s test:*", "dep-check": "aegir dep-check src/**/*.ts test/**/*.ts generated/**/*.ts", "fix": "run-s fix:*", "fix:gen": "./npm-scripts/fix/gen.sh", From 5ce2a5a89e05b79b6debb9ca0689eadd0c12e0f6 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Tue, 1 Mar 2022 15:21:28 +0100 Subject: [PATCH 08/19] fix(ci): lts node decrease noise, just test LTS for now --- .github/workflows/js-test-and-release.yml | 2 +- .github/workflows/test-and-release.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml index 93cf843..24380e4 100644 --- a/.github/workflows/js-test-and-release.yml +++ b/.github/workflows/js-test-and-release.yml @@ -26,7 +26,7 @@ jobs: strategy: matrix: os: [windows-latest, ubuntu-latest, macos-latest] - node: [16] + node: ['lts/*'] fail-fast: true steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/test-and-release.yml b/.github/workflows/test-and-release.yml index 35f4f5b..d4c475f 100644 --- a/.github/workflows/test-and-release.yml +++ b/.github/workflows/test-and-release.yml @@ -5,14 +5,14 @@ jobs: strategy: fail-fast: false matrix: - node: [14.x, 16.x] + node: ['lts/*'] os: [macos-latest, ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout Repository - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v2.5.1 + uses: actions/setup-node@v2 with: node-version: ${{ matrix.node }} - name: Install Dependencies @@ -29,13 +29,13 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/master' steps: - name: Checkout - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v2 with: fetch-depth: 0 - name: Setup Node.js - uses: actions/setup-node@v2.5.1 + uses: actions/setup-node@v2 with: - node-version: 14 + node-version: 'lts/*' - name: Install dependencies run: | npm install --no-progress --no-package-lock --no-save From 89f22ea59c2f08c16e80b33354aff0203b6e425c Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 1 Mar 2022 10:11:44 -0800 Subject: [PATCH 09/19] use deterministic pinning spec version --- openapitools.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openapitools.json b/openapitools.json index 3abec70..9f18f01 100644 --- a/openapitools.json +++ b/openapitools.json @@ -7,7 +7,7 @@ "storageDir": "", "generators": { "node": { - "inputSpec": "https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml", + "inputSpec": "https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/v1.0.0/ipfs-pinning-service.yaml", "strictSpec": true, "apiNameSuffix": "", "generatorName": "typescript-node", @@ -27,7 +27,7 @@ } }, "fetch": { - "inputSpec": "https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml", + "inputSpec": "https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/v1.0.0/ipfs-pinning-service.yaml", "strictSpec": true, "apiNameSuffix": "", "generatorName": "typescript-fetch", @@ -47,7 +47,7 @@ } }, "ts": { - "inputSpec": "https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml", + "inputSpec": "https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/v1.0.0/ipfs-pinning-service.yaml", "strictSpec": true, "apiNameSuffix": "", "generatorName": "typescript", diff --git a/package.json b/package.json index 0a42f95..a1239b5 100644 --- a/package.json +++ b/package.json @@ -150,7 +150,7 @@ "test:webworker": "aegir test --target webworker", "test:electron": "aegir test --target electron-main", "test:node": "aegir test --target node --cov && npx nyc report", - "pregen": "openapi-generator-cli validate -i https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml", + "pregen": "openapi-generator-cli validate -i https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/v1.0.0/ipfs-pinning-service.yaml", "gen": "run-p gen:fetch", "postgen": "run-s fix:gen", "gen:fetch": "openapi-generator-cli generate --generator-key fetch", From bdd35e06fd2fc8582f910e45ccd14651d723593f Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 1 Mar 2022 10:11:54 -0800 Subject: [PATCH 10/19] remove unused packages --- package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.json b/package.json index a1239b5..213c82f 100644 --- a/package.json +++ b/package.json @@ -167,10 +167,8 @@ "@swc/helpers": "^0.3.3", "@types/cors": "^2.8.12", "@types/express": "^4.17.13", - "@types/express-promise-router": "^3.0.0", "@types/mocha": "^9.1.0", "@types/node": "^17.0.21", - "@types/node-fetch": "^3.0.3", "@types/portscanner": "^2.1.1", "aegir": "^36.1.3", "check-aegir-project": "^1.0.3", From 8474f84bbc2a6af71d4798d1108fe44a60ec71d0 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Wed, 2 Mar 2022 18:41:45 -0800 Subject: [PATCH 11/19] trying to fix package consumption --- generated/fetch/src/apis/PinsApi.ts | 6 +++--- generated/fetch/src/models/Failure.ts | 2 +- generated/fetch/src/models/FailureError.ts | 2 +- generated/fetch/src/models/Pin.ts | 2 +- generated/fetch/src/models/PinResults.ts | 2 +- generated/fetch/src/models/PinStatus.ts | 2 +- generated/fetch/src/models/Status.ts | 2 +- generated/fetch/src/models/TextMatchingStrategy.ts | 2 +- generated/fetch/src/runtime.ts | 2 +- package.json | 3 ++- tsconfig.json | 5 +++-- 11 files changed, 16 insertions(+), 14 deletions(-) diff --git a/generated/fetch/src/apis/PinsApi.ts b/generated/fetch/src/apis/PinsApi.ts index 0a2f74a..f484e68 100644 --- a/generated/fetch/src/apis/PinsApi.ts +++ b/generated/fetch/src/apis/PinsApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * IPFS Pinning Service API - * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications > **Note**: while ready for implementation, this spec is still a work in progress! 🏗️ **Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec).** # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables filtering pins per app via `?meta={\"app_id\":}` - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) Note that it is OK for a client to omit or ignore these optional attributes; doing so should not impact the basic pinning functionality. ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. * * The version of the OpenAPI document: 1.0.0 * @@ -75,12 +75,12 @@ export interface PinsApiInterface { * @summary List pin objects * @param {Set} [cid] Return pin objects responsible for pinning the specified CID(s); be aware that using longer hash functions introduces further constraints on the number of CIDs that will fit under the limit of 2000 characters per URL in browser contexts * @param {string} [name] Return pin objects with specified name (by default a case-sensitive, exact match) - * @param {TextMatchingStrategy} [match] Customize the text matching strategy applied when the name filter is present; exact (the default) is a case-sensitive exact match, partial matches anywhere in the name, iexact and ipartial are case-insensitive versions of the exact and partial strategies + * @param {TextMatchingStrategy} [match] Customize the text matching strategy applied when name filter is present * @param {Set} [status] Return pin objects for pins with the specified status * @param {Date} [before] Return results created (queued) before provided timestamp * @param {Date} [after] Return results created (queued) after provided timestamp * @param {number} [limit] Max records to return - * @param {{ [key: string]: string; }} [meta] Return pin objects that match specified metadata keys passed as a string representation of a JSON object; when implementing a client library, make sure the parameter is URL-encoded to ensure safe transport + * @param {{ [key: string]: string; }} [meta] Return pin objects that match specified metadata * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof PinsApiInterface diff --git a/generated/fetch/src/models/Failure.ts b/generated/fetch/src/models/Failure.ts index e2f9961..aed6fcc 100644 --- a/generated/fetch/src/models/Failure.ts +++ b/generated/fetch/src/models/Failure.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * IPFS Pinning Service API - * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications > **Note**: while ready for implementation, this spec is still a work in progress! 🏗️ **Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec).** # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables filtering pins per app via `?meta={\"app_id\":}` - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) Note that it is OK for a client to omit or ignore these optional attributes; doing so should not impact the basic pinning functionality. ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. * * The version of the OpenAPI document: 1.0.0 * diff --git a/generated/fetch/src/models/FailureError.ts b/generated/fetch/src/models/FailureError.ts index 702b151..78a6351 100644 --- a/generated/fetch/src/models/FailureError.ts +++ b/generated/fetch/src/models/FailureError.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * IPFS Pinning Service API - * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications > **Note**: while ready for implementation, this spec is still a work in progress! 🏗️ **Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec).** # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables filtering pins per app via `?meta={\"app_id\":}` - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) Note that it is OK for a client to omit or ignore these optional attributes; doing so should not impact the basic pinning functionality. ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. * * The version of the OpenAPI document: 1.0.0 * diff --git a/generated/fetch/src/models/Pin.ts b/generated/fetch/src/models/Pin.ts index 682c980..a0db4cb 100644 --- a/generated/fetch/src/models/Pin.ts +++ b/generated/fetch/src/models/Pin.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * IPFS Pinning Service API - * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications > **Note**: while ready for implementation, this spec is still a work in progress! 🏗️ **Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec).** # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables filtering pins per app via `?meta={\"app_id\":}` - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) Note that it is OK for a client to omit or ignore these optional attributes; doing so should not impact the basic pinning functionality. ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. * * The version of the OpenAPI document: 1.0.0 * diff --git a/generated/fetch/src/models/PinResults.ts b/generated/fetch/src/models/PinResults.ts index 1395348..4ccf4fb 100644 --- a/generated/fetch/src/models/PinResults.ts +++ b/generated/fetch/src/models/PinResults.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * IPFS Pinning Service API - * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications > **Note**: while ready for implementation, this spec is still a work in progress! 🏗️ **Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec).** # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables filtering pins per app via `?meta={\"app_id\":}` - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) Note that it is OK for a client to omit or ignore these optional attributes; doing so should not impact the basic pinning functionality. ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. * * The version of the OpenAPI document: 1.0.0 * diff --git a/generated/fetch/src/models/PinStatus.ts b/generated/fetch/src/models/PinStatus.ts index 3ae5364..896ad3f 100644 --- a/generated/fetch/src/models/PinStatus.ts +++ b/generated/fetch/src/models/PinStatus.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * IPFS Pinning Service API - * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications > **Note**: while ready for implementation, this spec is still a work in progress! 🏗️ **Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec).** # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables filtering pins per app via `?meta={\"app_id\":}` - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) Note that it is OK for a client to omit or ignore these optional attributes; doing so should not impact the basic pinning functionality. ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. * * The version of the OpenAPI document: 1.0.0 * diff --git a/generated/fetch/src/models/Status.ts b/generated/fetch/src/models/Status.ts index 32d1ada..cd125a1 100644 --- a/generated/fetch/src/models/Status.ts +++ b/generated/fetch/src/models/Status.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * IPFS Pinning Service API - * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications > **Note**: while ready for implementation, this spec is still a work in progress! 🏗️ **Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec).** # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables filtering pins per app via `?meta={\"app_id\":}` - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) Note that it is OK for a client to omit or ignore these optional attributes; doing so should not impact the basic pinning functionality. ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. * * The version of the OpenAPI document: 1.0.0 * diff --git a/generated/fetch/src/models/TextMatchingStrategy.ts b/generated/fetch/src/models/TextMatchingStrategy.ts index eb6c76f..edbc042 100644 --- a/generated/fetch/src/models/TextMatchingStrategy.ts +++ b/generated/fetch/src/models/TextMatchingStrategy.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * IPFS Pinning Service API - * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications > **Note**: while ready for implementation, this spec is still a work in progress! 🏗️ **Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec).** # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables filtering pins per app via `?meta={\"app_id\":}` - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) Note that it is OK for a client to omit or ignore these optional attributes; doing so should not impact the basic pinning functionality. ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. * * The version of the OpenAPI document: 1.0.0 * diff --git a/generated/fetch/src/runtime.ts b/generated/fetch/src/runtime.ts index c7a1577..daf0911 100644 --- a/generated/fetch/src/runtime.ts +++ b/generated/fetch/src/runtime.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * IPFS Pinning Service API - * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications ### Document scope and intended audience The intended audience of this document is **IPFS developers** building pinning service clients or servers compatible with this OpenAPI spec. Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec). **IPFS users** should see the tutorial at [docs.ipfs.io/how-to/work-with-pinning-services](https://docs.ipfs.io/how-to/work-with-pinning-services/) instead. ### Related resources The latest version of this spec and additional resources can be found at: - Specification: https://github.com/ipfs/pinning-services-api-spec/raw/main/ipfs-pinning-service.yaml - Docs: https://ipfs.github.io/pinning-services-api-spec/ - Clients and services: https://github.com/ipfs/pinning-services-api-spec#adoption # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. This is an opt-in feature: It is OK for a client to omit or ignore these optional attributes, and doing so should not impact the basic pinning functionality. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables meta-filtering pins per app - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) ### Filtering based on metadata The contents of `Pin.meta` can be used as an advanced search filter for situations where searching by `name` and `cid` is not enough. Metadata key matching rule is `AND`: - lookup returns pins that have `meta` with all key-value pairs matching the passed values - pin metadata may have more keys, but only ones passed in the query are used for filtering The wire format for the `meta` when used as a query parameter is a [URL-escaped](https://en.wikipedia.org/wiki/Percent-encoding) stringified JSON object. A lookup example for pins that have a `meta` key-value pair `{\"app_id\":\"UUID\"}` is: - `GET /pins?meta=%7B%22app_id%22%3A%22UUID%22%7D` ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. + * ## About this spec The IPFS Pinning Service API is intended to be an implementation-agnostic API: - For use and implementation by pinning service providers - For use in client mode by IPFS nodes and GUI-based applications > **Note**: while ready for implementation, this spec is still a work in progress! 🏗️ **Your input and feedback are welcome and valuable as we develop this API spec. Please join the design discussion at [github.com/ipfs/pinning-services-api-spec](https://github.com/ipfs/pinning-services-api-spec).** # Schemas This section describes the most important object types and conventions. A full list of fields and schemas can be found in the `schemas` section of the [YAML file](https://github.com/ipfs/pinning-services-api-spec/blob/master/ipfs-pinning-service.yaml). ## Identifiers ### cid [Content Identifier (CID)](https://docs.ipfs.io/concepts/content-addressing/) points at the root of a DAG that is pinned recursively. ### requestid Unique identifier of a pin request. When a pin is created, the service responds with unique `requestid` that can be later used for pin removal. When the same `cid` is pinned again, a different `requestid` is returned to differentiate between those pin requests. Service implementation should use UUID, `hash(accessToken,Pin,PinStatus.created)`, or any other opaque identifier that provides equally strong protection against race conditions. ## Objects ### Pin object ![pin object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pin.png) The `Pin` object is a representation of a pin request. It includes the `cid` of data to be pinned, as well as optional metadata in `name`, `origins`, and `meta`. ### Pin status response ![pin status response object](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/pinstatus.png) The `PinStatus` object is a representation of the current state of a pinning operation. It includes the original `pin` object, along with the current `status` and globally unique `requestid` of the entire pinning request, which can be used for future status checks and management. Addresses in the `delegates` array are peers delegated by the pinning service for facilitating direct file transfers (more details in the provider hints section). Any additional vendor-specific information is returned in optional `info`. # The pin lifecycle ![pinning service objects and lifecycle](https://bafybeideck2fchyxna4wqwc2mo67yriokehw3yujboc5redjdaajrk2fjq.ipfs.dweb.link/lifecycle.png) ## Creating a new pin object The user sends a `Pin` object to `POST /pins` and receives a `PinStatus` response: - `requestid` in `PinStatus` is the identifier of the pin operation, which can can be used for checking status, and removing the pin in the future - `status` in `PinStatus` indicates the current state of a pin ## Checking status of in-progress pinning `status` (in `PinStatus`) may indicate a pending state (`queued` or `pinning`). This means the data behind `Pin.cid` was not found on the pinning service and is being fetched from the IPFS network at large, which may take time. In this case, the user can periodically check pinning progress via `GET /pins/{requestid}` until pinning is successful, or the user decides to remove the pending pin. ## Replacing an existing pin object The user can replace an existing pin object via `POST /pins/{requestid}`. This is a shortcut for removing a pin object identified by `requestid` and creating a new one in a single API call that protects against undesired garbage collection of blocks common to both pins. Useful when updating a pin representing a huge dataset where most of blocks did not change. The new pin object `requestid` is returned in the `PinStatus` response. The old pin object is deleted automatically. ## Removing a pin object A pin object can be removed via `DELETE /pins/{requestid}`. # Provider hints A pinning service will use the DHT and other discovery methods to locate pinned content; however, it is a good practice to provide additional provider hints to speed up the discovery phase and start the transfer immediately, especially if a client has the data in their own datastore or already knows of other providers. The most common scenario is a client putting its own IPFS node\'s multiaddrs in `Pin.origins`, and then attempt to connect to every multiaddr returned by a pinning service in `PinStatus.delegates` to initiate transfer. At the same time, a pinning service will try to connect to multiaddrs provided by the client in `Pin.origins`. This ensures data transfer starts immediately (without waiting for provider discovery over DHT), and mutual direct dial between a client and a service works around peer routing issues in restrictive network topologies, such as NATs, firewalls, etc. **NOTE:** Connections to multiaddrs in `origins` and `delegates` arrays should be attempted in best-effort fashion, and dial failure should not fail the pinning operation. When unable to act on explicit provider hints, DHT and other discovery methods should be used as a fallback by a pinning service. **NOTE:** All multiaddrs MUST end with `/p2p/{peerID}` and SHOULD be fully resolved and confirmed to be dialable from the public internet. Avoid sending addresses from local networks. # Custom metadata Pinning services are encouraged to add support for additional features by leveraging the optional `Pin.meta` and `PinStatus.info` fields. While these attributes can be application- or vendor-specific, we encourage the community at large to leverage these attributes as a sandbox to come up with conventions that could become part of future revisions of this API. ## Pin metadata String keys and values passed in `Pin.meta` are persisted with the pin object. Potential uses: - `Pin.meta[app_id]`: Attaching a unique identifier to pins created by an app enables filtering pins per app via `?meta={\"app_id\":}` - `Pin.meta[vendor_policy]`: Vendor-specific policy (for example: which region to use, how many copies to keep) Note that it is OK for a client to omit or ignore these optional attributes; doing so should not impact the basic pinning functionality. ## Pin status info Additional `PinStatus.info` can be returned by pinning service. Potential uses: - `PinStatus.info[status_details]`: more info about the current status (queue position, percentage of transferred data, summary of where data is stored, etc); when `PinStatus.status=failed`, it could provide a reason why a pin operation failed (e.g. lack of funds, DAG too big, etc.) - `PinStatus.info[dag_size]`: the size of pinned data, along with DAG overhead - `PinStatus.info[raw_size]`: the size of data without DAG overhead (eg. unixfs) - `PinStatus.info[pinned_until]`: if vendor supports time-bound pins, this could indicate when the pin will expire # Pagination and filtering Pin objects can be listed by executing `GET /pins` with optional parameters: - When no filters are provided, the endpoint will return a small batch of the 10 most recently created items, from the latest to the oldest. - The number of returned items can be adjusted with the `limit` parameter (implicit default is 10). - If the value in `PinResults.count` is bigger than the length of `PinResults.results`, the client can infer there are more results that can be queried. - To read more items, pass the `before` filter with the timestamp from `PinStatus.created` found in the oldest item in the current batch of results. Repeat to read all results. - Returned results can be fine-tuned by applying optional `after`, `cid`, `name`, `status`, or `meta` filters. > **Note**: pagination by the `created` timestamp requires each value to be globally unique. Any future considerations to add support for bulk creation must account for this. * * The version of the OpenAPI document: 1.0.0 * diff --git a/package.json b/package.json index 213c82f..39fbdc1 100644 --- a/package.json +++ b/package.json @@ -141,10 +141,11 @@ "lint:ts": "aegir ts -p check -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", "lint-TODO:project": "check-aegir-project # currently broken due to corrupting the repoUrl", "release": "aegir release", - "postinstall": "./npm-scripts/postinstall.sh", + "postinstall": "npm run gen && patch-package", "build": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", "build:main": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", "build:docs": "aegir ts docs", + "build:types": "aegir ts -p types -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", "test": "run-s test:*", "test:browser": "aegir test --target browser", "test:webworker": "aegir test --target webworker", diff --git a/tsconfig.json b/tsconfig.json index 87f3d6c..d804074 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "./node_modules/aegir/src/config/tsconfig.aegir.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist", "emitDeclarationOnly": false, @@ -7,7 +7,8 @@ "typeRoots": [ "./types", "./node_modules/@types" - ] + ], + "noEmitOnError": true }, "include": [ "src", From 0965f9b71d7b83dee4beefcecaa978c1a9717a32 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 14 Mar 2022 18:00:15 -0700 Subject: [PATCH 12/19] bug: fix build on windows removed shell scripts fixed manipulation of tsc with tsc-silent, and instead call tsc-silent directly for the generated source --- .aegir.cjs | 2 -- .gitignore | 3 ++ README.md | 2 +- npm-scripts/fix/gen.sh | 49 ---------------------------- npm-scripts/postinstall.sh | 10 ------ package.json | 15 +++++---- src/index.ts | 26 ++++++++++++--- tsconfig.generated.json | 30 +++++++++++++++++ tsconfig.json | 20 ++++++++---- types/global.d.ts | 4 --- types/mock-ipfs-pinning-service.d.ts | 4 +++ 11 files changed, 82 insertions(+), 83 deletions(-) delete mode 100755 npm-scripts/fix/gen.sh delete mode 100755 npm-scripts/postinstall.sh create mode 100644 tsconfig.generated.json create mode 100644 types/mock-ipfs-pinning-service.d.ts diff --git a/.aegir.cjs b/.aegir.cjs index 2537564..fc5d146 100644 --- a/.aegir.cjs +++ b/.aegir.cjs @@ -32,9 +32,7 @@ module.exports = { * @param {MockServerController} controller */ async after (_, controller) { - console.log('test after:') await controller.shutdown() - } } } diff --git a/.gitignore b/.gitignore index 1da604b..f24c437 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ package-lock.json *.bak .swc .envrc +.nyc_output +generated/fetch/package.json +generated/fetch/tsconfig.json diff --git a/README.md b/README.md index d5d7d04..459f2ac 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ const client = new PinsApi(config) // Get 10 failed Pins const pinsGetOptions: PinsGetRequest = { limit: 10, - status: Status.Failed + status: new Set([Status.Failed]) // requires a set, and not an array } const {count, results}: PinResults = await client.pinsGet(pinsGetOptions) diff --git a/npm-scripts/fix/gen.sh b/npm-scripts/fix/gen.sh deleted file mode 100755 index 0bb41e5..0000000 --- a/npm-scripts/fix/gen.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash - -main() { - # Get all generated files - # local FILES - # FILES=() - local SED_BACKUPS=() - local SED_ERROR=0 - - # remove openapi-generator's package and tsconfig json files - for PKG_JSON in generated/*/package.json; do - rm $PKG_JSON - done - for TSC_JSON in generated/*/tsconfig.json; do - rm $TSC_JSON - done - - for FILES_LIST in $(find generated/*/.openapi-generator/FILES); do - echo FILES_LIST = $FILES_LIST - for FILE in $(cat $FILES_LIST); do - local DIR=$(dirname $(dirname $FILES_LIST)) - local FILE_PATH="${DIR}/${FILE}" - echo "FILE=${FILE_PATH}" - - if test -e $FILE_PATH; then - # Replace all occurrances of "<" with "<" - # Replace all occurrances of ">" with ">" - sed -i .bak -e 's/<\;/\/g' $FILE_PATH || SED_ERROR=1 - SED_BACKUPS+=( $FILE_PATH.bak ) - fi - done - done - - echo -e "\$SED_ERROR: $SED_ERROR \n" - if ((SED_ERROR)); then - echo "Error when replacing text, not deleting the backup files, please investigate: ${SED_BACKUPS[@]}" - return 1 - else - rm ${SED_BACKUPS[@]} - fi - - - # echo "SED_BACKUPS = ${SED_BACKUPS[@]}" - # test build.. if build succeeds, remove backup file. - -} - - -main $@ diff --git a/npm-scripts/postinstall.sh b/npm-scripts/postinstall.sh deleted file mode 100755 index 0226048..0000000 --- a/npm-scripts/postinstall.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# Generate client code -npm run gen - -patch-package - -# Replace aegir's tsc with tsc-silent so we can ignore errors in generated code -mv node_modules/aegir/node_modules/typescript/bin/tsc node_modules/aegir/node_modules/typescript/bin/tsc-bak -ln -fs $(realpath --relative-to=node_modules/aegir/node_modules/typescript/bin $(npm bin)/tsc-silent) node_modules/aegir/node_modules/typescript/bin/tsc diff --git a/package.json b/package.json index 39fbdc1..a18b020 100644 --- a/package.json +++ b/package.json @@ -131,21 +131,22 @@ ] }, "scripts": { + "clean": "npx rimraf dist generated node_modules", "ci:test": "run-s test:*", "dep-check": "aegir dep-check src/**/*.ts test/**/*.ts generated/**/*.ts", "fix": "run-s fix:*", - "fix:gen": "./npm-scripts/fix/gen.sh", "fix:lint": "aegir lint --fix", "lint": "run-s lint:*", "lint:main": "aegir lint", - "lint:ts": "aegir ts -p check -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", + "lint:ts": "aegir ts -p check", "lint-TODO:project": "check-aegir-project # currently broken due to corrupting the repoUrl", "release": "aegir release", - "postinstall": "npm run gen && patch-package", - "build": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", - "build:main": "aegir build -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", + "postinstall": "run-s gen", + "build": "aegir build", + "build2": "tsc-silent -p tsconfig.generated.json --suppress 6133@generated 6192@generated --stats", + "build:main": "aegir build", "build:docs": "aegir ts docs", - "build:types": "aegir ts -p types -- -p tsconfig.json --suppress 6133@generated 6192@generated --stats", + "build:types": "aegir ts -p types", "test": "run-s test:*", "test:browser": "aegir test --target browser", "test:webworker": "aegir test --target webworker", @@ -153,7 +154,7 @@ "test:node": "aegir test --target node --cov && npx nyc report", "pregen": "openapi-generator-cli validate -i https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/v1.0.0/ipfs-pinning-service.yaml", "gen": "run-p gen:fetch", - "postgen": "run-s fix:gen", + "postgen": "tsc-silent -p tsconfig.generated.json --suppress 6133@generated 6192@generated --stats", "gen:fetch": "openapi-generator-cli generate --generator-key fetch", "gen:node": "openapi-generator-cli generate --generator-key node", "gen:ts": "openapi-generator-cli generate --generator-key ts" diff --git a/src/index.ts b/src/index.ts index 76f16ec..4c723e9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,11 @@ import fetchPonyfill from 'fetch-ponyfill' -import { Configuration as GeneratedConfiguration, ConfigurationParameters } from '../generated/fetch/src/index' +import { Configuration as GeneratedConfiguration } from '../generated/fetch/dist/src' +import type { ConfigurationParameters } from '../generated/fetch/dist/src' -class Configuration extends GeneratedConfiguration { +export * from '../generated/fetch/dist/src/apis' +export * from '../generated/fetch/dist/src/models' + +export class Configuration extends GeneratedConfiguration { constructor (options: ConfigurationParameters) { /** * Prevent the need for everyone to have to override the fetch API... @@ -13,5 +17,19 @@ class Configuration extends GeneratedConfiguration { } } -export * from '../generated/fetch/src/index' -export { Configuration } +export type { ConfigurationParameters } +export { + BASE_PATH, + BaseAPI, + BlobApiResponse, + COLLECTION_FORMATS, + // Configuration, // overwritten above + JSONApiResponse, + RequiredError, + TextApiResponse, + VoidApiResponse, + canConsumeForm, + exists, + mapValues, + querystring +} from '../generated/fetch/dist/src/runtime' diff --git a/tsconfig.generated.json b/tsconfig.generated.json new file mode 100644 index 0000000..7a1d882 --- /dev/null +++ b/tsconfig.generated.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "sourceRoot": "generated/fetch/src", + "outDir": "generated/fetch/dist", + "emitDeclarationOnly": false, + "module": "ES2020", + "target": "ES2020", + "typeRoots": [ + "./types", + "./node_modules/@types" + ], + "declaration": true, + "noEmitOnError": true, + "esModuleInterop": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "isolatedModules": false, + "rootDir": "generated/fetch", + "sourceMap": true, + "moduleResolution":"Node" + + }, + "include": [ + "generated/fetch/src", + "types/global.d.ts", + ], + "exclude": [ + "./generated/fetch/dist" + ] +} diff --git a/tsconfig.json b/tsconfig.json index d804074..6f2094a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,17 +6,25 @@ "module": "ES2020", "typeRoots": [ "./types", - "./node_modules/@types" + "./node_modules/@types", + "./generated/fetch/dist" ], - "noEmitOnError": true + "noEmitOnError": true, + "esModuleInterop": true, + "noUnusedLocals": false, + "noUnusedParameters": false }, "include": [ "src", - "generated", + "test", "test/**/*.ts", - "generated", - "types/**/*.d.ts" -, "MockServer.ts" ], + "types/**/*.d.ts", + "MockServer.ts", + "./generated/fetch/dist" + ], + "exclude": [ + "generated" + ], "ts-node": { "transpileOnly": true, "files": true, diff --git a/types/global.d.ts b/types/global.d.ts index 6335de6..95bbbe0 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -1,6 +1,2 @@ declare type GlobalFetch = WindowOrWorkerGlobalScope - -declare module 'mock-ipfs-pinning-service' { - export * from 'mock-ipfs-pinning-service/dist/index' -} diff --git a/types/mock-ipfs-pinning-service.d.ts b/types/mock-ipfs-pinning-service.d.ts new file mode 100644 index 0000000..3f2d0eb --- /dev/null +++ b/types/mock-ipfs-pinning-service.d.ts @@ -0,0 +1,4 @@ + +declare module 'mock-ipfs-pinning-service' { + export * from 'mock-ipfs-pinning-service/dist/index' +} From 8cdef23add0eddec551103038fc8042157914af7 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 15 Mar 2022 12:35:32 -0700 Subject: [PATCH 13/19] bug: Allow no .envrc file in CI environment Fixes https://github.com/ipfs-shipyard/js-pinning-service-http-client/runs/5546880251?check_suite_focus=true --- .aegir.cjs | 9 +++++++-- test/MockServer.ts | 8 +++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.aegir.cjs b/.aegir.cjs index fc5d146..99ae346 100644 --- a/.aegir.cjs +++ b/.aegir.cjs @@ -24,14 +24,19 @@ module.exports = { test: { cov: false, async before () { - return new MockServerController() + return { + env: { + MOCK_PINNING_SERVER_SECRET: 'ci', + }, + controller: new MockServerController(), + } }, /** * * @param {GlobalOptions & TestOptions} _ * @param {MockServerController} controller */ - async after (_, controller) { + async after (_, {controller}) { await controller.shutdown() } } diff --git a/test/MockServer.ts b/test/MockServer.ts index d671183..e820cd3 100644 --- a/test/MockServer.ts +++ b/test/MockServer.ts @@ -5,7 +5,13 @@ import portscanner from 'portscanner' import cors from 'cors' import { logger } from './logger' -import('dotenvrc') +try { + import('dotenvrc') +} catch (err) { + // no dotenvrc.. that's okay + // eslint-disable-next-line no-console + console.warn('No .envrc file found; assuming CI environment. If not: You should copy .envrc-copy and set your environment variables.') +} export class MockServer { private _server: Server | undefined = undefined From a1fe4d3bec396537cc9bfb1a565f07341fc9e483 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 15 Mar 2022 15:01:36 -0700 Subject: [PATCH 14/19] bug: fix github actions https://github.com/ipfs-shipyard/js-pinning-service-http-client/runs/5559857402?check_suite_focus=true --- .github/workflows/js-test-and-release.yml | 4 ++ .github/workflows/test-and-release.yml | 60 ----------------------- .github/workflows/typecheck.yml | 9 +++- package.json | 2 +- 4 files changed, 13 insertions(+), 62 deletions(-) delete mode 100644 .github/workflows/test-and-release.yml diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml index 24380e4..61a2bbd 100644 --- a/.github/workflows/js-test-and-release.yml +++ b/.github/workflows/js-test-and-release.yml @@ -17,6 +17,10 @@ jobs: with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master + - uses: actions/setup-java@v2 # https://github.com/actions/setup-java#basic + with: + distribution: 'temurin' + java-version: '17' - run: npm run --if-present lint - run: npm run --if-present dep-check diff --git a/.github/workflows/test-and-release.yml b/.github/workflows/test-and-release.yml deleted file mode 100644 index d4c475f..0000000 --- a/.github/workflows/test-and-release.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Test & Maybe Release -on: [push, pull_request] -jobs: - test: - strategy: - fail-fast: false - matrix: - node: ['lts/*'] - os: [macos-latest, ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node }} - - name: Install Dependencies - run: | - npm install --no-progress - - name: Run tests - run: | - npm config set script-shell bash - npm run ci:test - release: - name: Release - needs: test - runs-on: ubuntu-latest - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Setup Node.js - uses: actions/setup-node@v2 - with: - node-version: 'lts/*' - - name: Install dependencies - run: | - npm install --no-progress --no-package-lock --no-save - - name: Build - run: | - npm run build - - name: Install plugins - run: | - npm install \ - @semantic-release/commit-analyzer \ - conventional-changelog-conventionalcommits \ - @semantic-release/release-notes-generator \ - @semantic-release/npm \ - @semantic-release/github \ - @semantic-release/git \ - @semantic-release/changelog \ - --no-progress --no-package-lock --no-save - - name: Release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: npx semantic-release diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 961e39f..e3f94a6 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -21,9 +21,16 @@ jobs: uses: actions/setup-node@v2.5.1 with: node-version: ${{ matrix.node-version }} + - name: Use Java for openapi generator + uses: actions/setup-java@v2 # https://github.com/actions/setup-java#basic + with: + distribution: 'temurin' + java-version: '17' - name: Install dependencies run: npm install + - name: Generate client from openapi spec + run: npm run gen - name: Typecheck uses: gozala/typescript-error-reporter-action@v1.0.8 with: - project: test/tsconfig.json + project: tsconfig.json diff --git a/package.json b/package.json index a18b020..6e64ab4 100644 --- a/package.json +++ b/package.json @@ -161,7 +161,7 @@ }, "dependencies": { "fetch-ponyfill": "^7.1.0", - "patch-package": "^6.4.7" + "yargs": "^17.3.1" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.4.26", From ff538519011f75afe7848e2982e64be1f0afccfa Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 15 Mar 2022 17:18:36 -0700 Subject: [PATCH 15/19] github actions fix again --- .github/workflows/js-test-and-release.yml | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml index 61a2bbd..5dedfb6 100644 --- a/.github/workflows/js-test-and-release.yml +++ b/.github/workflows/js-test-and-release.yml @@ -17,13 +17,24 @@ jobs: with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master - - uses: actions/setup-java@v2 # https://github.com/actions/setup-java#basic - with: - distribution: 'temurin' - java-version: '17' + - run: npm run gen - run: npm run --if-present lint - run: npm run --if-present dep-check + cache-generated: + needs: check + runs-on: ubuntu-latest + steps: + - name: Cache generated files + uses: actions/cache@v2 + env: + cache-name: cache-generated-files + with: + path: generated + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('generated/**') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + test-node: needs: check runs-on: ${{ matrix.os }} @@ -135,7 +146,8 @@ jobs: flags: electron-renderer release: - needs: [test-node, test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer] + # needs: [test-node, test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer] + needs: [test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer] runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' # with #262 - 'refs/heads/${{{ github.default_branch }}}' steps: From c5b4f15286f0c48132d7c34ab2c8e987630a4e2b Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 15 Mar 2022 18:02:14 -0700 Subject: [PATCH 16/19] ugh --- .github/workflows/js-test-and-release.yml | 31 +++++------------------ 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml index 5dedfb6..60d8a7e 100644 --- a/.github/workflows/js-test-and-release.yml +++ b/.github/workflows/js-test-and-release.yml @@ -16,24 +16,13 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master + - name: Install dependencies + run: npm install - run: npm run gen - - run: npm run --if-present lint - - run: npm run --if-present dep-check - - cache-generated: - needs: check - runs-on: ubuntu-latest - steps: - - name: Cache generated files - uses: actions/cache@v2 - env: - cache-name: cache-generated-files - with: - path: generated - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('generated/**') }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- + - name: lint + run: npm run --if-present lint + - name: dependency check + run: npm run --if-present dep-check test-node: needs: check @@ -48,7 +37,6 @@ jobs: - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node }} - - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:node - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -63,7 +51,6 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:chrome - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -78,7 +65,6 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:chrome-webworker - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -93,7 +79,6 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:firefox - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -108,7 +93,6 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:firefox-webworker - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -123,7 +107,6 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master - run: npx xvfb-maybe npm run --if-present test:electron-main - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -138,7 +121,6 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master - run: npx xvfb-maybe npm run --if-present test:electron-renderer - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -157,7 +139,6 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* - - uses: ipfs/aegir/actions/cache-node-modules@master - uses: ipfs/aegir/actions/docker-login@master with: docker-token: ${{ secrets.DOCKER_TOKEN }} From fabe94b8b083ce4aa555d29f6ada96ed7cfc4d9d Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Tue, 15 Mar 2022 18:08:14 -0700 Subject: [PATCH 17/19] github action debugging is a pain --- .github/workflows/js-test-and-release.yml | 38 +++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml index 60d8a7e..ed07863 100644 --- a/.github/workflows/js-test-and-release.yml +++ b/.github/workflows/js-test-and-release.yml @@ -18,7 +18,8 @@ jobs: node-version: lts/* - name: Install dependencies run: npm install - - run: npm run gen + - name: Generate client files + run: npm run gen - name: lint run: npm run --if-present lint - name: dependency check @@ -37,6 +38,10 @@ jobs: - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node }} + - name: Install dependencies + run: npm install + - name: Generate client files + run: npm run gen - run: npm run --if-present test:node - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -51,6 +56,10 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* + - name: Install dependencies + run: npm install + - name: Generate client files + run: npm run gen - run: npm run --if-present test:chrome - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -65,6 +74,10 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* + - name: Install dependencies + run: npm install + - name: Generate client files + run: npm run gen - run: npm run --if-present test:chrome-webworker - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -79,6 +92,10 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* + - name: Install dependencies + run: npm install + - name: Generate client files + run: npm run gen - run: npm run --if-present test:firefox - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -93,6 +110,10 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* + - name: Install dependencies + run: npm install + - name: Generate client files + run: npm run gen - run: npm run --if-present test:firefox-webworker - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -107,6 +128,10 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* + - name: Install dependencies + run: npm install + - name: Generate client files + run: npm run gen - run: npx xvfb-maybe npm run --if-present test:electron-main - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -121,6 +146,10 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* + - name: Install dependencies + run: npm install + - name: Generate client files + run: npm run gen - run: npx xvfb-maybe npm run --if-present test:electron-renderer - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 with: @@ -128,8 +157,7 @@ jobs: flags: electron-renderer release: - # needs: [test-node, test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer] - needs: [test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer] + needs: [test-node, test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer] runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' # with #262 - 'refs/heads/${{{ github.default_branch }}}' steps: @@ -139,6 +167,10 @@ jobs: - uses: actions/setup-node@v2 with: node-version: lts/* + - name: Install dependencies + run: npm install + - name: Generate client files + run: npm run gen - uses: ipfs/aegir/actions/docker-login@master with: docker-token: ${{ secrets.DOCKER_TOKEN }} From e52cba50e53aee539c0bc60978375e5469e3874f Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Thu, 17 Mar 2022 15:41:11 +0100 Subject: [PATCH 18/19] chore: collapse generated files in diffs https://thoughtbot.com/blog/github-diff-supression --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0c0a3b9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +generated/** linguist-generated From a0ebdd6e61b43910b73313dd835e09d218f8541e Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Thu, 17 Mar 2022 15:58:04 +0100 Subject: [PATCH 19/19] docs(readme): license and npm install --- CONTRIBUTING.md | 31 +++++-------------------------- README.md | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3146df3..cf6e0f9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,30 +1,9 @@ -## @ipfs-shipyard/pinning-service-client@1.0.0 +# Contributing guidelines -This generator creates TypeScript/JavaScript client that utilizes fetch-api. +IPFS as a project, including js-ipfs and all of its modules, follows the [standard IPFS Community contributing guidelines](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md). -### Building +We also adhere to the [IPFS JavaScript Community contributing guidelines](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) which provide additional information of how to collaborate and contribute in the JavaScript implementation of IPFS. -To build and compile the typescript sources to javascript use: -``` -npm install -npm run build -``` +We appreciate your time and attention for going over these. Please open an issue on [ipfs/community](https://github.com/ipfs/community) if you have any question. -### Publishing - -First build the package then run ```npm publish``` - -### Consuming - -navigate to the folder of your consuming project and run one of the following commands. - -_published:_ - -``` -npm install @ipfs-shipyard/pinning-service-client@0.0.0 --save -``` - -_unPublished (not recommended):_ - -``` -npm install PATH_TO_GENERATED_PACKAGE --save +Thank you. diff --git a/README.md b/README.md index 459f2ac..dd2b440 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ -## @ipfs-shipyard/pinning-service-client@1.0.0 +## IPFS Pinning Service API Client for JS -This client was generated using [openapi-generator](https://github.com/OpenAPITools/openapi-generator) from the [ipfs pinning services API spec](https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/main/ipfs-pinning-service.yaml). +This client was generated using [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator) from the [IPFS Pinning Service API spec](https://ipfs.github.io/pinning-services-api-spec/). You can see the commands used to generate the client in the `gen:fetch` npm script. ### Usage +``` +npm install @ipfs-shipyard/pinning-service-client --save +``` + This client only has a programmatic API at the moment (no CLI). You use it like so: ```ts @@ -34,3 +38,32 @@ const client = new PinsApi(config) })() ``` + +## Developing + +### Building + +To build and compile the typescript sources to javascript use: +``` +npm install +npm run build +``` + +### Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md). + +### Publishing + +First build the package then run ```npm publish``` + +## License + +Licensed under either of + + * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) + * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions.