@content-island/api-client 0.3.1 → 0.5.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.
package/README.md CHANGED
@@ -6,25 +6,58 @@
6
6
  npm install @content-island/api-client
7
7
  ```
8
8
 
9
- ## Usage
9
+ ## Examples
10
10
 
11
- ```typescript
12
- import { createClient } from '@content-island/api-client';
11
+ ### Basic Usage
13
12
 
14
- const client = createClient({ accessToken: <your-token>});
13
+ ```typescript
14
+ // Your model
15
+ interface Post {
16
+ id: string;
17
+ title: string;
18
+ body: string;
19
+ order: number;
20
+ language: 'es' | 'en';
21
+ }
22
+ ```
15
23
 
16
- const project = client.getProject(); // Retrieve the project by access token
24
+ ```typescript
25
+ import { createClient, mapContentToModel } from '@content-island/api-client';
17
26
 
18
- const contents = client.getContentList(); // Retrieve the list of contents in the project
27
+ const client = createClient({ accessToken: <your-token>});
19
28
 
20
29
  const postContents = client.getContentList({ contentType: 'post'}); // Retrieve the list of contents in the project filtered by content type, for example 'post'
30
+ const englishPosts = postContents.map(content => mapContentToModel<Post>(content, 'en')); // Map the english content to your own model
31
+ const spanishPosts = postContents.map(content => mapContentToModel<Post>(content, 'es')); // Map the spanish content to your own model
21
32
 
33
+ // Or you can retrieve a content by id
22
34
  const content = client.getContent('content-id'); // Retrieve a content by id
35
+ const englishPost = mapContentToModel<Post>(content, 'en'); // Map the english content to your own model
36
+ const spanishPost = mapContentToModel<Post>(content, 'es'); // Map the spanish content to your own model
23
37
 
24
- const content = client.getContent('content-id', { contentType: 'post'}); // Retrieve a content by id filtered by content type, for example 'post'
38
+ ```
39
+
40
+ ### Filter by language
41
+
42
+ ```typescript
43
+ import { createClient, mapContentToModel } from '@content-island/api-client';
44
+
45
+ const client = createClient({ accessToken: <your-token>});
46
+
47
+ const englishPostContents = client.getContentList({ contentType: 'post', language: 'en'}); // Retrieve the english posts
48
+ const englishPosts = englishPostContents.map(content => mapContentToModel<Post>(content)); // Map content to your own model using the first language available, in this case 'en'
49
+
50
+ // Or you can retrieve contents by multiple languages
51
+ const postContents = client.getContentList({ contentType: 'post', language: { in: ['en', 'es']}}); // Retrieve the english or spanish posts
52
+
53
+ // Or you can retrieve a content by id
54
+ const englishContent = client.getContent('content-id', { language: 'en'}); // Retrieve a content by id
55
+ const englishPost = mapContentToModel<Post>(englishContent); // Map content to your own model using the first language available, in this case 'en'
25
56
 
26
57
  ```
27
58
 
59
+ > Check the [API/queryParams](#queryparams) section for more information about the query parameters.
60
+
28
61
  ## API
29
62
 
30
63
  ### `createClient(options): endpoints`
@@ -43,13 +76,13 @@ Creates a client instance.
43
76
 
44
77
  ##### `getProject()`
45
78
 
46
- Retrieves the project by access token.
79
+ Retrieves the project details by access token.
47
80
 
48
- ##### `getContentList(queryParams)`
81
+ ##### `getContentList(queryParams?)`
49
82
 
50
83
  Retrieves the list of contents in the project.
51
84
 
52
- ##### `getContent(contentId, queryParams)`
85
+ ##### `getContent(id, queryParams?)`
53
86
 
54
87
  Retrieves a content by id.
55
88
 
@@ -57,49 +90,91 @@ Retrieves a content by id.
57
90
 
58
91
  The query parameters to filter the list of contents.
59
92
 
60
- | param | Description |
61
- | ------------- | -------------------------------------------------------------------- |
62
- | `contentType` | The content type to filter the list of contents. For example: `post` |
93
+ | Key | Value | Description |
94
+ | ------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
95
+ | `id` | `Filter` | The id of the content to retrieve. This is useful to retrieve a list of contents by id. For example: `client.getContentList({ ids: { in: ['1', '2', '3']})` |
96
+ | `contentType` | `Filter` | The content type to filter the list of contents. For example: `post` |
97
+ | `language` | `Filter` | The language to filter the list of contents. For example: `en` |
63
98
 
64
- ### `mapFieldListToModel(fieldList)`
99
+ | Filter type | Description | Example |
100
+ | ------------------ | ------------------------------------------------------------------ | ------------------------------------ |
101
+ | `string` | Filter the content where the param is `equal to` this value | `{ contentType: 'post' }` |
102
+ | `{ in: string[] }` | Filter the content where the param `contains some` of these values | `{ language: { in: ['en', 'es'] } }` |
103
+
104
+ ### `mapContentToModel(content, language?)`
65
105
 
66
106
  Maps a list of fields to a model.
67
107
 
68
108
  ```typescript
69
- const fields: Field[] = [
70
- {
71
- id: '1',
72
- name: 'title',
73
- value: 'My title',
74
- type: 'short-text',
75
- isArray: false,
76
- language: 'en',
77
- },
78
- {
79
- id: '2',
80
- name: 'body',
81
- value: '# My body',
82
- type: 'long-text',
83
- isArray: false,
84
- language: 'en',
85
- },
86
- {
87
- id: '3',
88
- name: 'order',
89
- value: 1,
90
- type: 'number',
91
- isArray: false,
92
- language: 'en',
93
- },
94
- ];
109
+ const content: Content = {
110
+ id: '1',
111
+ contentType: { id: '10', name: 'post' },
112
+ lastUpdate: '2023-10-20T00:00:00.000Z',
113
+ fields: [
114
+ {
115
+ id: '100',
116
+ name: 'title',
117
+ value: 'My title',
118
+ type: 'short-text',
119
+ isArray: false,
120
+ language: 'en',
121
+ },
122
+ {
123
+ id: '200',
124
+ name: 'body',
125
+ value: '# My long text in markdown',
126
+ type: 'long-text',
127
+ isArray: false,
128
+ language: 'en',
129
+ },
130
+ {
131
+ id: '300',
132
+ name: 'order',
133
+ value: 1,
134
+ type: 'number',
135
+ isArray: false,
136
+ language: 'en',
137
+ },
138
+ {
139
+ id: '400',
140
+ name: 'title',
141
+ value: 'Mi titutlo',
142
+ type: 'short-text',
143
+ isArray: false,
144
+ language: 'es',
145
+ },
146
+ {
147
+ id: '500',
148
+ name: 'body',
149
+ value: '# Mi texto largo en markdown',
150
+ type: 'long-text',
151
+ isArray: false,
152
+ language: 'es',
153
+ },
154
+ {
155
+ id: '600',
156
+ name: 'order',
157
+ value: 1,
158
+ type: 'number',
159
+ isArray: false,
160
+ language: 'es',
161
+ },
162
+ ],
163
+ };
95
164
 
96
165
  interface Post {
166
+ id: string;
97
167
  title: string;
98
168
  body: string;
99
169
  order: number;
100
170
  }
101
171
 
102
- const post = mapFieldListToModel<Post>(fields);
172
+ const post = mapContentToModel<Post>(fields); // Get the first language available, in this case 'en'
173
+ console.log(post); // { id: '1', title: 'My title', body: '# My long text in markdown', order: 1 }
174
+
175
+ const englishPost = mapContentToModel<Post>(fields, 'en');
176
+ console.log(englishPost); // { id: '1', title: 'My title', body: '# My long text in markdown', order: 1 }
103
177
 
104
- console.log(post); // { title: 'My title', body: '# My body', order: 1 }
178
+ const spanishPost = mapContentToModel<Post>(fields, 'es');
179
+ console.log(spanishPost); // { id: '1', title: 'Mi titulo', body: '# Mi texto largo en markdown', order: 1 }
105
180
  ```
package/dist/index.d.ts CHANGED
@@ -1,4 +1,84 @@
1
- export type { Project, Content, Field, FieldType, Resource, ApiLookup } from '@content-island/b2b-api-model';
2
- export { createClient } from './client.js';
3
- export type { ApiClient, Options } from './client.js';
4
- export { mapFieldListToModel } from './mappers.js';
1
+ declare type AllowedQueryKeys = keyof Pick<Query, 'id' | 'contentType' | 'language'>;
2
+
3
+ export declare interface ApiClient {
4
+ getProject: () => Promise<Project>;
5
+ getContentList: (queryParam?: QueryParams) => Promise<Content[]>;
6
+ getContent: (id: string, queryParam?: QueryParams) => Promise<Content>;
7
+ }
8
+
9
+ export declare interface ApiLookup {
10
+ id: string;
11
+ name: string;
12
+ }
13
+
14
+ declare type BaseModel<Language> = {
15
+ id: string;
16
+ language?: Language;
17
+ };
18
+
19
+ export declare type ClientFilter = string | { in?: string[] };
20
+
21
+ export declare interface Content {
22
+ id: string;
23
+ contentType: ApiLookup;
24
+ lastUpdate: Date;
25
+ fields: Field[];
26
+ }
27
+
28
+ export declare const createClient: (options: Options) => ApiClient;
29
+
30
+ export declare interface Field {
31
+ id: string;
32
+ name: string;
33
+ value: any;
34
+ type: FieldType;
35
+ isArray: boolean;
36
+ language: string;
37
+ }
38
+
39
+ export declare type FieldType = 'short-text' | 'long-text' | 'number' | 'date' | 'date-time' | 'media' | 'boolean';
40
+
41
+ declare type Filter =
42
+ | string
43
+ | {
44
+ ne?: string;
45
+ all?: string;
46
+ in?: string;
47
+ nin?: string;
48
+ lt?: string;
49
+ lte?: string;
50
+ gt?: string;
51
+ gte?: string;
52
+ };
53
+
54
+ export declare const mapContentToModel: <Model extends BaseModel<Language>, Language = Model["language"]>(content: Content, language?: Language) => Model;
55
+
56
+ export declare interface Options {
57
+ accessToken: string;
58
+ domain?: string;
59
+ apiVersion?: string;
60
+ }
61
+
62
+ export declare interface Project {
63
+ id: string;
64
+ name: string;
65
+ languages: string[];
66
+ entities?: ApiLookup[];
67
+ }
68
+
69
+ declare type Query<F = Filter> = {
70
+ id?: F;
71
+ lastUpdate?: F;
72
+ language?: F;
73
+ contentType?: F;
74
+ [key: `fields.${string}`]: F;
75
+ };
76
+
77
+ export declare type QueryParams = Pick<Query<ClientFilter>, AllowedQueryKeys>;
78
+
79
+ export declare interface Resource {
80
+ name: string;
81
+ link: string;
82
+ }
83
+
84
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,54 @@
1
+ const T = {
2
+ DEFAULT_API_CLIENT_DOMAIN: "api.contentisland.net",
3
+ DEFAULT_API_CLIENT_VERSION: "1.0"
4
+ }, E = {
5
+ SESSION_KEY: "authorization",
6
+ SESSION_TYPE: "Bearer"
7
+ }, N = (e, t) => {
8
+ if (typeof t == "string")
9
+ return `${e}=${t}`;
10
+ if (t.in)
11
+ return `${e}[in]=${t.in.join(",")}`;
12
+ }, S = (e, t) => Object.entries(e).reduce(
13
+ (n, [r, s], a) => a === 0 ? N(r, s) : `${n}${t}${N(r, s)}`,
14
+ ""
15
+ ), u = (e) => e && Object.keys(e).length > 0 ? `?${S(e, "&")}` : "", o = {
16
+ PROYECT: "/project",
17
+ CONTENT_LIST: (e) => `/contents${u(e)}`,
18
+ CONTENT: (e, t) => {
19
+ const n = u(t);
20
+ return `/contents/${e}${n}`;
21
+ }
22
+ }, _ = (e) => {
23
+ const t = "https", n = e.domain ? e.domain : T.DEFAULT_API_CLIENT_DOMAIN, r = e.apiVersion ? e.apiVersion : T.DEFAULT_API_CLIENT_VERSION;
24
+ return `${t}://${n}/api/${r}`;
25
+ }, c = async (e, t) => fetch(`${_(t)}${e}`, {
26
+ headers: {
27
+ [E.SESSION_KEY]: `${E.SESSION_TYPE} ${t.accessToken}`
28
+ }
29
+ }).then((n) => {
30
+ if (n.ok)
31
+ return n.json();
32
+ throw Error(
33
+ JSON.stringify({
34
+ status: n.status,
35
+ statusText: n.statusText
36
+ })
37
+ );
38
+ }), $ = (e) => ({
39
+ getProject: () => c(o.PROYECT, e),
40
+ getContentList: (t) => c(o.CONTENT_LIST(t), e),
41
+ getContent: (t, n) => c(o.CONTENT(t, n), e)
42
+ }), g = (e) => e.reduce((t, n) => ({ ...t, [n.name]: n.value }), {}), O = (e, t, n) => {
43
+ var i;
44
+ const r = n ?? ((i = e[0]) == null ? void 0 : i.language), s = e.filter((l) => l.language === r), a = g(s);
45
+ return Object.keys(a).length === 0 && console.warn(`No fields found for language "${r}" and content id "${t}"`), {
46
+ id: t,
47
+ language: r,
48
+ ...a
49
+ };
50
+ }, d = (e, t) => Array.isArray(e == null ? void 0 : e.fields) ? O(e.fields, e.id, t) : {};
51
+ export {
52
+ $ as createClient,
53
+ d as mapContentToModel
54
+ };
@@ -0,0 +1 @@
1
+ (function(s,r){typeof exports=="object"&&typeof module<"u"?r(exports):typeof define=="function"&&define.amd?define(["exports"],r):(s=typeof globalThis<"u"?globalThis:s||self,r(s.ApiClient={}))})(this,function(s){"use strict";const r={DEFAULT_API_CLIENT_DOMAIN:"api.contentisland.net",DEFAULT_API_CLIENT_VERSION:"1.0"},u={SESSION_KEY:"authorization",SESSION_TYPE:"Bearer"},l=(e,t)=>{if(typeof t=="string")return`${e}=${t}`;if(t.in)return`${e}[in]=${t.in.join(",")}`},N=(e,t)=>Object.entries(e).reduce((n,[o,a],i)=>i===0?l(o,a):`${n}${t}${l(o,a)}`,""),d=e=>e&&Object.keys(e).length>0?`?${N(e,"&")}`:"",c={PROYECT:"/project",CONTENT_LIST:e=>`/contents${d(e)}`,CONTENT:(e,t)=>{const n=d(t);return`/contents/${e}${n}`}},S=e=>{const t="https",n=e.domain?e.domain:r.DEFAULT_API_CLIENT_DOMAIN,o=e.apiVersion?e.apiVersion:r.DEFAULT_API_CLIENT_VERSION;return`${t}://${n}/api/${o}`},T=async(e,t)=>fetch(`${S(t)}${e}`,{headers:{[u.SESSION_KEY]:`${u.SESSION_TYPE} ${t.accessToken}`}}).then(n=>{if(n.ok)return n.json();throw Error(JSON.stringify({status:n.status,statusText:n.statusText}))}),f=e=>({getProject:()=>T(c.PROYECT,e),getContentList:t=>T(c.CONTENT_LIST(t),e),getContent:(t,n)=>T(c.CONTENT(t,n),e)}),g=e=>e.reduce((t,n)=>({...t,[n.name]:n.value}),{}),O=(e,t,n)=>{var E;const o=n??((E=e[0])==null?void 0:E.language),a=e.filter($=>$.language===o),i=g(a);return Object.keys(i).length===0&&console.warn(`No fields found for language "${o}" and content id "${t}"`),{id:t,language:o,...i}},_=(e,t)=>Array.isArray(e==null?void 0:e.fields)?O(e.fields,e.id,t):{};s.createClient=f,s.mapContentToModel=_,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,41 +1,34 @@
1
1
  {
2
2
  "name": "@content-island/api-client",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Content Island - REST API Client",
5
5
  "private": false,
6
+ "sideEffects": false,
6
7
  "author": "Lemoncode",
7
8
  "license": "MIT",
8
9
  "files": [
9
10
  "dist"
10
11
  ],
11
12
  "type": "module",
12
- "module": "./dist/api-client.js",
13
- "main": "./dist/api-client.umd.cjs",
13
+ "module": "./dist/index.js",
14
+ "main": "./dist/index.umd.cjs",
14
15
  "types": "./dist/index.d.ts",
15
16
  "exports": {
16
17
  ".": {
17
- "import": "./dist/api-client.js",
18
- "require": "./dist/api-client.umd.cjs",
19
- "types": "./dist/index.d.ts"
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js",
20
+ "require": "./dist/index.umd.cjs"
20
21
  }
21
22
  },
22
23
  "scripts": {
23
- "prebuild": "if-env NODE_ENV=development && sh ./create-dev-env.sh || echo noop",
24
+ "prebuild:dev": "sh ./create-dev-env.sh",
25
+ "build:dev": "vite build --mode development",
24
26
  "build": "vite build",
25
- "type-check": "tsc --noEmit",
26
- "type-check:watch": "npm run type-check -- --watch --preserveWatchOutput",
27
+ "type-check": "tsc --noEmit --preserveWatchOutput",
27
28
  "test": "vitest run -c ./config/test/config.ts",
28
29
  "test:watch": "vitest -c ./config/test/config.ts"
29
30
  },
30
- "dependencies": {
31
- "@content-island/b2b-api-model": "^0.2.1"
32
- },
33
31
  "devDependencies": {
34
- "dotenv": "^16.3.1",
35
- "if-env": "^1.0.4",
36
- "typescript": "^5.2.2",
37
- "vite": "^4.4.9",
38
- "vite-plugin-dts": "^3.5.3",
39
- "vitest": "^0.34.6"
32
+ "@content-island/b2b-api-model": "*"
40
33
  }
41
34
  }
@@ -1,42 +0,0 @@
1
- const a = {
2
- IS_PRODUCTION: !0,
3
- DEFAULT_API_CLIENT_DOMAIN: "api.contentisland.net",
4
- DEFAULT_API_CLIENT_VERSION: "1.0"
5
- }, s = {
6
- SESSION_KEY: "authorization",
7
- SESSION_TYPE: "Bearer"
8
- }, S = (t, e) => Object.entries(t).reduce(
9
- (n, [o, T], E) => E === 0 ? `${o}=${T}` : `${n}${e}${o}=${T}`,
10
- ""
11
- ), N = (t) => t && Object.keys(t).length > 0 ? `?${S(t, "&")}` : "", r = {
12
- PROYECT: "/project",
13
- CONTENT_LIST: (t) => `/contents${N(t)}`,
14
- CONTENT: (t, e) => {
15
- const n = N(e);
16
- return `/contents/${t}${n}`;
17
- }
18
- }, _ = (t) => {
19
- const e = "https", n = t.domain ? t.domain : a.DEFAULT_API_CLIENT_DOMAIN, o = t.apiVersion ? t.apiVersion : a.DEFAULT_API_CLIENT_VERSION;
20
- return `${e}://${n}/api/${o}`;
21
- }, c = async (t, e) => fetch(`${_(e)}${t}`, {
22
- headers: {
23
- [s.SESSION_KEY]: `${s.SESSION_TYPE} ${e.accessToken}`
24
- }
25
- }).then((n) => {
26
- if (n.ok)
27
- return n.json();
28
- throw Error(
29
- JSON.stringify({
30
- status: n.status,
31
- statusText: n.statusText
32
- })
33
- );
34
- }), O = (t) => ({
35
- getProject: () => c(r.PROYECT, t),
36
- getContentList: (e) => c(r.CONTENT_LIST(e), t),
37
- getContent: (e, n) => c(r.CONTENT(e, n), t)
38
- }), I = (t) => t.reduce((e, n) => ({ ...e, [n.name]: n.value }), {}), i = (t) => Array.isArray(t) ? I(t) : {};
39
- export {
40
- O as createClient,
41
- i as mapFieldListToModel
42
- };
@@ -1 +0,0 @@
1
- (function(o,r){typeof exports=="object"&&typeof module<"u"?r(exports):typeof define=="function"&&define.amd?define(["exports"],r):(o=typeof globalThis<"u"?globalThis:o||self,r(o.ApiClient={}))})(this,function(o){"use strict";const r={IS_PRODUCTION:!0,DEFAULT_API_CLIENT_DOMAIN:"api.contentisland.net",DEFAULT_API_CLIENT_VERSION:"1.0"},T={SESSION_KEY:"authorization",SESSION_TYPE:"Bearer"},S=(t,e)=>Object.entries(t).reduce((n,[i,N],_)=>_===0?`${i}=${N}`:`${n}${e}${i}=${N}`,""),a=t=>t&&Object.keys(t).length>0?`?${S(t,"&")}`:"",c={PROYECT:"/project",CONTENT_LIST:t=>`/contents${a(t)}`,CONTENT:(t,e)=>{const n=a(e);return`/contents/${t}${n}`}},u=t=>{const e="https",n=t.domain?t.domain:r.DEFAULT_API_CLIENT_DOMAIN,i=t.apiVersion?t.apiVersion:r.DEFAULT_API_CLIENT_VERSION;return`${e}://${n}/api/${i}`},s=async(t,e)=>fetch(`${u(e)}${t}`,{headers:{[T.SESSION_KEY]:`${T.SESSION_TYPE} ${e.accessToken}`}}).then(n=>{if(n.ok)return n.json();throw Error(JSON.stringify({status:n.status,statusText:n.statusText}))}),E=t=>({getProject:()=>s(c.PROYECT,t),getContentList:e=>s(c.CONTENT_LIST(e),t),getContent:(e,n)=>s(c.CONTENT(e,n),t)}),d=t=>t.reduce((e,n)=>({...e,[n.name]:n.value}),{}),O=t=>Array.isArray(t)?d(t):{};o.createClient=E,o.mapFieldListToModel=O,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})});
package/dist/client.d.ts DELETED
@@ -1,13 +0,0 @@
1
- import { Project, Content } from '@content-island/b2b-api-model';
2
- import { QueryParams } from './model.js';
3
- export interface Options {
4
- accessToken: string;
5
- domain?: string;
6
- apiVersion?: string;
7
- }
8
- export interface ApiClient {
9
- getProject: () => Promise<Project>;
10
- getContentList: (queryParam?: QueryParams) => Promise<Content[]>;
11
- getContent: (id: string, queryParam?: QueryParams) => Promise<Content>;
12
- }
13
- export declare const createClient: (options: Options) => ApiClient;
@@ -1 +0,0 @@
1
- export {};
@@ -1,12 +0,0 @@
1
- export declare const ENV_CONSTANTS: {
2
- IS_PRODUCTION: boolean;
3
- DEFAULT_API_CLIENT_DOMAIN: string;
4
- DEFAULT_API_CLIENT_VERSION: string;
5
- };
6
- export declare const AUTH_CONSTANTS: {
7
- SESSION_KEY: string;
8
- SESSION_TYPE: string;
9
- };
10
- export declare const ALLOWED_QUERIES: {
11
- contentType: string;
12
- };
package/dist/helpers.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { QueryParams } from './model.js';
2
- export declare const formatQuery: (queryParams: QueryParams) => string;
@@ -1 +0,0 @@
1
- export {};
package/dist/mappers.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { Field } from '@content-island/b2b-api-model';
2
- export declare const mapFieldListToModel: <Model>(fields: Field[]) => Model;
@@ -1 +0,0 @@
1
- export {};
package/dist/model.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { ALLOWED_QUERIES } from './constants.js';
2
- export type QueryParams = Partial<typeof ALLOWED_QUERIES>;
package/dist/urls.d.ts DELETED
@@ -1,6 +0,0 @@
1
- import { QueryParams } from './model.js';
2
- export declare const API_URLS: {
3
- PROYECT: string;
4
- CONTENT_LIST: (queryParam: QueryParams) => string;
5
- CONTENT: (id: string, querParams: QueryParams) => string;
6
- };