backd-js 0.1.14 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @typedef {object} ErrorDetail
3
+ * @property {string} path Field or parameter the problem is about.
4
+ * @property {string} reason What's wrong with it.
5
+ */
6
+ export type ErrorDetail = {
7
+ /**
8
+ * Field or parameter the problem is about.
9
+ */
10
+ path: string;
11
+ /**
12
+ * What's wrong with it.
13
+ */
14
+ reason: string;
15
+ };
16
+ /**
17
+ * An error answered by backd, or a network failure (status 0).
18
+ * `code` is stable and meant for programs; `message` is for humans.
19
+ */
20
+ export declare class BackdError extends Error {
21
+ /** @type {number} */
22
+ status: number;
23
+ /** @type {string} */
24
+ code: string;
25
+ /** @type {ErrorDetail[]} */
26
+ details: ErrorDetail[];
27
+ /** @type {string | undefined} */
28
+ requestId: string | undefined;
29
+ /**
30
+ * @param {object} init
31
+ * @param {number} init.status HTTP status; 0 for network failures.
32
+ * @param {string} init.code backd error code, e.g. "validation_error".
33
+ * @param {string} init.message
34
+ * @param {ErrorDetail[]} [init.details]
35
+ * @param {string} [init.requestId] The request ID, to match server logs.
36
+ * @param {unknown} [init.cause]
37
+ */
38
+ constructor({ status, code, message, details, requestId, cause }: {
39
+ status: number;
40
+ code: string;
41
+ message: string;
42
+ details?: ErrorDetail[];
43
+ requestId?: string;
44
+ cause?: unknown;
45
+ });
46
+ }
47
+ /** 400: invalid body, query or header (`validation_error`, `invalid_json`, `invalid_query`, `invalid_header`). */
48
+ export declare class ValidationError extends BackdError {
49
+ }
50
+ /** 401: missing, invalid or expired credentials, or a wrong email or password. */
51
+ export declare class AuthenticationError extends BackdError {
52
+ }
53
+ /** 403: the caller isn't allowed to do this. */
54
+ export declare class ForbiddenError extends BackdError {
55
+ }
56
+ /**
57
+ * Not an HTTP error: a sign-up in a realm that requires verified addresses
58
+ * answers `202`, because the account exists but there is no session. Thrown
59
+ * by `auth.signup()` so the code after it, which expects a session, doesn't run.
60
+ */
61
+ export declare class VerificationRequiredError extends BackdError {
62
+ }
63
+ /** 404: unknown realm, collection, document, user or session. */
64
+ export declare class NotFoundError extends BackdError {
65
+ }
66
+ /** 409: a unique value already exists (`conflict`, `email_taken`) or concurrent writes (`write_conflict`). */
67
+ export declare class ConflictError extends BackdError {
68
+ }
69
+ /** 412: `If-Match` didn't match the current version. */
70
+ export declare class VersionMismatchError extends BackdError {
71
+ }
72
+ /** 429 and 503: try again later; `retryAfter` is in milliseconds when the server said. */
73
+ export declare class RetryableError extends BackdError {
74
+ /** @type {number | undefined} */
75
+ retryAfter: number | undefined;
76
+ /**
77
+ * @param {ConstructorParameters<typeof BackdError>[0] & { retryAfter?: number }} init
78
+ */
79
+ constructor(init: ConstructorParameters<typeof BackdError>[0] & {
80
+ retryAfter?: number;
81
+ });
82
+ }
83
+ /** 0: the request didn't get an answer (network error, abort, timeout). */
84
+ export declare class NetworkError extends BackdError {
85
+ }
86
+ /**
87
+ * The `BackdError` subclass for a status, or the base class if there's
88
+ * no specific one for it. Used for real responses (`errorFromResponse`)
89
+ * and to reconstruct the same shape from an async job's stored result,
90
+ * which never went through an HTTP response of its own (roadmap F14).
91
+ * @param {number} status
92
+ * @returns {typeof BackdError}
93
+ */
94
+ export declare function errorClassFor(status: number): typeof BackdError;
95
+ /**
96
+ * Builds the error for a non-2xx response.
97
+ * @param {Response} res
98
+ * @returns {Promise<BackdError>}
99
+ */
100
+ export declare function errorFromResponse(res: Response): Promise<BackdError>;
101
+ /**
102
+ * Parses a Retry-After header (seconds or an HTTP date) into milliseconds.
103
+ * @param {string | null} value
104
+ * @returns {number | undefined}
105
+ */
106
+ export declare function parseRetryAfter(value: string | null): number | undefined;
@@ -0,0 +1,135 @@
1
+ export type Client = import('./client.js').Client;
2
+ export type RequestOptions = import('./client.js').RequestOptions;
3
+ export type ErrorDetail = import('./errors.js').ErrorDetail;
4
+ export type JobResult = {
5
+ /**
6
+ * `ok`, `function_error`, `timeout`, `memory`, `cpu`, `crash`, `output_too_large` or `bundle`.
7
+ */
8
+ status: string;
9
+ /**
10
+ * The function's output, when `status` is `ok`.
11
+ */
12
+ output?: unknown;
13
+ /**
14
+ * The status a `sync` call would have answered with; absent only when `status` is `ok`.
15
+ */
16
+ http_status?: number;
17
+ /**
18
+ * The function's own code (`function_error`) or one of backd's own; absent only when `status` is `ok`.
19
+ */
20
+ code?: string;
21
+ /**
22
+ * Absent only when `status` is `ok`.
23
+ */
24
+ message?: string;
25
+ details?: ErrorDetail[];
26
+ duration_ms: number;
27
+ };
28
+ export type JobData = {
29
+ id: string;
30
+ /**
31
+ * `<database>/<name>`.
32
+ */
33
+ function: string;
34
+ status: 'queued' | 'running' | 'done';
35
+ created_at: string;
36
+ /**
37
+ * How many times a worker has started it.
38
+ */
39
+ attempts?: number;
40
+ /**
41
+ * When a failed attempt will be retried (the function's `retry` policy); null otherwise.
42
+ */
43
+ next_attempt_at?: string | null;
44
+ result: JobResult | null;
45
+ };
46
+ /**
47
+ * @typedef {import('./client.js').Client} Client
48
+ * @typedef {import('./client.js').RequestOptions} RequestOptions
49
+ * @typedef {import('./errors.js').ErrorDetail} ErrorDetail
50
+ */
51
+ /**
52
+ * How an `async` job ended, once `status` is `'done'` — the same shape
53
+ * a `sync` call's own answer would carry for the same outcome.
54
+ * @typedef {object} JobResult
55
+ * @property {string} status `ok`, `function_error`, `timeout`, `memory`, `cpu`, `crash`, `output_too_large` or `bundle`.
56
+ * @property {unknown} [output] The function's output, when `status` is `ok`.
57
+ * @property {number} [http_status] The status a `sync` call would have answered with; absent only when `status` is `ok`.
58
+ * @property {string} [code] The function's own code (`function_error`) or one of backd's own; absent only when `status` is `ok`.
59
+ * @property {string} [message] Absent only when `status` is `ok`.
60
+ * @property {ErrorDetail[]} [details]
61
+ * @property {number} duration_ms
62
+ */
63
+ /**
64
+ * A job as the API returns it: `POST .../_func/{name}`'s `202` body, or `GET .../_jobs/{id}`.
65
+ * @typedef {object} JobData
66
+ * @property {string} id
67
+ * @property {string} function `<database>/<name>`.
68
+ * @property {'queued' | 'running' | 'done'} status
69
+ * @property {string} created_at
70
+ * @property {number} [attempts] How many times a worker has started it.
71
+ * @property {string | null} [next_attempt_at] When a failed attempt will be retried (the function's `retry` policy); null otherwise.
72
+ * @property {JobResult | null} result
73
+ */
74
+ /**
75
+ * `job.wait()` gave up before the job finished (roadmap F14) — the job
76
+ * itself is unaffected and still running; call `wait()` again, or poll
77
+ * with `status()`, whenever you like.
78
+ */
79
+ export declare class JobTimeoutError extends Error {
80
+ /** @readonly */
81
+ jobId: string;
82
+ /** @param {string} jobId */
83
+ constructor(jobId: string);
84
+ }
85
+ /**
86
+ * A handle to an `async` function's job (roadmap F11, this client since
87
+ * F14): `db.fn(name, input)` returns one instead of the output directly
88
+ * when the function is `async`. Poll with `status()`, or use `wait()`
89
+ * to get the output the same way a `sync` call's return value works.
90
+ */
91
+ export declare class Job {
92
+ /** @internal */
93
+ client: import("./client.js").Client;
94
+ /** @internal */
95
+ database: string;
96
+ /** @readonly */
97
+ id: string;
98
+ /** @readonly The function this job runs, as `<database>/<name>`. */
99
+ function: string;
100
+ /** @internal */
101
+ data: JobData;
102
+ /**
103
+ * @param {Client} client
104
+ * @param {string} database
105
+ * @param {JobData} data
106
+ */
107
+ constructor(client: Client, database: string, data: JobData);
108
+ /** The job's data as of the last `status()` or `wait()` call, or when it was created. */
109
+ get raw(): JobData;
110
+ /**
111
+ * Polls the job's current status.
112
+ * @param {RequestOptions} [opts]
113
+ * @returns {Promise<'queued' | 'running' | 'done'>}
114
+ */
115
+ status(opts?: RequestOptions): Promise<'queued' | 'running' | 'done'>;
116
+ /**
117
+ * Polls until the job is done, then returns its output — the same
118
+ * value a `sync` call would have returned — or throws a `BackdError`
119
+ * matching what a `sync` call would have thrown for the same outcome
120
+ * (the function's own `code`, when it threw `ctx.error(...)`).
121
+ * @param {RequestOptions & { pollIntervalMs?: number, timeoutMs?: number }} [opts]
122
+ * `pollIntervalMs` default 500. Without `timeoutMs`, waits indefinitely.
123
+ * @returns {Promise<unknown>}
124
+ */
125
+ wait(opts?: RequestOptions & {
126
+ pollIntervalMs?: number;
127
+ timeoutMs?: number;
128
+ }): Promise<unknown>;
129
+ /**
130
+ * @internal
131
+ * @param {RequestOptions} [opts]
132
+ * @returns {Promise<JobData>}
133
+ */
134
+ _fetch(opts?: RequestOptions): Promise<JobData>;
135
+ }
@@ -0,0 +1,59 @@
1
+ export { createClient, Client } from './client.js';
2
+ export { Auth } from './auth.js';
3
+ export { Database, Collection, ifMatchValue } from './data.js';
4
+ export { Admin } from './admin.js';
5
+ export { Job, JobTimeoutError } from './functions.js';
6
+ export { BackdError, ValidationError, AuthenticationError, ForbiddenError, NotFoundError, ConflictError, VersionMismatchError, RetryableError, NetworkError, VerificationRequiredError, } from './errors.js';
7
+ export { memoryStorage, localStorageStorage } from './storage.js';
8
+ export type ClientOptions = import('./client.js').ClientOptions;
9
+ export type RequestOptions = import('./client.js').RequestOptions;
10
+ export type RetryOptions = import('./client.js').RetryOptions;
11
+ export type TokenStorage = import('./storage.js').TokenStorage;
12
+ export type User = import('./auth.js').User;
13
+ export type Session = import('./auth.js').Session;
14
+ export type SessionInfo = import('./auth.js').SessionInfo;
15
+ export type AuthEvent = import('./auth.js').AuthEvent;
16
+ export type ErrorDetail = import('./errors.js').ErrorDetail;
17
+ export type Meta = import('./data.js').Meta;
18
+ export type ListParams = import('./data.js').ListParams;
19
+ export type WriteOptions = import('./data.js').WriteOptions;
20
+ export type AdminUser = import('./admin.js').AdminUser;
21
+ export type UserPage = import('./admin.js').UserPage;
22
+ export type Invitation = import('./admin.js').Invitation;
23
+ export type NewInvitation = import('./admin.js').NewInvitation;
24
+ export type SentInvitation = import('./admin.js').SentInvitation;
25
+ export type OwnedReport = import('./admin.js').OwnedReport;
26
+ export type JobData = import('./functions.js').JobData;
27
+ export type JobResult = import('./functions.js').JobResult;
28
+ export type Doc<T extends object = Record<string, any>> = import('./data.js').Doc<T>;
29
+ export type Page<T extends object = Record<string, any>> = import('./data.js').Page<T>;
30
+ /**
31
+ * @typedef {import('./client.js').ClientOptions} ClientOptions
32
+ * @typedef {import('./client.js').RequestOptions} RequestOptions
33
+ * @typedef {import('./client.js').RetryOptions} RetryOptions
34
+ * @typedef {import('./storage.js').TokenStorage} TokenStorage
35
+ * @typedef {import('./auth.js').User} User
36
+ * @typedef {import('./auth.js').Session} Session
37
+ * @typedef {import('./auth.js').SessionInfo} SessionInfo
38
+ * @typedef {import('./auth.js').AuthEvent} AuthEvent
39
+ * @typedef {import('./errors.js').ErrorDetail} ErrorDetail
40
+ * @typedef {import('./data.js').Meta} Meta
41
+ * @typedef {import('./data.js').ListParams} ListParams
42
+ * @typedef {import('./data.js').WriteOptions} WriteOptions
43
+ * @typedef {import('./admin.js').AdminUser} AdminUser
44
+ * @typedef {import('./admin.js').UserPage} UserPage
45
+ * @typedef {import('./admin.js').Invitation} Invitation
46
+ * @typedef {import('./admin.js').NewInvitation} NewInvitation
47
+ * @typedef {import('./admin.js').SentInvitation} SentInvitation
48
+ * @typedef {import('./admin.js').OwnedReport} OwnedReport
49
+ * @typedef {import('./functions.js').JobData} JobData
50
+ * @typedef {import('./functions.js').JobResult} JobResult
51
+ */
52
+ /**
53
+ * @template {object} [T=Record<string, any>]
54
+ * @typedef {import('./data.js').Doc<T>} Doc
55
+ */
56
+ /**
57
+ * @template {object} [T=Record<string, any>]
58
+ * @typedef {import('./data.js').Page<T>} Page
59
+ */
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Where the client keeps the session token. Methods may be async.
3
+ * @typedef {object} TokenStorage
4
+ * @property {() => string | null | undefined | Promise<string | null | undefined>} get
5
+ * @property {(token: string) => void | Promise<void>} set
6
+ * @property {() => void | Promise<void>} remove
7
+ */
8
+ export type TokenStorage = {
9
+ get: () => string | null | undefined | Promise<string | null | undefined>;
10
+ set: (token: string) => void | Promise<void>;
11
+ remove: () => void | Promise<void>;
12
+ };
13
+ /**
14
+ * Keeps the token in memory: it is lost on reload, and scripts on the page
15
+ * can't read it from storage. The default.
16
+ * @returns {TokenStorage}
17
+ */
18
+ export declare function memoryStorage(): TokenStorage;
19
+ /**
20
+ * Keeps the token in `localStorage`, so sessions survive reloads. Any
21
+ * script running on the page (including injected ones) can read it:
22
+ * protect the app against cross-site scripting.
23
+ * @param {string} [key] Storage key; defaults to "backd.session".
24
+ * @returns {TokenStorage}
25
+ */
26
+ export declare function localStorageStorage(key?: string): TokenStorage;
package/.babelrc DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "presets": ["env"],
3
- "plugins": ["babel-plugin-add-module-exports"]
4
- }
package/.editorconfig DELETED
@@ -1,12 +0,0 @@
1
- root = true
2
-
3
- [*]
4
- indent_style = space
5
- indent_size = 2
6
- end_of_line = LF
7
- charset = utf-8
8
- trim_trailing_whitespace = true
9
- insert_final_newline = true
10
-
11
- [*.md]
12
- trim_trailing_whitespace = false
package/.eslintrc.js DELETED
@@ -1,28 +0,0 @@
1
- // https://eslint.org/docs/user-guide/configuring
2
-
3
- module.exports = {
4
- root: true,
5
- parser: 'babel-eslint',
6
- parserOptions: {
7
- sourceType: 'module'
8
- },
9
- env: {
10
- browser: true,
11
- es6: true,
12
- node: true
13
- },
14
- // https://github.com/standard/standard/blob/master/docs/RULES-en.md
15
- extends: 'standard',
16
- // required to lint *.vue files
17
- plugins: [
18
- ],
19
- // add your custom rules here
20
- rules: {
21
- // allow async-await
22
- 'generator-star-spacing': 'off',
23
- // allow debugger during development
24
- 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
25
- 'padded-blocks': 'off',
26
- 'no-unused-expressions': 'off'
27
- }
28
- }
package/.npmignore DELETED
@@ -1,9 +0,0 @@
1
- .DS_Store
2
- node_modules
3
- .docker
4
- .git
5
- docker-compose.yml
6
- src
7
- test
8
- publish.sh
9
- webpack.config.js
package/.nvmrc DELETED
@@ -1 +0,0 @@
1
- v6.10
package/.travis.yml DELETED
@@ -1,33 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - "node"
4
- - "7"
5
- - "6"
6
-
7
- sudo: required
8
- services:
9
- - docker
10
-
11
- env:
12
- COMPOSE_VERSION: 1.16.0
13
-
14
- before_install:
15
- - curl -L https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
16
- - chmod +x docker-compose
17
- - sudo mv docker-compose /usr/local/bin
18
- - docker-compose up -d mongodb
19
- - docker-compose run -e ADMIN_NAME -e ADMIN_EMAIL -e ADMIN_PASSWORD bootstrap
20
- - docker-compose up -d api
21
-
22
- script:
23
- - npm run test
24
-
25
- after_install:
26
- - docker-compose down
27
-
28
- notifications:
29
- email:
30
- on_success: always
31
- on_failure: always
32
- recipients:
33
- - antoniofernandezvara+backd@gmail.com