@content-island/vscode-api-client 0.1.6 → 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.
- package/dist/index.d.ts +53 -2
- package/dist/index.js +52 -46
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,27 @@ declare interface ApiClient {
|
|
|
11
11
|
getRawContentList: <M extends Model = Model & Record<string, any>>(queryParam?: ContentListQueryParams<M>) => Promise<Content[]>;
|
|
12
12
|
getRawContent: <M extends Model = Model & Record<string, any>>(queryParam: ContentQueryParams<M>) => Promise<Content>;
|
|
13
13
|
getContentListSize: <M extends Model = Model & Record<string, any>>(queryParam?: ContentListSizeQueryParams<M>) => Promise<number>;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Updates (or upserts, when selected by `fieldName`+`language`) a field value on an existing content.
|
|
16
|
+
*
|
|
17
|
+
* The selector chooses how to identify the target:
|
|
18
|
+
* - `{ fieldName, language }` — by field name and language. Upserts when the pair does not exist, which
|
|
19
|
+
* makes it ideal to add translations or fill values for new languages on an existing content.
|
|
20
|
+
*
|
|
21
|
+
* @example By reference (preferred for new integrations)
|
|
22
|
+
* await client.updateContentFieldValue(contentId, { fieldName: 'title', language: 'en' }, 'Hello');
|
|
23
|
+
*/
|
|
24
|
+
updateContentFieldValue(contentId: string, selector: FieldSelector, value: unknown): Promise<boolean>;
|
|
25
|
+
/** @deprecated Pass a `FieldSelector` instead: `updateContentFieldValue(contentId, { fieldName: "name", language: "en" }, value)`. */
|
|
26
|
+
updateContentFieldValue(contentId: string, fieldId: string, value: unknown): Promise<boolean>;
|
|
27
|
+
uploadMedia: (params: UploadMediaParams) => Promise<Media>;
|
|
28
|
+
createContent: (params: CreateContentParams) => Promise<CreateContentResponse>;
|
|
29
|
+
/**
|
|
30
|
+
* Publishes an existing content: snapshots its current draft fieldValues into publishedValues and
|
|
31
|
+
* sets its status to "published". Idempotent — re-publishing an already-published content refreshes
|
|
32
|
+
* the live snapshot from the current draft.
|
|
33
|
+
*/
|
|
34
|
+
publishContent: (contentId: string) => Promise<boolean>;
|
|
15
35
|
}
|
|
16
36
|
|
|
17
37
|
declare interface BaseModel {
|
|
@@ -31,6 +51,7 @@ export declare interface Content {
|
|
|
31
51
|
name: string;
|
|
32
52
|
contentType: Lookup;
|
|
33
53
|
lastUpdate: string;
|
|
54
|
+
status?: Status;
|
|
34
55
|
fields: Field[];
|
|
35
56
|
}
|
|
36
57
|
|
|
@@ -45,10 +66,27 @@ declare interface ContentTypeField extends Lookup {
|
|
|
45
66
|
tsType: string;
|
|
46
67
|
isArray: boolean;
|
|
47
68
|
isRequired?: boolean;
|
|
69
|
+
validations?: Validation[];
|
|
48
70
|
}
|
|
49
71
|
|
|
50
72
|
export declare const createClient: (options?: VSCodeClientOptions) => VSCodeApiClient;
|
|
51
73
|
|
|
74
|
+
declare interface CreateContentParams {
|
|
75
|
+
contentType: string;
|
|
76
|
+
name: string;
|
|
77
|
+
content?: Array<{
|
|
78
|
+
language?: LanguageCode;
|
|
79
|
+
fields: Array<{
|
|
80
|
+
name: string;
|
|
81
|
+
value: any;
|
|
82
|
+
}>;
|
|
83
|
+
}>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
declare interface CreateContentResponse {
|
|
87
|
+
id: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
52
90
|
declare interface Entity extends BaseModel {
|
|
53
91
|
type: 'entity';
|
|
54
92
|
fieldList?: Field_2[];
|
|
@@ -76,7 +114,7 @@ export declare interface Field {
|
|
|
76
114
|
value: any;
|
|
77
115
|
type: FieldType;
|
|
78
116
|
isArray: boolean;
|
|
79
|
-
language:
|
|
117
|
+
language: LanguageCode;
|
|
80
118
|
}
|
|
81
119
|
|
|
82
120
|
declare interface Field_2 {
|
|
@@ -88,6 +126,11 @@ declare interface Field_2 {
|
|
|
88
126
|
validations?: Validation[];
|
|
89
127
|
}
|
|
90
128
|
|
|
129
|
+
declare type FieldSelector = {
|
|
130
|
+
fieldName: string;
|
|
131
|
+
language: string;
|
|
132
|
+
};
|
|
133
|
+
|
|
91
134
|
export declare type FieldType =
|
|
92
135
|
| 'short-text'
|
|
93
136
|
| 'long-text'
|
|
@@ -104,6 +147,7 @@ declare type FilterableFields<M extends Model = Model> = {
|
|
|
104
147
|
lastUpdate?: ClientFilter<string>;
|
|
105
148
|
language?: M['language'];
|
|
106
149
|
contentType?: ClientFilter<string>;
|
|
150
|
+
status?: ClientFilter<Status>;
|
|
107
151
|
includeRelatedContent?: boolean;
|
|
108
152
|
} & AllowedFields<M, 'filter'>;
|
|
109
153
|
|
|
@@ -349,6 +393,13 @@ declare type SortableFields<M extends Model> = {
|
|
|
349
393
|
|
|
350
394
|
declare type SortOrder = 'asc' | 'desc';
|
|
351
395
|
|
|
396
|
+
declare type Status = 'draft' | 'published' | 'changed';
|
|
397
|
+
|
|
398
|
+
declare interface UploadMediaParams {
|
|
399
|
+
file: Blob | File;
|
|
400
|
+
fileName?: string;
|
|
401
|
+
}
|
|
402
|
+
|
|
352
403
|
declare type Validation = { name: string; customArgs?: any };
|
|
353
404
|
|
|
354
405
|
export declare interface VSCodeApiClient extends ApiClient {
|
package/dist/index.js
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
1
|
import { createClient as I } from "@content-island/api-client";
|
|
2
|
-
import { mapContentToModel as
|
|
3
|
-
import * as
|
|
2
|
+
import { mapContentToModel as z } from "@content-island/api-client";
|
|
3
|
+
import * as c from "vscode";
|
|
4
4
|
import _ from "node:crypto";
|
|
5
5
|
import A from "node:util";
|
|
6
|
-
let
|
|
6
|
+
let C;
|
|
7
7
|
const P = () => {
|
|
8
|
-
if (!
|
|
8
|
+
if (!C)
|
|
9
9
|
throw new Error("Extension context has not been set.");
|
|
10
|
-
return
|
|
10
|
+
return C;
|
|
11
11
|
}, S = (t) => {
|
|
12
|
-
|
|
12
|
+
C = t;
|
|
13
13
|
};
|
|
14
14
|
let l = {
|
|
15
15
|
getContext: P,
|
|
16
16
|
setContext: S
|
|
17
17
|
};
|
|
18
|
-
const
|
|
18
|
+
const d = {
|
|
19
19
|
IS_PRODUCTION: !0,
|
|
20
20
|
DEFAULT_API_CLIENT_DOMAIN: "api.contentisland.net",
|
|
21
21
|
DEFAULT_API_CLIENT_VERSION: "1.0",
|
|
22
22
|
DEFAULT_LOGIN_DOMAIN: "app.contentisland.net"
|
|
23
|
-
},
|
|
24
|
-
SALT: `${
|
|
25
|
-
ACCESS_TOKEN_BY_PROJECT_ID: (t) => `${
|
|
26
|
-
METADATA_BY_PROJECT_ID: (t) => `${
|
|
23
|
+
}, w = "content-island-vscode", u = {
|
|
24
|
+
SALT: `${w}.salt`,
|
|
25
|
+
ACCESS_TOKEN_BY_PROJECT_ID: (t) => `${w}.access-token.${t}`,
|
|
26
|
+
METADATA_BY_PROJECT_ID: (t) => `${w}.metadata.${t}`
|
|
27
27
|
}, h = {
|
|
28
28
|
get: async (t) => await l.getContext().secrets.get(u.METADATA_BY_PROJECT_ID(t)),
|
|
29
29
|
set: async (t, o) => {
|
|
30
30
|
await l.getContext().secrets.store(u.METADATA_BY_PROJECT_ID(t), o);
|
|
31
31
|
}
|
|
32
|
-
},
|
|
32
|
+
}, E = {
|
|
33
33
|
get: async (t) => await l.getContext().secrets.get(u.ACCESS_TOKEN_BY_PROJECT_ID(t)),
|
|
34
34
|
set: async (t, o) => {
|
|
35
35
|
await l.getContext().secrets.store(u.ACCESS_TOKEN_BY_PROJECT_ID(t), o);
|
|
36
36
|
}
|
|
37
37
|
}, L = (t) => {
|
|
38
|
-
const s = (t.secureProtocol === void 0 ?
|
|
38
|
+
const s = (t.secureProtocol === void 0 ? d.IS_PRODUCTION : t.secureProtocol) ? "https" : "http", e = t.domain ? t.domain : d.DEFAULT_API_CLIENT_DOMAIN, n = t.apiVersion ? t.apiVersion : d.DEFAULT_API_CLIENT_VERSION;
|
|
39
39
|
return `${s}://${e}/api/${n}`;
|
|
40
40
|
}, f = (t) => {
|
|
41
|
-
const s = (t.secureProtocol === void 0 ?
|
|
41
|
+
const s = (t.secureProtocol === void 0 ? d.IS_PRODUCTION : t.secureProtocol) ? "https" : "http", e = t.loginDomain ? t.loginDomain : d.DEFAULT_LOGIN_DOMAIN;
|
|
42
42
|
return `${s}://${e}/#/?redirect=vscode`;
|
|
43
|
-
},
|
|
43
|
+
}, p = 16, y = (t = p) => _.randomBytes(t).toString("hex"), O = 64, m = "sha512", x = 1e5, D = async (t, o, s = O) => (await A.promisify(_.pbkdf2)(t, o, x, s, m)).toString("hex"), N = async () => {
|
|
44
44
|
const t = l.getContext();
|
|
45
45
|
let o = await t.secrets.get(u.SALT);
|
|
46
|
-
return o || (o =
|
|
47
|
-
},
|
|
46
|
+
return o || (o = y(32), await t.secrets.store(u.SALT, o)), o;
|
|
47
|
+
}, M = 32, k = async (t) => {
|
|
48
48
|
const o = await N();
|
|
49
|
-
return await D(t, o,
|
|
50
|
-
},
|
|
49
|
+
return await D(t, o, M);
|
|
50
|
+
}, g = async (t) => {
|
|
51
51
|
const o = "Open Login Page";
|
|
52
|
-
if (await
|
|
52
|
+
if (await c.window.showInformationMessage(
|
|
53
53
|
"You need to log in to Content Island to continue. Do you want to open the login page?",
|
|
54
54
|
o
|
|
55
55
|
) !== o)
|
|
56
56
|
return;
|
|
57
|
-
const e =
|
|
58
|
-
await
|
|
59
|
-
},
|
|
57
|
+
const e = c.Uri.parse(f(t));
|
|
58
|
+
await c.env.openExternal(e);
|
|
59
|
+
}, R = (t) => {
|
|
60
60
|
try {
|
|
61
61
|
return JSON.parse(t.message);
|
|
62
62
|
} catch {
|
|
63
63
|
return null;
|
|
64
64
|
}
|
|
65
|
-
},
|
|
65
|
+
}, r = (t, o) => async (...s) => {
|
|
66
66
|
try {
|
|
67
67
|
return await t(...s);
|
|
68
68
|
} catch (e) {
|
|
69
|
-
const n =
|
|
69
|
+
const n = R(e);
|
|
70
70
|
if (n) {
|
|
71
71
|
if (n.status === 401)
|
|
72
|
-
throw await
|
|
73
|
-
n.status === 403 &&
|
|
72
|
+
throw await g(o), new Error("Unauthorized: Please log in to continue.");
|
|
73
|
+
n.status === 403 && c.window.showErrorMessage("Access forbidden: You do not have permission to perform this action.");
|
|
74
74
|
}
|
|
75
75
|
throw e;
|
|
76
76
|
}
|
|
@@ -90,24 +90,24 @@ const g = {
|
|
|
90
90
|
body: JSON.stringify(a)
|
|
91
91
|
});
|
|
92
92
|
} catch {
|
|
93
|
-
|
|
93
|
+
c.window.showErrorMessage(
|
|
94
94
|
"Unable to connect to the authorization server. Check your network connection and try again."
|
|
95
95
|
);
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
98
|
if (!n.ok) {
|
|
99
|
-
n.status === 401 ? await
|
|
99
|
+
n.status === 401 ? await g(t) : n.status === 403 && c.window.showErrorMessage(
|
|
100
100
|
"You do not have permission to access this resource. Please check your access rights in Content Island."
|
|
101
|
-
),
|
|
101
|
+
), c.window.showErrorMessage(
|
|
102
102
|
"Failed to obtain access token. Please complete the authorization in Content Island."
|
|
103
103
|
);
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
106
|
try {
|
|
107
|
-
const
|
|
108
|
-
return (!
|
|
107
|
+
const i = await n.json();
|
|
108
|
+
return (!i?.accessToken || typeof i.accessToken != "string") && (c.window.showErrorMessage("Invalid response from the authorization server."), await g(t)), i.accessToken;
|
|
109
109
|
} catch {
|
|
110
|
-
|
|
110
|
+
c.window.showErrorMessage("Error processing response from the authorization server.");
|
|
111
111
|
}
|
|
112
112
|
}, T = (t) => {
|
|
113
113
|
const o = `PREVIEW_${t.accessToken}`, s = I({ ...t, accessToken: o });
|
|
@@ -117,7 +117,7 @@ const g = {
|
|
|
117
117
|
const e = await s.getProject();
|
|
118
118
|
return {
|
|
119
119
|
...e,
|
|
120
|
-
id: await
|
|
120
|
+
id: await k(e.id)
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
123
|
};
|
|
@@ -131,14 +131,14 @@ const g = {
|
|
|
131
131
|
const a = await U(t, e, n);
|
|
132
132
|
if (a) {
|
|
133
133
|
s(a, n);
|
|
134
|
-
const
|
|
135
|
-
await
|
|
134
|
+
const i = await o.getProject();
|
|
135
|
+
await E.set(i.id, a), await h.set(i.id, n);
|
|
136
136
|
}
|
|
137
137
|
},
|
|
138
138
|
authorizeByProjectId: async (e) => {
|
|
139
|
-
const n = await
|
|
139
|
+
const n = await E.get(e), a = await h.get(e);
|
|
140
140
|
if (!n || !a) {
|
|
141
|
-
await
|
|
141
|
+
await g(t);
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
s(n, a);
|
|
@@ -146,16 +146,22 @@ const g = {
|
|
|
146
146
|
setVSCodeExtensionContext: (e) => {
|
|
147
147
|
l.setContext(e);
|
|
148
148
|
},
|
|
149
|
-
getProject: (...e) =>
|
|
150
|
-
getContentList: (...e) =>
|
|
151
|
-
getContent: (...e) =>
|
|
152
|
-
getRawContentList: (...e) =>
|
|
153
|
-
getRawContent: (...e) =>
|
|
154
|
-
getContentListSize: (...e) =>
|
|
155
|
-
updateContentFieldValue: (
|
|
149
|
+
getProject: (...e) => r(() => o.getProject(...e), t)(),
|
|
150
|
+
getContentList: (...e) => r(() => o.getContentList(...e), t)(),
|
|
151
|
+
getContent: (...e) => r(() => o.getContent(...e), t)(),
|
|
152
|
+
getRawContentList: (...e) => r(() => o.getRawContentList(...e), t)(),
|
|
153
|
+
getRawContent: (...e) => r(() => o.getRawContent(...e), t)(),
|
|
154
|
+
getContentListSize: (...e) => r(() => o.getContentListSize(...e), t)(),
|
|
155
|
+
updateContentFieldValue: (e, n, a) => r(
|
|
156
|
+
() => o.updateContentFieldValue(e, n, a),
|
|
157
|
+
t
|
|
158
|
+
)(),
|
|
159
|
+
uploadMedia: (...e) => r(() => o.uploadMedia(...e), t)(),
|
|
160
|
+
createContent: (...e) => r(() => o.createContent(...e), t)(),
|
|
161
|
+
publishContent: (...e) => r(() => o.publishContent(...e), t)()
|
|
156
162
|
};
|
|
157
163
|
};
|
|
158
164
|
export {
|
|
159
165
|
B as createClient,
|
|
160
|
-
|
|
166
|
+
z as mapContentToModel
|
|
161
167
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@content-island/vscode-api-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Content Island - VSCode Extension API Client",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
@@ -24,15 +24,15 @@
|
|
|
24
24
|
"#*": "./src/*"
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
|
-
"
|
|
28
|
-
"build:dev": "vite build --mode development",
|
|
27
|
+
"create-env": "sh ./create-dev-env.sh",
|
|
28
|
+
"build:dev": "npm run create-env && vite build --mode development",
|
|
29
29
|
"build": "vite build",
|
|
30
30
|
"type-check": "tsc --noEmit --preserveWatchOutput",
|
|
31
31
|
"test": "vitest run -c ./config/test/config.ts",
|
|
32
32
|
"test:watch": "vitest -c ./config/test/config.ts"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@content-island/api-client": "0.
|
|
35
|
+
"@content-island/api-client": "0.19.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@content-island/common-backend": "*",
|