mixi2-js 1.3.0 → 1.4.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.
@@ -287,11 +287,13 @@ declare class Client {
287
287
  private readonly authenticator;
288
288
  private readonly authKey?;
289
289
  constructor(options: ClientOptions);
290
+ getAccessToken(): Promise<string>;
290
291
  private getMetadata;
291
292
  private call;
292
293
  getUsers(userIdList: string[]): Promise<User[]>;
293
294
  getPosts(postIdList: string[]): Promise<Post[]>;
294
295
  createPost(request: CreatePostRequest): Promise<Post>;
296
+ deletePost(postId: string): Promise<boolean>;
295
297
  initiatePostMediaUpload(request: InitiatePostMediaUploadRequest): Promise<InitiatePostMediaUploadResponse>;
296
298
  getPostMediaStatus(mediaId: string): Promise<GetPostMediaStatusResponse>;
297
299
  sendChatMessage(request: SendChatMessageRequest): Promise<ChatMessage>;
@@ -287,11 +287,13 @@ declare class Client {
287
287
  private readonly authenticator;
288
288
  private readonly authKey?;
289
289
  constructor(options: ClientOptions);
290
+ getAccessToken(): Promise<string>;
290
291
  private getMetadata;
291
292
  private call;
292
293
  getUsers(userIdList: string[]): Promise<User[]>;
293
294
  getPosts(postIdList: string[]): Promise<Post[]>;
294
295
  createPost(request: CreatePostRequest): Promise<Post>;
296
+ deletePost(postId: string): Promise<boolean>;
295
297
  initiatePostMediaUpload(request: InitiatePostMediaUploadRequest): Promise<InitiatePostMediaUploadResponse>;
296
298
  getPostMediaStatus(mediaId: string): Promise<GetPostMediaStatusResponse>;
297
299
  sendChatMessage(request: SendChatMessageRequest): Promise<ChatMessage>;
@@ -148,6 +148,26 @@ var MediaUploader = class {
148
148
  };
149
149
  }
150
150
  /**
151
+ * 取得した uploadUrl にメディアデータを HTTP POST でアップロードする。
152
+ * Authorization ヘッダーに Bearer トークンを自動付与する。
153
+ * Content-Type は `application/octet-stream` を使用する。
154
+ */
155
+ async upload(uploadUrl, data) {
156
+ const token = await this.client.getAccessToken();
157
+ const res = await fetch(uploadUrl, {
158
+ method: "POST",
159
+ headers: {
160
+ Authorization: `Bearer ${token}`,
161
+ "Content-Type": "application/octet-stream"
162
+ },
163
+ body: data
164
+ });
165
+ if (!res.ok) {
166
+ const body = await res.text().catch(() => "");
167
+ throw new Error(`Media upload failed (${res.status}): ${body}`);
168
+ }
169
+ }
170
+ /**
151
171
  * メディアの処理が完了するまでポーリングして待機する。
152
172
  * 完了時に mediaId を返す。失敗時はエラーをスローする。
153
173
  */
@@ -1,4 +1,4 @@
1
- import { L as PostPublishingType, d as EventReason, f as EventType, h as InitiatePostMediaUploadRequest, j as PostMask, l as CreatePostRequest, o as EventHandler, t as Client, u as Event } from "../client-C90Zd_yq.cjs";
1
+ import { L as PostPublishingType, d as EventReason, f as EventType, h as InitiatePostMediaUploadRequest, j as PostMask, l as CreatePostRequest, o as EventHandler, t as Client, u as Event } from "../client-DK9LqeiF.cjs";
2
2
 
3
3
  //#region src/helpers/address.d.ts
4
4
  /**
@@ -114,6 +114,12 @@ declare class MediaUploader {
114
114
  * メディアアップロードを開始し、uploadUrl と mediaId を返す。
115
115
  */
116
116
  initiate(request: InitiatePostMediaUploadRequest): Promise<UploadedMedia>;
117
+ /**
118
+ * 取得した uploadUrl にメディアデータを HTTP POST でアップロードする。
119
+ * Authorization ヘッダーに Bearer トークンを自動付与する。
120
+ * Content-Type は `application/octet-stream` を使用する。
121
+ */
122
+ upload(uploadUrl: string, data: ArrayBuffer): Promise<void>;
117
123
  /**
118
124
  * メディアの処理が完了するまでポーリングして待機する。
119
125
  * 完了時に mediaId を返す。失敗時はエラーをスローする。
@@ -1,4 +1,4 @@
1
- import { L as PostPublishingType, d as EventReason, f as EventType, h as InitiatePostMediaUploadRequest, j as PostMask, l as CreatePostRequest, o as EventHandler, t as Client, u as Event } from "../client-DPeVTCYr.mjs";
1
+ import { L as PostPublishingType, d as EventReason, f as EventType, h as InitiatePostMediaUploadRequest, j as PostMask, l as CreatePostRequest, o as EventHandler, t as Client, u as Event } from "../client-GWUs7tD3.mjs";
2
2
 
3
3
  //#region src/helpers/address.d.ts
4
4
  /**
@@ -114,6 +114,12 @@ declare class MediaUploader {
114
114
  * メディアアップロードを開始し、uploadUrl と mediaId を返す。
115
115
  */
116
116
  initiate(request: InitiatePostMediaUploadRequest): Promise<UploadedMedia>;
117
+ /**
118
+ * 取得した uploadUrl にメディアデータを HTTP POST でアップロードする。
119
+ * Authorization ヘッダーに Bearer トークンを自動付与する。
120
+ * Content-Type は `application/octet-stream` を使用する。
121
+ */
122
+ upload(uploadUrl: string, data: ArrayBuffer): Promise<void>;
117
123
  /**
118
124
  * メディアの処理が完了するまでポーリングして待機する。
119
125
  * 完了時に mediaId を返す。失敗時はエラーをスローする。
@@ -147,6 +147,26 @@ var MediaUploader = class {
147
147
  };
148
148
  }
149
149
  /**
150
+ * 取得した uploadUrl にメディアデータを HTTP POST でアップロードする。
151
+ * Authorization ヘッダーに Bearer トークンを自動付与する。
152
+ * Content-Type は `application/octet-stream` を使用する。
153
+ */
154
+ async upload(uploadUrl, data) {
155
+ const token = await this.client.getAccessToken();
156
+ const res = await fetch(uploadUrl, {
157
+ method: "POST",
158
+ headers: {
159
+ Authorization: `Bearer ${token}`,
160
+ "Content-Type": "application/octet-stream"
161
+ },
162
+ body: data
163
+ });
164
+ if (!res.ok) {
165
+ const body = await res.text().catch(() => "");
166
+ throw new Error(`Media upload failed (${res.status}): ${body}`);
167
+ }
168
+ }
169
+ /**
150
170
  * メディアの処理が完了するまでポーリングして待機する。
151
171
  * 完了時に mediaId を返す。失敗時はエラーをスローする。
152
172
  */
package/dist/index.cjs CHANGED
@@ -315,6 +315,9 @@ var Client = class {
315
315
  this.authenticator = options.authenticator;
316
316
  this.authKey = options.authKey;
317
317
  }
318
+ async getAccessToken() {
319
+ return this.authenticator.getAccessToken();
320
+ }
318
321
  async getMetadata() {
319
322
  const token = await this.authenticator.getAccessToken();
320
323
  const metadata = new _grpc_grpc_js.Metadata();
@@ -322,18 +325,17 @@ var Client = class {
322
325
  if (this.authKey) metadata.add("x-auth-key", this.authKey);
323
326
  return metadata;
324
327
  }
325
- call(method, request) {
326
- return this.getMetadata().then((metadata) => {
327
- return new Promise((resolve, reject) => {
328
- const fn = this.grpcClient[method];
329
- if (!fn) {
330
- reject(/* @__PURE__ */ new Error(`Method "${method}" not found on gRPC client`));
331
- return;
332
- }
333
- fn.call(this.grpcClient, request, metadata, (err, response) => {
334
- if (err) reject(err);
335
- else resolve(response);
336
- });
328
+ async call(method, request) {
329
+ const metadata = await this.getMetadata();
330
+ return new Promise((resolve, reject) => {
331
+ const fn = this.grpcClient[method];
332
+ if (!fn) {
333
+ reject(/* @__PURE__ */ new Error(`Method "${method}" not found on gRPC client`));
334
+ return;
335
+ }
336
+ fn.call(this.grpcClient, request, metadata, (err, response) => {
337
+ if (err) reject(err);
338
+ else resolve(response);
337
339
  });
338
340
  });
339
341
  }
@@ -346,6 +348,9 @@ var Client = class {
346
348
  async createPost(request) {
347
349
  return convertPost((await this.call("createPost", request)).post);
348
350
  }
351
+ async deletePost(postId) {
352
+ return (await this.call("deletePost", { postId })).deleted ?? false;
353
+ }
349
354
  async initiatePostMediaUpload(request) {
350
355
  return this.call("initiatePostMediaUpload", request);
351
356
  }
@@ -525,27 +530,29 @@ var StreamWatcher = class {
525
530
  if (!fn) throw new Error("subscribeEvents method not found on stream client");
526
531
  return fn.call(this.streamClient, {}, metadata);
527
532
  }
528
- async reconnect() {
529
- const maxRetries = this.maxRetries;
530
- let lastError;
531
- for (let i = 0; i < maxRetries; i++) {
532
- if (this.aborted) throw new Error("Watcher aborted");
533
- await new Promise((resolve) => setTimeout(resolve, Math.pow(2, i) * 1e3));
534
- try {
535
- return await this.connect();
536
- } catch (err) {
537
- lastError = err instanceof Error ? err : new Error(String(err));
538
- console.warn(`Reconnect attempt ${i + 1}/${maxRetries} failed:`, lastError.message);
539
- }
540
- }
541
- throw lastError || /* @__PURE__ */ new Error("Failed to reconnect");
533
+ async reconnect(retryIndex) {
534
+ if (this.aborted) throw new Error("Watcher aborted");
535
+ const backoff = Math.min(Math.pow(2, retryIndex) * 1e3, 3e4);
536
+ await new Promise((resolve) => setTimeout(resolve, backoff));
537
+ if (this.aborted) throw new Error("Watcher aborted");
538
+ return this.connect();
542
539
  }
543
540
  async watch(handler) {
544
541
  this.aborted = false;
545
542
  let stream = await this.connect();
543
+ let consecutiveFailures = 0;
546
544
  return new Promise((resolve, reject) => {
547
545
  const setupStream = (s) => {
546
+ let receivedData = false;
547
+ const connectionTimeout = setTimeout(() => {
548
+ if (!receivedData && !this.aborted) s.destroy(/* @__PURE__ */ new Error("Connection timeout: no data received"));
549
+ }, 3e4);
548
550
  s.on("data", (response) => {
551
+ if (!receivedData) {
552
+ receivedData = true;
553
+ clearTimeout(connectionTimeout);
554
+ consecutiveFailures = 0;
555
+ }
549
556
  const events = (response.events || []).map(convertEvent);
550
557
  for (const event of events) {
551
558
  if (event.eventType === require_types.EventType.PING) continue;
@@ -554,14 +561,20 @@ var StreamWatcher = class {
554
561
  });
555
562
  let disconnected = false;
556
563
  const handleDisconnect = async () => {
564
+ clearTimeout(connectionTimeout);
557
565
  if (disconnected) return;
558
566
  disconnected = true;
559
567
  if (this.aborted) {
560
568
  resolve();
561
569
  return;
562
570
  }
571
+ if (!receivedData) consecutiveFailures++;
572
+ if (consecutiveFailures >= this.maxRetries) {
573
+ reject(/* @__PURE__ */ new Error(`Failed to reconnect after ${this.maxRetries} consecutive attempts`));
574
+ return;
575
+ }
563
576
  try {
564
- stream = await this.reconnect();
577
+ stream = await this.reconnect(consecutiveFailures);
565
578
  setupStream(stream);
566
579
  } catch (reconnectErr) {
567
580
  reject(reconnectErr);
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as PostCreatedEvent, B as SendChatMessageRequest, C as MediaUploadType, D as PingEvent, E as OfficialStampSet, F as PostMediaType, G as UserVisibility, H as User, I as PostMediaVideo, L as PostPublishingType, M as PostMaskType, N as PostMedia, O as Post, P as PostMediaImage, R as PostStamp, S as MediaUploadStatus, T as OfficialStamp, U as UserAccessLevel, V as StampSetType, W as UserAvatar, _ as LanguageCode, a as OAuth2Authenticator, b as MediaStamp, c as ChatMessageReceivedEvent, d as EventReason, f as EventType, g as InitiatePostMediaUploadResponse, h as InitiatePostMediaUploadRequest, i as AuthenticatorOptions, j as PostMask, k as PostAccessLevel, l as CreatePostRequest, m as GetStampsRequest, n as ClientOptions, o as EventHandler, p as GetPostMediaStatusResponse, r as Authenticator, s as ChatMessage, t as Client, u as Event, v as Media, w as MediaVideo, x as MediaType, y as MediaImage, z as PostVisibility } from "./client-C90Zd_yq.cjs";
1
+ import { A as PostCreatedEvent, B as SendChatMessageRequest, C as MediaUploadType, D as PingEvent, E as OfficialStampSet, F as PostMediaType, G as UserVisibility, H as User, I as PostMediaVideo, L as PostPublishingType, M as PostMaskType, N as PostMedia, O as Post, P as PostMediaImage, R as PostStamp, S as MediaUploadStatus, T as OfficialStamp, U as UserAccessLevel, V as StampSetType, W as UserAvatar, _ as LanguageCode, a as OAuth2Authenticator, b as MediaStamp, c as ChatMessageReceivedEvent, d as EventReason, f as EventType, g as InitiatePostMediaUploadResponse, h as InitiatePostMediaUploadRequest, i as AuthenticatorOptions, j as PostMask, k as PostAccessLevel, l as CreatePostRequest, m as GetStampsRequest, n as ClientOptions, o as EventHandler, p as GetPostMediaStatusResponse, r as Authenticator, s as ChatMessage, t as Client, u as Event, v as Media, w as MediaVideo, x as MediaType, y as MediaImage, z as PostVisibility } from "./client-DK9LqeiF.cjs";
2
2
  import http from "http";
3
3
 
4
4
  //#region src/webhook.d.ts
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as PostCreatedEvent, B as SendChatMessageRequest, C as MediaUploadType, D as PingEvent, E as OfficialStampSet, F as PostMediaType, G as UserVisibility, H as User, I as PostMediaVideo, L as PostPublishingType, M as PostMaskType, N as PostMedia, O as Post, P as PostMediaImage, R as PostStamp, S as MediaUploadStatus, T as OfficialStamp, U as UserAccessLevel, V as StampSetType, W as UserAvatar, _ as LanguageCode, a as OAuth2Authenticator, b as MediaStamp, c as ChatMessageReceivedEvent, d as EventReason, f as EventType, g as InitiatePostMediaUploadResponse, h as InitiatePostMediaUploadRequest, i as AuthenticatorOptions, j as PostMask, k as PostAccessLevel, l as CreatePostRequest, m as GetStampsRequest, n as ClientOptions, o as EventHandler, p as GetPostMediaStatusResponse, r as Authenticator, s as ChatMessage, t as Client, u as Event, v as Media, w as MediaVideo, x as MediaType, y as MediaImage, z as PostVisibility } from "./client-DPeVTCYr.mjs";
1
+ import { A as PostCreatedEvent, B as SendChatMessageRequest, C as MediaUploadType, D as PingEvent, E as OfficialStampSet, F as PostMediaType, G as UserVisibility, H as User, I as PostMediaVideo, L as PostPublishingType, M as PostMaskType, N as PostMedia, O as Post, P as PostMediaImage, R as PostStamp, S as MediaUploadStatus, T as OfficialStamp, U as UserAccessLevel, V as StampSetType, W as UserAvatar, _ as LanguageCode, a as OAuth2Authenticator, b as MediaStamp, c as ChatMessageReceivedEvent, d as EventReason, f as EventType, g as InitiatePostMediaUploadResponse, h as InitiatePostMediaUploadRequest, i as AuthenticatorOptions, j as PostMask, k as PostAccessLevel, l as CreatePostRequest, m as GetStampsRequest, n as ClientOptions, o as EventHandler, p as GetPostMediaStatusResponse, r as Authenticator, s as ChatMessage, t as Client, u as Event, v as Media, w as MediaVideo, x as MediaType, y as MediaImage, z as PostVisibility } from "./client-GWUs7tD3.mjs";
2
2
  import http from "http";
3
3
 
4
4
  //#region src/webhook.d.ts
package/dist/index.mjs CHANGED
@@ -287,6 +287,9 @@ var Client = class {
287
287
  this.authenticator = options.authenticator;
288
288
  this.authKey = options.authKey;
289
289
  }
290
+ async getAccessToken() {
291
+ return this.authenticator.getAccessToken();
292
+ }
290
293
  async getMetadata() {
291
294
  const token = await this.authenticator.getAccessToken();
292
295
  const metadata = new grpc.Metadata();
@@ -294,18 +297,17 @@ var Client = class {
294
297
  if (this.authKey) metadata.add("x-auth-key", this.authKey);
295
298
  return metadata;
296
299
  }
297
- call(method, request) {
298
- return this.getMetadata().then((metadata) => {
299
- return new Promise((resolve, reject) => {
300
- const fn = this.grpcClient[method];
301
- if (!fn) {
302
- reject(/* @__PURE__ */ new Error(`Method "${method}" not found on gRPC client`));
303
- return;
304
- }
305
- fn.call(this.grpcClient, request, metadata, (err, response) => {
306
- if (err) reject(err);
307
- else resolve(response);
308
- });
300
+ async call(method, request) {
301
+ const metadata = await this.getMetadata();
302
+ return new Promise((resolve, reject) => {
303
+ const fn = this.grpcClient[method];
304
+ if (!fn) {
305
+ reject(/* @__PURE__ */ new Error(`Method "${method}" not found on gRPC client`));
306
+ return;
307
+ }
308
+ fn.call(this.grpcClient, request, metadata, (err, response) => {
309
+ if (err) reject(err);
310
+ else resolve(response);
309
311
  });
310
312
  });
311
313
  }
@@ -318,6 +320,9 @@ var Client = class {
318
320
  async createPost(request) {
319
321
  return convertPost((await this.call("createPost", request)).post);
320
322
  }
323
+ async deletePost(postId) {
324
+ return (await this.call("deletePost", { postId })).deleted ?? false;
325
+ }
321
326
  async initiatePostMediaUpload(request) {
322
327
  return this.call("initiatePostMediaUpload", request);
323
328
  }
@@ -497,27 +502,29 @@ var StreamWatcher = class {
497
502
  if (!fn) throw new Error("subscribeEvents method not found on stream client");
498
503
  return fn.call(this.streamClient, {}, metadata);
499
504
  }
500
- async reconnect() {
501
- const maxRetries = this.maxRetries;
502
- let lastError;
503
- for (let i = 0; i < maxRetries; i++) {
504
- if (this.aborted) throw new Error("Watcher aborted");
505
- await new Promise((resolve) => setTimeout(resolve, Math.pow(2, i) * 1e3));
506
- try {
507
- return await this.connect();
508
- } catch (err) {
509
- lastError = err instanceof Error ? err : new Error(String(err));
510
- console.warn(`Reconnect attempt ${i + 1}/${maxRetries} failed:`, lastError.message);
511
- }
512
- }
513
- throw lastError || /* @__PURE__ */ new Error("Failed to reconnect");
505
+ async reconnect(retryIndex) {
506
+ if (this.aborted) throw new Error("Watcher aborted");
507
+ const backoff = Math.min(Math.pow(2, retryIndex) * 1e3, 3e4);
508
+ await new Promise((resolve) => setTimeout(resolve, backoff));
509
+ if (this.aborted) throw new Error("Watcher aborted");
510
+ return this.connect();
514
511
  }
515
512
  async watch(handler) {
516
513
  this.aborted = false;
517
514
  let stream = await this.connect();
515
+ let consecutiveFailures = 0;
518
516
  return new Promise((resolve, reject) => {
519
517
  const setupStream = (s) => {
518
+ let receivedData = false;
519
+ const connectionTimeout = setTimeout(() => {
520
+ if (!receivedData && !this.aborted) s.destroy(/* @__PURE__ */ new Error("Connection timeout: no data received"));
521
+ }, 3e4);
520
522
  s.on("data", (response) => {
523
+ if (!receivedData) {
524
+ receivedData = true;
525
+ clearTimeout(connectionTimeout);
526
+ consecutiveFailures = 0;
527
+ }
521
528
  const events = (response.events || []).map(convertEvent);
522
529
  for (const event of events) {
523
530
  if (event.eventType === EventType.PING) continue;
@@ -526,14 +533,20 @@ var StreamWatcher = class {
526
533
  });
527
534
  let disconnected = false;
528
535
  const handleDisconnect = async () => {
536
+ clearTimeout(connectionTimeout);
529
537
  if (disconnected) return;
530
538
  disconnected = true;
531
539
  if (this.aborted) {
532
540
  resolve();
533
541
  return;
534
542
  }
543
+ if (!receivedData) consecutiveFailures++;
544
+ if (consecutiveFailures >= this.maxRetries) {
545
+ reject(/* @__PURE__ */ new Error(`Failed to reconnect after ${this.maxRetries} consecutive attempts`));
546
+ return;
547
+ }
535
548
  try {
536
- stream = await this.reconnect();
549
+ stream = await this.reconnect(consecutiveFailures);
537
550
  setupStream(stream);
538
551
  } catch (reconnectErr) {
539
552
  reject(reconnectErr);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixi2-js",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
4
4
  "description": "TypeScript/JavaScript SDK for mixi2 Application API",
5
5
  "keywords": [
6
6
  "api",
@@ -72,6 +72,14 @@ message CreatePostResponse {
72
72
  model.v1.Post post = 1;
73
73
  }
74
74
 
75
+ message DeletePostRequest {
76
+ string post_id = 1;
77
+ }
78
+
79
+ message DeletePostResponse {
80
+ bool deleted = 1;
81
+ }
82
+
75
83
  message SendChatMessageRequest {
76
84
  string room_id = 1;
77
85
  optional string text = 2;
@@ -103,6 +111,7 @@ service ApplicationService {
103
111
  rpc GetUsers(GetUsersRequest) returns (GetUsersResponse);
104
112
  rpc GetPosts(GetPostsRequest) returns (GetPostsResponse);
105
113
  rpc CreatePost(CreatePostRequest) returns (CreatePostResponse);
114
+ rpc DeletePost(DeletePostRequest) returns (DeletePostResponse);
106
115
  rpc InitiatePostMediaUpload(InitiatePostMediaUploadRequest) returns (InitiatePostMediaUploadResponse);
107
116
  rpc GetPostMediaStatus(GetPostMediaStatusRequest) returns (GetPostMediaStatusResponse);
108
117
  rpc SendChatMessage(SendChatMessageRequest) returns (SendChatMessageResponse);