opensoma 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/package.json +5 -1
  2. package/dist/src/agent-browser-launcher.d.ts +43 -0
  3. package/dist/src/agent-browser-launcher.d.ts.map +1 -0
  4. package/dist/src/agent-browser-launcher.js +97 -0
  5. package/dist/src/agent-browser-launcher.js.map +1 -0
  6. package/dist/src/cli.d.ts.map +1 -1
  7. package/dist/src/cli.js +8 -5
  8. package/dist/src/cli.js.map +1 -1
  9. package/dist/src/client.d.ts +34 -7
  10. package/dist/src/client.d.ts.map +1 -1
  11. package/dist/src/client.js +224 -52
  12. package/dist/src/client.js.map +1 -1
  13. package/dist/src/commands/agent-browser.d.ts +3 -0
  14. package/dist/src/commands/agent-browser.d.ts.map +1 -0
  15. package/dist/src/commands/agent-browser.js +27 -0
  16. package/dist/src/commands/agent-browser.js.map +1 -0
  17. package/dist/src/commands/auth.d.ts +1 -1
  18. package/dist/src/commands/auth.d.ts.map +1 -1
  19. package/dist/src/commands/auth.js +4 -2
  20. package/dist/src/commands/auth.js.map +1 -1
  21. package/dist/src/commands/dashboard.d.ts +13 -0
  22. package/dist/src/commands/dashboard.d.ts.map +1 -1
  23. package/dist/src/commands/dashboard.js +10 -18
  24. package/dist/src/commands/dashboard.js.map +1 -1
  25. package/dist/src/commands/helpers.d.ts +1 -1
  26. package/dist/src/commands/helpers.d.ts.map +1 -1
  27. package/dist/src/commands/helpers.js +2 -2
  28. package/dist/src/commands/helpers.js.map +1 -1
  29. package/dist/src/commands/index.d.ts +3 -1
  30. package/dist/src/commands/index.d.ts.map +1 -1
  31. package/dist/src/commands/index.js +3 -1
  32. package/dist/src/commands/index.js.map +1 -1
  33. package/dist/src/commands/mentoring.d.ts.map +1 -1
  34. package/dist/src/commands/mentoring.js +54 -29
  35. package/dist/src/commands/mentoring.js.map +1 -1
  36. package/dist/src/commands/notice.d.ts.map +1 -1
  37. package/dist/src/commands/notice.js +2 -1
  38. package/dist/src/commands/notice.js.map +1 -1
  39. package/dist/src/commands/report.d.ts.map +1 -1
  40. package/dist/src/commands/report.js +4 -2
  41. package/dist/src/commands/report.js.map +1 -1
  42. package/dist/src/commands/room.d.ts.map +1 -1
  43. package/dist/src/commands/room.js +125 -2
  44. package/dist/src/commands/room.js.map +1 -1
  45. package/dist/src/commands/schedule.d.ts +3 -0
  46. package/dist/src/commands/schedule.d.ts.map +1 -0
  47. package/dist/src/commands/schedule.js +27 -0
  48. package/dist/src/commands/schedule.js.map +1 -0
  49. package/dist/src/commands/team.d.ts.map +1 -1
  50. package/dist/src/commands/team.js +55 -4
  51. package/dist/src/commands/team.js.map +1 -1
  52. package/dist/src/commands/toz.d.ts +16 -0
  53. package/dist/src/commands/toz.d.ts.map +1 -0
  54. package/dist/src/commands/toz.js +488 -0
  55. package/dist/src/commands/toz.js.map +1 -0
  56. package/dist/src/constants.d.ts +5 -5
  57. package/dist/src/constants.d.ts.map +1 -1
  58. package/dist/src/constants.js +20 -8
  59. package/dist/src/constants.js.map +1 -1
  60. package/dist/src/credential-manager.d.ts +15 -0
  61. package/dist/src/credential-manager.d.ts.map +1 -1
  62. package/dist/src/credential-manager.js +46 -0
  63. package/dist/src/credential-manager.js.map +1 -1
  64. package/dist/src/formatters.d.ts +11 -3
  65. package/dist/src/formatters.d.ts.map +1 -1
  66. package/dist/src/formatters.js +281 -52
  67. package/dist/src/formatters.js.map +1 -1
  68. package/dist/src/http.d.ts +8 -0
  69. package/dist/src/http.d.ts.map +1 -1
  70. package/dist/src/http.js +29 -1
  71. package/dist/src/http.js.map +1 -1
  72. package/dist/src/index.d.ts +8 -1
  73. package/dist/src/index.d.ts.map +1 -1
  74. package/dist/src/index.js +4 -1
  75. package/dist/src/index.js.map +1 -1
  76. package/dist/src/session-recovery.js +2 -0
  77. package/dist/src/session-recovery.js.map +1 -1
  78. package/dist/src/shared/utils/swmaestro.d.ts +34 -1
  79. package/dist/src/shared/utils/swmaestro.d.ts.map +1 -1
  80. package/dist/src/shared/utils/swmaestro.js +102 -39
  81. package/dist/src/shared/utils/swmaestro.js.map +1 -1
  82. package/dist/src/shared/utils/team-action-params.d.ts +3 -0
  83. package/dist/src/shared/utils/team-action-params.d.ts.map +1 -0
  84. package/dist/src/shared/utils/team-action-params.js +10 -0
  85. package/dist/src/shared/utils/team-action-params.js.map +1 -0
  86. package/dist/src/shared/utils/team-params.d.ts +12 -0
  87. package/dist/src/shared/utils/team-params.d.ts.map +1 -0
  88. package/dist/src/shared/utils/team-params.js +38 -0
  89. package/dist/src/shared/utils/team-params.js.map +1 -0
  90. package/dist/src/toz-client.d.ts +89 -0
  91. package/dist/src/toz-client.d.ts.map +1 -0
  92. package/dist/src/toz-client.js +204 -0
  93. package/dist/src/toz-client.js.map +1 -0
  94. package/dist/src/toz-pending-store.d.ts +30 -0
  95. package/dist/src/toz-pending-store.d.ts.map +1 -0
  96. package/dist/src/toz-pending-store.js +36 -0
  97. package/dist/src/toz-pending-store.js.map +1 -0
  98. package/dist/src/types.d.ts +147 -10
  99. package/dist/src/types.d.ts.map +1 -1
  100. package/dist/src/types.js +74 -6
  101. package/dist/src/types.js.map +1 -1
  102. package/package.json +5 -1
  103. package/src/agent-browser-launcher.test.ts +263 -0
  104. package/src/agent-browser-launcher.ts +159 -0
  105. package/src/cli.ts +10 -5
  106. package/src/client.test.ts +673 -30
  107. package/src/client.ts +287 -67
  108. package/src/commands/agent-browser.ts +33 -0
  109. package/src/commands/auth.test.ts +77 -26
  110. package/src/commands/auth.ts +5 -3
  111. package/src/commands/dashboard.test.ts +57 -0
  112. package/src/commands/dashboard.ts +22 -19
  113. package/src/commands/helpers.test.ts +76 -25
  114. package/src/commands/helpers.ts +3 -3
  115. package/src/commands/index.ts +3 -1
  116. package/src/commands/mentoring.ts +60 -29
  117. package/src/commands/notice.ts +2 -1
  118. package/src/commands/report.ts +4 -2
  119. package/src/commands/room.ts +160 -1
  120. package/src/commands/schedule.ts +32 -0
  121. package/src/commands/team.ts +73 -5
  122. package/src/commands/toz.test.ts +51 -0
  123. package/src/commands/toz.ts +607 -0
  124. package/src/constants.ts +20 -8
  125. package/src/credential-manager.test.ts +98 -0
  126. package/src/credential-manager.ts +50 -0
  127. package/src/formatters.test.ts +528 -33
  128. package/src/formatters.ts +309 -55
  129. package/src/http.test.ts +71 -2
  130. package/src/http.ts +41 -2
  131. package/src/index.ts +23 -1
  132. package/src/session-recovery.ts +2 -0
  133. package/src/shared/utils/swmaestro.test.ts +245 -9
  134. package/src/shared/utils/swmaestro.ts +150 -47
  135. package/src/shared/utils/team-action-params.test.ts +32 -0
  136. package/src/shared/utils/team-action-params.ts +10 -0
  137. package/src/shared/utils/team-params.test.ts +141 -0
  138. package/src/shared/utils/team-params.ts +53 -0
  139. package/src/toz-client.test.ts +243 -0
  140. package/src/toz-client.ts +311 -0
  141. package/src/toz-pending-store.test.ts +91 -0
  142. package/src/toz-pending-store.ts +62 -0
  143. package/src/types.test.ts +26 -13
  144. package/src/types.ts +87 -7
  145. package/dist/src/commands/event.d.ts +0 -3
  146. package/dist/src/commands/event.d.ts.map +0 -1
  147. package/dist/src/commands/event.js +0 -58
  148. package/dist/src/commands/event.js.map +0 -1
  149. package/src/commands/event.ts +0 -73
@@ -1 +1 @@
1
- {"version":3,"file":"credential-manager.d.ts","sourceRoot":"","sources":["../../src/credential-manager.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAY1C,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;CAChC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,iBAAiB,CAAQ;gBAErB,SAAS,CAAC,EAAE,MAAM;IAMxB,IAAI,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAgBjC,IAAI,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAe7C,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAK7C,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;YAKf,kBAAkB;YAUlB,oBAAoB;YAYpB,aAAa;YAab,aAAa;YAgBb,wBAAwB;YAYxB,wBAAwB;CAWvC"}
1
+ {"version":3,"file":"credential-manager.d.ts","sourceRoot":"","sources":["../../src/credential-manager.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAY1C,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;CAChC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,iBAAiB,CAAQ;gBAErB,SAAS,CAAC,EAAE,MAAM;IAMxB,IAAI,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAgBjC,IAAI,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAe7C,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAK7C,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAK7B;;;;;;;OAOG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBlC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1D,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC,cAAc,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;YAMzD,kBAAkB;YAUlB,oBAAoB;YAYpB,aAAa;YAab,aAAa;YAgBb,wBAAwB;YAYxB,wBAAwB;CAWvC"}
@@ -45,6 +45,52 @@ export class CredentialManager {
45
45
  await rm(this.credentialsPath, { force: true });
46
46
  await rm(this.encryptionKeyPath, { force: true });
47
47
  }
48
+ /**
49
+ * Wipe ephemeral session fields (sessionCookie, csrfToken, loggedInAt) while
50
+ * preserving long-term material (username, password, TOZ identity). Used when
51
+ * the server-side session expired but we still want automatic recovery on the
52
+ * next run via `recoverSession()`.
53
+ *
54
+ * No-op when no credentials file exists or no recovery material is stored.
55
+ */
56
+ async clearSessionState() {
57
+ const current = await this.getCredentials();
58
+ if (!current) {
59
+ return;
60
+ }
61
+ if (!current.username && !current.password && !current.tozName && !current.tozPhone) {
62
+ await this.remove();
63
+ return;
64
+ }
65
+ await this.setCredentials({
66
+ sessionCookie: '',
67
+ csrfToken: '',
68
+ username: current.username,
69
+ password: current.password,
70
+ tozName: current.tozName,
71
+ tozPhone: current.tozPhone,
72
+ });
73
+ }
74
+ async setTozIdentity(name, phone) {
75
+ const existing = await this.getCredentials();
76
+ if (!existing) {
77
+ throw new Error('SWMaestro credentials not found. Run: opensoma auth login first.');
78
+ }
79
+ await this.setCredentials({ ...existing, tozName: name, tozPhone: phone });
80
+ }
81
+ async clearTozIdentity() {
82
+ const existing = await this.getCredentials();
83
+ if (!existing)
84
+ return;
85
+ const { tozName: _name, tozPhone: _phone, ...rest } = existing;
86
+ await this.setCredentials(rest);
87
+ }
88
+ async getTozIdentity() {
89
+ const creds = await this.getCredentials();
90
+ if (!creds?.tozName || !creds?.tozPhone)
91
+ return null;
92
+ return { name: creds.tozName, phone: creds.tozPhone };
93
+ }
48
94
  async hydrateCredentials(credentials) {
49
95
  if (!credentials.encryptedPassword) {
50
96
  return credentials;
@@ -1 +1 @@
1
- {"version":3,"file":"credential-manager.js","sourceRoot":"","sources":["../../src/credential-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"credential-manager.js","sourceRoot":"","sources":["../../src/credential-manager.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,24 @@
1
- import { type ApplicationHistoryItem, type ApprovalListItem, type Dashboard, type EventListItem, type MemberInfo, type MentoringDetail, type MentoringListItem, type NoticeDetail, type NoticeListItem, type Pagination, type ReportDetail, type ReportListItem, type RoomCard, type TeamInfo } from './types.js';
1
+ import { type ApplicationHistoryItem, type ApprovalListItem, type Dashboard, type MemberInfo, type MentoringDetail, type MentoringEditForm, type MentoringListItem, type NoticeDetail, type NoticeListItem, type Pagination, type ReportDetail, type ReportListItem, type RoomCard, type RoomReservationDetail, type RoomReservationListItem, type ScheduleListItem, type TeamInfo } from './types.js';
2
2
  export declare function parseMentoringList(html: string): MentoringListItem[];
3
3
  export declare function parseMentoringDetail(html: string, id?: number): MentoringDetail;
4
+ export declare function parseMentoringEditForm(html: string, id?: number): MentoringEditForm;
4
5
  export declare function parseRoomList(html: string): RoomCard[];
5
6
  export declare function parseRoomSlots(html: string): RoomCard['timeSlots'];
7
+ export declare function parseRoomReservationDetail(html: string): RoomReservationDetail;
8
+ export declare function parseRoomReservationList(html: string): RoomReservationListItem[];
6
9
  export declare function parseDashboard(html: string): Dashboard;
7
10
  export declare function parseNoticeList(html: string): NoticeListItem[];
8
11
  export declare function parseNoticeDetail(html: string, id?: number): NoticeDetail;
9
12
  export declare function parseTeamInfo(html: string): TeamInfo;
10
13
  export declare function parseMemberInfo(html: string): MemberInfo;
11
- export declare function parseEventList(html: string): EventListItem[];
14
+ export declare function parseScheduleList(html: string): {
15
+ items: ScheduleListItem[];
16
+ pagination: Pagination;
17
+ };
12
18
  export declare function parseApplicationHistory(html: string): ApplicationHistoryItem[];
13
- export declare function parsePagination(html: string): Pagination;
19
+ export declare function parsePagination(html: string, options?: {
20
+ itemCount?: number;
21
+ }): Pagination;
14
22
  export declare function parseCsrfToken(html: string): string;
15
23
  export declare function parseReportList(html: string): ReportListItem[];
16
24
  export declare function parseReportDetail(html: string, id?: number): ReportDetail;
@@ -1 +1 @@
1
- {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/formatters.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,sBAAsB,EAE3B,KAAK,gBAAgB,EAErB,KAAK,SAAS,EAEd,KAAK,aAAa,EAElB,KAAK,UAAU,EAEf,KAAK,eAAe,EAEpB,KAAK,iBAAiB,EAEtB,KAAK,YAAY,EAEjB,KAAK,cAAc,EAEnB,KAAK,UAAU,EAEf,KAAK,YAAY,EAEjB,KAAK,cAAc,EAEnB,KAAK,QAAQ,EAEb,KAAK,QAAQ,EAEd,MAAM,SAAS,CAAA;AAIhB,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAmBpE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAI,GAAG,eAAe,CAgD1E;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAiBtD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CASlE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAqBtD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAW9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAI,GAAG,YAAY,CAqBpE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAepD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAYxD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAY5D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,EAAE,CAe9E;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAWxD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAgB9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAI,GAAG,YAAY,CAiEpE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CA0BlE"}
1
+ {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/formatters.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,sBAAsB,EAE3B,KAAK,gBAAgB,EAErB,KAAK,SAAS,EAEd,KAAK,UAAU,EAEf,KAAK,eAAe,EAEpB,KAAK,iBAAiB,EAEtB,KAAK,iBAAiB,EAEtB,KAAK,YAAY,EAEjB,KAAK,cAAc,EAEnB,KAAK,UAAU,EAEf,KAAK,YAAY,EAEjB,KAAK,cAAc,EAEnB,KAAK,QAAQ,EAEb,KAAK,qBAAqB,EAE1B,KAAK,uBAAuB,EAG5B,KAAK,gBAAgB,EAErB,KAAK,QAAQ,EAEd,MAAM,SAAS,CAAA;AAIhB,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAmBpE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAI,GAAG,eAAe,CAgD1E;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAI,GAAG,iBAAiB,CA4B9E;AAiDD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAiBtD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CASlE;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,CAwB9E;AAmBD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,EAAE,CAqBhF;AAgBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAsBtD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAW9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAI,GAAG,YAAY,CAqBpE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAWpD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAYxD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAyBrG;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,EAAE,CAkB9E;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAa1F;AAuBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAoB9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAI,GAAG,YAAY,CAiEpE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CA0BlE"}
@@ -1,6 +1,6 @@
1
1
  import { parse } from 'node-html-parser';
2
2
  import { decodeHtmlEntities } from './shared/utils/html.js';
3
- import { ApplicationHistoryItemSchema, ApprovalListItemSchema, DashboardSchema, EventListItemSchema, MemberInfoSchema, MentoringDetailSchema, MentoringListItemSchema, NoticeDetailSchema, NoticeListItemSchema, PaginationSchema, ReportDetailSchema, ReportListItemSchema, RoomCardSchema, TeamInfoSchema, } from './types.js';
3
+ import { ApplicationHistoryItemSchema, ApprovalListItemSchema, DashboardSchema, MemberInfoSchema, MentoringDetailSchema, MentoringEditFormSchema, MentoringListItemSchema, NoticeDetailSchema, NoticeListItemSchema, PaginationSchema, ReportDetailSchema, ReportListItemSchema, RoomCardSchema, RoomReservationDetailSchema, RoomReservationListItemSchema, ScheduleListItemSchema, TeamInfoSchema, } from './types.js';
4
4
  export function parseMentoringList(html) {
5
5
  return findTableRows(html, 9).map((cells) => {
6
6
  const titleLink = cells[1]?.querySelector('a');
@@ -63,6 +63,82 @@ export function parseMentoringDetail(html, id = 0) {
63
63
  applicants,
64
64
  });
65
65
  }
66
+ export function parseMentoringEditForm(html, id = 0) {
67
+ const root = parse(html);
68
+ const form = root.querySelector('form#board') ?? root.querySelector('form');
69
+ const fields = readFormFields(form);
70
+ const initial = parseInitialDataBlock(html);
71
+ const pick = (key) => {
72
+ const formValue = fields[key];
73
+ if (formValue && formValue.trim() !== '')
74
+ return formValue;
75
+ return initial[key] ?? '';
76
+ };
77
+ const receiptType = pick('receiptType') === 'DIRECT' ? 'DIRECT' : 'UNTIL_LECTURE';
78
+ return MentoringEditFormSchema.parse({
79
+ id: id || extractNumber(fields.qustnrSn ?? ''),
80
+ title: fields.qustnrSj ?? '',
81
+ reportCd: pick('reportCd'),
82
+ receiptType,
83
+ bgndeDate: pick('bgndeDate'),
84
+ bgndeTime: pick('bgndeTime'),
85
+ enddeDate: pick('enddeDate'),
86
+ enddeTime: pick('enddeTime'),
87
+ eventDt: pick('eventDt'),
88
+ eventStime: pick('eventStime'),
89
+ eventEtime: pick('eventEtime'),
90
+ applyCnt: extractNumber(fields.applyCnt ?? ''),
91
+ place: fields.place ?? '',
92
+ });
93
+ }
94
+ function parseInitialDataBlock(html) {
95
+ const block = html.match(/var\s+INITIAL_DATA\s*=\s*\{([\s\S]*?)\};/)?.[1];
96
+ if (!block)
97
+ return {};
98
+ const fields = {};
99
+ for (const match of block.matchAll(/(\w+)\s*:\s*'([^']*)'/g)) {
100
+ fields[match[1]] = match[2];
101
+ }
102
+ return fields;
103
+ }
104
+ function readFormFields(form) {
105
+ if (!form)
106
+ return {};
107
+ const fields = {};
108
+ for (const input of form.querySelectorAll('input')) {
109
+ const name = input.getAttribute('name');
110
+ if (!name)
111
+ continue;
112
+ const type = (input.getAttribute('type') ?? '').toLowerCase();
113
+ if (type === 'radio' || type === 'checkbox') {
114
+ const rawAttrs = input.rawAttrs ?? '';
115
+ const isChecked = /\bchecked\b/.test(rawAttrs);
116
+ if (isChecked) {
117
+ fields[name] = input.getAttribute('value') ?? '';
118
+ }
119
+ else if (!(name in fields)) {
120
+ fields[name] = '';
121
+ }
122
+ }
123
+ else {
124
+ fields[name] = input.getAttribute('value') ?? '';
125
+ }
126
+ }
127
+ for (const select of form.querySelectorAll('select')) {
128
+ const name = select.getAttribute('name');
129
+ if (!name)
130
+ continue;
131
+ const selected = select.querySelector('option[selected]');
132
+ fields[name] = selected?.getAttribute('value') ?? '';
133
+ }
134
+ for (const textarea of form.querySelectorAll('textarea')) {
135
+ const name = textarea.getAttribute('name');
136
+ if (!name)
137
+ continue;
138
+ fields[name] = textarea.text ?? '';
139
+ }
140
+ return fields;
141
+ }
66
142
  export function parseRoomList(html) {
67
143
  const root = parse(html);
68
144
  const cards = root.querySelectorAll('ul.bbs-reserve > li.item');
@@ -87,6 +163,82 @@ export function parseRoomSlots(html) {
87
163
  }
88
164
  return slots.map(parseRoomTimeSlot).filter((slot) => Boolean(slot.time));
89
165
  }
166
+ export function parseRoomReservationDetail(html) {
167
+ const root = parse(html);
168
+ const form = root.querySelector('form#frm') ?? root.querySelector('form');
169
+ const fields = {};
170
+ for (const input of form?.querySelectorAll('input, select, textarea') ?? []) {
171
+ const name = input.getAttribute('name');
172
+ if (!name)
173
+ continue;
174
+ fields[name] = input.getAttribute('value') ?? input.text ?? '';
175
+ }
176
+ const statusCode = fields.receiptStatCd ?? '';
177
+ return RoomReservationDetailSchema.parse({
178
+ rentId: extractNumber(fields.rentId ?? ''),
179
+ itemId: extractNumber(fields.itemId ?? ''),
180
+ title: fields.title ?? '',
181
+ date: fields.rentDt ?? extractReservationDate(fields.rentBgnde),
182
+ startTime: extractReservationTime(fields.rentBgnde),
183
+ endTime: extractReservationTime(fields.rentEndde),
184
+ attendees: extractNumber(fields.rentNum ?? '') || 1,
185
+ notes: fields.infoCn ?? '',
186
+ status: resolveReservationStatus(statusCode),
187
+ statusCode,
188
+ });
189
+ }
190
+ function extractReservationDate(value) {
191
+ if (!value)
192
+ return '';
193
+ return value.slice(0, 10);
194
+ }
195
+ function extractReservationTime(value) {
196
+ if (!value)
197
+ return '';
198
+ const match = value.match(/\d{2}:\d{2}/);
199
+ return match?.[0] ?? '';
200
+ }
201
+ function resolveReservationStatus(code) {
202
+ if (code === 'RS001')
203
+ return 'confirmed';
204
+ if (code === 'RS002')
205
+ return 'cancelled';
206
+ return 'unknown';
207
+ }
208
+ export function parseRoomReservationList(html) {
209
+ return findTableRows(html, 7).map((cells) => {
210
+ const venueLink = cells[1]?.querySelector('a');
211
+ const rentId = extractUrlParam(venueLink?.getAttribute('href'), 'rentId');
212
+ const titleLink = cells[2]?.querySelector('.rel a');
213
+ const periodText = cleanText(cells[3]);
214
+ const statusLabel = cleanText(cells[5]);
215
+ return RoomReservationListItemSchema.parse({
216
+ rentId,
217
+ venue: cleanText(venueLink ?? cells[1]),
218
+ title: cleanText(titleLink),
219
+ date: extractFirstDate(periodText),
220
+ startTime: extractReservationStartTime(periodText),
221
+ endTime: extractReservationEndTime(periodText),
222
+ author: cleanText(cells[4]),
223
+ status: statusLabelToStatus(statusLabel),
224
+ statusLabel,
225
+ registeredAt: cleanText(cells[6]),
226
+ });
227
+ });
228
+ }
229
+ function statusLabelToStatus(label) {
230
+ if (label.includes('예약완료'))
231
+ return 'confirmed';
232
+ if (label.includes('예약취소') || label.includes('취소'))
233
+ return 'cancelled';
234
+ return 'unknown';
235
+ }
236
+ function extractReservationStartTime(text) {
237
+ return text.match(/\d{2}:\d{2}/)?.[0] ?? '';
238
+ }
239
+ function extractReservationEndTime(text) {
240
+ return text.match(/\d{2}:\d{2}/g)?.[1] ?? '';
241
+ }
90
242
  export function parseDashboard(html) {
91
243
  const root = parse(html);
92
244
  const profileCard = root.querySelector('ul.dash-top > li.dash-card');
@@ -104,6 +256,7 @@ export function parseDashboard(html) {
104
256
  organization: extractDashEtcValue(dashEtc, '소속'),
105
257
  position: extractDashEtcValue(dashEtc, '직책'),
106
258
  team: team.name || team.members || team.mentor ? team : undefined,
259
+ teams: [],
107
260
  mentoringSessions: parseDashboardLinks(root, (href) => href.includes('/mentoLec/')),
108
261
  roomReservations: parseDashboardLinks(root, (href) => href.includes('/itemRent/') || href.includes('/officeMng/')),
109
262
  });
@@ -143,15 +296,11 @@ export function parseTeamInfo(html) {
143
296
  const root = parse(html);
144
297
  const cards = root.querySelectorAll('ul.bbs-team > li');
145
298
  const summaryText = cleanText(root.querySelector('p.ico-team'));
146
- const summaryNumbers = summaryText.match(/(\d+)\/(\d+)팀/);
299
+ const summary = parseTeamSummary(summaryText);
147
300
  return TeamInfoSchema.parse({
148
- teams: cards.map((card) => ({
149
- name: cleanText(card.querySelector('.top strong.t a')),
150
- memberCount: extractMemberCount(cleanText(card)),
151
- joinStatus: extractJoinStatus(card),
152
- })),
153
- currentTeams: summaryNumbers ? Number.parseInt(summaryNumbers[1], 10) : 0,
154
- maxTeams: summaryNumbers ? Number.parseInt(summaryNumbers[2], 10) : 0,
301
+ teams: cards.map((card) => parseTeamCard(card)),
302
+ currentTeams: summary.current,
303
+ maxTeams: summary.max,
155
304
  });
156
305
  }
157
306
  export function parseMemberInfo(html) {
@@ -166,42 +315,72 @@ export function parseMemberInfo(html) {
166
315
  position: labels['직책'] || '',
167
316
  });
168
317
  }
169
- export function parseEventList(html) {
170
- return findTableRows(html, 7).map((cells) => EventListItemSchema.parse({
171
- id: extractLinkParam(cells[2], ['qustnrSn', 'bbsId', 'nttId']) || extractNumber(cleanText(cells[0])),
318
+ export function parseScheduleList(html) {
319
+ const root = parse(html);
320
+ const monthlyScheduleTable = findTableByHeaders(root, ['날짜', '구분', '제목']);
321
+ const scheduleRows = monthlyScheduleTable?.querySelectorAll('tbody tr') ?? [];
322
+ const items = scheduleRows
323
+ .map((row) => row.querySelectorAll('td'))
324
+ .filter((cells) => cells.length === 3)
325
+ .map((cells, index) => ScheduleListItemSchema.parse({
326
+ id: index + 1,
172
327
  category: cleanText(cells[1]),
173
- title: cleanText(cells[2]?.querySelector('a') ?? cells[2]),
174
- registrationPeriod: extractDateRange(cleanText(cells[3])),
175
- eventPeriod: extractDateRange(cleanText(cells[4])),
176
- status: stripWrappingBrackets(cleanText(cells[5])),
177
- createdAt: cleanText(cells[6]),
328
+ title: cleanText(cells[2]),
329
+ period: extractDateRange(cleanText(cells[0])),
178
330
  }));
331
+ // SWMaestro's monthly schedule page does not render the bbs-total pagination block,
332
+ // so synthesize a single-page response when items exist but parsePagination found none.
333
+ const parsedPagination = parsePagination(html, { itemCount: items.length });
334
+ const pagination = parsedPagination.total === 0 && items.length > 0
335
+ ? PaginationSchema.parse({ total: items.length, currentPage: 1, totalPages: 1 })
336
+ : parsedPagination;
337
+ return { items, pagination };
179
338
  }
180
339
  export function parseApplicationHistory(html) {
181
- return findTableRows(html, 10).map((cells) => ApplicationHistoryItemSchema.parse({
182
- id: extractNumber(cleanText(cells[0])),
183
- category: cleanText(cells[1]),
184
- title: cleanText(cells[2]?.querySelector('a') ?? cells[2]),
185
- author: cleanText(cells[3]),
186
- sessionDate: normalizeDate(cleanText(cells[4])),
187
- appliedAt: cleanText(cells[5]),
188
- applicationStatus: stripWrappingBrackets(cleanText(cells[6])),
189
- approvalStatus: stripWrappingBrackets(cleanText(cells[7])),
190
- applicationDetail: cleanText(cells[8]),
191
- note: cleanText(cells[9]),
192
- }));
340
+ return findTableRows(html, 10).map((cells) => {
341
+ const link = cells[2]?.querySelector('a');
342
+ const url = link?.getAttribute('href');
343
+ return ApplicationHistoryItemSchema.parse({
344
+ id: extractNumber(cleanText(cells[0])),
345
+ category: cleanText(cells[1]),
346
+ title: cleanText(link ?? cells[2]),
347
+ ...(url ? { url } : {}),
348
+ author: cleanText(cells[3]),
349
+ sessionDate: normalizeDate(cleanText(cells[4])),
350
+ appliedAt: cleanText(cells[5]),
351
+ applicationStatus: stripWrappingBrackets(cleanText(cells[6])),
352
+ approvalStatus: stripWrappingBrackets(cleanText(cells[7])),
353
+ applicationDetail: cleanText(cells[8]),
354
+ note: cleanText(cells[9]),
355
+ });
356
+ });
193
357
  }
194
- export function parsePagination(html) {
358
+ export function parsePagination(html, options) {
195
359
  const root = parse(html);
196
360
  const items = root.querySelectorAll('ul.bbs-total > li').map((item) => cleanText(item));
197
361
  const total = extractNumber(items.find((item) => item.includes('Total')) ?? '');
198
362
  const pageMatch = items.find((item) => item.includes('Page'))?.match(/(\d+)\s*\/\s*(\d+)\s*Page/i);
363
+ const currentPage = pageMatch ? Number.parseInt(pageMatch[1], 10) : 1;
364
+ const parsedTotalPages = pageMatch ? Number.parseInt(pageMatch[2], 10) : 1;
199
365
  return PaginationSchema.parse({
200
366
  total,
201
- currentPage: pageMatch ? Number.parseInt(pageMatch[1], 10) : 1,
202
- totalPages: pageMatch ? Number.parseInt(pageMatch[2], 10) : 1,
367
+ currentPage,
368
+ totalPages: deriveTotalPages({ total, currentPage, parsedTotalPages, itemCount: options?.itemCount }),
203
369
  });
204
370
  }
371
+ function deriveTotalPages({ total, currentPage, parsedTotalPages, itemCount, }) {
372
+ if (total <= 0)
373
+ return 1;
374
+ const fallback = Math.max(1, parsedTotalPages, currentPage);
375
+ if (itemCount === undefined)
376
+ return fallback;
377
+ // SWMaestro's `1/50 Page` text is unreliable on some lists (e.g. report) — the server emits a
378
+ // hardcoded cap regardless of actual data. When the visible items already cover the total,
379
+ // there is only one page; correct the bogus value rather than echo it.
380
+ if (currentPage === 1 && total <= itemCount)
381
+ return 1;
382
+ return fallback;
383
+ }
205
384
  export function parseCsrfToken(html) {
206
385
  const token = parse(html).querySelector('input[name="csrfToken"]')?.getAttribute('value');
207
386
  if (!token) {
@@ -211,11 +390,15 @@ export function parseCsrfToken(html) {
211
390
  }
212
391
  export function parseReportList(html) {
213
392
  return findTableRows(html, 9).map((cells) => {
214
- const link = cells[2]?.querySelector('a');
393
+ // Native list cell layout: `td.tit > div.date_m > span.l > a` holds the
394
+ // category, and `td.tit > div.rel > a` holds the actual title that matches
395
+ // the `제목` label on the detail page (e.g. "[자유 멘토링] 2026년 04월 30일
396
+ // 멘토링 보고"). Prefer the `.rel a` so list and detail titles agree.
397
+ const titleLink = cells[2]?.querySelector('div.rel a') ?? cells[2]?.querySelector('a');
215
398
  return ReportListItemSchema.parse({
216
- id: extractUrlParam(link?.getAttribute('href'), 'reportId'),
399
+ id: extractUrlParam(titleLink?.getAttribute('href'), 'reportId'),
217
400
  category: cleanText(cells[1]),
218
- title: cleanText(link ?? cells[2]),
401
+ title: cleanText(titleLink ?? cells[2]),
219
402
  progressDate: cleanText(cells[3]),
220
403
  status: cleanText(cells[4]),
221
404
  author: cleanText(cells[5]),
@@ -317,6 +500,12 @@ function findTableRows(html, cellCount) {
317
500
  .map((row) => row.querySelectorAll('td'))
318
501
  .filter((cells) => cells.length === cellCount);
319
502
  }
503
+ function findTableByHeaders(root, headers) {
504
+ return root.querySelectorAll('table').find((table) => {
505
+ const tableHeaders = table.querySelectorAll('thead th').map((header) => cleanText(header));
506
+ return headers.every((header, index) => tableHeaders[index] === header);
507
+ });
508
+ }
320
509
  function extractLabelMap(root) {
321
510
  const map = {};
322
511
  for (const row of root.querySelectorAll('tr')) {
@@ -441,16 +630,6 @@ function extractUrlParam(url, key) {
441
630
  return 0;
442
631
  }
443
632
  }
444
- function extractLinkParam(cell, keys) {
445
- const href = cell?.querySelector('a')?.getAttribute('href');
446
- for (const key of keys) {
447
- const value = extractUrlParam(href, key);
448
- if (value > 0) {
449
- return value;
450
- }
451
- }
452
- return 0;
453
- }
454
633
  function extractDateRange(text) {
455
634
  const dates = text.match(/\d{4}[.-]\d{2}[.-]\d{2}/g)?.map(normalizeDate) ?? [];
456
635
  return { start: dates[0] ?? '', end: dates[1] ?? '' };
@@ -476,15 +655,65 @@ function extractCapacity(text) {
476
655
  const match = text.match(/(\d+)\s*인/);
477
656
  return match ? Number.parseInt(match[1], 10) : 0;
478
657
  }
479
- function extractMemberCount(text) {
480
- const match = text.match(/(\d+)\s*명/);
481
- return match ? Number.parseInt(match[1], 10) : 0;
658
+ function parseTeamCard(card) {
659
+ const titleAnchor = card.querySelector('.top strong.t a');
660
+ const teamPageGoArgs = parseTeamPageGoArgs(titleAnchor?.getAttribute('onclick') ?? '');
661
+ const infoItems = card.querySelectorAll('.top ul.info > li');
662
+ const ictItems = card.querySelectorAll('.bot ul.ict > li');
663
+ return {
664
+ name: cleanText(titleAnchor),
665
+ projectName: cleanText(card.querySelector('.top .add-txt')),
666
+ ownerId: teamPageGoArgs[1] ?? '',
667
+ teamId: teamPageGoArgs[2] ?? '',
668
+ leader: extractInfoLeader(infoItems),
669
+ members: extractInfoMembers(infoItems, '팀원'),
670
+ mentors: extractInfoMembers(infoItems, '멘토'),
671
+ ictCategoryMajor: extractIctCategory(ictItems, '대'),
672
+ ictCategoryMinor: extractIctCategory(ictItems, '중'),
673
+ teamCompleted: card.querySelector('.team-com .t1') !== null,
674
+ mentorCompleted: card.querySelector('.team-com .t2') !== null,
675
+ joinStatus: extractJoinStatus(card),
676
+ };
677
+ }
678
+ function parseTeamSummary(text) {
679
+ const match = text.match(/(\d+)\s*(?:\/\s*(\d+))?\s*팀/);
680
+ return {
681
+ current: match ? Number.parseInt(match[1], 10) : 0,
682
+ max: match?.[2] ? Number.parseInt(match[2], 10) : 0,
683
+ };
684
+ }
685
+ function parseTeamPageGoArgs(onclick) {
686
+ // teamPageGo('전수열','f6d192...','ef9d3b...');
687
+ const match = onclick.match(/teamPageGo\(\s*'([^']*)'\s*,\s*'([^']*)'\s*,\s*'([^']*)'\s*\)/);
688
+ return match ? [match[1], match[2], match[3]] : [];
689
+ }
690
+ function findInfoItemByLabel(items, label) {
691
+ return items.find((item) => cleanText(item.querySelector('strong')).startsWith(label));
692
+ }
693
+ function extractInfoLeader(items) {
694
+ const leaderItem = findInfoItemByLabel(items, '팀장');
695
+ return cleanText(leaderItem?.querySelector('span a')) || cleanText(leaderItem?.querySelector('span'));
696
+ }
697
+ function extractInfoMembers(items, label) {
698
+ const item = findInfoItemByLabel(items, label);
699
+ if (!item)
700
+ return [];
701
+ return item.querySelectorAll('span a').map((anchor) => ({
702
+ name: cleanText(anchor),
703
+ userId: extractPopuserUserId(anchor.getAttribute('href') ?? ''),
704
+ }));
705
+ }
706
+ function extractPopuserUserId(href) {
707
+ // javascript: popuser('113889210806408397ea7db2ea855f71')
708
+ const match = href.match(/popuser\(\s*'([^']*)'/);
709
+ return match ? match[1] : '';
710
+ }
711
+ function extractIctCategory(items, group) {
712
+ const item = items.find((node) => cleanText(node).includes(`(${group})`));
713
+ return cleanText(item?.querySelector('span'));
482
714
  }
483
715
  function extractJoinStatus(card) {
484
- return (cleanText(card.querySelector('button')) ||
485
- cleanText(card.querySelector('.btn')) ||
486
- cleanText(card.querySelector('[class*="join"]')) ||
487
- '');
716
+ return cleanText(card.querySelector('.bot .btn_w .btn-team'));
488
717
  }
489
718
  function extractTrailingStatus(text) {
490
719
  const match = text.match(/(예약완료|예약중|대기|접수중|마감|승인완료|신청완료)$/);