@line-harness/sdk 0.1.0 → 0.2.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/index.cjs CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ AdPlatformsResource: () => AdPlatformsResource,
23
24
  BroadcastsResource: () => BroadcastsResource,
24
25
  FormsResource: () => FormsResource,
25
26
  FriendsResource: () => FriendsResource,
@@ -27,6 +28,7 @@ __export(index_exports, {
27
28
  LineHarnessError: () => LineHarnessError,
28
29
  RichMenusResource: () => RichMenusResource,
29
30
  ScenariosResource: () => ScenariosResource,
31
+ StaffResource: () => StaffResource,
30
32
  TagsResource: () => TagsResource,
31
33
  TrackedLinksResource: () => TrackedLinksResource,
32
34
  parseDelay: () => parseDelay
@@ -62,6 +64,9 @@ var HttpClient = class {
62
64
  async put(path, body) {
63
65
  return this.request("PUT", path, body);
64
66
  }
67
+ async patch(path, body) {
68
+ return this.request("PATCH", path, body);
69
+ }
65
70
  async delete(path) {
66
71
  return this.request("DELETE", path);
67
72
  }
@@ -115,10 +120,8 @@ var FriendsResource = class {
115
120
  const res = await this.http.get(`/api/friends/${id}`);
116
121
  return res.data;
117
122
  }
118
- async count(params) {
119
- const accountId = params?.accountId ?? this.defaultAccountId;
120
- const path = accountId ? `/api/friends/count?lineAccountId=${encodeURIComponent(accountId)}` : "/api/friends/count";
121
- const res = await this.http.get(path);
123
+ async count() {
124
+ const res = await this.http.get("/api/friends/count");
122
125
  return res.data.count;
123
126
  }
124
127
  async addTag(friendId, tagId) {
@@ -333,6 +336,75 @@ var FormsResource = class {
333
336
  }
334
337
  };
335
338
 
339
+ // src/resources/ad-platforms.ts
340
+ var AdPlatformsResource = class {
341
+ constructor(http) {
342
+ this.http = http;
343
+ }
344
+ async list() {
345
+ const res = await this.http.get("/api/ad-platforms");
346
+ return res.data;
347
+ }
348
+ async create(input) {
349
+ const res = await this.http.post("/api/ad-platforms", input);
350
+ return res.data;
351
+ }
352
+ async update(id, input) {
353
+ const res = await this.http.put(`/api/ad-platforms/${id}`, input);
354
+ return res.data;
355
+ }
356
+ async delete(id) {
357
+ await this.http.delete(`/api/ad-platforms/${id}`);
358
+ }
359
+ async getLogs(id, limit) {
360
+ const path = limit ? `/api/ad-platforms/${id}/logs?limit=${limit}` : `/api/ad-platforms/${id}/logs`;
361
+ const res = await this.http.get(path);
362
+ return res.data;
363
+ }
364
+ async test(platform, eventName, friendId) {
365
+ const res = await this.http.post("/api/ad-platforms/test", {
366
+ platform,
367
+ eventName,
368
+ friendId
369
+ });
370
+ return res.data;
371
+ }
372
+ };
373
+
374
+ // src/resources/staff.ts
375
+ var StaffResource = class {
376
+ constructor(http) {
377
+ this.http = http;
378
+ }
379
+ async list() {
380
+ const res = await this.http.get("/api/staff");
381
+ return res.data;
382
+ }
383
+ async get(id) {
384
+ const res = await this.http.get(`/api/staff/${id}`);
385
+ return res.data;
386
+ }
387
+ async me() {
388
+ const res = await this.http.get("/api/staff/me");
389
+ return res.data;
390
+ }
391
+ async create(input) {
392
+ const res = await this.http.post("/api/staff", input);
393
+ return res.data;
394
+ }
395
+ async update(id, input) {
396
+ const res = await this.http.patch(`/api/staff/${id}`, input);
397
+ return res.data;
398
+ }
399
+ async delete(id) {
400
+ await this.http.delete(`/api/staff/${id}`);
401
+ }
402
+ async regenerateKey(id) {
403
+ const res = await this.http.post(`/api/staff/${id}/regenerate-key`);
404
+ return res.data;
405
+ }
406
+ };
407
+
336
408
  // src/delay.ts
337
409
  var MULTIPLIERS = {
338
410
  m: 1,
@@ -413,6 +485,8 @@ var LineHarness = class {
413
485
  richMenus;
414
486
  trackedLinks;
415
487
  forms;
488
+ adPlatforms;
489
+ staff;
416
490
  apiUrl;
417
491
  defaultAccountId;
418
492
  workflows;
@@ -437,6 +511,8 @@ var LineHarness = class {
437
511
  this.richMenus = new RichMenusResource(http);
438
512
  this.trackedLinks = new TrackedLinksResource(http);
439
513
  this.forms = new FormsResource(http);
514
+ this.adPlatforms = new AdPlatformsResource(http);
515
+ this.staff = new StaffResource(http);
440
516
  this.workflows = new Workflows(this.friends, this.scenarios, this.broadcasts);
441
517
  this.createStepScenario = this.workflows.createStepScenario.bind(this.workflows);
442
518
  this.broadcastText = this.workflows.broadcastText.bind(this.workflows);
@@ -461,6 +537,7 @@ var LineHarness = class {
461
537
  };
462
538
  // Annotate the CommonJS export names for ESM import in node:
463
539
  0 && (module.exports = {
540
+ AdPlatformsResource,
464
541
  BroadcastsResource,
465
542
  FormsResource,
466
543
  FriendsResource,
@@ -468,6 +545,7 @@ var LineHarness = class {
468
545
  LineHarnessError,
469
546
  RichMenusResource,
470
547
  ScenariosResource,
548
+ StaffResource,
471
549
  TagsResource,
472
550
  TrackedLinksResource,
473
551
  parseDelay
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/resources/friends.ts","../src/resources/tags.ts","../src/resources/scenarios.ts","../src/resources/broadcasts.ts","../src/resources/rich-menus.ts","../src/resources/tracked-links.ts","../src/resources/forms.ts","../src/delay.ts","../src/workflows.ts","../src/client.ts"],"sourcesContent":["export { LineHarness } from './client.js'\nexport { LineHarnessError } from './errors.js'\nexport { parseDelay } from './delay.js'\n\n// Resource classes (for advanced usage / type narrowing)\nexport { FriendsResource } from './resources/friends.js'\nexport { TagsResource } from './resources/tags.js'\nexport { ScenariosResource } from './resources/scenarios.js'\nexport { BroadcastsResource } from './resources/broadcasts.js'\nexport { RichMenusResource } from './resources/rich-menus.js'\nexport { TrackedLinksResource } from './resources/tracked-links.js'\nexport { FormsResource } from './resources/forms.js'\n\n// All types\nexport type {\n LineHarnessConfig,\n ApiResponse,\n PaginatedData,\n ScenarioTriggerType,\n MessageType,\n BroadcastStatus,\n Friend,\n FriendListParams,\n Tag,\n CreateTagInput,\n Scenario,\n ScenarioListItem,\n ScenarioWithSteps,\n ScenarioStep,\n CreateScenarioInput,\n CreateStepInput,\n UpdateScenarioInput,\n UpdateStepInput,\n FriendScenarioEnrollment,\n Broadcast,\n CreateBroadcastInput,\n UpdateBroadcastInput,\n SegmentRule,\n SegmentCondition,\n StepDefinition,\n RichMenu,\n RichMenuBounds,\n RichMenuAction,\n RichMenuArea,\n CreateRichMenuInput,\n TrackedLink,\n LinkClick,\n TrackedLinkWithClicks,\n CreateTrackedLinkInput,\n FormField,\n Form,\n CreateFormInput,\n UpdateFormInput,\n FormSubmission,\n} from './types.js'\n","export class LineHarnessError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly endpoint: string,\n ) {\n super(message)\n this.name = 'LineHarnessError'\n }\n}\n","import { LineHarnessError } from './errors.js'\n\ninterface HttpClientConfig {\n baseUrl: string\n apiKey: string\n timeout: number\n}\n\nexport class HttpClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n private readonly timeout: number\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '')\n this.apiKey = config.apiKey\n this.timeout = config.timeout\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>('GET', path)\n }\n\n async post<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('POST', path, body)\n }\n\n async put<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PUT', path, body)\n }\n\n async delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>('DELETE', path)\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n }\n\n const options: RequestInit = {\n method,\n headers,\n signal: AbortSignal.timeout(this.timeout),\n }\n\n if (body !== undefined) {\n options.body = JSON.stringify(body)\n }\n\n const res = await fetch(url, options)\n\n if (!res.ok) {\n let errorMessage = `HTTP ${res.status}`\n try {\n const errorBody = (await res.json()) as { error?: string }\n if (errorBody.error) errorMessage = errorBody.error\n } catch {\n // ignore parse errors\n }\n throw new LineHarnessError(errorMessage, res.status, `${method} ${path}`)\n }\n\n return res.json() as Promise<T>\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, PaginatedData, Friend, FriendListParams, MessageType } from '../types.js'\n\nexport class FriendsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: FriendListParams): Promise<PaginatedData<Friend>> {\n const query = new URLSearchParams()\n if (params?.limit !== undefined) query.set('limit', String(params.limit))\n if (params?.offset !== undefined) query.set('offset', String(params.offset))\n if (params?.tagId) query.set('tagId', params.tagId)\n const accountId = params?.accountId ?? this.defaultAccountId\n if (accountId) query.set('lineAccountId', accountId)\n const qs = query.toString()\n const path = qs ? `/api/friends?${qs}` : '/api/friends'\n const res = await this.http.get<ApiResponse<PaginatedData<Friend>>>(path)\n return res.data\n }\n\n async get(id: string): Promise<Friend> {\n const res = await this.http.get<ApiResponse<Friend>>(`/api/friends/${id}`)\n return res.data\n }\n\n async count(params?: { accountId?: string }): Promise<number> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const path = accountId\n ? `/api/friends/count?lineAccountId=${encodeURIComponent(accountId)}`\n : '/api/friends/count'\n const res = await this.http.get<ApiResponse<{ count: number }>>(path)\n return res.data.count\n }\n\n async addTag(friendId: string, tagId: string): Promise<void> {\n await this.http.post(`/api/friends/${friendId}/tags`, { tagId })\n }\n\n async removeTag(friendId: string, tagId: string): Promise<void> {\n await this.http.delete(`/api/friends/${friendId}/tags/${tagId}`)\n }\n\n async sendMessage(friendId: string, content: string, messageType: MessageType = 'text'): Promise<{ messageId: string }> {\n const res = await this.http.post<ApiResponse<{ messageId: string }>>(`/api/friends/${friendId}/messages`, {\n messageType,\n content,\n })\n return res.data\n }\n\n async setMetadata(friendId: string, fields: Record<string, unknown>): Promise<Friend> {\n const res = await this.http.put<ApiResponse<Friend>>(`/api/friends/${friendId}/metadata`, fields)\n return res.data\n }\n\n async setRichMenu(friendId: string, richMenuId: string): Promise<void> {\n await this.http.post(`/api/friends/${friendId}/rich-menu`, { richMenuId })\n }\n\n async removeRichMenu(friendId: string): Promise<void> {\n await this.http.delete(`/api/friends/${friendId}/rich-menu`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, Tag, CreateTagInput } from '../types.js'\n\nexport class TagsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Tag[]> {\n const res = await this.http.get<ApiResponse<Tag[]>>('/api/tags')\n return res.data\n }\n\n async create(input: CreateTagInput): Promise<Tag> {\n const res = await this.http.post<ApiResponse<Tag>>('/api/tags', input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/tags/${id}`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type {\n ApiResponse,\n Scenario,\n ScenarioListItem,\n ScenarioWithSteps,\n ScenarioStep,\n CreateScenarioInput,\n CreateStepInput,\n UpdateScenarioInput,\n UpdateStepInput,\n FriendScenarioEnrollment,\n} from '../types.js'\n\nexport class ScenariosResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: { accountId?: string }): Promise<ScenarioListItem[]> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const query = accountId ? `?lineAccountId=${accountId}` : ''\n const res = await this.http.get<ApiResponse<ScenarioListItem[]>>(`/api/scenarios${query}`)\n return res.data\n }\n\n async get(id: string): Promise<ScenarioWithSteps> {\n const res = await this.http.get<ApiResponse<ScenarioWithSteps>>(`/api/scenarios/${id}`)\n return res.data\n }\n\n async create(input: CreateScenarioInput & { lineAccountId?: string }): Promise<Scenario> {\n const body = { ...input }\n if (!body.lineAccountId && this.defaultAccountId) {\n body.lineAccountId = this.defaultAccountId\n }\n const res = await this.http.post<ApiResponse<Scenario>>('/api/scenarios', body)\n return res.data\n }\n\n async update(id: string, input: UpdateScenarioInput): Promise<Scenario> {\n const res = await this.http.put<ApiResponse<Scenario>>(`/api/scenarios/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/scenarios/${id}`)\n }\n\n async addStep(scenarioId: string, input: CreateStepInput): Promise<ScenarioStep> {\n const res = await this.http.post<ApiResponse<ScenarioStep>>(`/api/scenarios/${scenarioId}/steps`, input)\n return res.data\n }\n\n async updateStep(scenarioId: string, stepId: string, input: UpdateStepInput): Promise<ScenarioStep> {\n const res = await this.http.put<ApiResponse<ScenarioStep>>(`/api/scenarios/${scenarioId}/steps/${stepId}`, input)\n return res.data\n }\n\n async deleteStep(scenarioId: string, stepId: string): Promise<void> {\n await this.http.delete(`/api/scenarios/${scenarioId}/steps/${stepId}`)\n }\n\n async enroll(scenarioId: string, friendId: string): Promise<FriendScenarioEnrollment> {\n const res = await this.http.post<ApiResponse<FriendScenarioEnrollment>>(\n `/api/scenarios/${scenarioId}/enroll/${friendId}`\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, Broadcast, CreateBroadcastInput, UpdateBroadcastInput, SegmentCondition } from '../types.js'\n\nexport class BroadcastsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: { accountId?: string }): Promise<Broadcast[]> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const query = accountId ? `?lineAccountId=${accountId}` : ''\n const res = await this.http.get<ApiResponse<Broadcast[]>>(`/api/broadcasts${query}`)\n return res.data\n }\n\n async get(id: string): Promise<Broadcast> {\n const res = await this.http.get<ApiResponse<Broadcast>>(`/api/broadcasts/${id}`)\n return res.data\n }\n\n async create(input: CreateBroadcastInput & { lineAccountId?: string }): Promise<Broadcast> {\n const body = { ...input }\n if (!body.lineAccountId && this.defaultAccountId) {\n body.lineAccountId = this.defaultAccountId\n }\n const res = await this.http.post<ApiResponse<Broadcast>>('/api/broadcasts', body)\n return res.data\n }\n\n async update(id: string, input: UpdateBroadcastInput): Promise<Broadcast> {\n const res = await this.http.put<ApiResponse<Broadcast>>(`/api/broadcasts/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/broadcasts/${id}`)\n }\n\n async send(id: string): Promise<Broadcast> {\n const res = await this.http.post<ApiResponse<Broadcast>>(`/api/broadcasts/${id}/send`)\n return res.data\n }\n\n async sendToSegment(id: string, conditions: SegmentCondition): Promise<Broadcast> {\n const res = await this.http.post<ApiResponse<Broadcast>>(\n `/api/broadcasts/${id}/send-segment`,\n { conditions },\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, RichMenu, CreateRichMenuInput } from '../types.js'\n\nexport class RichMenusResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<RichMenu[]> {\n const res = await this.http.get<ApiResponse<RichMenu[]>>('/api/rich-menus')\n return res.data\n }\n\n async create(menu: CreateRichMenuInput): Promise<{ richMenuId: string }> {\n const res = await this.http.post<ApiResponse<{ richMenuId: string }>>('/api/rich-menus', menu)\n return res.data\n }\n\n async delete(richMenuId: string): Promise<void> {\n await this.http.delete(`/api/rich-menus/${encodeURIComponent(richMenuId)}`)\n }\n\n async setDefault(richMenuId: string): Promise<void> {\n await this.http.post(`/api/rich-menus/${encodeURIComponent(richMenuId)}/default`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, TrackedLink, TrackedLinkWithClicks, CreateTrackedLinkInput } from '../types.js'\n\nexport class TrackedLinksResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<TrackedLink[]> {\n const res = await this.http.get<ApiResponse<TrackedLink[]>>('/api/tracked-links')\n return res.data\n }\n\n async create(input: CreateTrackedLinkInput): Promise<TrackedLink> {\n const res = await this.http.post<ApiResponse<TrackedLink>>('/api/tracked-links', input)\n return res.data\n }\n\n async get(id: string): Promise<TrackedLinkWithClicks> {\n const res = await this.http.get<ApiResponse<TrackedLinkWithClicks>>(`/api/tracked-links/${id}`)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/tracked-links/${id}`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type {\n ApiResponse,\n Form,\n FormSubmission,\n CreateFormInput,\n UpdateFormInput,\n} from '../types.js'\n\nexport class FormsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Form[]> {\n const res = await this.http.get<ApiResponse<Form[]>>('/api/forms')\n return res.data\n }\n\n async get(id: string): Promise<Form> {\n const res = await this.http.get<ApiResponse<Form>>(`/api/forms/${id}`)\n return res.data\n }\n\n async create(input: CreateFormInput): Promise<Form> {\n const res = await this.http.post<ApiResponse<Form>>('/api/forms', input)\n return res.data\n }\n\n async update(id: string, input: UpdateFormInput): Promise<Form> {\n const res = await this.http.put<ApiResponse<Form>>(`/api/forms/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/forms/${id}`)\n }\n\n async getSubmissions(formId: string): Promise<FormSubmission[]> {\n const res = await this.http.get<ApiResponse<FormSubmission[]>>(\n `/api/forms/${formId}/submissions`,\n )\n return res.data\n }\n}\n","const MULTIPLIERS: Record<string, number> = {\n m: 1,\n h: 60,\n d: 1440,\n w: 10080,\n}\n\nexport function parseDelay(input: string): number {\n const match = input.match(/^(\\d+)([mhdw])$/)\n if (!match) {\n throw new Error(`Invalid delay format: \"${input}\". Use format like \"30m\", \"1h\", \"1d\", \"1w\".`)\n }\n return Number(match[1]) * MULTIPLIERS[match[2]]\n}\n","import type { FriendsResource } from './resources/friends.js'\nimport type { ScenariosResource } from './resources/scenarios.js'\nimport type { BroadcastsResource } from './resources/broadcasts.js'\nimport type { StepDefinition, ScenarioTriggerType, ScenarioWithSteps, Broadcast, MessageType, SegmentCondition } from './types.js'\nimport { parseDelay } from './delay.js'\n\nexport class Workflows {\n constructor(\n private readonly friends: FriendsResource,\n private readonly scenarios: ScenariosResource,\n private readonly broadcasts: BroadcastsResource,\n ) {}\n\n async createStepScenario(\n name: string,\n triggerType: ScenarioTriggerType,\n steps: StepDefinition[],\n ): Promise<ScenarioWithSteps> {\n const scenario = await this.scenarios.create({ name, triggerType })\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i]\n await this.scenarios.addStep(scenario.id, {\n stepOrder: i + 1,\n delayMinutes: parseDelay(step.delay),\n messageType: step.type,\n messageContent: step.content,\n })\n }\n\n return this.scenarios.get(scenario.id)\n }\n\n async broadcastText(text: string): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: text.slice(0, 50),\n messageType: 'text',\n messageContent: text,\n targetType: 'all',\n })\n return this.broadcasts.send(broadcast.id)\n }\n\n async broadcastToTag(\n tagId: string,\n messageType: MessageType,\n content: string,\n ): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: content.slice(0, 50),\n messageType,\n messageContent: content,\n targetType: 'tag',\n targetTagId: tagId,\n })\n return this.broadcasts.send(broadcast.id)\n }\n\n async broadcastToSegment(\n messageType: MessageType,\n content: string,\n conditions: SegmentCondition,\n ): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: content.slice(0, 50),\n messageType,\n messageContent: content,\n targetType: 'all',\n })\n return this.broadcasts.sendToSegment(broadcast.id, conditions)\n }\n\n async sendTextToFriend(friendId: string, text: string): Promise<{ messageId: string }> {\n return this.friends.sendMessage(friendId, text, 'text')\n }\n\n async sendFlexToFriend(friendId: string, flexJson: string): Promise<{ messageId: string }> {\n return this.friends.sendMessage(friendId, flexJson, 'flex')\n }\n}\n","import { HttpClient } from './http.js'\nimport { FriendsResource } from './resources/friends.js'\nimport { TagsResource } from './resources/tags.js'\nimport { ScenariosResource } from './resources/scenarios.js'\nimport { BroadcastsResource } from './resources/broadcasts.js'\nimport { RichMenusResource } from './resources/rich-menus.js'\nimport { TrackedLinksResource } from './resources/tracked-links.js'\nimport { FormsResource } from './resources/forms.js'\nimport { Workflows } from './workflows.js'\nimport type { LineHarnessConfig, StepDefinition, ScenarioTriggerType, ScenarioWithSteps, Broadcast, MessageType, SegmentCondition } from './types.js'\n\nexport class LineHarness {\n readonly friends: FriendsResource\n readonly tags: TagsResource\n readonly scenarios: ScenariosResource\n readonly broadcasts: BroadcastsResource\n readonly richMenus: RichMenusResource\n readonly trackedLinks: TrackedLinksResource\n readonly forms: FormsResource\n\n private readonly apiUrl: string\n private readonly defaultAccountId: string | undefined\n private readonly workflows: Workflows\n\n readonly createStepScenario: (name: string, triggerType: ScenarioTriggerType, steps: StepDefinition[]) => Promise<ScenarioWithSteps>\n readonly broadcastText: (text: string) => Promise<Broadcast>\n readonly broadcastToTag: (tagId: string, messageType: MessageType, content: string) => Promise<Broadcast>\n readonly broadcastToSegment: (messageType: MessageType, content: string, conditions: SegmentCondition) => Promise<Broadcast>\n readonly sendTextToFriend: (friendId: string, text: string) => Promise<{ messageId: string }>\n readonly sendFlexToFriend: (friendId: string, flexJson: string) => Promise<{ messageId: string }>\n\n constructor(config: LineHarnessConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '')\n this.defaultAccountId = config.lineAccountId\n\n const http = new HttpClient({\n baseUrl: this.apiUrl,\n apiKey: config.apiKey,\n timeout: config.timeout ?? 30_000,\n })\n\n this.friends = new FriendsResource(http, this.defaultAccountId)\n this.tags = new TagsResource(http)\n this.scenarios = new ScenariosResource(http, this.defaultAccountId)\n this.broadcasts = new BroadcastsResource(http, this.defaultAccountId)\n this.richMenus = new RichMenusResource(http)\n this.trackedLinks = new TrackedLinksResource(http)\n this.forms = new FormsResource(http)\n this.workflows = new Workflows(this.friends, this.scenarios, this.broadcasts)\n\n this.createStepScenario = this.workflows.createStepScenario.bind(this.workflows)\n this.broadcastText = this.workflows.broadcastText.bind(this.workflows)\n this.broadcastToTag = this.workflows.broadcastToTag.bind(this.workflows)\n this.broadcastToSegment = this.workflows.broadcastToSegment.bind(this.workflows)\n this.sendTextToFriend = this.workflows.sendTextToFriend.bind(this.workflows)\n this.sendFlexToFriend = this.workflows.sendFlexToFriend.bind(this.workflows)\n }\n\n /**\n * Generate friend-add URL with OAuth (bot_prompt=aggressive)\n * This URL does friend-add + UUID in one step.\n *\n * @param ref - Attribution code (e.g., 'lp-a', 'instagram', 'seminar-0322')\n * @param redirect - URL to redirect after completion\n */\n getAuthUrl(options?: { ref?: string; redirect?: string }): string {\n const url = new URL(`${this.apiUrl}/auth/line`)\n if (options?.ref) url.searchParams.set('ref', options.ref)\n if (options?.redirect) url.searchParams.set('redirect', options.redirect)\n return url.toString()\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YACE,SACgB,QACA,UAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;;;ACDO,IAAM,aAAN,MAAiB;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAA0B;AACpC,SAAK,UAAU,OAAO,QAAQ,QAAQ,OAAO,EAAE;AAC/C,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO;AAAA,EACxB;AAAA,EAEA,MAAM,IAAiB,MAA0B;AAC/C,WAAO,KAAK,QAAW,OAAO,IAAI;AAAA,EACpC;AAAA,EAEA,MAAM,KAAkB,MAAc,MAA4B;AAChE,WAAO,KAAK,QAAW,QAAQ,MAAM,IAAI;AAAA,EAC3C;AAAA,EAEA,MAAM,IAAiB,MAAc,MAA4B;AAC/D,WAAO,KAAK,QAAW,OAAO,MAAM,IAAI;AAAA,EAC1C;AAAA,EAEA,MAAM,OAAoB,MAA0B;AAClD,WAAO,KAAK,QAAW,UAAU,IAAI;AAAA,EACvC;AAAA,EAEA,MAAc,QAAW,QAAgB,MAAc,MAA4B;AACjF,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI;AAClC,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,KAAK,MAAM;AAAA,MACpC,gBAAgB;AAAA,IAClB;AAEA,UAAM,UAAuB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,QAAQ,YAAY,QAAQ,KAAK,OAAO;AAAA,IAC1C;AAEA,QAAI,SAAS,QAAW;AACtB,cAAQ,OAAO,KAAK,UAAU,IAAI;AAAA,IACpC;AAEA,UAAM,MAAM,MAAM,MAAM,KAAK,OAAO;AAEpC,QAAI,CAAC,IAAI,IAAI;AACX,UAAI,eAAe,QAAQ,IAAI,MAAM;AACrC,UAAI;AACF,cAAM,YAAa,MAAM,IAAI,KAAK;AAClC,YAAI,UAAU,MAAO,gBAAe,UAAU;AAAA,MAChD,QAAQ;AAAA,MAER;AACA,YAAM,IAAI,iBAAiB,cAAc,IAAI,QAAQ,GAAG,MAAM,IAAI,IAAI,EAAE;AAAA,IAC1E;AAEA,WAAO,IAAI,KAAK;AAAA,EAClB;AACF;;;AChEO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YACmB,MACA,kBACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAEH,MAAM,KAAK,QAA2D;AACpE,UAAM,QAAQ,IAAI,gBAAgB;AAClC,QAAI,QAAQ,UAAU,OAAW,OAAM,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AACxE,QAAI,QAAQ,WAAW,OAAW,OAAM,IAAI,UAAU,OAAO,OAAO,MAAM,CAAC;AAC3E,QAAI,QAAQ,MAAO,OAAM,IAAI,SAAS,OAAO,KAAK;AAClD,UAAM,YAAY,QAAQ,aAAa,KAAK;AAC5C,QAAI,UAAW,OAAM,IAAI,iBAAiB,SAAS;AACnD,UAAM,KAAK,MAAM,SAAS;AAC1B,UAAM,OAAO,KAAK,gBAAgB,EAAE,KAAK;AACzC,UAAM,MAAM,MAAM,KAAK,KAAK,IAAwC,IAAI;AACxE,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,IAAI,IAA6B;AACrC,UAAM,MAAM,MAAM,KAAK,KAAK,IAAyB,gBAAgB,EAAE,EAAE;AACzE,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,MAAM,QAAkD;AAC5D,UAAM,YAAY,QAAQ,aAAa,KAAK;AAC5C,UAAM,OAAO,YACT,oCAAoC,mBAAmB,SAAS,CAAC,KACjE;AACJ,UAAM,MAAM,MAAM,KAAK,KAAK,IAAoC,IAAI;AACpE,WAAO,IAAI,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,OAAO,UAAkB,OAA8B;AAC3D,UAAM,KAAK,KAAK,KAAK,gBAAgB,QAAQ,SAAS,EAAE,MAAM,CAAC;AAAA,EACjE;AAAA,EAEA,MAAM,UAAU,UAAkB,OAA8B;AAC9D,UAAM,KAAK,KAAK,OAAO,gBAAgB,QAAQ,SAAS,KAAK,EAAE;AAAA,EACjE;AAAA,EAEA,MAAM,YAAY,UAAkB,SAAiB,cAA2B,QAAwC;AACtH,UAAM,MAAM,MAAM,KAAK,KAAK,KAAyC,gBAAgB,QAAQ,aAAa;AAAA,MACxG;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,YAAY,UAAkB,QAAkD;AACpF,UAAM,MAAM,MAAM,KAAK,KAAK,IAAyB,gBAAgB,QAAQ,aAAa,MAAM;AAChG,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,YAAY,UAAkB,YAAmC;AACrE,UAAM,KAAK,KAAK,KAAK,gBAAgB,QAAQ,cAAc,EAAE,WAAW,CAAC;AAAA,EAC3E;AAAA,EAEA,MAAM,eAAe,UAAiC;AACpD,UAAM,KAAK,KAAK,OAAO,gBAAgB,QAAQ,YAAY;AAAA,EAC7D;AACF;;;AC7DO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEhD,MAAM,OAAuB;AAC3B,UAAM,MAAM,MAAM,KAAK,KAAK,IAAwB,WAAW;AAC/D,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,OAAqC;AAChD,UAAM,MAAM,MAAM,KAAK,KAAK,KAAuB,aAAa,KAAK;AACrE,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,KAAK,KAAK,OAAO,aAAa,EAAE,EAAE;AAAA,EAC1C;AACF;;;ACLO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YACmB,MACA,kBACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAEH,MAAM,KAAK,QAA8D;AACvE,UAAM,YAAY,QAAQ,aAAa,KAAK;AAC5C,UAAM,QAAQ,YAAY,kBAAkB,SAAS,KAAK;AAC1D,UAAM,MAAM,MAAM,KAAK,KAAK,IAAqC,iBAAiB,KAAK,EAAE;AACzF,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,IAAI,IAAwC;AAChD,UAAM,MAAM,MAAM,KAAK,KAAK,IAAoC,kBAAkB,EAAE,EAAE;AACtF,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,OAA4E;AACvF,UAAM,OAAO,EAAE,GAAG,MAAM;AACxB,QAAI,CAAC,KAAK,iBAAiB,KAAK,kBAAkB;AAChD,WAAK,gBAAgB,KAAK;AAAA,IAC5B;AACA,UAAM,MAAM,MAAM,KAAK,KAAK,KAA4B,kBAAkB,IAAI;AAC9E,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,IAAY,OAA+C;AACtE,UAAM,MAAM,MAAM,KAAK,KAAK,IAA2B,kBAAkB,EAAE,IAAI,KAAK;AACpF,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,KAAK,KAAK,OAAO,kBAAkB,EAAE,EAAE;AAAA,EAC/C;AAAA,EAEA,MAAM,QAAQ,YAAoB,OAA+C;AAC/E,UAAM,MAAM,MAAM,KAAK,KAAK,KAAgC,kBAAkB,UAAU,UAAU,KAAK;AACvG,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,WAAW,YAAoB,QAAgB,OAA+C;AAClG,UAAM,MAAM,MAAM,KAAK,KAAK,IAA+B,kBAAkB,UAAU,UAAU,MAAM,IAAI,KAAK;AAChH,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,WAAW,YAAoB,QAA+B;AAClE,UAAM,KAAK,KAAK,OAAO,kBAAkB,UAAU,UAAU,MAAM,EAAE;AAAA,EACvE;AAAA,EAEA,MAAM,OAAO,YAAoB,UAAqD;AACpF,UAAM,MAAM,MAAM,KAAK,KAAK;AAAA,MAC1B,kBAAkB,UAAU,WAAW,QAAQ;AAAA,IACjD;AACA,WAAO,IAAI;AAAA,EACb;AACF;;;ACnEO,IAAM,qBAAN,MAAyB;AAAA,EAC9B,YACmB,MACA,kBACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAEH,MAAM,KAAK,QAAuD;AAChE,UAAM,YAAY,QAAQ,aAAa,KAAK;AAC5C,UAAM,QAAQ,YAAY,kBAAkB,SAAS,KAAK;AAC1D,UAAM,MAAM,MAAM,KAAK,KAAK,IAA8B,kBAAkB,KAAK,EAAE;AACnF,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,IAAI,IAAgC;AACxC,UAAM,MAAM,MAAM,KAAK,KAAK,IAA4B,mBAAmB,EAAE,EAAE;AAC/E,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,OAA8E;AACzF,UAAM,OAAO,EAAE,GAAG,MAAM;AACxB,QAAI,CAAC,KAAK,iBAAiB,KAAK,kBAAkB;AAChD,WAAK,gBAAgB,KAAK;AAAA,IAC5B;AACA,UAAM,MAAM,MAAM,KAAK,KAAK,KAA6B,mBAAmB,IAAI;AAChF,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,IAAY,OAAiD;AACxE,UAAM,MAAM,MAAM,KAAK,KAAK,IAA4B,mBAAmB,EAAE,IAAI,KAAK;AACtF,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,KAAK,KAAK,OAAO,mBAAmB,EAAE,EAAE;AAAA,EAChD;AAAA,EAEA,MAAM,KAAK,IAAgC;AACzC,UAAM,MAAM,MAAM,KAAK,KAAK,KAA6B,mBAAmB,EAAE,OAAO;AACrF,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,cAAc,IAAY,YAAkD;AAChF,UAAM,MAAM,MAAM,KAAK,KAAK;AAAA,MAC1B,mBAAmB,EAAE;AAAA,MACrB,EAAE,WAAW;AAAA,IACf;AACA,WAAO,IAAI;AAAA,EACb;AACF;;;AChDO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEhD,MAAM,OAA4B;AAChC,UAAM,MAAM,MAAM,KAAK,KAAK,IAA6B,iBAAiB;AAC1E,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,MAA4D;AACvE,UAAM,MAAM,MAAM,KAAK,KAAK,KAA0C,mBAAmB,IAAI;AAC7F,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,YAAmC;AAC9C,UAAM,KAAK,KAAK,OAAO,mBAAmB,mBAAmB,UAAU,CAAC,EAAE;AAAA,EAC5E;AAAA,EAEA,MAAM,WAAW,YAAmC;AAClD,UAAM,KAAK,KAAK,KAAK,mBAAmB,mBAAmB,UAAU,CAAC,UAAU;AAAA,EAClF;AACF;;;ACpBO,IAAM,uBAAN,MAA2B;AAAA,EAChC,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEhD,MAAM,OAA+B;AACnC,UAAM,MAAM,MAAM,KAAK,KAAK,IAAgC,oBAAoB;AAChF,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,OAAqD;AAChE,UAAM,MAAM,MAAM,KAAK,KAAK,KAA+B,sBAAsB,KAAK;AACtF,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,IAAI,IAA4C;AACpD,UAAM,MAAM,MAAM,KAAK,KAAK,IAAwC,sBAAsB,EAAE,EAAE;AAC9F,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,KAAK,KAAK,OAAO,sBAAsB,EAAE,EAAE;AAAA,EACnD;AACF;;;ACfO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAA6B,MAAkB;AAAlB;AAAA,EAAmB;AAAA,EAEhD,MAAM,OAAwB;AAC5B,UAAM,MAAM,MAAM,KAAK,KAAK,IAAyB,YAAY;AACjE,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,IAAI,IAA2B;AACnC,UAAM,MAAM,MAAM,KAAK,KAAK,IAAuB,cAAc,EAAE,EAAE;AACrE,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,OAAuC;AAClD,UAAM,MAAM,MAAM,KAAK,KAAK,KAAwB,cAAc,KAAK;AACvE,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,IAAY,OAAuC;AAC9D,UAAM,MAAM,MAAM,KAAK,KAAK,IAAuB,cAAc,EAAE,IAAI,KAAK;AAC5E,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,KAAK,KAAK,OAAO,cAAc,EAAE,EAAE;AAAA,EAC3C;AAAA,EAEA,MAAM,eAAe,QAA2C;AAC9D,UAAM,MAAM,MAAM,KAAK,KAAK;AAAA,MAC1B,cAAc,MAAM;AAAA,IACtB;AACA,WAAO,IAAI;AAAA,EACb;AACF;;;AC1CA,IAAM,cAAsC;AAAA,EAC1C,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAEO,SAAS,WAAW,OAAuB;AAChD,QAAM,QAAQ,MAAM,MAAM,iBAAiB;AAC3C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,0BAA0B,KAAK,6CAA6C;AAAA,EAC9F;AACA,SAAO,OAAO,MAAM,CAAC,CAAC,IAAI,YAAY,MAAM,CAAC,CAAC;AAChD;;;ACPO,IAAM,YAAN,MAAgB;AAAA,EACrB,YACmB,SACA,WACA,YACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAEH,MAAM,mBACJ,MACA,aACA,OAC4B;AAC5B,UAAM,WAAW,MAAM,KAAK,UAAU,OAAO,EAAE,MAAM,YAAY,CAAC;AAElE,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,KAAK,UAAU,QAAQ,SAAS,IAAI;AAAA,QACxC,WAAW,IAAI;AAAA,QACf,cAAc,WAAW,KAAK,KAAK;AAAA,QACnC,aAAa,KAAK;AAAA,QAClB,gBAAgB,KAAK;AAAA,MACvB,CAAC;AAAA,IACH;AAEA,WAAO,KAAK,UAAU,IAAI,SAAS,EAAE;AAAA,EACvC;AAAA,EAEA,MAAM,cAAc,MAAkC;AACpD,UAAM,YAAY,MAAM,KAAK,WAAW,OAAO;AAAA,MAC7C,OAAO,KAAK,MAAM,GAAG,EAAE;AAAA,MACvB,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,YAAY;AAAA,IACd,CAAC;AACD,WAAO,KAAK,WAAW,KAAK,UAAU,EAAE;AAAA,EAC1C;AAAA,EAEA,MAAM,eACJ,OACA,aACA,SACoB;AACpB,UAAM,YAAY,MAAM,KAAK,WAAW,OAAO;AAAA,MAC7C,OAAO,QAAQ,MAAM,GAAG,EAAE;AAAA,MAC1B;AAAA,MACA,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,aAAa;AAAA,IACf,CAAC;AACD,WAAO,KAAK,WAAW,KAAK,UAAU,EAAE;AAAA,EAC1C;AAAA,EAEA,MAAM,mBACJ,aACA,SACA,YACoB;AACpB,UAAM,YAAY,MAAM,KAAK,WAAW,OAAO;AAAA,MAC7C,OAAO,QAAQ,MAAM,GAAG,EAAE;AAAA,MAC1B;AAAA,MACA,gBAAgB;AAAA,MAChB,YAAY;AAAA,IACd,CAAC;AACD,WAAO,KAAK,WAAW,cAAc,UAAU,IAAI,UAAU;AAAA,EAC/D;AAAA,EAEA,MAAM,iBAAiB,UAAkB,MAA8C;AACrF,WAAO,KAAK,QAAQ,YAAY,UAAU,MAAM,MAAM;AAAA,EACxD;AAAA,EAEA,MAAM,iBAAiB,UAAkB,UAAkD;AACzF,WAAO,KAAK,QAAQ,YAAY,UAAU,UAAU,MAAM;AAAA,EAC5D;AACF;;;ACpEO,IAAM,cAAN,MAAkB;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EAER;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAA2B;AACrC,SAAK,SAAS,OAAO,OAAO,QAAQ,OAAO,EAAE;AAC7C,SAAK,mBAAmB,OAAO;AAE/B,UAAM,OAAO,IAAI,WAAW;AAAA,MAC1B,SAAS,KAAK;AAAA,MACd,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO,WAAW;AAAA,IAC7B,CAAC;AAED,SAAK,UAAU,IAAI,gBAAgB,MAAM,KAAK,gBAAgB;AAC9D,SAAK,OAAO,IAAI,aAAa,IAAI;AACjC,SAAK,YAAY,IAAI,kBAAkB,MAAM,KAAK,gBAAgB;AAClE,SAAK,aAAa,IAAI,mBAAmB,MAAM,KAAK,gBAAgB;AACpE,SAAK,YAAY,IAAI,kBAAkB,IAAI;AAC3C,SAAK,eAAe,IAAI,qBAAqB,IAAI;AACjD,SAAK,QAAQ,IAAI,cAAc,IAAI;AACnC,SAAK,YAAY,IAAI,UAAU,KAAK,SAAS,KAAK,WAAW,KAAK,UAAU;AAE5E,SAAK,qBAAqB,KAAK,UAAU,mBAAmB,KAAK,KAAK,SAAS;AAC/E,SAAK,gBAAgB,KAAK,UAAU,cAAc,KAAK,KAAK,SAAS;AACrE,SAAK,iBAAiB,KAAK,UAAU,eAAe,KAAK,KAAK,SAAS;AACvE,SAAK,qBAAqB,KAAK,UAAU,mBAAmB,KAAK,KAAK,SAAS;AAC/E,SAAK,mBAAmB,KAAK,UAAU,iBAAiB,KAAK,KAAK,SAAS;AAC3E,SAAK,mBAAmB,KAAK,UAAU,iBAAiB,KAAK,KAAK,SAAS;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,SAAuD;AAChE,UAAM,MAAM,IAAI,IAAI,GAAG,KAAK,MAAM,YAAY;AAC9C,QAAI,SAAS,IAAK,KAAI,aAAa,IAAI,OAAO,QAAQ,GAAG;AACzD,QAAI,SAAS,SAAU,KAAI,aAAa,IAAI,YAAY,QAAQ,QAAQ;AACxE,WAAO,IAAI,SAAS;AAAA,EACtB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/resources/friends.ts","../src/resources/tags.ts","../src/resources/scenarios.ts","../src/resources/broadcasts.ts","../src/resources/rich-menus.ts","../src/resources/tracked-links.ts","../src/resources/forms.ts","../src/resources/ad-platforms.ts","../src/resources/staff.ts","../src/delay.ts","../src/workflows.ts","../src/client.ts"],"sourcesContent":["export { LineHarness } from './client.js'\nexport { LineHarnessError } from './errors.js'\nexport { parseDelay } from './delay.js'\n\n// Resource classes (for advanced usage / type narrowing)\nexport { FriendsResource } from './resources/friends.js'\nexport { TagsResource } from './resources/tags.js'\nexport { ScenariosResource } from './resources/scenarios.js'\nexport { BroadcastsResource } from './resources/broadcasts.js'\nexport { RichMenusResource } from './resources/rich-menus.js'\nexport { TrackedLinksResource } from './resources/tracked-links.js'\nexport { FormsResource } from './resources/forms.js'\nexport { AdPlatformsResource } from './resources/ad-platforms.js'\nexport { StaffResource } from './resources/staff.js'\n\n// All types\nexport type {\n LineHarnessConfig,\n ApiResponse,\n PaginatedData,\n ScenarioTriggerType,\n MessageType,\n BroadcastStatus,\n Friend,\n FriendListParams,\n Tag,\n CreateTagInput,\n Scenario,\n ScenarioListItem,\n ScenarioWithSteps,\n ScenarioStep,\n CreateScenarioInput,\n CreateStepInput,\n UpdateScenarioInput,\n UpdateStepInput,\n FriendScenarioEnrollment,\n Broadcast,\n CreateBroadcastInput,\n UpdateBroadcastInput,\n SegmentRule,\n SegmentCondition,\n StepDefinition,\n RichMenu,\n RichMenuBounds,\n RichMenuAction,\n RichMenuArea,\n CreateRichMenuInput,\n TrackedLink,\n LinkClick,\n TrackedLinkWithClicks,\n CreateTrackedLinkInput,\n FormField,\n Form,\n CreateFormInput,\n UpdateFormInput,\n FormSubmission,\n StaffRole,\n StaffMember,\n StaffProfile,\n CreateStaffInput,\n UpdateStaffInput,\n} from './types.js'\n\nexport type {\n AdPlatform,\n AdConversionLog,\n CreateAdPlatformInput,\n UpdateAdPlatformInput,\n} from './resources/ad-platforms.js'\n","export class LineHarnessError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly endpoint: string,\n ) {\n super(message)\n this.name = 'LineHarnessError'\n }\n}\n","import { LineHarnessError } from './errors.js'\n\ninterface HttpClientConfig {\n baseUrl: string\n apiKey: string\n timeout: number\n}\n\nexport class HttpClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n private readonly timeout: number\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '')\n this.apiKey = config.apiKey\n this.timeout = config.timeout\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>('GET', path)\n }\n\n async post<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('POST', path, body)\n }\n\n async put<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PUT', path, body)\n }\n\n async patch<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PATCH', path, body)\n }\n\n async delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>('DELETE', path)\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n }\n\n const options: RequestInit = {\n method,\n headers,\n signal: AbortSignal.timeout(this.timeout),\n }\n\n if (body !== undefined) {\n options.body = JSON.stringify(body)\n }\n\n const res = await fetch(url, options)\n\n if (!res.ok) {\n let errorMessage = `HTTP ${res.status}`\n try {\n const errorBody = (await res.json()) as { error?: string }\n if (errorBody.error) errorMessage = errorBody.error\n } catch {\n // ignore parse errors\n }\n throw new LineHarnessError(errorMessage, res.status, `${method} ${path}`)\n }\n\n return res.json() as Promise<T>\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, PaginatedData, Friend, FriendListParams, MessageType } from '../types.js'\n\nexport class FriendsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: FriendListParams): Promise<PaginatedData<Friend>> {\n const query = new URLSearchParams()\n if (params?.limit !== undefined) query.set('limit', String(params.limit))\n if (params?.offset !== undefined) query.set('offset', String(params.offset))\n if (params?.tagId) query.set('tagId', params.tagId)\n const accountId = params?.accountId ?? this.defaultAccountId\n if (accountId) query.set('lineAccountId', accountId)\n const qs = query.toString()\n const path = qs ? `/api/friends?${qs}` : '/api/friends'\n const res = await this.http.get<ApiResponse<PaginatedData<Friend>>>(path)\n return res.data\n }\n\n async get(id: string): Promise<Friend> {\n const res = await this.http.get<ApiResponse<Friend>>(`/api/friends/${id}`)\n return res.data\n }\n\n async count(): Promise<number> {\n const res = await this.http.get<ApiResponse<{ count: number }>>('/api/friends/count')\n return res.data.count\n }\n\n async addTag(friendId: string, tagId: string): Promise<void> {\n await this.http.post(`/api/friends/${friendId}/tags`, { tagId })\n }\n\n async removeTag(friendId: string, tagId: string): Promise<void> {\n await this.http.delete(`/api/friends/${friendId}/tags/${tagId}`)\n }\n\n async sendMessage(friendId: string, content: string, messageType: MessageType = 'text'): Promise<{ messageId: string }> {\n const res = await this.http.post<ApiResponse<{ messageId: string }>>(`/api/friends/${friendId}/messages`, {\n messageType,\n content,\n })\n return res.data\n }\n\n async setMetadata(friendId: string, fields: Record<string, unknown>): Promise<Friend> {\n const res = await this.http.put<ApiResponse<Friend>>(`/api/friends/${friendId}/metadata`, fields)\n return res.data\n }\n\n async setRichMenu(friendId: string, richMenuId: string): Promise<void> {\n await this.http.post(`/api/friends/${friendId}/rich-menu`, { richMenuId })\n }\n\n async removeRichMenu(friendId: string): Promise<void> {\n await this.http.delete(`/api/friends/${friendId}/rich-menu`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, Tag, CreateTagInput } from '../types.js'\n\nexport class TagsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Tag[]> {\n const res = await this.http.get<ApiResponse<Tag[]>>('/api/tags')\n return res.data\n }\n\n async create(input: CreateTagInput): Promise<Tag> {\n const res = await this.http.post<ApiResponse<Tag>>('/api/tags', input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/tags/${id}`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type {\n ApiResponse,\n Scenario,\n ScenarioListItem,\n ScenarioWithSteps,\n ScenarioStep,\n CreateScenarioInput,\n CreateStepInput,\n UpdateScenarioInput,\n UpdateStepInput,\n FriendScenarioEnrollment,\n} from '../types.js'\n\nexport class ScenariosResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: { accountId?: string }): Promise<ScenarioListItem[]> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const query = accountId ? `?lineAccountId=${accountId}` : ''\n const res = await this.http.get<ApiResponse<ScenarioListItem[]>>(`/api/scenarios${query}`)\n return res.data\n }\n\n async get(id: string): Promise<ScenarioWithSteps> {\n const res = await this.http.get<ApiResponse<ScenarioWithSteps>>(`/api/scenarios/${id}`)\n return res.data\n }\n\n async create(input: CreateScenarioInput & { lineAccountId?: string }): Promise<Scenario> {\n const body = { ...input }\n if (!body.lineAccountId && this.defaultAccountId) {\n body.lineAccountId = this.defaultAccountId\n }\n const res = await this.http.post<ApiResponse<Scenario>>('/api/scenarios', body)\n return res.data\n }\n\n async update(id: string, input: UpdateScenarioInput): Promise<Scenario> {\n const res = await this.http.put<ApiResponse<Scenario>>(`/api/scenarios/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/scenarios/${id}`)\n }\n\n async addStep(scenarioId: string, input: CreateStepInput): Promise<ScenarioStep> {\n const res = await this.http.post<ApiResponse<ScenarioStep>>(`/api/scenarios/${scenarioId}/steps`, input)\n return res.data\n }\n\n async updateStep(scenarioId: string, stepId: string, input: UpdateStepInput): Promise<ScenarioStep> {\n const res = await this.http.put<ApiResponse<ScenarioStep>>(`/api/scenarios/${scenarioId}/steps/${stepId}`, input)\n return res.data\n }\n\n async deleteStep(scenarioId: string, stepId: string): Promise<void> {\n await this.http.delete(`/api/scenarios/${scenarioId}/steps/${stepId}`)\n }\n\n async enroll(scenarioId: string, friendId: string): Promise<FriendScenarioEnrollment> {\n const res = await this.http.post<ApiResponse<FriendScenarioEnrollment>>(\n `/api/scenarios/${scenarioId}/enroll/${friendId}`\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, Broadcast, CreateBroadcastInput, UpdateBroadcastInput, SegmentCondition } from '../types.js'\n\nexport class BroadcastsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: { accountId?: string }): Promise<Broadcast[]> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const query = accountId ? `?lineAccountId=${accountId}` : ''\n const res = await this.http.get<ApiResponse<Broadcast[]>>(`/api/broadcasts${query}`)\n return res.data\n }\n\n async get(id: string): Promise<Broadcast> {\n const res = await this.http.get<ApiResponse<Broadcast>>(`/api/broadcasts/${id}`)\n return res.data\n }\n\n async create(input: CreateBroadcastInput & { lineAccountId?: string }): Promise<Broadcast> {\n const body = { ...input }\n if (!body.lineAccountId && this.defaultAccountId) {\n body.lineAccountId = this.defaultAccountId\n }\n const res = await this.http.post<ApiResponse<Broadcast>>('/api/broadcasts', body)\n return res.data\n }\n\n async update(id: string, input: UpdateBroadcastInput): Promise<Broadcast> {\n const res = await this.http.put<ApiResponse<Broadcast>>(`/api/broadcasts/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/broadcasts/${id}`)\n }\n\n async send(id: string): Promise<Broadcast> {\n const res = await this.http.post<ApiResponse<Broadcast>>(`/api/broadcasts/${id}/send`)\n return res.data\n }\n\n async sendToSegment(id: string, conditions: SegmentCondition): Promise<Broadcast> {\n const res = await this.http.post<ApiResponse<Broadcast>>(\n `/api/broadcasts/${id}/send-segment`,\n { conditions },\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, RichMenu, CreateRichMenuInput } from '../types.js'\n\nexport class RichMenusResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<RichMenu[]> {\n const res = await this.http.get<ApiResponse<RichMenu[]>>('/api/rich-menus')\n return res.data\n }\n\n async create(menu: CreateRichMenuInput): Promise<{ richMenuId: string }> {\n const res = await this.http.post<ApiResponse<{ richMenuId: string }>>('/api/rich-menus', menu)\n return res.data\n }\n\n async delete(richMenuId: string): Promise<void> {\n await this.http.delete(`/api/rich-menus/${encodeURIComponent(richMenuId)}`)\n }\n\n async setDefault(richMenuId: string): Promise<void> {\n await this.http.post(`/api/rich-menus/${encodeURIComponent(richMenuId)}/default`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, TrackedLink, TrackedLinkWithClicks, CreateTrackedLinkInput } from '../types.js'\n\nexport class TrackedLinksResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<TrackedLink[]> {\n const res = await this.http.get<ApiResponse<TrackedLink[]>>('/api/tracked-links')\n return res.data\n }\n\n async create(input: CreateTrackedLinkInput): Promise<TrackedLink> {\n const res = await this.http.post<ApiResponse<TrackedLink>>('/api/tracked-links', input)\n return res.data\n }\n\n async get(id: string): Promise<TrackedLinkWithClicks> {\n const res = await this.http.get<ApiResponse<TrackedLinkWithClicks>>(`/api/tracked-links/${id}`)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/tracked-links/${id}`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type {\n ApiResponse,\n Form,\n FormSubmission,\n CreateFormInput,\n UpdateFormInput,\n} from '../types.js'\n\nexport class FormsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Form[]> {\n const res = await this.http.get<ApiResponse<Form[]>>('/api/forms')\n return res.data\n }\n\n async get(id: string): Promise<Form> {\n const res = await this.http.get<ApiResponse<Form>>(`/api/forms/${id}`)\n return res.data\n }\n\n async create(input: CreateFormInput): Promise<Form> {\n const res = await this.http.post<ApiResponse<Form>>('/api/forms', input)\n return res.data\n }\n\n async update(id: string, input: UpdateFormInput): Promise<Form> {\n const res = await this.http.put<ApiResponse<Form>>(`/api/forms/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/forms/${id}`)\n }\n\n async getSubmissions(formId: string): Promise<FormSubmission[]> {\n const res = await this.http.get<ApiResponse<FormSubmission[]>>(\n `/api/forms/${formId}/submissions`,\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse } from '../types.js'\n\nexport interface AdPlatform {\n id: string\n name: string\n displayName: string | null\n config: Record<string, unknown>\n isActive: boolean\n createdAt: string\n updatedAt: string\n}\n\nexport interface AdConversionLog {\n id: string\n adPlatformId: string\n friendId: string\n eventName: string\n clickId: string | null\n clickIdType: string | null\n status: string\n errorMessage: string | null\n createdAt: string\n}\n\nexport interface CreateAdPlatformInput {\n name: 'meta' | 'x' | 'google' | 'tiktok'\n displayName?: string\n config: Record<string, unknown>\n}\n\nexport interface UpdateAdPlatformInput {\n name?: string\n displayName?: string | null\n config?: Record<string, unknown>\n isActive?: boolean\n}\n\nexport class AdPlatformsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<AdPlatform[]> {\n const res = await this.http.get<ApiResponse<AdPlatform[]>>('/api/ad-platforms')\n return res.data\n }\n\n async create(input: CreateAdPlatformInput): Promise<AdPlatform> {\n const res = await this.http.post<ApiResponse<AdPlatform>>('/api/ad-platforms', input)\n return res.data\n }\n\n async update(id: string, input: UpdateAdPlatformInput): Promise<AdPlatform> {\n const res = await this.http.put<ApiResponse<AdPlatform>>(`/api/ad-platforms/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/ad-platforms/${id}`)\n }\n\n async getLogs(id: string, limit?: number): Promise<AdConversionLog[]> {\n const path = limit\n ? `/api/ad-platforms/${id}/logs?limit=${limit}`\n : `/api/ad-platforms/${id}/logs`\n const res = await this.http.get<ApiResponse<AdConversionLog[]>>(path)\n return res.data\n }\n\n async test(platform: string, eventName: string, friendId?: string): Promise<{ message: string }> {\n const res = await this.http.post<ApiResponse<{ message: string }>>('/api/ad-platforms/test', {\n platform,\n eventName,\n friendId,\n })\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, StaffMember, StaffProfile, CreateStaffInput, UpdateStaffInput } from '../types.js'\n\nexport class StaffResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<StaffMember[]> {\n const res = await this.http.get<ApiResponse<StaffMember[]>>('/api/staff')\n return res.data\n }\n\n async get(id: string): Promise<StaffMember> {\n const res = await this.http.get<ApiResponse<StaffMember>>(`/api/staff/${id}`)\n return res.data\n }\n\n async me(): Promise<StaffProfile> {\n const res = await this.http.get<ApiResponse<StaffProfile>>('/api/staff/me')\n return res.data\n }\n\n async create(input: CreateStaffInput): Promise<StaffMember> {\n const res = await this.http.post<ApiResponse<StaffMember>>('/api/staff', input)\n return res.data\n }\n\n async update(id: string, input: UpdateStaffInput): Promise<StaffMember> {\n const res = await this.http.patch<ApiResponse<StaffMember>>(`/api/staff/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/staff/${id}`)\n }\n\n async regenerateKey(id: string): Promise<{ apiKey: string }> {\n const res = await this.http.post<ApiResponse<{ apiKey: string }>>(`/api/staff/${id}/regenerate-key`)\n return res.data\n }\n}\n","const MULTIPLIERS: Record<string, number> = {\n m: 1,\n h: 60,\n d: 1440,\n w: 10080,\n}\n\nexport function parseDelay(input: string): number {\n const match = input.match(/^(\\d+)([mhdw])$/)\n if (!match) {\n throw new Error(`Invalid delay format: \"${input}\". Use format like \"30m\", \"1h\", \"1d\", \"1w\".`)\n }\n return Number(match[1]) * MULTIPLIERS[match[2]]\n}\n","import type { FriendsResource } from './resources/friends.js'\nimport type { ScenariosResource } from './resources/scenarios.js'\nimport type { BroadcastsResource } from './resources/broadcasts.js'\nimport type { StepDefinition, ScenarioTriggerType, ScenarioWithSteps, Broadcast, MessageType, SegmentCondition } from './types.js'\nimport { parseDelay } from './delay.js'\n\nexport class Workflows {\n constructor(\n private readonly friends: FriendsResource,\n private readonly scenarios: ScenariosResource,\n private readonly broadcasts: BroadcastsResource,\n ) {}\n\n async createStepScenario(\n name: string,\n triggerType: ScenarioTriggerType,\n steps: StepDefinition[],\n ): Promise<ScenarioWithSteps> {\n const scenario = await this.scenarios.create({ name, triggerType })\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i]\n await this.scenarios.addStep(scenario.id, {\n stepOrder: i + 1,\n delayMinutes: parseDelay(step.delay),\n messageType: step.type,\n messageContent: step.content,\n })\n }\n\n return this.scenarios.get(scenario.id)\n }\n\n async broadcastText(text: string): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: text.slice(0, 50),\n messageType: 'text',\n messageContent: text,\n targetType: 'all',\n })\n return this.broadcasts.send(broadcast.id)\n }\n\n async broadcastToTag(\n tagId: string,\n messageType: MessageType,\n content: string,\n ): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: content.slice(0, 50),\n messageType,\n messageContent: content,\n targetType: 'tag',\n targetTagId: tagId,\n })\n return this.broadcasts.send(broadcast.id)\n }\n\n async broadcastToSegment(\n messageType: MessageType,\n content: string,\n conditions: SegmentCondition,\n ): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: content.slice(0, 50),\n messageType,\n messageContent: content,\n targetType: 'all',\n })\n return this.broadcasts.sendToSegment(broadcast.id, conditions)\n }\n\n async sendTextToFriend(friendId: string, text: string): Promise<{ messageId: string }> {\n return this.friends.sendMessage(friendId, text, 'text')\n }\n\n async sendFlexToFriend(friendId: string, flexJson: string): Promise<{ messageId: string }> {\n return this.friends.sendMessage(friendId, flexJson, 'flex')\n }\n}\n","import { HttpClient } from './http.js'\nimport { FriendsResource } from './resources/friends.js'\nimport { TagsResource } from './resources/tags.js'\nimport { ScenariosResource } from './resources/scenarios.js'\nimport { BroadcastsResource } from './resources/broadcasts.js'\nimport { RichMenusResource } from './resources/rich-menus.js'\nimport { TrackedLinksResource } from './resources/tracked-links.js'\nimport { FormsResource } from './resources/forms.js'\nimport { AdPlatformsResource } from './resources/ad-platforms.js'\nimport { StaffResource } from './resources/staff.js'\nimport { Workflows } from './workflows.js'\nimport type { LineHarnessConfig, StepDefinition, ScenarioTriggerType, ScenarioWithSteps, Broadcast, MessageType, SegmentCondition } from './types.js'\n\nexport class LineHarness {\n readonly friends: FriendsResource\n readonly tags: TagsResource\n readonly scenarios: ScenariosResource\n readonly broadcasts: BroadcastsResource\n readonly richMenus: RichMenusResource\n readonly trackedLinks: TrackedLinksResource\n readonly forms: FormsResource\n readonly adPlatforms: AdPlatformsResource\n readonly staff: StaffResource\n\n private readonly apiUrl: string\n private readonly defaultAccountId: string | undefined\n private readonly workflows: Workflows\n\n readonly createStepScenario: (name: string, triggerType: ScenarioTriggerType, steps: StepDefinition[]) => Promise<ScenarioWithSteps>\n readonly broadcastText: (text: string) => Promise<Broadcast>\n readonly broadcastToTag: (tagId: string, messageType: MessageType, content: string) => Promise<Broadcast>\n readonly broadcastToSegment: (messageType: MessageType, content: string, conditions: SegmentCondition) => Promise<Broadcast>\n readonly sendTextToFriend: (friendId: string, text: string) => Promise<{ messageId: string }>\n readonly sendFlexToFriend: (friendId: string, flexJson: string) => Promise<{ messageId: string }>\n\n constructor(config: LineHarnessConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '')\n this.defaultAccountId = config.lineAccountId\n\n const http = new HttpClient({\n baseUrl: this.apiUrl,\n apiKey: config.apiKey,\n timeout: config.timeout ?? 30_000,\n })\n\n this.friends = new FriendsResource(http, this.defaultAccountId)\n this.tags = new TagsResource(http)\n this.scenarios = new ScenariosResource(http, this.defaultAccountId)\n this.broadcasts = new BroadcastsResource(http, this.defaultAccountId)\n this.richMenus = new RichMenusResource(http)\n this.trackedLinks = new TrackedLinksResource(http)\n this.forms = new FormsResource(http)\n this.adPlatforms = new AdPlatformsResource(http)\n this.staff = new StaffResource(http)\n this.workflows = new Workflows(this.friends, this.scenarios, this.broadcasts)\n\n this.createStepScenario = this.workflows.createStepScenario.bind(this.workflows)\n this.broadcastText = this.workflows.broadcastText.bind(this.workflows)\n this.broadcastToTag = this.workflows.broadcastToTag.bind(this.workflows)\n this.broadcastToSegment = this.workflows.broadcastToSegment.bind(this.workflows)\n this.sendTextToFriend = this.workflows.sendTextToFriend.bind(this.workflows)\n this.sendFlexToFriend = this.workflows.sendFlexToFriend.bind(this.workflows)\n }\n\n /**\n * Generate friend-add URL with OAuth (bot_prompt=aggressive)\n * This URL does friend-add + UUID in one step.\n *\n * @param ref - Attribution code (e.g., 'lp-a', 'instagram', 'seminar-0322')\n * @param redirect - URL to redirect after completion\n */\n getAuthUrl(options?: { ref?: string; redirect?: string }): string {\n const url = new URL(`${this.apiUrl}/auth/line`)\n if (options?.ref) url.searchParams.set('ref', options.ref)\n if (options?.redirect) url.searchParams.set('redirect', options.redirect)\n return url.toString()\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -11,6 +11,7 @@ declare class HttpClient {
11
11
  get<T = unknown>(path: string): Promise<T>;
12
12
  post<T = unknown>(path: string, body?: unknown): Promise<T>;
13
13
  put<T = unknown>(path: string, body?: unknown): Promise<T>;
14
+ patch<T = unknown>(path: string, body?: unknown): Promise<T>;
14
15
  delete<T = unknown>(path: string): Promise<T>;
15
16
  private request;
16
17
  }
@@ -302,6 +303,38 @@ interface FormSubmission {
302
303
  data: Record<string, unknown>;
303
304
  createdAt: string;
304
305
  }
306
+ type StaffRole = 'owner' | 'admin' | 'staff';
307
+ interface StaffMember {
308
+ id: string;
309
+ name: string;
310
+ email: string | null;
311
+ role: StaffRole;
312
+ /**
313
+ * Masked API key (e.g. `lh_****1234`).
314
+ * The full key is only returned once — on create or regenerate-key responses.
315
+ */
316
+ apiKey: string;
317
+ isActive: boolean;
318
+ createdAt: string;
319
+ updatedAt: string;
320
+ }
321
+ interface StaffProfile {
322
+ id: string;
323
+ name: string;
324
+ role: StaffRole;
325
+ email: string | null;
326
+ }
327
+ interface CreateStaffInput {
328
+ name: string;
329
+ email?: string;
330
+ role: 'admin' | 'staff';
331
+ }
332
+ interface UpdateStaffInput {
333
+ name?: string;
334
+ email?: string | null;
335
+ role?: StaffRole;
336
+ isActive?: boolean;
337
+ }
305
338
  interface StepDefinition {
306
339
  delay: string;
307
340
  type: MessageType;
@@ -314,9 +347,7 @@ declare class FriendsResource {
314
347
  constructor(http: HttpClient, defaultAccountId?: string | undefined);
315
348
  list(params?: FriendListParams): Promise<PaginatedData<Friend>>;
316
349
  get(id: string): Promise<Friend>;
317
- count(params?: {
318
- accountId?: string;
319
- }): Promise<number>;
350
+ count(): Promise<number>;
320
351
  addTag(friendId: string, tagId: string): Promise<void>;
321
352
  removeTag(friendId: string, tagId: string): Promise<void>;
322
353
  sendMessage(friendId: string, content: string, messageType?: MessageType): Promise<{
@@ -402,6 +433,64 @@ declare class FormsResource {
402
433
  getSubmissions(formId: string): Promise<FormSubmission[]>;
403
434
  }
404
435
 
436
+ interface AdPlatform {
437
+ id: string;
438
+ name: string;
439
+ displayName: string | null;
440
+ config: Record<string, unknown>;
441
+ isActive: boolean;
442
+ createdAt: string;
443
+ updatedAt: string;
444
+ }
445
+ interface AdConversionLog {
446
+ id: string;
447
+ adPlatformId: string;
448
+ friendId: string;
449
+ eventName: string;
450
+ clickId: string | null;
451
+ clickIdType: string | null;
452
+ status: string;
453
+ errorMessage: string | null;
454
+ createdAt: string;
455
+ }
456
+ interface CreateAdPlatformInput {
457
+ name: 'meta' | 'x' | 'google' | 'tiktok';
458
+ displayName?: string;
459
+ config: Record<string, unknown>;
460
+ }
461
+ interface UpdateAdPlatformInput {
462
+ name?: string;
463
+ displayName?: string | null;
464
+ config?: Record<string, unknown>;
465
+ isActive?: boolean;
466
+ }
467
+ declare class AdPlatformsResource {
468
+ private readonly http;
469
+ constructor(http: HttpClient);
470
+ list(): Promise<AdPlatform[]>;
471
+ create(input: CreateAdPlatformInput): Promise<AdPlatform>;
472
+ update(id: string, input: UpdateAdPlatformInput): Promise<AdPlatform>;
473
+ delete(id: string): Promise<void>;
474
+ getLogs(id: string, limit?: number): Promise<AdConversionLog[]>;
475
+ test(platform: string, eventName: string, friendId?: string): Promise<{
476
+ message: string;
477
+ }>;
478
+ }
479
+
480
+ declare class StaffResource {
481
+ private readonly http;
482
+ constructor(http: HttpClient);
483
+ list(): Promise<StaffMember[]>;
484
+ get(id: string): Promise<StaffMember>;
485
+ me(): Promise<StaffProfile>;
486
+ create(input: CreateStaffInput): Promise<StaffMember>;
487
+ update(id: string, input: UpdateStaffInput): Promise<StaffMember>;
488
+ delete(id: string): Promise<void>;
489
+ regenerateKey(id: string): Promise<{
490
+ apiKey: string;
491
+ }>;
492
+ }
493
+
405
494
  declare class LineHarness {
406
495
  readonly friends: FriendsResource;
407
496
  readonly tags: TagsResource;
@@ -410,6 +499,8 @@ declare class LineHarness {
410
499
  readonly richMenus: RichMenusResource;
411
500
  readonly trackedLinks: TrackedLinksResource;
412
501
  readonly forms: FormsResource;
502
+ readonly adPlatforms: AdPlatformsResource;
503
+ readonly staff: StaffResource;
413
504
  private readonly apiUrl;
414
505
  private readonly defaultAccountId;
415
506
  private readonly workflows;
@@ -445,4 +536,4 @@ declare class LineHarnessError extends Error {
445
536
 
446
537
  declare function parseDelay(input: string): number;
447
538
 
448
- export { type ApiResponse, type Broadcast, type BroadcastStatus, BroadcastsResource, type CreateBroadcastInput, type CreateFormInput, type CreateRichMenuInput, type CreateScenarioInput, type CreateStepInput, type CreateTagInput, type CreateTrackedLinkInput, type Form, type FormField, type FormSubmission, FormsResource, type Friend, type FriendListParams, type FriendScenarioEnrollment, FriendsResource, LineHarness, type LineHarnessConfig, LineHarnessError, type LinkClick, type MessageType, type PaginatedData, type RichMenu, type RichMenuAction, type RichMenuArea, type RichMenuBounds, RichMenusResource, type Scenario, type ScenarioListItem, type ScenarioStep, type ScenarioTriggerType, type ScenarioWithSteps, ScenariosResource, type SegmentCondition, type SegmentRule, type StepDefinition, type Tag, TagsResource, type TrackedLink, type TrackedLinkWithClicks, TrackedLinksResource, type UpdateBroadcastInput, type UpdateFormInput, type UpdateScenarioInput, type UpdateStepInput, parseDelay };
539
+ export { type AdConversionLog, type AdPlatform, AdPlatformsResource, type ApiResponse, type Broadcast, type BroadcastStatus, BroadcastsResource, type CreateAdPlatformInput, type CreateBroadcastInput, type CreateFormInput, type CreateRichMenuInput, type CreateScenarioInput, type CreateStaffInput, type CreateStepInput, type CreateTagInput, type CreateTrackedLinkInput, type Form, type FormField, type FormSubmission, FormsResource, type Friend, type FriendListParams, type FriendScenarioEnrollment, FriendsResource, LineHarness, type LineHarnessConfig, LineHarnessError, type LinkClick, type MessageType, type PaginatedData, type RichMenu, type RichMenuAction, type RichMenuArea, type RichMenuBounds, RichMenusResource, type Scenario, type ScenarioListItem, type ScenarioStep, type ScenarioTriggerType, type ScenarioWithSteps, ScenariosResource, type SegmentCondition, type SegmentRule, type StaffMember, type StaffProfile, StaffResource, type StaffRole, type StepDefinition, type Tag, TagsResource, type TrackedLink, type TrackedLinkWithClicks, TrackedLinksResource, type UpdateAdPlatformInput, type UpdateBroadcastInput, type UpdateFormInput, type UpdateScenarioInput, type UpdateStaffInput, type UpdateStepInput, parseDelay };
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ declare class HttpClient {
11
11
  get<T = unknown>(path: string): Promise<T>;
12
12
  post<T = unknown>(path: string, body?: unknown): Promise<T>;
13
13
  put<T = unknown>(path: string, body?: unknown): Promise<T>;
14
+ patch<T = unknown>(path: string, body?: unknown): Promise<T>;
14
15
  delete<T = unknown>(path: string): Promise<T>;
15
16
  private request;
16
17
  }
@@ -302,6 +303,38 @@ interface FormSubmission {
302
303
  data: Record<string, unknown>;
303
304
  createdAt: string;
304
305
  }
306
+ type StaffRole = 'owner' | 'admin' | 'staff';
307
+ interface StaffMember {
308
+ id: string;
309
+ name: string;
310
+ email: string | null;
311
+ role: StaffRole;
312
+ /**
313
+ * Masked API key (e.g. `lh_****1234`).
314
+ * The full key is only returned once — on create or regenerate-key responses.
315
+ */
316
+ apiKey: string;
317
+ isActive: boolean;
318
+ createdAt: string;
319
+ updatedAt: string;
320
+ }
321
+ interface StaffProfile {
322
+ id: string;
323
+ name: string;
324
+ role: StaffRole;
325
+ email: string | null;
326
+ }
327
+ interface CreateStaffInput {
328
+ name: string;
329
+ email?: string;
330
+ role: 'admin' | 'staff';
331
+ }
332
+ interface UpdateStaffInput {
333
+ name?: string;
334
+ email?: string | null;
335
+ role?: StaffRole;
336
+ isActive?: boolean;
337
+ }
305
338
  interface StepDefinition {
306
339
  delay: string;
307
340
  type: MessageType;
@@ -314,9 +347,7 @@ declare class FriendsResource {
314
347
  constructor(http: HttpClient, defaultAccountId?: string | undefined);
315
348
  list(params?: FriendListParams): Promise<PaginatedData<Friend>>;
316
349
  get(id: string): Promise<Friend>;
317
- count(params?: {
318
- accountId?: string;
319
- }): Promise<number>;
350
+ count(): Promise<number>;
320
351
  addTag(friendId: string, tagId: string): Promise<void>;
321
352
  removeTag(friendId: string, tagId: string): Promise<void>;
322
353
  sendMessage(friendId: string, content: string, messageType?: MessageType): Promise<{
@@ -402,6 +433,64 @@ declare class FormsResource {
402
433
  getSubmissions(formId: string): Promise<FormSubmission[]>;
403
434
  }
404
435
 
436
+ interface AdPlatform {
437
+ id: string;
438
+ name: string;
439
+ displayName: string | null;
440
+ config: Record<string, unknown>;
441
+ isActive: boolean;
442
+ createdAt: string;
443
+ updatedAt: string;
444
+ }
445
+ interface AdConversionLog {
446
+ id: string;
447
+ adPlatformId: string;
448
+ friendId: string;
449
+ eventName: string;
450
+ clickId: string | null;
451
+ clickIdType: string | null;
452
+ status: string;
453
+ errorMessage: string | null;
454
+ createdAt: string;
455
+ }
456
+ interface CreateAdPlatformInput {
457
+ name: 'meta' | 'x' | 'google' | 'tiktok';
458
+ displayName?: string;
459
+ config: Record<string, unknown>;
460
+ }
461
+ interface UpdateAdPlatformInput {
462
+ name?: string;
463
+ displayName?: string | null;
464
+ config?: Record<string, unknown>;
465
+ isActive?: boolean;
466
+ }
467
+ declare class AdPlatformsResource {
468
+ private readonly http;
469
+ constructor(http: HttpClient);
470
+ list(): Promise<AdPlatform[]>;
471
+ create(input: CreateAdPlatformInput): Promise<AdPlatform>;
472
+ update(id: string, input: UpdateAdPlatformInput): Promise<AdPlatform>;
473
+ delete(id: string): Promise<void>;
474
+ getLogs(id: string, limit?: number): Promise<AdConversionLog[]>;
475
+ test(platform: string, eventName: string, friendId?: string): Promise<{
476
+ message: string;
477
+ }>;
478
+ }
479
+
480
+ declare class StaffResource {
481
+ private readonly http;
482
+ constructor(http: HttpClient);
483
+ list(): Promise<StaffMember[]>;
484
+ get(id: string): Promise<StaffMember>;
485
+ me(): Promise<StaffProfile>;
486
+ create(input: CreateStaffInput): Promise<StaffMember>;
487
+ update(id: string, input: UpdateStaffInput): Promise<StaffMember>;
488
+ delete(id: string): Promise<void>;
489
+ regenerateKey(id: string): Promise<{
490
+ apiKey: string;
491
+ }>;
492
+ }
493
+
405
494
  declare class LineHarness {
406
495
  readonly friends: FriendsResource;
407
496
  readonly tags: TagsResource;
@@ -410,6 +499,8 @@ declare class LineHarness {
410
499
  readonly richMenus: RichMenusResource;
411
500
  readonly trackedLinks: TrackedLinksResource;
412
501
  readonly forms: FormsResource;
502
+ readonly adPlatforms: AdPlatformsResource;
503
+ readonly staff: StaffResource;
413
504
  private readonly apiUrl;
414
505
  private readonly defaultAccountId;
415
506
  private readonly workflows;
@@ -445,4 +536,4 @@ declare class LineHarnessError extends Error {
445
536
 
446
537
  declare function parseDelay(input: string): number;
447
538
 
448
- export { type ApiResponse, type Broadcast, type BroadcastStatus, BroadcastsResource, type CreateBroadcastInput, type CreateFormInput, type CreateRichMenuInput, type CreateScenarioInput, type CreateStepInput, type CreateTagInput, type CreateTrackedLinkInput, type Form, type FormField, type FormSubmission, FormsResource, type Friend, type FriendListParams, type FriendScenarioEnrollment, FriendsResource, LineHarness, type LineHarnessConfig, LineHarnessError, type LinkClick, type MessageType, type PaginatedData, type RichMenu, type RichMenuAction, type RichMenuArea, type RichMenuBounds, RichMenusResource, type Scenario, type ScenarioListItem, type ScenarioStep, type ScenarioTriggerType, type ScenarioWithSteps, ScenariosResource, type SegmentCondition, type SegmentRule, type StepDefinition, type Tag, TagsResource, type TrackedLink, type TrackedLinkWithClicks, TrackedLinksResource, type UpdateBroadcastInput, type UpdateFormInput, type UpdateScenarioInput, type UpdateStepInput, parseDelay };
539
+ export { type AdConversionLog, type AdPlatform, AdPlatformsResource, type ApiResponse, type Broadcast, type BroadcastStatus, BroadcastsResource, type CreateAdPlatformInput, type CreateBroadcastInput, type CreateFormInput, type CreateRichMenuInput, type CreateScenarioInput, type CreateStaffInput, type CreateStepInput, type CreateTagInput, type CreateTrackedLinkInput, type Form, type FormField, type FormSubmission, FormsResource, type Friend, type FriendListParams, type FriendScenarioEnrollment, FriendsResource, LineHarness, type LineHarnessConfig, LineHarnessError, type LinkClick, type MessageType, type PaginatedData, type RichMenu, type RichMenuAction, type RichMenuArea, type RichMenuBounds, RichMenusResource, type Scenario, type ScenarioListItem, type ScenarioStep, type ScenarioTriggerType, type ScenarioWithSteps, ScenariosResource, type SegmentCondition, type SegmentRule, type StaffMember, type StaffProfile, StaffResource, type StaffRole, type StepDefinition, type Tag, TagsResource, type TrackedLink, type TrackedLinkWithClicks, TrackedLinksResource, type UpdateAdPlatformInput, type UpdateBroadcastInput, type UpdateFormInput, type UpdateScenarioInput, type UpdateStaffInput, type UpdateStepInput, parseDelay };
package/dist/index.mjs CHANGED
@@ -27,6 +27,9 @@ var HttpClient = class {
27
27
  async put(path, body) {
28
28
  return this.request("PUT", path, body);
29
29
  }
30
+ async patch(path, body) {
31
+ return this.request("PATCH", path, body);
32
+ }
30
33
  async delete(path) {
31
34
  return this.request("DELETE", path);
32
35
  }
@@ -80,10 +83,8 @@ var FriendsResource = class {
80
83
  const res = await this.http.get(`/api/friends/${id}`);
81
84
  return res.data;
82
85
  }
83
- async count(params) {
84
- const accountId = params?.accountId ?? this.defaultAccountId;
85
- const path = accountId ? `/api/friends/count?lineAccountId=${encodeURIComponent(accountId)}` : "/api/friends/count";
86
- const res = await this.http.get(path);
86
+ async count() {
87
+ const res = await this.http.get("/api/friends/count");
87
88
  return res.data.count;
88
89
  }
89
90
  async addTag(friendId, tagId) {
@@ -298,6 +299,75 @@ var FormsResource = class {
298
299
  }
299
300
  };
300
301
 
302
+ // src/resources/ad-platforms.ts
303
+ var AdPlatformsResource = class {
304
+ constructor(http) {
305
+ this.http = http;
306
+ }
307
+ async list() {
308
+ const res = await this.http.get("/api/ad-platforms");
309
+ return res.data;
310
+ }
311
+ async create(input) {
312
+ const res = await this.http.post("/api/ad-platforms", input);
313
+ return res.data;
314
+ }
315
+ async update(id, input) {
316
+ const res = await this.http.put(`/api/ad-platforms/${id}`, input);
317
+ return res.data;
318
+ }
319
+ async delete(id) {
320
+ await this.http.delete(`/api/ad-platforms/${id}`);
321
+ }
322
+ async getLogs(id, limit) {
323
+ const path = limit ? `/api/ad-platforms/${id}/logs?limit=${limit}` : `/api/ad-platforms/${id}/logs`;
324
+ const res = await this.http.get(path);
325
+ return res.data;
326
+ }
327
+ async test(platform, eventName, friendId) {
328
+ const res = await this.http.post("/api/ad-platforms/test", {
329
+ platform,
330
+ eventName,
331
+ friendId
332
+ });
333
+ return res.data;
334
+ }
335
+ };
336
+
337
+ // src/resources/staff.ts
338
+ var StaffResource = class {
339
+ constructor(http) {
340
+ this.http = http;
341
+ }
342
+ async list() {
343
+ const res = await this.http.get("/api/staff");
344
+ return res.data;
345
+ }
346
+ async get(id) {
347
+ const res = await this.http.get(`/api/staff/${id}`);
348
+ return res.data;
349
+ }
350
+ async me() {
351
+ const res = await this.http.get("/api/staff/me");
352
+ return res.data;
353
+ }
354
+ async create(input) {
355
+ const res = await this.http.post("/api/staff", input);
356
+ return res.data;
357
+ }
358
+ async update(id, input) {
359
+ const res = await this.http.patch(`/api/staff/${id}`, input);
360
+ return res.data;
361
+ }
362
+ async delete(id) {
363
+ await this.http.delete(`/api/staff/${id}`);
364
+ }
365
+ async regenerateKey(id) {
366
+ const res = await this.http.post(`/api/staff/${id}/regenerate-key`);
367
+ return res.data;
368
+ }
369
+ };
370
+
301
371
  // src/delay.ts
302
372
  var MULTIPLIERS = {
303
373
  m: 1,
@@ -378,6 +448,8 @@ var LineHarness = class {
378
448
  richMenus;
379
449
  trackedLinks;
380
450
  forms;
451
+ adPlatforms;
452
+ staff;
381
453
  apiUrl;
382
454
  defaultAccountId;
383
455
  workflows;
@@ -402,6 +474,8 @@ var LineHarness = class {
402
474
  this.richMenus = new RichMenusResource(http);
403
475
  this.trackedLinks = new TrackedLinksResource(http);
404
476
  this.forms = new FormsResource(http);
477
+ this.adPlatforms = new AdPlatformsResource(http);
478
+ this.staff = new StaffResource(http);
405
479
  this.workflows = new Workflows(this.friends, this.scenarios, this.broadcasts);
406
480
  this.createStepScenario = this.workflows.createStepScenario.bind(this.workflows);
407
481
  this.broadcastText = this.workflows.broadcastText.bind(this.workflows);
@@ -425,6 +499,7 @@ var LineHarness = class {
425
499
  }
426
500
  };
427
501
  export {
502
+ AdPlatformsResource,
428
503
  BroadcastsResource,
429
504
  FormsResource,
430
505
  FriendsResource,
@@ -432,6 +507,7 @@ export {
432
507
  LineHarnessError,
433
508
  RichMenusResource,
434
509
  ScenariosResource,
510
+ StaffResource,
435
511
  TagsResource,
436
512
  TrackedLinksResource,
437
513
  parseDelay
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/friends.ts","../src/resources/tags.ts","../src/resources/scenarios.ts","../src/resources/broadcasts.ts","../src/resources/rich-menus.ts","../src/resources/tracked-links.ts","../src/resources/forms.ts","../src/delay.ts","../src/workflows.ts","../src/client.ts"],"sourcesContent":["export class LineHarnessError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly endpoint: string,\n ) {\n super(message)\n this.name = 'LineHarnessError'\n }\n}\n","import { LineHarnessError } from './errors.js'\n\ninterface HttpClientConfig {\n baseUrl: string\n apiKey: string\n timeout: number\n}\n\nexport class HttpClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n private readonly timeout: number\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '')\n this.apiKey = config.apiKey\n this.timeout = config.timeout\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>('GET', path)\n }\n\n async post<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('POST', path, body)\n }\n\n async put<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PUT', path, body)\n }\n\n async delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>('DELETE', path)\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n }\n\n const options: RequestInit = {\n method,\n headers,\n signal: AbortSignal.timeout(this.timeout),\n }\n\n if (body !== undefined) {\n options.body = JSON.stringify(body)\n }\n\n const res = await fetch(url, options)\n\n if (!res.ok) {\n let errorMessage = `HTTP ${res.status}`\n try {\n const errorBody = (await res.json()) as { error?: string }\n if (errorBody.error) errorMessage = errorBody.error\n } catch {\n // ignore parse errors\n }\n throw new LineHarnessError(errorMessage, res.status, `${method} ${path}`)\n }\n\n return res.json() as Promise<T>\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, PaginatedData, Friend, FriendListParams, MessageType } from '../types.js'\n\nexport class FriendsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: FriendListParams): Promise<PaginatedData<Friend>> {\n const query = new URLSearchParams()\n if (params?.limit !== undefined) query.set('limit', String(params.limit))\n if (params?.offset !== undefined) query.set('offset', String(params.offset))\n if (params?.tagId) query.set('tagId', params.tagId)\n const accountId = params?.accountId ?? this.defaultAccountId\n if (accountId) query.set('lineAccountId', accountId)\n const qs = query.toString()\n const path = qs ? `/api/friends?${qs}` : '/api/friends'\n const res = await this.http.get<ApiResponse<PaginatedData<Friend>>>(path)\n return res.data\n }\n\n async get(id: string): Promise<Friend> {\n const res = await this.http.get<ApiResponse<Friend>>(`/api/friends/${id}`)\n return res.data\n }\n\n async count(params?: { accountId?: string }): Promise<number> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const path = accountId\n ? `/api/friends/count?lineAccountId=${encodeURIComponent(accountId)}`\n : '/api/friends/count'\n const res = await this.http.get<ApiResponse<{ count: number }>>(path)\n return res.data.count\n }\n\n async addTag(friendId: string, tagId: string): Promise<void> {\n await this.http.post(`/api/friends/${friendId}/tags`, { tagId })\n }\n\n async removeTag(friendId: string, tagId: string): Promise<void> {\n await this.http.delete(`/api/friends/${friendId}/tags/${tagId}`)\n }\n\n async sendMessage(friendId: string, content: string, messageType: MessageType = 'text'): Promise<{ messageId: string }> {\n const res = await this.http.post<ApiResponse<{ messageId: string }>>(`/api/friends/${friendId}/messages`, {\n messageType,\n content,\n })\n return res.data\n }\n\n async setMetadata(friendId: string, fields: Record<string, unknown>): Promise<Friend> {\n const res = await this.http.put<ApiResponse<Friend>>(`/api/friends/${friendId}/metadata`, fields)\n return res.data\n }\n\n async setRichMenu(friendId: string, richMenuId: string): Promise<void> {\n await this.http.post(`/api/friends/${friendId}/rich-menu`, { richMenuId })\n }\n\n async removeRichMenu(friendId: string): Promise<void> {\n await this.http.delete(`/api/friends/${friendId}/rich-menu`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, Tag, CreateTagInput } from '../types.js'\n\nexport class TagsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Tag[]> {\n const res = await this.http.get<ApiResponse<Tag[]>>('/api/tags')\n return res.data\n }\n\n async create(input: CreateTagInput): Promise<Tag> {\n const res = await this.http.post<ApiResponse<Tag>>('/api/tags', input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/tags/${id}`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type {\n ApiResponse,\n Scenario,\n ScenarioListItem,\n ScenarioWithSteps,\n ScenarioStep,\n CreateScenarioInput,\n CreateStepInput,\n UpdateScenarioInput,\n UpdateStepInput,\n FriendScenarioEnrollment,\n} from '../types.js'\n\nexport class ScenariosResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: { accountId?: string }): Promise<ScenarioListItem[]> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const query = accountId ? `?lineAccountId=${accountId}` : ''\n const res = await this.http.get<ApiResponse<ScenarioListItem[]>>(`/api/scenarios${query}`)\n return res.data\n }\n\n async get(id: string): Promise<ScenarioWithSteps> {\n const res = await this.http.get<ApiResponse<ScenarioWithSteps>>(`/api/scenarios/${id}`)\n return res.data\n }\n\n async create(input: CreateScenarioInput & { lineAccountId?: string }): Promise<Scenario> {\n const body = { ...input }\n if (!body.lineAccountId && this.defaultAccountId) {\n body.lineAccountId = this.defaultAccountId\n }\n const res = await this.http.post<ApiResponse<Scenario>>('/api/scenarios', body)\n return res.data\n }\n\n async update(id: string, input: UpdateScenarioInput): Promise<Scenario> {\n const res = await this.http.put<ApiResponse<Scenario>>(`/api/scenarios/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/scenarios/${id}`)\n }\n\n async addStep(scenarioId: string, input: CreateStepInput): Promise<ScenarioStep> {\n const res = await this.http.post<ApiResponse<ScenarioStep>>(`/api/scenarios/${scenarioId}/steps`, input)\n return res.data\n }\n\n async updateStep(scenarioId: string, stepId: string, input: UpdateStepInput): Promise<ScenarioStep> {\n const res = await this.http.put<ApiResponse<ScenarioStep>>(`/api/scenarios/${scenarioId}/steps/${stepId}`, input)\n return res.data\n }\n\n async deleteStep(scenarioId: string, stepId: string): Promise<void> {\n await this.http.delete(`/api/scenarios/${scenarioId}/steps/${stepId}`)\n }\n\n async enroll(scenarioId: string, friendId: string): Promise<FriendScenarioEnrollment> {\n const res = await this.http.post<ApiResponse<FriendScenarioEnrollment>>(\n `/api/scenarios/${scenarioId}/enroll/${friendId}`\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, Broadcast, CreateBroadcastInput, UpdateBroadcastInput, SegmentCondition } from '../types.js'\n\nexport class BroadcastsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: { accountId?: string }): Promise<Broadcast[]> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const query = accountId ? `?lineAccountId=${accountId}` : ''\n const res = await this.http.get<ApiResponse<Broadcast[]>>(`/api/broadcasts${query}`)\n return res.data\n }\n\n async get(id: string): Promise<Broadcast> {\n const res = await this.http.get<ApiResponse<Broadcast>>(`/api/broadcasts/${id}`)\n return res.data\n }\n\n async create(input: CreateBroadcastInput & { lineAccountId?: string }): Promise<Broadcast> {\n const body = { ...input }\n if (!body.lineAccountId && this.defaultAccountId) {\n body.lineAccountId = this.defaultAccountId\n }\n const res = await this.http.post<ApiResponse<Broadcast>>('/api/broadcasts', body)\n return res.data\n }\n\n async update(id: string, input: UpdateBroadcastInput): Promise<Broadcast> {\n const res = await this.http.put<ApiResponse<Broadcast>>(`/api/broadcasts/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/broadcasts/${id}`)\n }\n\n async send(id: string): Promise<Broadcast> {\n const res = await this.http.post<ApiResponse<Broadcast>>(`/api/broadcasts/${id}/send`)\n return res.data\n }\n\n async sendToSegment(id: string, conditions: SegmentCondition): Promise<Broadcast> {\n const res = await this.http.post<ApiResponse<Broadcast>>(\n `/api/broadcasts/${id}/send-segment`,\n { conditions },\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, RichMenu, CreateRichMenuInput } from '../types.js'\n\nexport class RichMenusResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<RichMenu[]> {\n const res = await this.http.get<ApiResponse<RichMenu[]>>('/api/rich-menus')\n return res.data\n }\n\n async create(menu: CreateRichMenuInput): Promise<{ richMenuId: string }> {\n const res = await this.http.post<ApiResponse<{ richMenuId: string }>>('/api/rich-menus', menu)\n return res.data\n }\n\n async delete(richMenuId: string): Promise<void> {\n await this.http.delete(`/api/rich-menus/${encodeURIComponent(richMenuId)}`)\n }\n\n async setDefault(richMenuId: string): Promise<void> {\n await this.http.post(`/api/rich-menus/${encodeURIComponent(richMenuId)}/default`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, TrackedLink, TrackedLinkWithClicks, CreateTrackedLinkInput } from '../types.js'\n\nexport class TrackedLinksResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<TrackedLink[]> {\n const res = await this.http.get<ApiResponse<TrackedLink[]>>('/api/tracked-links')\n return res.data\n }\n\n async create(input: CreateTrackedLinkInput): Promise<TrackedLink> {\n const res = await this.http.post<ApiResponse<TrackedLink>>('/api/tracked-links', input)\n return res.data\n }\n\n async get(id: string): Promise<TrackedLinkWithClicks> {\n const res = await this.http.get<ApiResponse<TrackedLinkWithClicks>>(`/api/tracked-links/${id}`)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/tracked-links/${id}`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type {\n ApiResponse,\n Form,\n FormSubmission,\n CreateFormInput,\n UpdateFormInput,\n} from '../types.js'\n\nexport class FormsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Form[]> {\n const res = await this.http.get<ApiResponse<Form[]>>('/api/forms')\n return res.data\n }\n\n async get(id: string): Promise<Form> {\n const res = await this.http.get<ApiResponse<Form>>(`/api/forms/${id}`)\n return res.data\n }\n\n async create(input: CreateFormInput): Promise<Form> {\n const res = await this.http.post<ApiResponse<Form>>('/api/forms', input)\n return res.data\n }\n\n async update(id: string, input: UpdateFormInput): Promise<Form> {\n const res = await this.http.put<ApiResponse<Form>>(`/api/forms/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/forms/${id}`)\n }\n\n async getSubmissions(formId: string): Promise<FormSubmission[]> {\n const res = await this.http.get<ApiResponse<FormSubmission[]>>(\n `/api/forms/${formId}/submissions`,\n )\n return res.data\n }\n}\n","const MULTIPLIERS: Record<string, number> = {\n m: 1,\n h: 60,\n d: 1440,\n w: 10080,\n}\n\nexport function parseDelay(input: string): number {\n const match = input.match(/^(\\d+)([mhdw])$/)\n if (!match) {\n throw new Error(`Invalid delay format: \"${input}\". Use format like \"30m\", \"1h\", \"1d\", \"1w\".`)\n }\n return Number(match[1]) * MULTIPLIERS[match[2]]\n}\n","import type { FriendsResource } from './resources/friends.js'\nimport type { ScenariosResource } from './resources/scenarios.js'\nimport type { BroadcastsResource } from './resources/broadcasts.js'\nimport type { StepDefinition, ScenarioTriggerType, ScenarioWithSteps, Broadcast, MessageType, SegmentCondition } from './types.js'\nimport { parseDelay } from './delay.js'\n\nexport class Workflows {\n constructor(\n private readonly friends: FriendsResource,\n private readonly scenarios: ScenariosResource,\n private readonly broadcasts: BroadcastsResource,\n ) {}\n\n async createStepScenario(\n name: string,\n triggerType: ScenarioTriggerType,\n steps: StepDefinition[],\n ): Promise<ScenarioWithSteps> {\n const scenario = await this.scenarios.create({ name, triggerType })\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i]\n await this.scenarios.addStep(scenario.id, {\n stepOrder: i + 1,\n delayMinutes: parseDelay(step.delay),\n messageType: step.type,\n messageContent: step.content,\n })\n }\n\n return this.scenarios.get(scenario.id)\n }\n\n async broadcastText(text: string): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: text.slice(0, 50),\n messageType: 'text',\n messageContent: text,\n targetType: 'all',\n })\n return this.broadcasts.send(broadcast.id)\n }\n\n async broadcastToTag(\n tagId: string,\n messageType: MessageType,\n content: string,\n ): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: content.slice(0, 50),\n messageType,\n messageContent: content,\n targetType: 'tag',\n targetTagId: tagId,\n })\n return this.broadcasts.send(broadcast.id)\n }\n\n async broadcastToSegment(\n messageType: MessageType,\n content: string,\n conditions: SegmentCondition,\n ): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: content.slice(0, 50),\n messageType,\n messageContent: content,\n targetType: 'all',\n })\n return this.broadcasts.sendToSegment(broadcast.id, conditions)\n }\n\n async sendTextToFriend(friendId: string, text: string): Promise<{ messageId: string }> {\n return this.friends.sendMessage(friendId, text, 'text')\n }\n\n async sendFlexToFriend(friendId: string, flexJson: string): Promise<{ messageId: string }> {\n return this.friends.sendMessage(friendId, flexJson, 'flex')\n }\n}\n","import { HttpClient } from './http.js'\nimport { FriendsResource } from './resources/friends.js'\nimport { TagsResource } from './resources/tags.js'\nimport { ScenariosResource } from './resources/scenarios.js'\nimport { BroadcastsResource } from './resources/broadcasts.js'\nimport { RichMenusResource } from './resources/rich-menus.js'\nimport { TrackedLinksResource } from './resources/tracked-links.js'\nimport { FormsResource } from './resources/forms.js'\nimport { Workflows } from './workflows.js'\nimport type { LineHarnessConfig, StepDefinition, ScenarioTriggerType, ScenarioWithSteps, Broadcast, MessageType, SegmentCondition } from './types.js'\n\nexport class LineHarness {\n readonly friends: FriendsResource\n readonly tags: TagsResource\n readonly scenarios: ScenariosResource\n readonly broadcasts: BroadcastsResource\n readonly richMenus: RichMenusResource\n readonly trackedLinks: TrackedLinksResource\n readonly forms: FormsResource\n\n private readonly apiUrl: string\n private readonly defaultAccountId: string | undefined\n private readonly workflows: Workflows\n\n readonly createStepScenario: (name: string, triggerType: ScenarioTriggerType, steps: StepDefinition[]) => Promise<ScenarioWithSteps>\n readonly broadcastText: (text: string) => Promise<Broadcast>\n readonly broadcastToTag: (tagId: string, messageType: MessageType, content: string) => Promise<Broadcast>\n readonly broadcastToSegment: (messageType: MessageType, content: string, conditions: SegmentCondition) => Promise<Broadcast>\n readonly sendTextToFriend: (friendId: string, text: string) => Promise<{ messageId: string }>\n readonly sendFlexToFriend: (friendId: string, flexJson: string) => Promise<{ messageId: string }>\n\n constructor(config: LineHarnessConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '')\n this.defaultAccountId = config.lineAccountId\n\n const http = new HttpClient({\n baseUrl: this.apiUrl,\n apiKey: config.apiKey,\n timeout: config.timeout ?? 30_000,\n })\n\n this.friends = new FriendsResource(http, this.defaultAccountId)\n this.tags = new TagsResource(http)\n this.scenarios = new ScenariosResource(http, this.defaultAccountId)\n this.broadcasts = new BroadcastsResource(http, this.defaultAccountId)\n this.richMenus = new RichMenusResource(http)\n this.trackedLinks = new TrackedLinksResource(http)\n this.forms = new FormsResource(http)\n this.workflows = new Workflows(this.friends, this.scenarios, this.broadcasts)\n\n this.createStepScenario = this.workflows.createStepScenario.bind(this.workflows)\n this.broadcastText = this.workflows.broadcastText.bind(this.workflows)\n this.broadcastToTag = this.workflows.broadcastToTag.bind(this.workflows)\n this.broadcastToSegment = this.workflows.broadcastToSegment.bind(this.workflows)\n this.sendTextToFriend = this.workflows.sendTextToFriend.bind(this.workflows)\n this.sendFlexToFriend = this.workflows.sendFlexToFriend.bind(this.workflows)\n }\n\n /**\n * Generate friend-add URL with OAuth (bot_prompt=aggressive)\n * This URL does friend-add + UUID in one step.\n *\n * @param ref - Attribution code (e.g., 'lp-a', 'instagram', 'seminar-0322')\n * @param redirect - URL to redirect after completion\n */\n getAuthUrl(options?: { ref?: string; redirect?: string }): string {\n const url = new URL(`${this.apiUrl}/auth/line`)\n if (options?.ref) url.searchParams.set('ref', options.ref)\n if (options?.redirect) url.searchParams.set('redirect', options.redirect)\n return url.toString()\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/friends.ts","../src/resources/tags.ts","../src/resources/scenarios.ts","../src/resources/broadcasts.ts","../src/resources/rich-menus.ts","../src/resources/tracked-links.ts","../src/resources/forms.ts","../src/resources/ad-platforms.ts","../src/resources/staff.ts","../src/delay.ts","../src/workflows.ts","../src/client.ts"],"sourcesContent":["export class LineHarnessError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly endpoint: string,\n ) {\n super(message)\n this.name = 'LineHarnessError'\n }\n}\n","import { LineHarnessError } from './errors.js'\n\ninterface HttpClientConfig {\n baseUrl: string\n apiKey: string\n timeout: number\n}\n\nexport class HttpClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n private readonly timeout: number\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '')\n this.apiKey = config.apiKey\n this.timeout = config.timeout\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>('GET', path)\n }\n\n async post<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('POST', path, body)\n }\n\n async put<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PUT', path, body)\n }\n\n async patch<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PATCH', path, body)\n }\n\n async delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>('DELETE', path)\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n }\n\n const options: RequestInit = {\n method,\n headers,\n signal: AbortSignal.timeout(this.timeout),\n }\n\n if (body !== undefined) {\n options.body = JSON.stringify(body)\n }\n\n const res = await fetch(url, options)\n\n if (!res.ok) {\n let errorMessage = `HTTP ${res.status}`\n try {\n const errorBody = (await res.json()) as { error?: string }\n if (errorBody.error) errorMessage = errorBody.error\n } catch {\n // ignore parse errors\n }\n throw new LineHarnessError(errorMessage, res.status, `${method} ${path}`)\n }\n\n return res.json() as Promise<T>\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, PaginatedData, Friend, FriendListParams, MessageType } from '../types.js'\n\nexport class FriendsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: FriendListParams): Promise<PaginatedData<Friend>> {\n const query = new URLSearchParams()\n if (params?.limit !== undefined) query.set('limit', String(params.limit))\n if (params?.offset !== undefined) query.set('offset', String(params.offset))\n if (params?.tagId) query.set('tagId', params.tagId)\n const accountId = params?.accountId ?? this.defaultAccountId\n if (accountId) query.set('lineAccountId', accountId)\n const qs = query.toString()\n const path = qs ? `/api/friends?${qs}` : '/api/friends'\n const res = await this.http.get<ApiResponse<PaginatedData<Friend>>>(path)\n return res.data\n }\n\n async get(id: string): Promise<Friend> {\n const res = await this.http.get<ApiResponse<Friend>>(`/api/friends/${id}`)\n return res.data\n }\n\n async count(): Promise<number> {\n const res = await this.http.get<ApiResponse<{ count: number }>>('/api/friends/count')\n return res.data.count\n }\n\n async addTag(friendId: string, tagId: string): Promise<void> {\n await this.http.post(`/api/friends/${friendId}/tags`, { tagId })\n }\n\n async removeTag(friendId: string, tagId: string): Promise<void> {\n await this.http.delete(`/api/friends/${friendId}/tags/${tagId}`)\n }\n\n async sendMessage(friendId: string, content: string, messageType: MessageType = 'text'): Promise<{ messageId: string }> {\n const res = await this.http.post<ApiResponse<{ messageId: string }>>(`/api/friends/${friendId}/messages`, {\n messageType,\n content,\n })\n return res.data\n }\n\n async setMetadata(friendId: string, fields: Record<string, unknown>): Promise<Friend> {\n const res = await this.http.put<ApiResponse<Friend>>(`/api/friends/${friendId}/metadata`, fields)\n return res.data\n }\n\n async setRichMenu(friendId: string, richMenuId: string): Promise<void> {\n await this.http.post(`/api/friends/${friendId}/rich-menu`, { richMenuId })\n }\n\n async removeRichMenu(friendId: string): Promise<void> {\n await this.http.delete(`/api/friends/${friendId}/rich-menu`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, Tag, CreateTagInput } from '../types.js'\n\nexport class TagsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Tag[]> {\n const res = await this.http.get<ApiResponse<Tag[]>>('/api/tags')\n return res.data\n }\n\n async create(input: CreateTagInput): Promise<Tag> {\n const res = await this.http.post<ApiResponse<Tag>>('/api/tags', input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/tags/${id}`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type {\n ApiResponse,\n Scenario,\n ScenarioListItem,\n ScenarioWithSteps,\n ScenarioStep,\n CreateScenarioInput,\n CreateStepInput,\n UpdateScenarioInput,\n UpdateStepInput,\n FriendScenarioEnrollment,\n} from '../types.js'\n\nexport class ScenariosResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: { accountId?: string }): Promise<ScenarioListItem[]> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const query = accountId ? `?lineAccountId=${accountId}` : ''\n const res = await this.http.get<ApiResponse<ScenarioListItem[]>>(`/api/scenarios${query}`)\n return res.data\n }\n\n async get(id: string): Promise<ScenarioWithSteps> {\n const res = await this.http.get<ApiResponse<ScenarioWithSteps>>(`/api/scenarios/${id}`)\n return res.data\n }\n\n async create(input: CreateScenarioInput & { lineAccountId?: string }): Promise<Scenario> {\n const body = { ...input }\n if (!body.lineAccountId && this.defaultAccountId) {\n body.lineAccountId = this.defaultAccountId\n }\n const res = await this.http.post<ApiResponse<Scenario>>('/api/scenarios', body)\n return res.data\n }\n\n async update(id: string, input: UpdateScenarioInput): Promise<Scenario> {\n const res = await this.http.put<ApiResponse<Scenario>>(`/api/scenarios/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/scenarios/${id}`)\n }\n\n async addStep(scenarioId: string, input: CreateStepInput): Promise<ScenarioStep> {\n const res = await this.http.post<ApiResponse<ScenarioStep>>(`/api/scenarios/${scenarioId}/steps`, input)\n return res.data\n }\n\n async updateStep(scenarioId: string, stepId: string, input: UpdateStepInput): Promise<ScenarioStep> {\n const res = await this.http.put<ApiResponse<ScenarioStep>>(`/api/scenarios/${scenarioId}/steps/${stepId}`, input)\n return res.data\n }\n\n async deleteStep(scenarioId: string, stepId: string): Promise<void> {\n await this.http.delete(`/api/scenarios/${scenarioId}/steps/${stepId}`)\n }\n\n async enroll(scenarioId: string, friendId: string): Promise<FriendScenarioEnrollment> {\n const res = await this.http.post<ApiResponse<FriendScenarioEnrollment>>(\n `/api/scenarios/${scenarioId}/enroll/${friendId}`\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, Broadcast, CreateBroadcastInput, UpdateBroadcastInput, SegmentCondition } from '../types.js'\n\nexport class BroadcastsResource {\n constructor(\n private readonly http: HttpClient,\n private readonly defaultAccountId?: string,\n ) {}\n\n async list(params?: { accountId?: string }): Promise<Broadcast[]> {\n const accountId = params?.accountId ?? this.defaultAccountId\n const query = accountId ? `?lineAccountId=${accountId}` : ''\n const res = await this.http.get<ApiResponse<Broadcast[]>>(`/api/broadcasts${query}`)\n return res.data\n }\n\n async get(id: string): Promise<Broadcast> {\n const res = await this.http.get<ApiResponse<Broadcast>>(`/api/broadcasts/${id}`)\n return res.data\n }\n\n async create(input: CreateBroadcastInput & { lineAccountId?: string }): Promise<Broadcast> {\n const body = { ...input }\n if (!body.lineAccountId && this.defaultAccountId) {\n body.lineAccountId = this.defaultAccountId\n }\n const res = await this.http.post<ApiResponse<Broadcast>>('/api/broadcasts', body)\n return res.data\n }\n\n async update(id: string, input: UpdateBroadcastInput): Promise<Broadcast> {\n const res = await this.http.put<ApiResponse<Broadcast>>(`/api/broadcasts/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/broadcasts/${id}`)\n }\n\n async send(id: string): Promise<Broadcast> {\n const res = await this.http.post<ApiResponse<Broadcast>>(`/api/broadcasts/${id}/send`)\n return res.data\n }\n\n async sendToSegment(id: string, conditions: SegmentCondition): Promise<Broadcast> {\n const res = await this.http.post<ApiResponse<Broadcast>>(\n `/api/broadcasts/${id}/send-segment`,\n { conditions },\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, RichMenu, CreateRichMenuInput } from '../types.js'\n\nexport class RichMenusResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<RichMenu[]> {\n const res = await this.http.get<ApiResponse<RichMenu[]>>('/api/rich-menus')\n return res.data\n }\n\n async create(menu: CreateRichMenuInput): Promise<{ richMenuId: string }> {\n const res = await this.http.post<ApiResponse<{ richMenuId: string }>>('/api/rich-menus', menu)\n return res.data\n }\n\n async delete(richMenuId: string): Promise<void> {\n await this.http.delete(`/api/rich-menus/${encodeURIComponent(richMenuId)}`)\n }\n\n async setDefault(richMenuId: string): Promise<void> {\n await this.http.post(`/api/rich-menus/${encodeURIComponent(richMenuId)}/default`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, TrackedLink, TrackedLinkWithClicks, CreateTrackedLinkInput } from '../types.js'\n\nexport class TrackedLinksResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<TrackedLink[]> {\n const res = await this.http.get<ApiResponse<TrackedLink[]>>('/api/tracked-links')\n return res.data\n }\n\n async create(input: CreateTrackedLinkInput): Promise<TrackedLink> {\n const res = await this.http.post<ApiResponse<TrackedLink>>('/api/tracked-links', input)\n return res.data\n }\n\n async get(id: string): Promise<TrackedLinkWithClicks> {\n const res = await this.http.get<ApiResponse<TrackedLinkWithClicks>>(`/api/tracked-links/${id}`)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/tracked-links/${id}`)\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type {\n ApiResponse,\n Form,\n FormSubmission,\n CreateFormInput,\n UpdateFormInput,\n} from '../types.js'\n\nexport class FormsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<Form[]> {\n const res = await this.http.get<ApiResponse<Form[]>>('/api/forms')\n return res.data\n }\n\n async get(id: string): Promise<Form> {\n const res = await this.http.get<ApiResponse<Form>>(`/api/forms/${id}`)\n return res.data\n }\n\n async create(input: CreateFormInput): Promise<Form> {\n const res = await this.http.post<ApiResponse<Form>>('/api/forms', input)\n return res.data\n }\n\n async update(id: string, input: UpdateFormInput): Promise<Form> {\n const res = await this.http.put<ApiResponse<Form>>(`/api/forms/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/forms/${id}`)\n }\n\n async getSubmissions(formId: string): Promise<FormSubmission[]> {\n const res = await this.http.get<ApiResponse<FormSubmission[]>>(\n `/api/forms/${formId}/submissions`,\n )\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse } from '../types.js'\n\nexport interface AdPlatform {\n id: string\n name: string\n displayName: string | null\n config: Record<string, unknown>\n isActive: boolean\n createdAt: string\n updatedAt: string\n}\n\nexport interface AdConversionLog {\n id: string\n adPlatformId: string\n friendId: string\n eventName: string\n clickId: string | null\n clickIdType: string | null\n status: string\n errorMessage: string | null\n createdAt: string\n}\n\nexport interface CreateAdPlatformInput {\n name: 'meta' | 'x' | 'google' | 'tiktok'\n displayName?: string\n config: Record<string, unknown>\n}\n\nexport interface UpdateAdPlatformInput {\n name?: string\n displayName?: string | null\n config?: Record<string, unknown>\n isActive?: boolean\n}\n\nexport class AdPlatformsResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<AdPlatform[]> {\n const res = await this.http.get<ApiResponse<AdPlatform[]>>('/api/ad-platforms')\n return res.data\n }\n\n async create(input: CreateAdPlatformInput): Promise<AdPlatform> {\n const res = await this.http.post<ApiResponse<AdPlatform>>('/api/ad-platforms', input)\n return res.data\n }\n\n async update(id: string, input: UpdateAdPlatformInput): Promise<AdPlatform> {\n const res = await this.http.put<ApiResponse<AdPlatform>>(`/api/ad-platforms/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/ad-platforms/${id}`)\n }\n\n async getLogs(id: string, limit?: number): Promise<AdConversionLog[]> {\n const path = limit\n ? `/api/ad-platforms/${id}/logs?limit=${limit}`\n : `/api/ad-platforms/${id}/logs`\n const res = await this.http.get<ApiResponse<AdConversionLog[]>>(path)\n return res.data\n }\n\n async test(platform: string, eventName: string, friendId?: string): Promise<{ message: string }> {\n const res = await this.http.post<ApiResponse<{ message: string }>>('/api/ad-platforms/test', {\n platform,\n eventName,\n friendId,\n })\n return res.data\n }\n}\n","import type { HttpClient } from '../http.js'\nimport type { ApiResponse, StaffMember, StaffProfile, CreateStaffInput, UpdateStaffInput } from '../types.js'\n\nexport class StaffResource {\n constructor(private readonly http: HttpClient) {}\n\n async list(): Promise<StaffMember[]> {\n const res = await this.http.get<ApiResponse<StaffMember[]>>('/api/staff')\n return res.data\n }\n\n async get(id: string): Promise<StaffMember> {\n const res = await this.http.get<ApiResponse<StaffMember>>(`/api/staff/${id}`)\n return res.data\n }\n\n async me(): Promise<StaffProfile> {\n const res = await this.http.get<ApiResponse<StaffProfile>>('/api/staff/me')\n return res.data\n }\n\n async create(input: CreateStaffInput): Promise<StaffMember> {\n const res = await this.http.post<ApiResponse<StaffMember>>('/api/staff', input)\n return res.data\n }\n\n async update(id: string, input: UpdateStaffInput): Promise<StaffMember> {\n const res = await this.http.patch<ApiResponse<StaffMember>>(`/api/staff/${id}`, input)\n return res.data\n }\n\n async delete(id: string): Promise<void> {\n await this.http.delete(`/api/staff/${id}`)\n }\n\n async regenerateKey(id: string): Promise<{ apiKey: string }> {\n const res = await this.http.post<ApiResponse<{ apiKey: string }>>(`/api/staff/${id}/regenerate-key`)\n return res.data\n }\n}\n","const MULTIPLIERS: Record<string, number> = {\n m: 1,\n h: 60,\n d: 1440,\n w: 10080,\n}\n\nexport function parseDelay(input: string): number {\n const match = input.match(/^(\\d+)([mhdw])$/)\n if (!match) {\n throw new Error(`Invalid delay format: \"${input}\". Use format like \"30m\", \"1h\", \"1d\", \"1w\".`)\n }\n return Number(match[1]) * MULTIPLIERS[match[2]]\n}\n","import type { FriendsResource } from './resources/friends.js'\nimport type { ScenariosResource } from './resources/scenarios.js'\nimport type { BroadcastsResource } from './resources/broadcasts.js'\nimport type { StepDefinition, ScenarioTriggerType, ScenarioWithSteps, Broadcast, MessageType, SegmentCondition } from './types.js'\nimport { parseDelay } from './delay.js'\n\nexport class Workflows {\n constructor(\n private readonly friends: FriendsResource,\n private readonly scenarios: ScenariosResource,\n private readonly broadcasts: BroadcastsResource,\n ) {}\n\n async createStepScenario(\n name: string,\n triggerType: ScenarioTriggerType,\n steps: StepDefinition[],\n ): Promise<ScenarioWithSteps> {\n const scenario = await this.scenarios.create({ name, triggerType })\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i]\n await this.scenarios.addStep(scenario.id, {\n stepOrder: i + 1,\n delayMinutes: parseDelay(step.delay),\n messageType: step.type,\n messageContent: step.content,\n })\n }\n\n return this.scenarios.get(scenario.id)\n }\n\n async broadcastText(text: string): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: text.slice(0, 50),\n messageType: 'text',\n messageContent: text,\n targetType: 'all',\n })\n return this.broadcasts.send(broadcast.id)\n }\n\n async broadcastToTag(\n tagId: string,\n messageType: MessageType,\n content: string,\n ): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: content.slice(0, 50),\n messageType,\n messageContent: content,\n targetType: 'tag',\n targetTagId: tagId,\n })\n return this.broadcasts.send(broadcast.id)\n }\n\n async broadcastToSegment(\n messageType: MessageType,\n content: string,\n conditions: SegmentCondition,\n ): Promise<Broadcast> {\n const broadcast = await this.broadcasts.create({\n title: content.slice(0, 50),\n messageType,\n messageContent: content,\n targetType: 'all',\n })\n return this.broadcasts.sendToSegment(broadcast.id, conditions)\n }\n\n async sendTextToFriend(friendId: string, text: string): Promise<{ messageId: string }> {\n return this.friends.sendMessage(friendId, text, 'text')\n }\n\n async sendFlexToFriend(friendId: string, flexJson: string): Promise<{ messageId: string }> {\n return this.friends.sendMessage(friendId, flexJson, 'flex')\n }\n}\n","import { HttpClient } from './http.js'\nimport { FriendsResource } from './resources/friends.js'\nimport { TagsResource } from './resources/tags.js'\nimport { ScenariosResource } from './resources/scenarios.js'\nimport { BroadcastsResource } from './resources/broadcasts.js'\nimport { RichMenusResource } from './resources/rich-menus.js'\nimport { TrackedLinksResource } from './resources/tracked-links.js'\nimport { FormsResource } from './resources/forms.js'\nimport { AdPlatformsResource } from './resources/ad-platforms.js'\nimport { StaffResource } from './resources/staff.js'\nimport { Workflows } from './workflows.js'\nimport type { LineHarnessConfig, StepDefinition, ScenarioTriggerType, ScenarioWithSteps, Broadcast, MessageType, SegmentCondition } from './types.js'\n\nexport class LineHarness {\n readonly friends: FriendsResource\n readonly tags: TagsResource\n readonly scenarios: ScenariosResource\n readonly broadcasts: BroadcastsResource\n readonly richMenus: RichMenusResource\n readonly trackedLinks: TrackedLinksResource\n readonly forms: FormsResource\n readonly adPlatforms: AdPlatformsResource\n readonly staff: StaffResource\n\n private readonly apiUrl: string\n private readonly defaultAccountId: string | undefined\n private readonly workflows: Workflows\n\n readonly createStepScenario: (name: string, triggerType: ScenarioTriggerType, steps: StepDefinition[]) => Promise<ScenarioWithSteps>\n readonly broadcastText: (text: string) => Promise<Broadcast>\n readonly broadcastToTag: (tagId: string, messageType: MessageType, content: string) => Promise<Broadcast>\n readonly broadcastToSegment: (messageType: MessageType, content: string, conditions: SegmentCondition) => Promise<Broadcast>\n readonly sendTextToFriend: (friendId: string, text: string) => Promise<{ messageId: string }>\n readonly sendFlexToFriend: (friendId: string, flexJson: string) => Promise<{ messageId: string }>\n\n constructor(config: LineHarnessConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '')\n this.defaultAccountId = config.lineAccountId\n\n const http = new HttpClient({\n baseUrl: this.apiUrl,\n apiKey: config.apiKey,\n timeout: config.timeout ?? 30_000,\n })\n\n this.friends = new FriendsResource(http, this.defaultAccountId)\n this.tags = new TagsResource(http)\n this.scenarios = new ScenariosResource(http, this.defaultAccountId)\n this.broadcasts = new BroadcastsResource(http, this.defaultAccountId)\n this.richMenus = new RichMenusResource(http)\n this.trackedLinks = new TrackedLinksResource(http)\n this.forms = new FormsResource(http)\n this.adPlatforms = new AdPlatformsResource(http)\n this.staff = new StaffResource(http)\n this.workflows = new Workflows(this.friends, this.scenarios, this.broadcasts)\n\n this.createStepScenario = this.workflows.createStepScenario.bind(this.workflows)\n this.broadcastText = this.workflows.broadcastText.bind(this.workflows)\n this.broadcastToTag = this.workflows.broadcastToTag.bind(this.workflows)\n this.broadcastToSegment = this.workflows.broadcastToSegment.bind(this.workflows)\n this.sendTextToFriend = this.workflows.sendTextToFriend.bind(this.workflows)\n this.sendFlexToFriend = this.workflows.sendFlexToFriend.bind(this.workflows)\n }\n\n /**\n * Generate friend-add URL with OAuth (bot_prompt=aggressive)\n * This URL does friend-add + UUID in one step.\n *\n * @param ref - Attribution code (e.g., 'lp-a', 'instagram', 'seminar-0322')\n * @param redirect - URL to redirect after completion\n */\n getAuthUrl(options?: { ref?: string; redirect?: string }): string {\n const url = new URL(`${this.apiUrl}/auth/line`)\n if (options?.ref) url.searchParams.set('ref', options.ref)\n if (options?.redirect) url.searchParams.set('redirect', options.redirect)\n return url.toString()\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@line-harness/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "AI-native SDK for LINE Harness — programmatic LINE official account automation",
5
5
  "type": "module",
6
6
  "exports": {