chukyo-sdk 0.1.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 (177) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +227 -0
  3. package/dist/cjs/albo/client.js +133 -0
  4. package/dist/cjs/albo/index.js +55 -0
  5. package/dist/cjs/albo/parser/albo.js +110 -0
  6. package/dist/cjs/albo/types/albo.js +351 -0
  7. package/dist/cjs/albo/types/alboCalendar.js +51 -0
  8. package/dist/cjs/albo/types/alboCommon.js +55 -0
  9. package/dist/cjs/albo/types/alboInformation.js +136 -0
  10. package/dist/cjs/albo/types/alboMenu.js +92 -0
  11. package/dist/cjs/albo/types/alboQuestionnaire.js +229 -0
  12. package/dist/cjs/albo/types/alboSharedItem.js +137 -0
  13. package/dist/cjs/albo/types/alboSystem.js +103 -0
  14. package/dist/cjs/albo/types/alboUniversalForm.js +51 -0
  15. package/dist/cjs/common/dom.js +137 -0
  16. package/dist/cjs/common/utils.js +29 -0
  17. package/dist/cjs/constants.js +127 -0
  18. package/dist/cjs/core/request.js +39 -0
  19. package/dist/cjs/cubics/client.js +49 -0
  20. package/dist/cjs/cubics/index.js +22 -0
  21. package/dist/cjs/cubics/parser/cubics.js +103 -0
  22. package/dist/cjs/cubics/types/cubics.js +90 -0
  23. package/dist/cjs/errors.js +55 -0
  24. package/dist/cjs/index.js +50 -0
  25. package/dist/cjs/manabo/client.js +135 -0
  26. package/dist/cjs/manabo/index.js +44 -0
  27. package/dist/cjs/manabo/parser/manaboClass.js +386 -0
  28. package/dist/cjs/manabo/parser/manaboEntry.js +38 -0
  29. package/dist/cjs/manabo/parser/manaboMail.js +153 -0
  30. package/dist/cjs/manabo/parser/manaboNews.js +26 -0
  31. package/dist/cjs/manabo/parser/manaboTimetable.js +93 -0
  32. package/dist/cjs/manabo/types/manaboClass.js +223 -0
  33. package/dist/cjs/manabo/types/manaboEntry.js +43 -0
  34. package/dist/cjs/manabo/types/manaboMail.js +117 -0
  35. package/dist/cjs/manabo/types/manaboNews.js +20 -0
  36. package/dist/cjs/manabo/types/manaboTimetable.js +79 -0
  37. package/dist/cjs/package.json +1 -0
  38. package/dist/cjs/shib/builder.js +239 -0
  39. package/dist/cjs/shib/index.js +32 -0
  40. package/dist/cjs/shib/parser/shibLogin.js +138 -0
  41. package/dist/cjs/shib/parser/shibUser.js +51 -0
  42. package/dist/cjs/shib/types/common.js +2 -0
  43. package/dist/cjs/shib/types/shibLogin.js +92 -0
  44. package/dist/cjs/shib/types/shibUser.js +44 -0
  45. package/dist/cjs/transports/fetch.js +84 -0
  46. package/dist/cjs/types.js +9 -0
  47. package/dist/esm/albo/client.d.ts +80 -0
  48. package/dist/esm/albo/client.d.ts.map +1 -0
  49. package/dist/esm/albo/client.js +129 -0
  50. package/dist/esm/albo/index.d.ts +12 -0
  51. package/dist/esm/albo/index.d.ts.map +1 -0
  52. package/dist/esm/albo/index.js +11 -0
  53. package/dist/esm/albo/parser/albo.d.ts +69 -0
  54. package/dist/esm/albo/parser/albo.d.ts.map +1 -0
  55. package/dist/esm/albo/parser/albo.js +84 -0
  56. package/dist/esm/albo/types/albo.d.ts +460 -0
  57. package/dist/esm/albo/types/albo.d.ts.map +1 -0
  58. package/dist/esm/albo/types/albo.js +348 -0
  59. package/dist/esm/albo/types/alboCalendar.d.ts +58 -0
  60. package/dist/esm/albo/types/alboCalendar.d.ts.map +1 -0
  61. package/dist/esm/albo/types/alboCalendar.js +48 -0
  62. package/dist/esm/albo/types/alboCommon.d.ts +52 -0
  63. package/dist/esm/albo/types/alboCommon.d.ts.map +1 -0
  64. package/dist/esm/albo/types/alboCommon.js +51 -0
  65. package/dist/esm/albo/types/alboInformation.d.ts +214 -0
  66. package/dist/esm/albo/types/alboInformation.d.ts.map +1 -0
  67. package/dist/esm/albo/types/alboInformation.js +133 -0
  68. package/dist/esm/albo/types/alboMenu.d.ts +114 -0
  69. package/dist/esm/albo/types/alboMenu.d.ts.map +1 -0
  70. package/dist/esm/albo/types/alboMenu.js +89 -0
  71. package/dist/esm/albo/types/alboQuestionnaire.d.ts +442 -0
  72. package/dist/esm/albo/types/alboQuestionnaire.d.ts.map +1 -0
  73. package/dist/esm/albo/types/alboQuestionnaire.js +226 -0
  74. package/dist/esm/albo/types/alboSharedItem.d.ts +205 -0
  75. package/dist/esm/albo/types/alboSharedItem.d.ts.map +1 -0
  76. package/dist/esm/albo/types/alboSharedItem.js +134 -0
  77. package/dist/esm/albo/types/alboSystem.d.ts +129 -0
  78. package/dist/esm/albo/types/alboSystem.d.ts.map +1 -0
  79. package/dist/esm/albo/types/alboSystem.js +100 -0
  80. package/dist/esm/albo/types/alboUniversalForm.d.ts +63 -0
  81. package/dist/esm/albo/types/alboUniversalForm.d.ts.map +1 -0
  82. package/dist/esm/albo/types/alboUniversalForm.js +48 -0
  83. package/dist/esm/common/dom.d.ts +35 -0
  84. package/dist/esm/common/dom.d.ts.map +1 -0
  85. package/dist/esm/common/dom.js +120 -0
  86. package/dist/esm/common/utils.d.ts +15 -0
  87. package/dist/esm/common/utils.d.ts.map +1 -0
  88. package/dist/esm/common/utils.js +22 -0
  89. package/dist/esm/constants.d.ts +113 -0
  90. package/dist/esm/constants.d.ts.map +1 -0
  91. package/dist/esm/constants.js +124 -0
  92. package/dist/esm/core/request.d.ts +29 -0
  93. package/dist/esm/core/request.d.ts.map +1 -0
  94. package/dist/esm/core/request.js +33 -0
  95. package/dist/esm/cubics/client.d.ts +13 -0
  96. package/dist/esm/cubics/client.d.ts.map +1 -0
  97. package/dist/esm/cubics/client.js +45 -0
  98. package/dist/esm/cubics/index.d.ts +4 -0
  99. package/dist/esm/cubics/index.d.ts.map +1 -0
  100. package/dist/esm/cubics/index.js +3 -0
  101. package/dist/esm/cubics/parser/cubics.d.ts +8 -0
  102. package/dist/esm/cubics/parser/cubics.d.ts.map +1 -0
  103. package/dist/esm/cubics/parser/cubics.js +99 -0
  104. package/dist/esm/cubics/types/cubics.d.ts +94 -0
  105. package/dist/esm/cubics/types/cubics.d.ts.map +1 -0
  106. package/dist/esm/cubics/types/cubics.js +87 -0
  107. package/dist/esm/errors.d.ts +46 -0
  108. package/dist/esm/errors.d.ts.map +1 -0
  109. package/dist/esm/errors.js +46 -0
  110. package/dist/esm/index.d.ts +19 -0
  111. package/dist/esm/index.d.ts.map +1 -0
  112. package/dist/esm/index.js +25 -0
  113. package/dist/esm/manabo/client.d.ts +75 -0
  114. package/dist/esm/manabo/client.d.ts.map +1 -0
  115. package/dist/esm/manabo/client.js +131 -0
  116. package/dist/esm/manabo/index.d.ts +12 -0
  117. package/dist/esm/manabo/index.d.ts.map +1 -0
  118. package/dist/esm/manabo/index.js +11 -0
  119. package/dist/esm/manabo/parser/manaboClass.d.ts +9 -0
  120. package/dist/esm/manabo/parser/manaboClass.d.ts.map +1 -0
  121. package/dist/esm/manabo/parser/manaboClass.js +377 -0
  122. package/dist/esm/manabo/parser/manaboEntry.d.ts +8 -0
  123. package/dist/esm/manabo/parser/manaboEntry.d.ts.map +1 -0
  124. package/dist/esm/manabo/parser/manaboEntry.js +33 -0
  125. package/dist/esm/manabo/parser/manaboMail.d.ts +8 -0
  126. package/dist/esm/manabo/parser/manaboMail.d.ts.map +1 -0
  127. package/dist/esm/manabo/parser/manaboMail.js +145 -0
  128. package/dist/esm/manabo/parser/manaboNews.d.ts +7 -0
  129. package/dist/esm/manabo/parser/manaboNews.d.ts.map +1 -0
  130. package/dist/esm/manabo/parser/manaboNews.js +22 -0
  131. package/dist/esm/manabo/parser/manaboTimetable.d.ts +4 -0
  132. package/dist/esm/manabo/parser/manaboTimetable.d.ts.map +1 -0
  133. package/dist/esm/manabo/parser/manaboTimetable.js +89 -0
  134. package/dist/esm/manabo/types/manaboClass.d.ts +294 -0
  135. package/dist/esm/manabo/types/manaboClass.d.ts.map +1 -0
  136. package/dist/esm/manabo/types/manaboClass.js +220 -0
  137. package/dist/esm/manabo/types/manaboEntry.d.ts +24 -0
  138. package/dist/esm/manabo/types/manaboEntry.d.ts.map +1 -0
  139. package/dist/esm/manabo/types/manaboEntry.js +40 -0
  140. package/dist/esm/manabo/types/manaboMail.d.ts +103 -0
  141. package/dist/esm/manabo/types/manaboMail.d.ts.map +1 -0
  142. package/dist/esm/manabo/types/manaboMail.js +114 -0
  143. package/dist/esm/manabo/types/manaboNews.d.ts +15 -0
  144. package/dist/esm/manabo/types/manaboNews.d.ts.map +1 -0
  145. package/dist/esm/manabo/types/manaboNews.js +17 -0
  146. package/dist/esm/manabo/types/manaboTimetable.d.ts +88 -0
  147. package/dist/esm/manabo/types/manaboTimetable.d.ts.map +1 -0
  148. package/dist/esm/manabo/types/manaboTimetable.js +76 -0
  149. package/dist/esm/package.json +1 -0
  150. package/dist/esm/shib/builder.d.ts +154 -0
  151. package/dist/esm/shib/builder.d.ts.map +1 -0
  152. package/dist/esm/shib/builder.js +212 -0
  153. package/dist/esm/shib/index.d.ts +15 -0
  154. package/dist/esm/shib/index.d.ts.map +1 -0
  155. package/dist/esm/shib/index.js +14 -0
  156. package/dist/esm/shib/parser/shibLogin.d.ts +47 -0
  157. package/dist/esm/shib/parser/shibLogin.d.ts.map +1 -0
  158. package/dist/esm/shib/parser/shibLogin.js +127 -0
  159. package/dist/esm/shib/parser/shibUser.d.ts +11 -0
  160. package/dist/esm/shib/parser/shibUser.d.ts.map +1 -0
  161. package/dist/esm/shib/parser/shibUser.js +46 -0
  162. package/dist/esm/shib/types/common.d.ts +20 -0
  163. package/dist/esm/shib/types/common.d.ts.map +1 -0
  164. package/dist/esm/shib/types/common.js +1 -0
  165. package/dist/esm/shib/types/shibLogin.d.ts +62 -0
  166. package/dist/esm/shib/types/shibLogin.d.ts.map +1 -0
  167. package/dist/esm/shib/types/shibLogin.js +89 -0
  168. package/dist/esm/shib/types/shibUser.d.ts +36 -0
  169. package/dist/esm/shib/types/shibUser.d.ts.map +1 -0
  170. package/dist/esm/shib/types/shibUser.js +41 -0
  171. package/dist/esm/transports/fetch.d.ts +36 -0
  172. package/dist/esm/transports/fetch.d.ts.map +1 -0
  173. package/dist/esm/transports/fetch.js +80 -0
  174. package/dist/esm/types.d.ts +71 -0
  175. package/dist/esm/types.d.ts.map +1 -0
  176. package/dist/esm/types.js +8 -0
  177. package/package.json +72 -0
@@ -0,0 +1,48 @@
1
+ import { z } from "zod";
2
+ import { alboEnvelope, paginationShape } from "./alboCommon";
3
+ // ---------------------------------------------------------------------------
4
+ // 汎用申請(universal-form / 各種手続き)系。
5
+ // - GET /api/universal-form/{page} … 申請フォーム一覧
6
+ // - GET /api/universal-form-category/{page} … 申請カテゴリ一覧
7
+ // ---------------------------------------------------------------------------
8
+ /** 汎用申請のカテゴリ */
9
+ export const AlboUniversalFormCategorySchema = z.object({
10
+ /** カテゴリ UUID @example "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" */
11
+ uuid: z.string().meta({ description: "カテゴリ UUID", example: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" }),
12
+ /** カテゴリ名(例: "教務") @example "教務" */
13
+ name: z.string().meta({ description: "カテゴリ名", example: "教務" }),
14
+ /** カテゴリ名(英語。無ければ null) @example null */
15
+ name_en: z.string().nullable().meta({ description: "カテゴリ名(英語)", example: null }),
16
+ /** 説明(無ければ null) @example null */
17
+ description: z.string().nullable().meta({ description: "説明", example: null }),
18
+ /** 説明(英語。無ければ null) @example null */
19
+ description_en: z.string().nullable().meta({ description: "説明(英語)", example: null }),
20
+ /** 強制申請に設定できるか(0/1 の数値フラグ) @example 0 */
21
+ can_set_forced: z.number().meta({ description: "強制申請に設定できるか(0/1)", example: 0 }),
22
+ /** 表示順 @example 0 */
23
+ order: z.number().meta({ description: "表示順", example: 0 }),
24
+ /** 作成者 @example "system" */
25
+ created_by: z.string().meta({ description: "作成者", example: "system" }),
26
+ /** 更新者(無ければ null) @example null */
27
+ updated_by: z.string().nullable().meta({ description: "更新者", example: null }),
28
+ /** 作成日時(UNIX 秒) @example 1700000000 */
29
+ created_at: z.number().meta({ description: "作成日時(UNIX 秒)", example: 1700000000 }),
30
+ /** 更新日時(UNIX 秒) @example 1700000000 */
31
+ updated_at: z.number().meta({ description: "更新日時(UNIX 秒)", example: 1700000000 }),
32
+ });
33
+ /** 汎用申請カテゴリ一覧取得 API のレスポンス全体 */
34
+ export const AlboUniversalFormCategoryListSchema = alboEnvelope(z.object({
35
+ ...paginationShape,
36
+ /** カテゴリ配列 */
37
+ items: z.array(AlboUniversalFormCategorySchema).meta({ description: "カテゴリ配列" }),
38
+ }));
39
+ /**
40
+ * 汎用申請一覧取得 API のレスポンス全体。
41
+ * 観測できたのは対象フォームが 0 件(`items: []`)のケースのみ。
42
+ * 個々のフォーム項目の構造は未確認のため、要素は無変換で保持する。
43
+ */
44
+ export const AlboUniversalFormSchema = alboEnvelope(z.object({
45
+ ...paginationShape,
46
+ /** 申請フォームの配列 @example [] */
47
+ items: z.array(z.unknown()).meta({ description: "申請フォームの配列", example: [] }),
48
+ }));
@@ -0,0 +1,35 @@
1
+ import type { AnyNode, Document, Element } from "domhandler";
2
+ type Root = Document | Element | AnyNode[] | null | undefined;
3
+ /** HTML 文字列を Document に変換する */
4
+ export declare const loadDocument: (html: string) => Document;
5
+ /** セレクタに一致する全 Element を返す */
6
+ export declare const queryAll: (selector: string, root: Root) => Element[];
7
+ /** セレクタに一致する最初の Element を返す(無ければ null) */
8
+ export declare const queryOne: (selector: string, root: Root) => Element | null;
9
+ /** 属性値を取得する(無ければ null) */
10
+ export declare const getAttribute: (element: Element | null | undefined, name: string) => string | null;
11
+ /** ノード配下のテキストを連結して返す */
12
+ export declare const getTextContent: (node: AnyNode | null | undefined) => string;
13
+ /**
14
+ * 要素の innerHTML を返す。数値文字参照の復号・改行正規化・` ` 復元・
15
+ * 値のない `alt` の補完を行い、後段のパースを安定させる。
16
+ */
17
+ export declare const getInnerHtml: (element: Element | null | undefined) => string;
18
+ /** 要素が指定クラスを持つか */
19
+ export declare const elementHasClass: (element: Element | null | undefined, className: string) => boolean;
20
+ /** 自身から祖先方向へ辿り、セレクタに最初に一致する要素を返す */
21
+ export declare const closest: (element: Element | null | undefined, selector: string) => Element | null;
22
+ /** 次の兄弟要素を返す */
23
+ export declare const nextSiblingElement: (element: Element | null | undefined) => Element | null;
24
+ /** 前の兄弟要素を返す */
25
+ export declare const previousSiblingElement: (element: Element | null | undefined) => Element | null;
26
+ /** ノードが Element(タグ)か */
27
+ export declare const isElement: (node: AnyNode | null | undefined) => node is Element;
28
+ /** ノード配列から Element だけを抽出する */
29
+ export declare const filterElements: (nodes: AnyNode[]) => Element[];
30
+ /** 子ノードのうち Element だけを返す */
31
+ export declare const getChildrenElements: (element: Element | null | undefined) => Element[];
32
+ /** 要素がセレクタに一致するか */
33
+ export declare const matches: (element: Element | null | undefined, selector: string) => boolean;
34
+ export { type Element } from "domhandler";
35
+ //# sourceMappingURL=dom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../../src/common/dom.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAY7D,KAAK,IAAI,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAe9D,+BAA+B;AAC/B,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,QAA+B,CAAC;AAE5E,6BAA6B;AAC7B,eAAO,MAAM,QAAQ,GAAI,UAAU,MAAM,EAAE,MAAM,IAAI,KAAG,OAAO,EAAwC,CAAC;AAExG,0CAA0C;AAC1C,eAAO,MAAM,QAAQ,GAAI,UAAU,MAAM,EAAE,MAAM,IAAI,KAAG,OAAO,GAAG,IAA0C,CAAC;AAE7G,0BAA0B;AAC1B,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,MAAM,KAAG,MAAM,GAAG,IAMzF,CAAC;AAEF,wBAAwB;AACxB,eAAO,MAAM,cAAc,GAAI,MAAM,OAAO,GAAG,IAAI,GAAG,SAAS,KAAG,MAKjE,CAAC;AAaF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,GAAG,IAAI,GAAG,SAAS,KAAG,MASlE,CAAC;AAEF,mBAAmB;AACnB,eAAO,MAAM,eAAe,GAAI,SAAS,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,WAAW,MAAM,KAAG,OASxF,CAAC;AAEF,oCAAoC;AACpC,eAAO,MAAM,OAAO,GAAI,SAAS,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,UAAU,MAAM,KAAG,OAAO,GAAG,IAUzF,CAAC;AAEF,gBAAgB;AAChB,eAAO,MAAM,kBAAkB,GAAI,SAAS,OAAO,GAAG,IAAI,GAAG,SAAS,KAAG,OAAO,GAAG,IAKlF,CAAC;AAEF,gBAAgB;AAChB,eAAO,MAAM,sBAAsB,GAAI,SAAS,OAAO,GAAG,IAAI,GAAG,SAAS,KAAG,OAAO,GAAG,IAKtF,CAAC;AAEF,wBAAwB;AACxB,eAAO,MAAM,SAAS,GAAI,MAAM,OAAO,GAAG,IAAI,GAAG,SAAS,KAAG,IAAI,IAAI,OAAgC,CAAC;AAEtG,8BAA8B;AAC9B,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,EAAE,KAAG,OAAO,EAA0D,CAAC;AAEpH,4BAA4B;AAC5B,eAAO,MAAM,mBAAmB,GAAI,SAAS,OAAO,GAAG,IAAI,GAAG,SAAS,KAAG,OAAO,EAKhF,CAAC;AAEF,oBAAoB;AACpB,eAAO,MAAM,OAAO,GAAI,SAAS,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,UAAU,MAAM,KAAG,OAK/E,CAAC;AAEF,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * HTML パース用の薄い DOM ヘルパ層。
3
+ *
4
+ * `htmlparser2`(`parseDocument`)でパースし、`css-select` でセレクタ検索、
5
+ * `domutils` でノード走査する。各 parser はこのヘルパ経由で DOM を扱う。
6
+ */
7
+ import { parseDocument } from "htmlparser2";
8
+ import { is as matchesSelector, selectAll, selectOne } from "css-select";
9
+ import { getAttributeValue, getInnerHTML, getParent, isTag, nextElementSibling, prevElementSibling, textContent, } from "domutils";
10
+ const toArray = (root) => {
11
+ if (!root) {
12
+ return [];
13
+ }
14
+ if (Array.isArray(root)) {
15
+ return root;
16
+ }
17
+ if ("children" in root && Array.isArray(root.children)) {
18
+ return root.children;
19
+ }
20
+ return [root];
21
+ };
22
+ /** HTML 文字列を Document に変換する */
23
+ export const loadDocument = (html) => parseDocument(html);
24
+ /** セレクタに一致する全 Element を返す */
25
+ export const queryAll = (selector, root) => selectAll(selector, toArray(root));
26
+ /** セレクタに一致する最初の Element を返す(無ければ null) */
27
+ export const queryOne = (selector, root) => selectOne(selector, toArray(root));
28
+ /** 属性値を取得する(無ければ null) */
29
+ export const getAttribute = (element, name) => {
30
+ if (!element) {
31
+ return null;
32
+ }
33
+ const value = getAttributeValue(element, name);
34
+ return typeof value === "string" ? value : null;
35
+ };
36
+ /** ノード配下のテキストを連結して返す */
37
+ export const getTextContent = (node) => {
38
+ if (!node) {
39
+ return "";
40
+ }
41
+ return textContent(node);
42
+ };
43
+ const decodeNumericEntities = (value) => value
44
+ .replace(/&#x([0-9a-fA-F]+);/g, (match, hex) => {
45
+ const codePoint = Number.parseInt(hex, 16);
46
+ return Number.isNaN(codePoint) ? match : String.fromCodePoint(codePoint);
47
+ })
48
+ .replace(/&#([0-9]+);/g, (match, dec) => {
49
+ const codePoint = Number.parseInt(dec, 10);
50
+ return Number.isNaN(codePoint) ? match : String.fromCodePoint(codePoint);
51
+ });
52
+ /**
53
+ * 要素の innerHTML を返す。数値文字参照の復号・改行正規化・` ` 復元・
54
+ * 値のない `alt` の補完を行い、後段のパースを安定させる。
55
+ */
56
+ export const getInnerHtml = (element) => {
57
+ if (!element) {
58
+ return "";
59
+ }
60
+ const inner = getInnerHTML(element);
61
+ const decoded = decodeNumericEntities(inner);
62
+ const normalised = decoded.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
63
+ const withNbsp = normalised.replace(/\u00a0/g, " ");
64
+ return withNbsp.replace(/\salt(?!\s*=)(?=[\s/>])/g, ' alt=""');
65
+ };
66
+ /** 要素が指定クラスを持つか */
67
+ export const elementHasClass = (element, className) => {
68
+ if (!element) {
69
+ return false;
70
+ }
71
+ const classAttr = getAttribute(element, "class");
72
+ if (!classAttr) {
73
+ return false;
74
+ }
75
+ return classAttr.split(/\s+/).includes(className);
76
+ };
77
+ /** 自身から祖先方向へ辿り、セレクタに最初に一致する要素を返す */
78
+ export const closest = (element, selector) => {
79
+ let current = element;
80
+ while (current) {
81
+ if (matchesSelector(current, selector)) {
82
+ return current;
83
+ }
84
+ const parent = getParent(current);
85
+ current = parent && isTag(parent) ? parent : null;
86
+ }
87
+ return null;
88
+ };
89
+ /** 次の兄弟要素を返す */
90
+ export const nextSiblingElement = (element) => {
91
+ if (!element) {
92
+ return null;
93
+ }
94
+ return nextElementSibling(element) ?? null;
95
+ };
96
+ /** 前の兄弟要素を返す */
97
+ export const previousSiblingElement = (element) => {
98
+ if (!element) {
99
+ return null;
100
+ }
101
+ return prevElementSibling(element) ?? null;
102
+ };
103
+ /** ノードが Element(タグ)か */
104
+ export const isElement = (node) => !!node && isTag(node);
105
+ /** ノード配列から Element だけを抽出する */
106
+ export const filterElements = (nodes) => nodes.filter((node) => isTag(node));
107
+ /** 子ノードのうち Element だけを返す */
108
+ export const getChildrenElements = (element) => {
109
+ if (!element) {
110
+ return [];
111
+ }
112
+ return filterElements(element.children ?? []);
113
+ };
114
+ /** 要素がセレクタに一致するか */
115
+ export const matches = (element, selector) => {
116
+ if (!element) {
117
+ return false;
118
+ }
119
+ return matchesSelector(element, selector);
120
+ };
@@ -0,0 +1,15 @@
1
+ /** 連続する空白を1つに畳み、前後を trim する */
2
+ export declare const normalizeWhitespace: (value: string) => string;
3
+ /** 文字列中の最初のシングルクォート内の値を返す(onclick 引数の抽出などに使う) */
4
+ export declare const extractFirstQuotedValue: (raw: string | undefined | null) => string | null;
5
+ /**
6
+ * `{ key: value }` を form-urlencoded ボディに変換する。
7
+ * shib のフォーム POST(loginuserpass 等)のボディ組み立てに使う。
8
+ */
9
+ export declare const formEncode: (params: Record<string, string>) => string;
10
+ /**
11
+ * `[key, value]` ペア配列を form-urlencoded ボディに変換する(キー重複対応)。
12
+ * `Fido2DeviceAdd` のように同名キー(`procchk` を 2 回)を送る必要がある場合に使う。
13
+ */
14
+ export declare const formEncodeArray: (params: ReadonlyArray<readonly [string, string]>) => string;
15
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/common/utils.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,KAAG,MAA2C,CAAC;AAEhG,iDAAiD;AACjD,eAAO,MAAM,uBAAuB,GAAI,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI,KAAG,MAAM,GAAG,IAMjF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,MAG1C,CAAC;AAEnB;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAG,MACkB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /** 連続する空白を1つに畳み、前後を trim する */
2
+ export const normalizeWhitespace = (value) => value.replace(/\s+/g, " ").trim();
3
+ /** 文字列中の最初のシングルクォート内の値を返す(onclick 引数の抽出などに使う) */
4
+ export const extractFirstQuotedValue = (raw) => {
5
+ if (!raw) {
6
+ return null;
7
+ }
8
+ const match = raw.match(/'([^']+)'/);
9
+ return match ? (match[1] ?? null) : null;
10
+ };
11
+ /**
12
+ * `{ key: value }` を form-urlencoded ボディに変換する。
13
+ * shib のフォーム POST(loginuserpass 等)のボディ組み立てに使う。
14
+ */
15
+ export const formEncode = (params) => Object.entries(params)
16
+ .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
17
+ .join("&");
18
+ /**
19
+ * `[key, value]` ペア配列を form-urlencoded ボディに変換する(キー重複対応)。
20
+ * `Fido2DeviceAdd` のように同名キー(`procchk` を 2 回)を送る必要がある場合に使う。
21
+ */
22
+ export const formEncodeArray = (params) => params.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
@@ -0,0 +1,113 @@
1
+ /**
2
+ * ポータルのデータ系エンドポイント URL と運用値。
3
+ *
4
+ * 運用値(リトライ回数・タイムアウト)は旧 UMEBO の実運用で得た値。根拠なく変えない。
5
+ * ※ Shibboleth 認証 URL やレート制限・セッション失効時間は SDK には持たない
6
+ * (認証・レート制限は利用側 = umebo の責務)。
7
+ */
8
+ /** HTTP タイムアウト(ms) */
9
+ export declare const HTTP_TIMEOUT_MS = 10000;
10
+ /** CUBICS セッション不安定対策のリトライ回数 */
11
+ export declare const CUBICS_RETRY_COUNT = 3;
12
+ /** CUBICS リトライの固定遅延(ms) */
13
+ export declare const CUBICS_RETRY_DELAY_MS = 200;
14
+ /** CUBICS リトライのランダム加算遅延の上限(ms) */
15
+ export declare const CUBICS_RETRY_DELAY_RANDOM_MS = 300;
16
+ export declare const CUBICS_URLS: {
17
+ /** ベース URL */
18
+ readonly base: "https://cubics-as.chukyo-u.ac.jp";
19
+ };
20
+ export declare const ALBO_URLS: {
21
+ /** ベース URL */
22
+ readonly base: "https://albo.chukyo-u.ac.jp";
23
+ /** SAML ログイン起点 */
24
+ readonly login: "https://albo.chukyo-u.ac.jp/api/saml/login";
25
+ /** 認証完了確認(ここへの到達でログイン成立) */
26
+ readonly dashboard: "https://albo.chukyo-u.ac.jp/dashboard";
27
+ };
28
+ /**
29
+ * 学年暦(学部)カレンダーソース UUID。`GET /api/calendar-source/` が返す一覧の1件で、
30
+ * 年度更新等で値が変わり得る。`AlboClient#getCalendar` はこれをデフォルト値として使うが、
31
+ * 呼び出し側は `getCalendar({ calendarSourceUuid: ... })` で任意のソース(学部/大学院など)
32
+ * に差し替えられる。差し替え先の UUID は `getCalendarSource()` の結果から取得できる。
33
+ */
34
+ export declare const ALBO_DEFAULT_CALENDAR_SOURCE_UUID = "ac304d66-b0a8-11f0-afed-06347f3ce845";
35
+ export declare const MANABO_URLS: {
36
+ /** ベース URL */
37
+ readonly base: "https://manabo.cnc.chukyo-u.ac.jp";
38
+ /** Shibboleth 認証 URL */
39
+ readonly auth: "https://manabo.cnc.chukyo-u.ac.jp/auth/shibboleth/";
40
+ };
41
+ /**
42
+ * Shibboleth 認証系エンドポイント。
43
+ *
44
+ * ※ この SDK は認証フローを「実行」しない。`src/shib` のビルダ/パーサが、
45
+ * 各ステップのリクエスト記述子の組み立てと、レスポンスの構造化に使う。
46
+ * HTTP 実行・Cookie 管理・リダイレクト追従・パスキー暗号処理は呼び出し側の責務。
47
+ * 値は umebo の実運用 URL(acl/constants.ts)に一致。
48
+ */
49
+ export declare const SHIB_URLS: {
50
+ /** Shibboleth オリジン(フォーム POST の Origin ヘッダに使う) */
51
+ readonly origin: "https://shib.chukyo-u.ac.jp";
52
+ /** WebAuthn RP ID */
53
+ readonly rpId: "shib.chukyo-u.ac.jp";
54
+ /** ACE User SP ログイン起点 */
55
+ readonly clspLogin: "https://shib.chukyo-u.ac.jp/clsp/login";
56
+ /** CLSP SAML ログイン起点(パスキー登録フローの起点) */
57
+ readonly clspSamlLogin: "https://shib.chukyo-u.ac.jp/clsp/saml/login";
58
+ /** 認証方式チェック(Password / OTP / Passkey の可否) */
59
+ readonly checktype: "https://shib.chukyo-u.ac.jp/cloudlink/module.php/cloudlink/checktype.php";
60
+ /** ログインフォーム POST(authtype=0 PW / 2 OTP / 3 Passkey) */
61
+ readonly cloudlinkLoginForm: "https://shib.chukyo-u.ac.jp/cloudlink/module.php/cloudlink/loginuserpass.php";
62
+ /** ログインフロー用 WebAuthn API(start/finish-authentication) */
63
+ readonly webauthn: "https://shib.chukyo-u.ac.jp/cloudlink/module.php/cloudlink/webauthn.php";
64
+ /** ACE User メニュー */
65
+ readonly userMenu: "https://shib.chukyo-u.ac.jp/User/Menu";
66
+ /** ACE User メニュー選択 */
67
+ readonly userMenuSelect: "https://shib.chukyo-u.ac.jp/User/MenuSelect";
68
+ /** ACE User タイムゾーン・言語設定完了 */
69
+ readonly userTimeZoneLangEnd: "https://shib.chukyo-u.ac.jp/User/TimeZoneLangEnd";
70
+ /** ACE User FIDO2 デバイス追加ページ */
71
+ readonly userFido2DeviceAdd: "https://shib.chukyo-u.ac.jp/User/Fido2DeviceAdd";
72
+ /** ACE User FIDO2 デバイス追加完了 */
73
+ readonly userFido2DeviceAddEnd: "https://shib.chukyo-u.ac.jp/User/Fido2DeviceAddEnd";
74
+ /** ACE User FIDO2 デバイス一覧 */
75
+ readonly userFido2DeviceList: "https://shib.chukyo-u.ac.jp/User/Fido2DeviceList";
76
+ /** ACE User FIDO2 デバイス削除完了 */
77
+ readonly userFido2DeviceDelEnd: "https://shib.chukyo-u.ac.jp/User/Fido2DeviceDelEnd";
78
+ /** ACE User 登録フロー用 WebAuthn API(start/finish-registration) */
79
+ readonly userWebauthn: "https://shib.chukyo-u.ac.jp/User/webauthn";
80
+ /** OTP 認証方式選択チェック */
81
+ readonly userSelectAuthTypeCheck: "https://shib.chukyo-u.ac.jp/User/SelectAuthTypeCheck";
82
+ /** OTP メールアドレス入力チェック */
83
+ readonly userInputMailAddresCheck: "https://shib.chukyo-u.ac.jp/User/InputMailAddresCheck";
84
+ /** OTP 仮パスワード入力チェック */
85
+ readonly userInputTemporaryOtpCheck: "https://shib.chukyo-u.ac.jp/User/InputTemporaryOtpCheck";
86
+ /** OTP アプリインストール導線表示チェック */
87
+ readonly userDisplayInstallAppliLinkCheck: "https://shib.chukyo-u.ac.jp/User/DisplayInstallAppliLinkCheck";
88
+ /** OTP(PC 用)入力チェック */
89
+ readonly userInputOtpForPCCheck: "https://shib.chukyo-u.ac.jp/User/InputOtpForPCCheck";
90
+ /** OTP 仮パスワード入力 */
91
+ readonly userInputTemporaryOtp: "https://shib.chukyo-u.ac.jp/User/InputTemporaryOtp";
92
+ /** ACE User ログアウト(SLO 連鎖の起点) */
93
+ readonly userLogout: "https://shib.chukyo-u.ac.jp/User/Logout";
94
+ };
95
+ /** サービス記述子(enterUrl / goalUrl)。SessionProvider に渡す。 */
96
+ export declare const SERVICES: {
97
+ readonly cubics: {
98
+ readonly key: "cubics";
99
+ readonly enterUrl: "https://cubics-as.chukyo-u.ac.jp/unias/UnSSOLoginControl2";
100
+ readonly goalUrl: "https://cubics-as.chukyo-u.ac.jp/unias/UnSSOLoginControl2";
101
+ };
102
+ readonly albo: {
103
+ readonly key: "albo";
104
+ readonly enterUrl: "https://albo.chukyo-u.ac.jp/api/saml/login";
105
+ readonly goalUrl: "https://albo.chukyo-u.ac.jp/dashboard";
106
+ };
107
+ readonly manabo: {
108
+ readonly key: "manabo";
109
+ readonly enterUrl: "https://manabo.cnc.chukyo-u.ac.jp/auth/shibboleth/";
110
+ readonly goalUrl: "https://manabo.cnc.chukyo-u.ac.jp/auth/shibboleth/";
111
+ };
112
+ };
113
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,sBAAsB;AACtB,eAAO,MAAM,eAAe,QAAS,CAAC;AAEtC,+BAA+B;AAC/B,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,2BAA2B;AAC3B,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,kCAAkC;AAClC,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAKhD,eAAO,MAAM,WAAW;IACpB,cAAc;;CAER,CAAC;AAKX,eAAO,MAAM,SAAS;IAClB,cAAc;;IAEd,kBAAkB;;IAElB,4BAA4B;;CAEtB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,yCAAyC,CAAC;AAKxF,eAAO,MAAM,WAAW;IACpB,cAAc;;IAEd,wBAAwB;;CAElB,CAAC;AAKX;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS;IAClB,iDAAiD;;IAEjD,qBAAqB;;IAErB,yBAAyB;;IAEzB,qCAAqC;;IAErC,6CAA6C;;IAE7C,uDAAuD;;IAEvD,yDAAyD;;IAEzD,oBAAoB;;IAEpB,sBAAsB;;IAEtB,6BAA6B;;IAE7B,+BAA+B;;IAE/B,8BAA8B;;IAE9B,4BAA4B;;IAE5B,8BAA8B;;IAE9B,8DAA8D;;IAE9D,qBAAqB;;IAErB,wBAAwB;;IAExB,uBAAuB;;IAEvB,4BAA4B;;IAE5B,sBAAsB;;IAEtB,mBAAmB;;IAEnB,gCAAgC;;CAE1B,CAAC;AAEX,uDAAuD;AACvD,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;CAgBX,CAAC"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * ポータルのデータ系エンドポイント URL と運用値。
3
+ *
4
+ * 運用値(リトライ回数・タイムアウト)は旧 UMEBO の実運用で得た値。根拠なく変えない。
5
+ * ※ Shibboleth 認証 URL やレート制限・セッション失効時間は SDK には持たない
6
+ * (認証・レート制限は利用側 = umebo の責務)。
7
+ */
8
+ /** HTTP タイムアウト(ms) */
9
+ export const HTTP_TIMEOUT_MS = 10_000;
10
+ /** CUBICS セッション不安定対策のリトライ回数 */
11
+ export const CUBICS_RETRY_COUNT = 3;
12
+ /** CUBICS リトライの固定遅延(ms) */
13
+ export const CUBICS_RETRY_DELAY_MS = 200;
14
+ /** CUBICS リトライのランダム加算遅延の上限(ms) */
15
+ export const CUBICS_RETRY_DELAY_RANDOM_MS = 300;
16
+ // ============================================
17
+ // CUBICS(教務システム)— 画面遷移型 HTML
18
+ // ============================================
19
+ export const CUBICS_URLS = {
20
+ /** ベース URL */
21
+ base: "https://cubics-as.chukyo-u.ac.jp",
22
+ };
23
+ // ============================================
24
+ // Albo(ポータルサイト)— 3システムで唯一の JSON REST API
25
+ // ============================================
26
+ export const ALBO_URLS = {
27
+ /** ベース URL */
28
+ base: "https://albo.chukyo-u.ac.jp",
29
+ /** SAML ログイン起点 */
30
+ login: "https://albo.chukyo-u.ac.jp/api/saml/login",
31
+ /** 認証完了確認(ここへの到達でログイン成立) */
32
+ dashboard: "https://albo.chukyo-u.ac.jp/dashboard",
33
+ };
34
+ /**
35
+ * 学年暦(学部)カレンダーソース UUID。`GET /api/calendar-source/` が返す一覧の1件で、
36
+ * 年度更新等で値が変わり得る。`AlboClient#getCalendar` はこれをデフォルト値として使うが、
37
+ * 呼び出し側は `getCalendar({ calendarSourceUuid: ... })` で任意のソース(学部/大学院など)
38
+ * に差し替えられる。差し替え先の UUID は `getCalendarSource()` の結果から取得できる。
39
+ */
40
+ export const ALBO_DEFAULT_CALENDAR_SOURCE_UUID = "ac304d66-b0a8-11f0-afed-06347f3ce845";
41
+ // ============================================
42
+ // MaNaBo(学習管理システム)— API なし、glexa_ajax_* POST で HTML 断片
43
+ // ============================================
44
+ export const MANABO_URLS = {
45
+ /** ベース URL */
46
+ base: "https://manabo.cnc.chukyo-u.ac.jp",
47
+ /** Shibboleth 認証 URL */
48
+ auth: "https://manabo.cnc.chukyo-u.ac.jp/auth/shibboleth/",
49
+ };
50
+ // ============================================
51
+ // Shibboleth(共通認証 / CloudLink IdP + ACE User ポータル)
52
+ // ============================================
53
+ /**
54
+ * Shibboleth 認証系エンドポイント。
55
+ *
56
+ * ※ この SDK は認証フローを「実行」しない。`src/shib` のビルダ/パーサが、
57
+ * 各ステップのリクエスト記述子の組み立てと、レスポンスの構造化に使う。
58
+ * HTTP 実行・Cookie 管理・リダイレクト追従・パスキー暗号処理は呼び出し側の責務。
59
+ * 値は umebo の実運用 URL(acl/constants.ts)に一致。
60
+ */
61
+ export const SHIB_URLS = {
62
+ /** Shibboleth オリジン(フォーム POST の Origin ヘッダに使う) */
63
+ origin: "https://shib.chukyo-u.ac.jp",
64
+ /** WebAuthn RP ID */
65
+ rpId: "shib.chukyo-u.ac.jp",
66
+ /** ACE User SP ログイン起点 */
67
+ clspLogin: "https://shib.chukyo-u.ac.jp/clsp/login",
68
+ /** CLSP SAML ログイン起点(パスキー登録フローの起点) */
69
+ clspSamlLogin: "https://shib.chukyo-u.ac.jp/clsp/saml/login",
70
+ /** 認証方式チェック(Password / OTP / Passkey の可否) */
71
+ checktype: "https://shib.chukyo-u.ac.jp/cloudlink/module.php/cloudlink/checktype.php",
72
+ /** ログインフォーム POST(authtype=0 PW / 2 OTP / 3 Passkey) */
73
+ cloudlinkLoginForm: "https://shib.chukyo-u.ac.jp/cloudlink/module.php/cloudlink/loginuserpass.php",
74
+ /** ログインフロー用 WebAuthn API(start/finish-authentication) */
75
+ webauthn: "https://shib.chukyo-u.ac.jp/cloudlink/module.php/cloudlink/webauthn.php",
76
+ /** ACE User メニュー */
77
+ userMenu: "https://shib.chukyo-u.ac.jp/User/Menu",
78
+ /** ACE User メニュー選択 */
79
+ userMenuSelect: "https://shib.chukyo-u.ac.jp/User/MenuSelect",
80
+ /** ACE User タイムゾーン・言語設定完了 */
81
+ userTimeZoneLangEnd: "https://shib.chukyo-u.ac.jp/User/TimeZoneLangEnd",
82
+ /** ACE User FIDO2 デバイス追加ページ */
83
+ userFido2DeviceAdd: "https://shib.chukyo-u.ac.jp/User/Fido2DeviceAdd",
84
+ /** ACE User FIDO2 デバイス追加完了 */
85
+ userFido2DeviceAddEnd: "https://shib.chukyo-u.ac.jp/User/Fido2DeviceAddEnd",
86
+ /** ACE User FIDO2 デバイス一覧 */
87
+ userFido2DeviceList: "https://shib.chukyo-u.ac.jp/User/Fido2DeviceList",
88
+ /** ACE User FIDO2 デバイス削除完了 */
89
+ userFido2DeviceDelEnd: "https://shib.chukyo-u.ac.jp/User/Fido2DeviceDelEnd",
90
+ /** ACE User 登録フロー用 WebAuthn API(start/finish-registration) */
91
+ userWebauthn: "https://shib.chukyo-u.ac.jp/User/webauthn",
92
+ /** OTP 認証方式選択チェック */
93
+ userSelectAuthTypeCheck: "https://shib.chukyo-u.ac.jp/User/SelectAuthTypeCheck",
94
+ /** OTP メールアドレス入力チェック */
95
+ userInputMailAddresCheck: "https://shib.chukyo-u.ac.jp/User/InputMailAddresCheck",
96
+ /** OTP 仮パスワード入力チェック */
97
+ userInputTemporaryOtpCheck: "https://shib.chukyo-u.ac.jp/User/InputTemporaryOtpCheck",
98
+ /** OTP アプリインストール導線表示チェック */
99
+ userDisplayInstallAppliLinkCheck: "https://shib.chukyo-u.ac.jp/User/DisplayInstallAppliLinkCheck",
100
+ /** OTP(PC 用)入力チェック */
101
+ userInputOtpForPCCheck: "https://shib.chukyo-u.ac.jp/User/InputOtpForPCCheck",
102
+ /** OTP 仮パスワード入力 */
103
+ userInputTemporaryOtp: "https://shib.chukyo-u.ac.jp/User/InputTemporaryOtp",
104
+ /** ACE User ログアウト(SLO 連鎖の起点) */
105
+ userLogout: "https://shib.chukyo-u.ac.jp/User/Logout",
106
+ };
107
+ /** サービス記述子(enterUrl / goalUrl)。SessionProvider に渡す。 */
108
+ export const SERVICES = {
109
+ cubics: {
110
+ key: "cubics",
111
+ enterUrl: `${CUBICS_URLS.base}/unias/UnSSOLoginControl2`,
112
+ goalUrl: `${CUBICS_URLS.base}/unias/UnSSOLoginControl2`,
113
+ },
114
+ albo: {
115
+ key: "albo",
116
+ enterUrl: ALBO_URLS.login,
117
+ goalUrl: ALBO_URLS.dashboard,
118
+ },
119
+ manabo: {
120
+ key: "manabo",
121
+ enterUrl: MANABO_URLS.auth,
122
+ goalUrl: MANABO_URLS.auth,
123
+ },
124
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * クライアント共通のリクエスト実行ヘルパ。
3
+ *
4
+ * SessionProvider があれば Cookie ヘッダを注入し、なければ付与しない
5
+ * (ブラウザ拡張では Transport 側の credentials に委ねる)。
6
+ */
7
+ import type { PortalService, SessionProvider, Transport, TransportResponse } from "../types";
8
+ import type { ZodSafeParseResult } from "zod";
9
+ export interface RequestContext {
10
+ readonly transport: Transport;
11
+ readonly session?: SessionProvider;
12
+ }
13
+ export interface PortalRequestInit {
14
+ method: "GET" | "POST";
15
+ url: string;
16
+ headers?: Record<string, string>;
17
+ body?: string;
18
+ signal?: AbortSignal;
19
+ }
20
+ /** Cookie を(あれば)注入して1回リクエストする。 */
21
+ export declare const portalRequest: (ctx: RequestContext, service: PortalService, init: PortalRequestInit) => Promise<TransportResponse>;
22
+ /** Cookie を注入してボディ文字列だけを返す。 */
23
+ export declare const portalRequestText: (ctx: RequestContext, service: PortalService, init: PortalRequestInit) => Promise<string>;
24
+ /**
25
+ * parser の {@link ZodSafeParseResult} を DTO に unwrap する。失敗時は {@link ParseError}。
26
+ * 各クライアントメソッドの戻り値を「生 DTO」に統一するための共通処理。
27
+ */
28
+ export declare const unwrap: <T>(result: ZodSafeParseResult<T>) => T;
29
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/core/request.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,KAAK,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;CACtC;AAED,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC;CACxB;AAED,kCAAkC;AAClC,eAAO,MAAM,aAAa,GACtB,KAAK,cAAc,EACnB,SAAS,aAAa,EACtB,MAAM,iBAAiB,KACxB,OAAO,CAAC,iBAAiB,CAe3B,CAAC;AAEF,+BAA+B;AAC/B,eAAO,MAAM,iBAAiB,GAC1B,KAAK,cAAc,EACnB,SAAS,aAAa,EACtB,MAAM,iBAAiB,KACxB,OAAO,CAAC,MAAM,CAGhB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,QAAQ,kBAAkB,CAAC,CAAC,CAAC,KAAG,CAKzD,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { ParseError } from "../errors";
2
+ /** Cookie を(あれば)注入して1回リクエストする。 */
3
+ export const portalRequest = async (ctx, service, init) => {
4
+ const headers = {
5
+ "Accept-Language": "ja",
6
+ ...init.headers,
7
+ };
8
+ if (ctx.session) {
9
+ headers["cookie"] = await ctx.session.getCookieHeader(service);
10
+ }
11
+ return ctx.transport.request({
12
+ method: init.method,
13
+ url: init.url,
14
+ headers,
15
+ ...(init.body != null ? { body: init.body } : {}),
16
+ ...(init.signal ? { signal: init.signal } : {}),
17
+ });
18
+ };
19
+ /** Cookie を注入してボディ文字列だけを返す。 */
20
+ export const portalRequestText = async (ctx, service, init) => {
21
+ const res = await portalRequest(ctx, service, init);
22
+ return res.body;
23
+ };
24
+ /**
25
+ * parser の {@link ZodSafeParseResult} を DTO に unwrap する。失敗時は {@link ParseError}。
26
+ * 各クライアントメソッドの戻り値を「生 DTO」に統一するための共通処理。
27
+ */
28
+ export const unwrap = (result) => {
29
+ if (!result.success) {
30
+ throw new ParseError({ cause: result.error });
31
+ }
32
+ return result.data;
33
+ };
@@ -0,0 +1,13 @@
1
+ import { type RequestContext } from "../core/request";
2
+ import type { CubicsAsTimetableDTO } from "./types/cubics";
3
+ export declare class CubicsClient {
4
+ private readonly ctx;
5
+ constructor(ctx: RequestContext);
6
+ /** セッション無効時は base 外へのリダイレクト、または "Missing cookie" タイトルが返る */
7
+ private isSessionValid;
8
+ private waitForRetryDelay;
9
+ private fetchText;
10
+ /** 週間時間割を取得する */
11
+ getTimetable(): Promise<CubicsAsTimetableDTO>;
12
+ }
13
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/cubics/client.ts"],"names":[],"mappings":"AAYA,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAI3D,qBAAa,YAAY;IACT,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,cAAc;IAEhD,4DAA4D;IAC5D,OAAO,CAAC,cAAc;YAOR,iBAAiB;YAKjB,SAAS;IAevB,iBAAiB;IACX,YAAY,IAAI,OAAO,CAAC,oBAAoB,CAAC;CAMtD"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * CUBICS クライアント。画面遷移型でセッションが不安定なため、無効を検知したら
3
+ * セッションを invalidate してランダム遅延を挟み最大 {@link CUBICS_RETRY_COUNT} 回リトライする。
4
+ */
5
+ import { CUBICS_RETRY_COUNT, CUBICS_RETRY_DELAY_MS, CUBICS_RETRY_DELAY_RANDOM_MS, CUBICS_URLS, SERVICES, } from "../constants";
6
+ import { ExpiredSessionError } from "../errors";
7
+ import { portalRequest, unwrap } from "../core/request";
8
+ import { parseCubicsAsTimetable } from "./parser/cubics";
9
+ const INVALID_TITLES = ["<title>Missing cookie</title>", "<title>クッキーが見つかりません</title>"];
10
+ export class CubicsClient {
11
+ ctx;
12
+ constructor(ctx) {
13
+ this.ctx = ctx;
14
+ }
15
+ /** セッション無効時は base 外へのリダイレクト、または "Missing cookie" タイトルが返る */
16
+ isSessionValid(res) {
17
+ if (!res.url.startsWith(CUBICS_URLS.base)) {
18
+ return false;
19
+ }
20
+ return !INVALID_TITLES.some((title) => res.body.includes(title));
21
+ }
22
+ async waitForRetryDelay() {
23
+ const delay = CUBICS_RETRY_DELAY_MS + Math.floor(Math.random() * CUBICS_RETRY_DELAY_RANDOM_MS);
24
+ await new Promise((resolve) => setTimeout(resolve, delay));
25
+ }
26
+ async fetchText(path) {
27
+ for (let attempt = 0; attempt <= CUBICS_RETRY_COUNT; attempt++) {
28
+ const res = await portalRequest(this.ctx, SERVICES.cubics, {
29
+ method: "GET",
30
+ url: `${CUBICS_URLS.base}${path}`,
31
+ });
32
+ if (this.isSessionValid(res)) {
33
+ return res.body;
34
+ }
35
+ this.ctx.session?.invalidate(SERVICES.cubics.key);
36
+ await this.waitForRetryDelay();
37
+ }
38
+ throw new ExpiredSessionError();
39
+ }
40
+ /** 週間時間割を取得する */
41
+ async getTimetable() {
42
+ const html = await this.fetchText("/unias/UnSSOLoginControl2?REQ_ACTION_DO=/ARF010.do&REQ_PRFR_MNU_ID=MNUIDSTD0103");
43
+ return unwrap(parseCubicsAsTimetable(html));
44
+ }
45
+ }
@@ -0,0 +1,4 @@
1
+ export { parseCubicsAsTimetable } from "./parser/cubics";
2
+ export * from "./types/cubics";
3
+ export { CubicsClient } from "./client";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cubics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { parseCubicsAsTimetable } from "./parser/cubics";
2
+ export * from "./types/cubics";
3
+ export { CubicsClient } from "./client";