@amirstack/chapar 0.1.0 → 0.1.1

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.
package/dist/chapar.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type ChaparConfiguration } from './config';
1
+ import { type ChaparConfiguration } from './config.ts';
2
2
  type SendParameters = {
3
3
  content: {
4
4
  text: string;
@@ -10,4 +10,3 @@ export declare class Chapar {
10
10
  send(params: SendParameters): Promise<void>;
11
11
  }
12
12
  export {};
13
- //# sourceMappingURL=chapar.d.ts.map
package/dist/chapar.js ADDED
@@ -0,0 +1,32 @@
1
+ import { ChaparConfig } from './config.js';
2
+ import { ChaparUnhandledError } from './errors.js';
3
+ import { parseResponse } from './response.js';
4
+ export class Chapar {
5
+ #config;
6
+ constructor(config) {
7
+ this.#config = new ChaparConfig(config);
8
+ }
9
+ async #request(params) {
10
+ const config = this.#config.resolve();
11
+ try {
12
+ return await fetch(`${config.apiUrl}/messages`, {
13
+ method: 'POST',
14
+ headers: {
15
+ 'Content-Type': 'application/json',
16
+ 'CF-Access-Client-Id': config.auth.clientId,
17
+ 'CF-Access-Client-Secret': config.auth.clientSecret,
18
+ },
19
+ body: JSON.stringify(params),
20
+ });
21
+ }
22
+ catch (cause) {
23
+ throw new ChaparUnhandledError('The request could not be completed', {
24
+ cause,
25
+ });
26
+ }
27
+ }
28
+ async send(params) {
29
+ const response = await this.#request(params);
30
+ await parseResponse(response);
31
+ }
32
+ }
package/dist/config.d.ts CHANGED
@@ -15,4 +15,3 @@ export declare class ChaparConfig {
15
15
  resolve(): ResolvedConfiguration;
16
16
  }
17
17
  export {};
18
- //# sourceMappingURL=config.d.ts.map
package/dist/config.js ADDED
@@ -0,0 +1,32 @@
1
+ import { ChaparConfigResolvingFailure } from './errors.js';
2
+ export class ChaparConfig {
3
+ #config;
4
+ constructor(config) {
5
+ this.#config = config;
6
+ }
7
+ #readEnv(key) {
8
+ if (typeof process === 'undefined' || typeof process.env === 'undefined') {
9
+ return undefined;
10
+ }
11
+ return process.env[key];
12
+ }
13
+ #resolveValue(value, envKey, name) {
14
+ if (value) {
15
+ return value;
16
+ }
17
+ const envValue = this.#readEnv(envKey);
18
+ if (envValue) {
19
+ return envValue;
20
+ }
21
+ throw new ChaparConfigResolvingFailure(`Missing required configuration: ${name}`);
22
+ }
23
+ resolve() {
24
+ return {
25
+ apiUrl: this.#resolveValue(this.#config?.apiUrl, 'CHAPAR_API_URL', 'apiUrl'),
26
+ auth: {
27
+ clientId: this.#resolveValue(this.#config?.auth?.clientId, 'CHAPAR_AUTH_CLIENT_ID', 'auth.clientId'),
28
+ clientSecret: this.#resolveValue(this.#config?.auth?.clientSecret, 'CHAPAR_AUTH_CLIENT_SECRET', 'auth.clientSecret'),
29
+ },
30
+ };
31
+ }
32
+ }
package/dist/errors.d.ts CHANGED
@@ -19,4 +19,3 @@ export declare class ChaparUnhandledError extends ChaparError {
19
19
  }
20
20
  export declare class ChaparConfigResolvingFailure extends ChaparError {
21
21
  }
22
- //# sourceMappingURL=errors.d.ts.map
package/dist/errors.js ADDED
@@ -0,0 +1,21 @@
1
+ export class ChaparError extends Error {
2
+ }
3
+ export class ChaparAuthError extends ChaparError {
4
+ }
5
+ export class ChaparUnparsableError extends ChaparError {
6
+ }
7
+ export class ChaparServerError extends ChaparError {
8
+ }
9
+ export class ChaparSendError extends ChaparError {
10
+ code;
11
+ details;
12
+ constructor(error) {
13
+ super(error.message);
14
+ this.code = error.code;
15
+ this.details = error.details;
16
+ }
17
+ }
18
+ export class ChaparUnhandledError extends ChaparError {
19
+ }
20
+ export class ChaparConfigResolvingFailure extends ChaparError {
21
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export { Chapar } from './chapar';
2
- export { ChaparConfig, type ChaparConfiguration } from './config';
3
- export { ChaparAuthError, ChaparConfigResolvingFailure, ChaparError, ChaparSendError, ChaparServerError, ChaparUnhandledError, ChaparUnparsableError, } from './errors';
4
- //# sourceMappingURL=index.d.ts.map
1
+ export { Chapar } from './chapar.ts';
2
+ export { ChaparConfig, type ChaparConfiguration } from './config.ts';
3
+ export { ChaparAuthError, ChaparConfigResolvingFailure, ChaparError, ChaparSendError, ChaparServerError, ChaparUnhandledError, ChaparUnparsableError, } from './errors.ts';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { Chapar } from './chapar.js';
2
+ export { ChaparConfig } from './config.js';
3
+ export { ChaparAuthError, ChaparConfigResolvingFailure, ChaparError, ChaparSendError, ChaparServerError, ChaparUnhandledError, ChaparUnparsableError, } from './errors.js';
@@ -1,2 +1 @@
1
1
  export declare function parseResponse(response: Response): Promise<unknown>;
2
- //# sourceMappingURL=response.d.ts.map
@@ -0,0 +1,50 @@
1
+ import { ChaparAuthError, ChaparSendError, ChaparServerError, ChaparUnparsableError, } from './errors.js';
2
+ const isRecord = (value) => typeof value === 'object' && value !== null;
3
+ function parseEnvelope(data) {
4
+ if (!isRecord(data) || typeof data.ok !== 'boolean') {
5
+ throw new ChaparUnparsableError();
6
+ }
7
+ if (data.ok) {
8
+ return { ok: true, data: data.data };
9
+ }
10
+ const { error } = data;
11
+ if (!isRecord(error) ||
12
+ typeof error.code !== 'string' ||
13
+ typeof error.message !== 'string') {
14
+ throw new ChaparUnparsableError();
15
+ }
16
+ return {
17
+ ok: false,
18
+ error: {
19
+ code: error.code,
20
+ message: error.message,
21
+ details: error.details,
22
+ },
23
+ };
24
+ }
25
+ async function readJson(response) {
26
+ if (response.headers.get('Content-Type') !== 'application/json') {
27
+ throw new ChaparUnparsableError();
28
+ }
29
+ try {
30
+ return await response.json();
31
+ }
32
+ catch (cause) {
33
+ throw new ChaparUnparsableError('The response body was not valid JSON', {
34
+ cause,
35
+ });
36
+ }
37
+ }
38
+ export async function parseResponse(response) {
39
+ if (response.status === 401 || response.status === 403) {
40
+ throw new ChaparAuthError();
41
+ }
42
+ if (response.status >= 500) {
43
+ throw new ChaparServerError();
44
+ }
45
+ const parsed = parseEnvelope(await readJson(response));
46
+ if (!parsed.ok) {
47
+ throw new ChaparSendError(parsed.error);
48
+ }
49
+ return parsed.data;
50
+ }
package/package.json CHANGED
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "name": "@amirstack/chapar",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Client for sending messages through the Chapar API.",
5
5
  "author": "Amir Ziaei <a@amirziaei.me> (https://amirziaei.me)",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/amir-ziaei/chapar",
9
+ "url": "git+https://github.com/amir-ziaei/chapar.git",
10
10
  "directory": "packages/client"
11
11
  },
12
12
  "homepage": "https://github.com/amir-ziaei/chapar/tree/main/packages/client#readme",
13
+ "keywords": [
14
+ "client",
15
+ "messaging",
16
+ "delivery"
17
+ ],
13
18
  "files": [
14
19
  "LICENSE",
15
20
  "README.md",
@@ -17,20 +22,20 @@
17
22
  "src",
18
23
  "!src/**/*.test.ts"
19
24
  ],
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
20
28
  "type": "module",
29
+ "sideEffects": false,
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
21
32
  "exports": {
22
- ".": "./src/lib/index.ts",
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ },
23
37
  "./package.json": "./package.json"
24
38
  },
25
- "publishConfig": {
26
- "exports": {
27
- ".": {
28
- "types": "./dist/index.d.ts",
29
- "default": "./dist/index.js"
30
- },
31
- "./package.json": "./package.json"
32
- }
33
- },
34
39
  "scripts": {
35
40
  "build": "tsc -p tsconfig.build.json",
36
41
  "test": "vitest",
@@ -43,7 +48,7 @@
43
48
  "prepublishOnly": "bun run build"
44
49
  },
45
50
  "devDependencies": {
46
- "@types/bun": "latest",
51
+ "@types/node": "^26.1.1",
47
52
  "msw": "^2.14.6",
48
53
  "vitest": "^4.1.10"
49
54
  }
package/src/lib/chapar.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { ChaparConfig, type ChaparConfiguration } from './config'
2
- import { ChaparUnhandledError } from './errors'
3
- import { parseResponse } from './response'
1
+ import { ChaparConfig, type ChaparConfiguration } from './config.ts'
2
+ import { ChaparUnhandledError } from './errors.ts'
3
+ import { parseResponse } from './response.ts'
4
4
 
5
5
  type SendParameters = {
6
6
  content: {
@@ -18,9 +18,10 @@ export class Chapar {
18
18
  async #request(params: SendParameters): Promise<Response> {
19
19
  const config = this.#config.resolve()
20
20
  try {
21
- return await fetch(config.apiUrl, {
21
+ return await fetch(`${config.apiUrl}/messages`, {
22
22
  method: 'POST',
23
23
  headers: {
24
+ 'Content-Type': 'application/json',
24
25
  'CF-Access-Client-Id': config.auth.clientId,
25
26
  'CF-Access-Client-Secret': config.auth.clientSecret,
26
27
  },
package/src/lib/config.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ChaparConfigResolvingFailure } from './errors'
1
+ import { ChaparConfigResolvingFailure } from './errors.ts'
2
2
 
3
3
  export type ChaparConfiguration = {
4
4
  apiUrl?: string
package/src/lib/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { Chapar } from './chapar'
2
- export { ChaparConfig, type ChaparConfiguration } from './config'
1
+ export { Chapar } from './chapar.ts'
2
+ export { ChaparConfig, type ChaparConfiguration } from './config.ts'
3
3
  export {
4
4
  ChaparAuthError,
5
5
  ChaparConfigResolvingFailure,
@@ -8,4 +8,4 @@ export {
8
8
  ChaparServerError,
9
9
  ChaparUnhandledError,
10
10
  ChaparUnparsableError,
11
- } from './errors'
11
+ } from './errors.ts'
@@ -3,7 +3,7 @@ import {
3
3
  ChaparSendError,
4
4
  ChaparServerError,
5
5
  ChaparUnparsableError,
6
- } from './errors'
6
+ } from './errors.ts'
7
7
 
8
8
  const isRecord = (value: unknown): value is Record<string, unknown> =>
9
9
  typeof value === 'object' && value !== null
@@ -1 +0,0 @@
1
- {"version":3,"file":"chapar.d.ts","sourceRoot":"","sources":["../src/lib/chapar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAIjE,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;CACF,CAAA;AAED,qBAAa,MAAM;;IAGjB,YAAY,MAAM,CAAC,EAAE,mBAAmB,EAEvC;IAoBK,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhD;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/lib/config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,YAAY,CAAC,EAAE,MAAM,CAAA;KACtB,CAAA;CACF,CAAA;AAED,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GACpD,CAAC,GACD,CAAC,SAAS,MAAM,GACd;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GACxC,CAAC,CAAA;AAEP,KAAK,qBAAqB,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAA;AAE9D,qBAAa,YAAY;;IAGvB,YAAY,MAAM,CAAC,EAAE,mBAAmB,EAEvC;IA0BD,OAAO,IAAI,qBAAqB,CAoB/B;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/lib/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,WAAY,SAAQ,KAAK;CAAG;AACzC,qBAAa,eAAgB,SAAQ,WAAW;CAAG;AACnD,qBAAa,qBAAsB,SAAQ,WAAW;CAAG;AACzD,qBAAa,iBAAkB,SAAQ,WAAW;CAAG;AACrD,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IAEzB,YAAY,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,EAItE;CACF;AACD,qBAAa,oBAAqB,SAAQ,WAAW;CAAG;AACxD,qBAAa,4BAA6B,SAAQ,WAAW;CAAG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACjE,OAAO,EACL,eAAe,EACf,4BAA4B,EAC5B,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,UAAU,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../src/lib/response.ts"],"names":[],"mappings":"AA0DA,wBAAsB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAaxE"}