@vtecx/vtecxnext 2.2.1 → 2.2.3

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.
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { NextRequest } from 'next/server';
3
2
  import type { Readable } from 'node:stream';
4
3
  /**
@@ -27,18 +26,23 @@ export type CreateGroupadminInfo = {
27
26
  };
28
27
  export declare class VtecxNext {
29
28
  /** Request */
30
- readonly req: NextRequest;
29
+ readonly req: NextRequest | undefined;
31
30
  /** Response status */
32
31
  private resStatus;
33
32
  /** Response headers */
34
33
  private resHeaders;
35
34
  /** binary data */
36
35
  private bufferData;
36
+ /** Access Token (for batch) */
37
+ private accessToken;
38
+ /** login cookies */
39
+ private loginCookies;
37
40
  /**
38
41
  * constructor
39
42
  * @param req Request
43
+ * @param accessToken Access token (for batch)
40
44
  */
41
- constructor(req: NextRequest);
45
+ constructor(req?: NextRequest, accessToken?: string);
42
46
  /**
43
47
  * get url parameter.
44
48
  * @param name parameter name
@@ -773,14 +777,16 @@ export declare class VtecxNext {
773
777
  * @param uri key
774
778
  * @param bysize true if registering with specified size
775
779
  * @param filename attachment file name
780
+ * @param arrayBuffer content (for batch)
776
781
  * @return message
777
782
  */
778
- putcontent: (uri: string, filename?: string) => Promise<any>;
783
+ putcontent: (uri: string, filename?: string, arrayBuffer?: ArrayBuffer) => Promise<any>;
779
784
  /**
780
785
  * upload content
781
786
  * @param uri key
782
787
  * @param bysize true if registering with specified size
783
788
  * @param filename attachment file name
789
+ * @param arrayBuffer content (for batch)
784
790
  * @return message
785
791
  */
786
792
  private putcontentProc;
@@ -900,6 +906,16 @@ export declare class VtecxNext {
900
906
  * @param response vte.cxからのレスポンス
901
907
  */
902
908
  private setCookie;
909
+ /**
910
+ * ログイン時にレスポンスされたvte.cxからのset-cookieを保持する。
911
+ * @param response vte.cxからのレスポンス
912
+ */
913
+ private setLoginCookie;
914
+ /**
915
+ * ログイン後のCookie編集
916
+ * @returns cookie
917
+ */
918
+ private editRequestCookie;
903
919
  /**
904
920
  * vte.cxからのレスポンスヘッダを、ブラウザへレスポンスする。
905
921
  * コンテンツの戻し時に使用。
package/dist/vtecxnext.js CHANGED
@@ -54,12 +54,23 @@ class VtecxNext {
54
54
  resHeaders = {};
55
55
  /** binary data */
56
56
  bufferData = null;
57
+ /** Access Token (for batch) */
58
+ accessToken;
59
+ /** login cookies */
60
+ loginCookies = {};
57
61
  /**
58
62
  * constructor
59
63
  * @param req Request
64
+ * @param accessToken Access token (for batch)
60
65
  */
61
- constructor(req) {
62
- this.req = req;
66
+ constructor(req, accessToken) {
67
+ if (req) {
68
+ this.req = req;
69
+ }
70
+ else {
71
+ this.req = undefined;
72
+ this.accessToken = accessToken;
73
+ }
63
74
  }
64
75
  /**
65
76
  * get url parameter.
@@ -67,6 +78,9 @@ class VtecxNext {
67
78
  * @returns parameter value
68
79
  */
69
80
  getParameter = (name) => {
81
+ if (!this.req) {
82
+ throw new VtecxNextError(421, 'Request is required.');
83
+ }
70
84
  const url = new URL(this.req.url);
71
85
  const params = url.searchParams;
72
86
  const val = params.get(name);
@@ -91,6 +105,9 @@ class VtecxNext {
91
105
  * @returns buffer
92
106
  */
93
107
  buffer = async (readable) => {
108
+ if (!this.req) {
109
+ throw new VtecxNextError(421, 'Request is required.');
110
+ }
94
111
  let tmpReadable;
95
112
  if (readable === undefined || readable === null) {
96
113
  const arrayBuffer = await this.req.arrayBuffer();
@@ -127,6 +144,9 @@ class VtecxNext {
127
144
  */
128
145
  checkXRequestedWith = () => {
129
146
  //console.log(`[vtecxnext checkXRequestedWith] start.`)
147
+ if (!this.req) {
148
+ throw new VtecxNextError(421, 'Request is required.');
149
+ }
130
150
  let hasX = false;
131
151
  this.req.headers.forEach((value, key, parent) => {
132
152
  //console.log(`[vtecxnext checkXRequestedWith] key=${key} value=${value}`)
@@ -365,6 +385,8 @@ class VtecxNext {
365
385
  }
366
386
  // vte.cxからのset-cookieを転記
367
387
  this.setCookie(response);
388
+ // 引き続きAPIで処理を行う場合のため、set-cookie情報を保持しておく
389
+ this.setLoginCookie(response);
368
390
  const data = await response.json();
369
391
  return { status: response.status, message: data.feed.title };
370
392
  };
@@ -3039,6 +3061,9 @@ class VtecxNext {
3039
3061
  */
3040
3062
  savefiles = async (uri, bysize) => {
3041
3063
  //console.log(`[vtecxnext savefiles] start. uri=${uri}`)
3064
+ if (!this.req) {
3065
+ throw new VtecxNextError(421, 'Request is required.');
3066
+ }
3042
3067
  // キー入力値チェック
3043
3068
  checkUri(uri);
3044
3069
  const formData = await this.req.formData();
@@ -3092,32 +3117,43 @@ class VtecxNext {
3092
3117
  * @param uri key
3093
3118
  * @param bysize true if registering with specified size
3094
3119
  * @param filename attachment file name
3120
+ * @param arrayBuffer content (for batch)
3095
3121
  * @return message
3096
3122
  */
3097
- putcontent = async (uri, filename) => {
3098
- return this.putcontentProc(uri, false, filename);
3123
+ putcontent = async (uri, filename, arrayBuffer) => {
3124
+ return this.putcontentProc(uri, false, filename, arrayBuffer);
3099
3125
  };
3100
3126
  /**
3101
3127
  * upload content
3102
3128
  * @param uri key
3103
3129
  * @param bysize true if registering with specified size
3104
3130
  * @param filename attachment file name
3131
+ * @param arrayBuffer content (for batch)
3105
3132
  * @return message
3106
3133
  */
3107
- putcontentProc = async (uri, bysize, filename) => {
3134
+ putcontentProc = async (uri, bysize, filename, arrayBuffer) => {
3108
3135
  //console.log(`[vtecxnext putcontent] start. uri=${uri} content-type:${req.headers['content-type']} content-length:${req.headers['content-length']}`)
3136
+ if (!this.req && !arrayBuffer) {
3137
+ throw new VtecxNextError(421, 'Request is required.');
3138
+ }
3109
3139
  // キー入力値チェック
3110
3140
  checkUri(uri);
3111
3141
  // vte.cxへリクエスト
3112
3142
  const method = 'PUT';
3113
3143
  const url = `${SERVLETPATH_PROVIDER}${uri}?_content${bysize ? '&_bysize' : ''}`;
3114
3144
  //console.log(`[vtecxnext putcontent] request. url=${url}`)
3115
- const headers = { 'Content-Type': this.req.headers.get('content-type') };
3145
+ const headers = { 'Content-Type': this.req?.headers.get('content-type') };
3116
3146
  if (filename) {
3117
3147
  headers['Content-Disposition'] = `attachment; filename="${encodeURIComponent(filename)}"`;
3118
3148
  }
3119
3149
  //const buf = await buffer(this.req)
3120
- const buf = await this.req.arrayBuffer();
3150
+ let buf;
3151
+ if (arrayBuffer) {
3152
+ buf = arrayBuffer;
3153
+ }
3154
+ else if (this.req) {
3155
+ buf = await this.req.arrayBuffer();
3156
+ }
3121
3157
  let response;
3122
3158
  try {
3123
3159
  response = await this.requestVtecx(method, url, buf, headers);
@@ -3149,6 +3185,9 @@ class VtecxNext {
3149
3185
  */
3150
3186
  postcontent = async (parenturi, extension, filename) => {
3151
3187
  //console.log(`[vtecxnext postcontent] start. parenturi=${parenturi} extension=${extension} filename=${filename}`)
3188
+ if (!this.req) {
3189
+ throw new VtecxNextError(421, 'Request is required.');
3190
+ }
3152
3191
  // キー入力値チェック
3153
3192
  checkUri(parenturi);
3154
3193
  // vte.cxへリクエスト
@@ -3256,7 +3295,7 @@ class VtecxNext {
3256
3295
  const method = 'PUT';
3257
3296
  const url = `${SERVLETPATH_PROVIDER}${uri}?_content&_signedurl`;
3258
3297
  //console.log(`[vtecxnext getSignedUrlToPutContent] request. url=${url}`)
3259
- const headers = { 'Content-Type': this.req.headers.get('content-type') };
3298
+ const headers = { 'Content-Type': this.req?.headers?.get('content-type') };
3260
3299
  if (filename) {
3261
3300
  headers['Content-Disposition'] = `attachment; filename="${encodeURIComponent(filename)}"`;
3262
3301
  }
@@ -3288,7 +3327,7 @@ class VtecxNext {
3288
3327
  const method = 'POST';
3289
3328
  const url = `${SERVLETPATH_PROVIDER}${parenturi}?_content&_signedurl${extension ? '&_ext=' + extension : ''}`;
3290
3329
  //console.log(`[vtecxnext getSignedUrlToPostContent] request. url=${url}`)
3291
- const headers = { 'Content-Type': this.req.headers.get('content-type') };
3330
+ const headers = { 'Content-Type': this.req?.headers?.get('content-type') };
3292
3331
  if (filename) {
3293
3332
  headers['Content-Disposition'] = `attachment; filename="${encodeURIComponent(filename)}"`;
3294
3333
  }
@@ -3554,8 +3593,12 @@ class VtecxNext {
3554
3593
  */
3555
3594
  requestVtecx = async (method, url, body, additionalHeaders, targetService, mode) => {
3556
3595
  // cookieの値をvte.cxへのリクエストヘッダに設定
3557
- const cookie = this.req ? this.req.headers.get('cookie') : undefined;
3596
+ const cookie = this.editRequestCookie();
3597
+ //console.log(`[requestVtecx] cookie = ${cookie}`)
3558
3598
  const headers = cookie ? { 'Cookie': cookie } : {};
3599
+ if (this.accessToken) {
3600
+ headers.Authorization = `Token ${this.accessToken}`;
3601
+ }
3559
3602
  if (additionalHeaders) {
3560
3603
  //console.log(`[vtecxnext requestVtecx] additionalHeaders for`)
3561
3604
  for (const key in additionalHeaders) {
@@ -3596,6 +3639,50 @@ class VtecxNext {
3596
3639
  this.resHeaders['set-cookie'] = setCookieVal;
3597
3640
  }
3598
3641
  };
3642
+ /**
3643
+ * ログイン時にレスポンスされたvte.cxからのset-cookieを保持する。
3644
+ * @param response vte.cxからのレスポンス
3645
+ */
3646
+ setLoginCookie = (response) => {
3647
+ // set-cookieの値をレスポンスヘッダ格納変数にセット
3648
+ let setCookieVal = response.headers.get('set-cookie');
3649
+ if (setCookieVal) {
3650
+ const tmpCookies = setCookieVal.split(';');
3651
+ for (const tmpCookie of tmpCookies) {
3652
+ const tmpKeyVal = tmpCookie.split('=');
3653
+ this.loginCookies[tmpKeyVal[0]] = tmpKeyVal[1];
3654
+ }
3655
+ }
3656
+ };
3657
+ /**
3658
+ * ログイン後のCookie編集
3659
+ * @returns cookie
3660
+ */
3661
+ editRequestCookie = () => {
3662
+ let cookie = this.req ? this.req.headers.get('cookie') : null;
3663
+ if (!this.loginCookies) {
3664
+ return cookie;
3665
+ }
3666
+ let retCookie = '';
3667
+ if (cookie) {
3668
+ const tmpCookies = cookie.split(';');
3669
+ for (const tmpCookie of tmpCookies) {
3670
+ const tmpKeyVal = tmpCookie.trim().split('=');
3671
+ const tmpName = tmpKeyVal[0];
3672
+ const tmpVal = tmpKeyVal[1];
3673
+ if (!this.loginCookies.hasOwnProperty(tmpName)) {
3674
+ retCookie = `${retCookie}${tmpName}=${tmpVal}; `;
3675
+ //} else {
3676
+ //console.log(`[editRequestCookie] hasOwnProperty (not set) : ${tmpName}=${tmpVal}`)
3677
+ }
3678
+ }
3679
+ }
3680
+ for (const tmpName in this.loginCookies) {
3681
+ const tmpVal = this.loginCookies[tmpName];
3682
+ retCookie = `${retCookie}${tmpName}=${tmpVal};`;
3683
+ }
3684
+ return retCookie;
3685
+ };
3599
3686
  /**
3600
3687
  * vte.cxからのレスポンスヘッダを、ブラウザへレスポンスする。
3601
3688
  * コンテンツの戻し時に使用。
@@ -3623,6 +3710,9 @@ class VtecxNext {
3623
3710
  */
3624
3711
  oauth = async (provider, oauthUrl) => {
3625
3712
  //console.log(`[vtecxnext oauth] start. provider=${provider} oauthUrl=${oauthUrl}`)
3713
+ if (!this.req) {
3714
+ throw new VtecxNextError(421, 'Request is required.');
3715
+ }
3626
3716
  // TODO reCAPTCHAを必須とすべき?
3627
3717
  // 入力チェック
3628
3718
  checkNotNull(provider, 'OAuth provider');
@@ -3672,6 +3762,9 @@ class VtecxNext {
3672
3762
  */
3673
3763
  oauthGetAccesstoken = async (provider, accesstokenUrl) => {
3674
3764
  //console.log(`[vtecxnext oauthGetAccesstoken] start. provider=${provider} oauthUrl=${accesstokenUrl}`)
3765
+ if (!this.req) {
3766
+ throw new VtecxNextError(421, 'Request is required.');
3767
+ }
3675
3768
  // stateチェック
3676
3769
  const parseUrl = url_1.default.parse(this.req.url ?? '', true);
3677
3770
  const state = parseUrl.query.state;
@@ -3721,12 +3814,16 @@ class VtecxNext {
3721
3814
  'client_id': client_id,
3722
3815
  'client_secret': client_secret
3723
3816
  };
3724
- const accesstokenBody = createURLSearchParams(accessTokenData);
3817
+ const accesstokenBody = createURLSearchParams(accessTokenData).toString();
3725
3818
  //const accesstokenBodyStr = `grant_type=authorization_code&code=${code}&redirect_uri=${encodeRedirect_uri}&client_id=${client_id}&client_secret=${client_secret}`
3726
3819
  //console.log(`[vtecxnext oauthGetAccesstoken] accesstokenUrl=${accesstokenUrl}`)
3727
3820
  //console.log(`[vtecxnext oauthGetAccesstoken] accesstokenBodyStr=${accesstokenBodyStr}`)
3728
3821
  //const accesstokenBody = Buffer.from(accesstokenBodyStr, 'utf-8')
3729
3822
  const requestInit = {
3823
+ headers: {
3824
+ 'Content-Type': 'application/x-www-form-urlencoded',
3825
+ 'Content-Length': String(accesstokenBody.length),
3826
+ },
3730
3827
  body: accesstokenBody,
3731
3828
  method: accesstokenMethod,
3732
3829
  cache: 'no-cache',
@@ -3909,33 +4006,28 @@ exports.FetchError = FetchError;
3909
4006
  * vte.cxへリクエスト
3910
4007
  * @param method メソッド
3911
4008
  * @param url サーブレットパス以降のURL
3912
- * @param headers リクエストヘッダ。連想配列で指定。
4009
+ * @param pHeaders リクエストヘッダ。連想配列で指定。
3913
4010
  * @param body リクエストデータ
3914
4011
  * @param mode RequestMode ("cors" | "navigate" | "no-cors" | "same-origin")
3915
4012
  * @returns promise
3916
4013
  */
3917
- const fetchVtecx = async (method, url, headers, body, mode) => {
4014
+ const fetchVtecx = async (method, url, pHeaders, body, mode) => {
3918
4015
  //console.log(`[vtecxnext fetchVtecx] url=${process.env.VTECX_URL}${url}`)
3919
- headers['X-Requested-With'] = 'XMLHttpRequest';
4016
+ const headers = [];
4017
+ if (pHeaders) {
4018
+ for (const key in pHeaders) {
4019
+ //console.log(`[vtecxnext fetchVtecx] request header = ${key}: ${pHeaders[key]}`)
4020
+ headers.push([key, pHeaders[key]]);
4021
+ }
4022
+ }
4023
+ headers.push(['X-Requested-With', 'XMLHttpRequest']);
3920
4024
  if (VTECX_SERVICENAME) {
3921
- headers['X-SERVICENAME'] = VTECX_SERVICENAME;
4025
+ headers.push(['X-SERVICENAME', VTECX_SERVICENAME]);
3922
4026
  }
3923
4027
  const apiKey = process.env.VTECX_APIKEY;
3924
4028
  if (apiKey && !url.startsWith(SERVLETPATH_DATA)) {
3925
- //headers['Authorization'] = `APIKey ${apiKey}`
3926
4029
  const apiKeyVal = `APIKey ${apiKey}`;
3927
- if (headers.Authorization) {
3928
- if (Array.isArray(headers.Authorization)) {
3929
- headers.Authorization.push(apiKeyVal);
3930
- }
3931
- else {
3932
- const tmp = headers.Authorization;
3933
- headers.Authorization = [tmp, apiKeyVal];
3934
- }
3935
- }
3936
- else {
3937
- headers.Authorization = apiKeyVal;
3938
- }
4030
+ headers.push(['Authorization', apiKeyVal]);
3939
4031
  }
3940
4032
  //console.log(`[vtecxnext fetchVtecx] headers = ${JSON.stringify(headers)}`)
3941
4033
  const requestInit = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtecx/vtecxnext",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "vte.cx Next.js api",
5
5
  "main": "dist/index.js",
6
6
  "files": [