CIT Hub Developer Documentation
このページの目次

CIT HUB EXTENSIONS

開発者ドキュメント / APIリファレンス

APIを使って、
CIT Hubを拡張する。

TypeScript SDKから利用できる機能、必要な権限、データの範囲、互換性をまとめています。実装例から読み始め、APIの詳細へ進めます。

Host API v34SDK v0.34.0Runtime QuickJS / TypeScript対象 iOS・iPadOS・macOS・Android
このリファレンスについて
ここに記載するのは現行実装を確認できるAPIです。Capabilityが存在するかは capabilities.has() で実行時に確認してください。未提供APIは末尾に明示しています。

APIの全体像

拡張機能はアプリ内の隔離されたTypeScriptランタイムで動作します。画面はiOS・AndroidのネイティブUIで描画し、CIT Hubの個人データは端末内で読み取ります。

最初のAPI呼び出し

import { app, capabilities, cit } from '../sdk/index';

const host = app.hostVersion();
const canReadSchedule = capabilities.has('timetable.read');
const nextClass = canReadSchedule ? await cit.timetable.next() : null;

console.log({ host, nextClass });

APIは機能単位の権限とホストCapabilityを検査します。権限が宣言されていない場合や、古いアプリに必要なAPIがない場合は、呼び出しは明示的なエラーになります。

対応状況の見方

SDKに型があることと、すべてのOSで実機検証済みであることは同じではありません。次の区分を確認し、必要に応じて実行時Capabilityとエラーを扱ってください。

●実装済みAPI

本ページで説明する範囲。個別のOS制約・権限・データ取得条件は各節に記載しています。

●制約・部分対応あり

OSや元データの制約を受けます。例: 端末内キャッシュがない場合のデータAPI、OSに任される通知時刻。

●未提供

APIとして公開していない機能です。計画・要望・SDK上の型だけでは利用可能とは限りません。

セキュリティ境界
拡張機能はPortal/Manabaのパスワード、OTP秘密鍵、Cookie、他ユーザー情報、任意ネイティブコードにアクセスできません。本人データも宣言権限の範囲に限られ、外部送信は開発者が記述した処理に対して接続先を限定します。

はじめに

SDK ZIPを展開し、Node.js 22以降の環境で開発キット内のビルダーを使います。サンプルのソースを編集し、生成したJSONを開発者コンソールへアップロードしてください。

npm install
npm run build -- examples/study-status.ts

TypeScriptソースは開発者のPC上でビルドされます。信頼できないソースをビルドしないでください。アップロードされたコードをCIT Hubのサーバーで実行することはありません。

実行型拡張機能

import { defineProgram, interactive, state, ui } from '../sdk/index';

const count = state.create(0);
export default defineProgram({
  name: 'カウンター',
  version: '1.0.0',
  description: '操作回数を数えます',
  permissions: [],
  render: () => [
    ui.page('カウンター', [
      ui.heading(`現在 ${count.value}`),
      interactive.button('1増やす', () => count.set(count.value + 1))
    ])
  ]
});

defineProgram は隔離ランタイムで処理し、画面はネイティブ部品で描画します。DOM、任意のネイティブコード、グローバルなfetch、Portal/ManabaのCookieや秘密情報にはアクセスできません。

Runtime

アプリ内のQuickJS環境は、拡張機能ごとに分離されています。Promise、async/await、標準的なTypeScriptロジックとStateを利用できます。

制約上限・挙動
処理時間1回あたり最大250ms。超過時はその実行を停止
メモリ16MB
未完了のホスト要求32件
タイマー同時32件、10ms以上、最大24時間。OSによる遅延あり
ホスト要求1要求10秒、要求内容60KBまで

アプリ情報とライフサイクル

app.version()
app.extensionId()
app.environment()       // development | production
app.hostVersion()
app.capabilities()
app.onLaunch(callback)
app.onAppear(callback)
app.onDisappear(callback)
app.onResume(callback)
app.onSuspend(callback)
app.onOpenURL(callback)
app.onNotification(callback)
app.onMemoryWarning(callback)
capabilities.has('location.current')

イベント登録APIは購読解除関数を返します。通知やURLのイベントは対象拡張機能が開いている場合に配送します。アプリ終了後の任意バックグラウンド実行は保証されません。

標準UIと入力

SwiftUI・Jetpack Composeの標準コンポーネントで描画します。任意CSSや固定座標ではなく、宣言型の組み合わせで画面を作ります。

分類SDK API
テキストui.text, ui.heading, ui.label, ui.markdown, ui.code, ui.caption, ui.badge, ui.icon
レイアウトui.vstack, ui.hstack, ui.zstack, ui.grid, ui.scroll, ui.horizontalScroll, ui.spacer, ui.divider, ui.section, ui.disclosure, ui.footer
入力interactive.textField, interactive.textArea, interactive.secureField, interactive.toggle, ui.number, ui.slider, interactive.select, interactive.multiSelect, ui.date
画面・操作ui.page, ui.courseList, ui.dataList, interactive.button, ui.link
見た目ui.styled(node, style)。テーマ色、文字サイズ、配置、余白、間隔をホストの許容範囲で指定

文字・入力部品の詳細な上限、スタイル属性、動的状態イベントはSDK同梱の型定義と詳細API仕様(Markdown)を参照してください。

状態同期する選択入力(host API v32)

const campus = state.create('新習志野');
interactive.select('campus', 'キャンパス', ['新習志野', '津田沼'], campus);
ui.text(`選択中: ${campus.value}`);

選択肢を選ぶと値がStateに入り、そのStateを参照する画面が更新されます。選択肢は1〜100件、1件200文字以内で重複不可です。SDKはこの入力を使う拡張機能に minimumHostAPI: 32 を設定します。

状態同期する複数選択(host API v34)

const supplies = state.create<string[]>(['講義資料']);
interactive.multiSelect('supplies', '持ち物', ['講義資料', '実験器具'], supplies);
ui.text(`選択中: ${supplies.value.join('、')}`);

複数選択UIはiOS・iPadOS・macOSとAndroidのネイティブ部品で表示されます。更新値は文字列配列としてStateへ同期されます。選択肢は1〜30件、各120文字以内で重複不可です。SDKが minimumHostAPI: 34 を設定します。

複数行テキスト入力(host API v23)

const memo = state.create('');
interactive.textArea('memo', '授業メモ', memo);
ui.caption(`${memo.value.length} / 4000`);

入力値はStateへ反映され、入力上限は4,000文字です。端末内へ保存する場合は、用途に合うstorageなどのAPIと権限を別途使用してください。

状態とイベント

const value = state.create(0);
value.get();
value.set(1);
value.update(current => current + 1);
value.reset();
const stop = value.watch((next, previous) => {});
stop();

interactive.button('保存', async () => {
  await storage.set('draft', value.get());
});

State更新は画面を再描画します。イベントコールバック内で非同期のホストAPIを呼び出せます。ホスト要求は権限とCapabilityを別々に検査します。

CIT Hubの本人データ

APIPermission内容
cit.courses.list/get/search/byWeekday/forPeriod
cit.timetable.today/tomorrow/week/current/next/at/freePeriods
timetable.read端末に取得済みの授業・教室・時限・日付別授業
cit.assignments.list/get/pending/overdue/dueSoon/search/byCourse/betweenassignments.read端末に取得済みの課題。提出済み状態は元データにない場合推定しません
cit.todo.list/get/search/watch/create/update/complete/uncomplete/deletetodos.read, todos.write本人が登録したToDo。読み取りと変更は別権限
cit.courseNotes.list/get/create/update/deletecourseNotes.read, courseNotes.write本人の授業メモ
cit.semester.current/list, cit.academicCalendar.list/on/between/isClassDaytimetable.read, calendar.read端末キャッシュに存在する学期・学年暦。根拠不足は不明値
cit.bus.routes/stops/timetable/next/between/serviceStatusbus.readアプリが取得・キャッシュした公開バス時刻表
cit.cafeteria.locations/menu/cameraStatuscafeteria.read食堂拠点、メニューリンク、公開カメラ稼働状況
cit.settings.appearance/notifications/enabledServices, cit.services.list, cit.user.preferencessettings.read本人が有効にしているサービスのタブ名と表示・通知設定。任意のサービスを自動では開きません

これらの情報は端末内で読み、拡張APIサーバーへ転送しません。キャッシュ未取得の場合は空または利用できない旨を返します。元データにない単位数、提出状態、全学休講情報は推定しません。

import { cit } from '../sdk/index';

const today = await cit.timetable.today();
const due = await cit.assignments.dueSoon(7);
const notes = await cit.courseNotes.list();
const enabledServices = await cit.services.list();

保存・データベース

端末内Key-Value

storage.get/set/has/remove/clear/keys は本人・拡張機能・開発/公開環境ごとに分離されます。拡張機能固有データを最大256KB保存できます。他端末との同期はしません。

保護された端末内保存

secureStorage.get/set/delete はiOS/macOSのKeychainまたはAndroidの暗号化保存を使います。CIT Hub本体の認証情報にはアクセスできません。

ローカルデータベース

database.createTable/insert/update/delete/get/query/transaction/watch。比較条件、並べ替え、件数制限のクエリをSDKで構成できます。スキーマは拡張機能専用でSQLite互換ではなく、非同期処理をtransaction callbackから実行できません。

ユーザー専用Cloud KV

cloudUser.get/set/delete はCIT Hubアカウントと拡張機能に隔離されます。revisionによる競合検出、暗号化、容量上限があります。サーバーFunctionsやユーザー間共有ではありません。

ファイル

拡張機能専用領域(host API v30)

await files.write('draft.txt', new TextEncoder().encode('メモ'));
const bytes = await files.read('draft.txt');
await files.copy('draft.txt', 'backup.txt');
await files.move('backup.txt', 'archive.txt');
const names = await files.list();

権限はfiles.storage。最大256KiB/ファイル、最大100ファイル・合計5MiBです。ファイル名のみを受け付け、パス区切り、親ディレクトリ指定、シンボリックリンク、既存宛先への上書きを拒否します。拡張機能の領域外へアクセスできません。

ユーザーが選ぶファイル

ui.file でシステムの選択画面を開きます。files.selection.info/readSelected は選択済みファイルの内容をチャンクで読みます。追加の files.selection.read が必要です。任意フォルダの一覧はできません。

写真・メディア・共有

ui.coursePicker、ui.capturePhoto、ui.importPhotos、ui.photoGrid で、授業選択・撮影・写真取り込み・一覧を組み合わせられます。データは端末内の拡張機能専用領域に保存します。ユーザー操作なしの撮影や写真ライブラリ全体の列挙はできません。

ui.image/video/audio は許可されたHTTPSメディアを表示します。ui.file でユーザーが選んだファイルをアプリ内プレビューまたは対応アプリへ渡せます。ui.shareText、ui.copyText は利用者の操作から実行します。

全コーデック、画像編集、録音、PDFページ操作のすべてをサポートするわけではありません。対応OS・形式はAPI仕様を確認してください。

ネットワーク

network.status() と network.onChange(callback) は端末の接続状態を参照します。接続先名、IP、SSIDは返しません。

const response = await network.fetch('https://api.example.com/items', {
  method: 'GET',
  headers: { Accept: 'application/json' }
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);

network.fetch/get/post/put/patch/delete は network.fetch 権限とmanifestの許可ホスト宣言を必要とします。HTTPS標準ポートのみ、Cookie/Host等の危険なヘッダーは禁止、本文32 KiB・応答1 MiB・ヘッダー20個までです。リダイレクトは追従せず、プライベート・予約済みIPに解決される接続先も拒否します。任意ホストを宣言なく呼び出すことはできません。

ファイル転送(host API v33)

const downloaded = await network.downloadFile(
  'https://api.example.com/handout.pdf',
  'handout.pdf'
);
if (downloaded.ok) {
  const bytes = await files.read(downloaded.file.name);
  // bytes は拡張機能専用ストレージから読み出した Uint8Array
}

network.downloadFile(url, destinationName, headers?) は取得したファイルを拡張機能専用ストレージへ保存し、名前・サイズ・HTTP状態を返します。network.uploadFile(url, sourceName, options?) は同じ専用領域に保存済みのファイルをPOSTまたはPUTで送ります。どちらも利用者が押したボタンの処理中に呼ぶ必要があり、network.fetch と files.storage の両権限、manifestの完全一致HTTPSホスト宣言が必要です。任意の端末ファイルパスにはアクセスできません。

ファイル転送はリクエスト・レスポンス各256 KiBまでです。ダウンロードはリダイレクトしません。保存時は拡張機能専用ストレージのファイル名・件数・総容量制限を適用します。通常のテキスト通信も応答上限は256 KiBです。通信先には端末のIP等が伝わり、アップロードしたファイルの内容も通信先へ渡ります。

端末・位置情報・触覚

device.info/platform/osVersion/deviceClass/screen/locale/timezone/appearance/capabilities は画面やOSの情報を返します。端末固有識別子は提供しません。

location.current() は location.use とユーザー操作を必要とし、単発の現在地・精度・取得時刻を返します。バックグラウンド追跡や位置のサーバー保存はありません。

haptics.light/medium/heavy/success/warning/error は対応端末のみ実行されます。accessibility.status で利用可能なアクセシビリティ状態を取得し、accessibility.label/hint/role で対応UI要素を補助できます。

ローカル通知と権限

const status = await notification.permission();
await notification.schedule({
  id: 'study-reminder',
  title: '復習',
  body: '今日のノートを確認する',
  at: new Date(Date.now() + 60 * 60 * 1000),
  repeat: 'none',
  data: { screen: 'review' }
});
notification.onOpen(event => console.log(event.data));

notifications.schedule 権限が必要です。許可状態は permissions.status/request で確認し、OS許可を要求する処理はユーザー操作から開始します。schedule/cancel/cancelAll/listScheduled/onOpen を利用できます。端末内通知であり、サーバーPushや端末間同期ではありません。OS都合で通知時刻が遅れる場合があります。

permissions.openSettings() は settings.open 権限と直接操作が必要です。宣言されていない権限を要求することはできません。

ユーティリティと暗号

NamespaceAPI
mathround, floor, ceil, min, max, abs, random, clamp, sum, average, median
textformat, replace, split, join, contains, startsWith, endsWith, trim, lowercase, uppercase, regex
jsonparse, stringify
datenow, parse, format, add, subtract, diff, startOfDay/endOfDay, startOfWeek/endOfWeek, isToday/isPast/isFuture, timezone
utilsuuid, sleep, debounce, throttle
geodistance, bearing, contains
cryptorandomBytes, UUID用途の安全乱数、SHA-256、HMAC、AES-256-GCM

暗号機能は拡張機能が渡したデータだけを端末内で処理します。CIT HubのKeychain、OTP、ログインCookie、アプリセッションの秘密情報にはアクセスできません。暗号化キーは拡張機能専用の secureStorage で管理してください。

エラー

ExtensionError、PermissionError、UserInteractionError、UnsupportedError、NetworkError、StorageError、ValidationError、ConflictError、NotFoundError、RateLimitError を提供します。未知のホストエラーもcodeを保持した ExtensionError で通知します。

開発者サーバーAPI

開発者コンソールとCIT Hubアプリが使用するAPIです。一般拡張機能のJavaScriptをサーバーで実行するFunctions APIではありません。

操作説明認証
capabilitieshost API version・対応permissionの固定メタデータ不要
register/login/logout/logout-all/password-change開発者アカウントとセッション管理アカウント認証
upload/submit/mine/catalog/developer本人の開発版、審査提出、承認済みカタログアプリ確認または開発者セッション
install/open/uninstallアプリ内の追加、起動、削除。host API互換性を検査本人のアカウント
data-save拡張機能専用のユーザー入力値本人・拡張機能scope
list/review審査・公開停止別管理キー

ユーザーデータはアカウント単位で隔離され、レビュー権限と一般ユーザー権限は別です。APIトークンやアプリ認証情報を拡張機能へ渡しません。

権限と互換性

使用するデータやOS機能だけをmanifestの permissions に宣言します。審査・追加確認で利用者に説明されます。Capabilityが存在してもOS権限が許可されたとは限りません。permissions.status() で区別してください。

export default defineProgram({
  name: '授業準備',
  version: '1.0.0',
  description: '次の授業と準備メモを表示します',
  permissions: ['timetable.read', 'courseNotes.read'],
  render: () => [/* native UI */]
});

SDK builderは利用APIから minimumHostAPI を設定します。現行アプリより新しいhost APIを要求する拡張機能は、古いアプリで追加・起動できません。

権限一覧

manifestには、実際に使う機能の権限だけを記載します。CIT Hubデータの権限は本人の端末内データへのアクセスを許可し、OS権限や外部通信の許可とは別に検査されます。

権限対象API範囲
timetable.readcit.courses.* / cit.timetable.*端末に取得済みの本人の時間割
assignments.readcit.assignments.*端末に取得済みの本人の課題
todos.read / todos.writecit.todo.*本人が作成したToDoの読み取り・変更
courseNotes.read / courseNotes.writecit.courseNotes.*本人の授業メモ
calendar.read / bus.read / cafeteria.readcit.academicCalendar.* / cit.bus.* / cit.cafeteria.*アプリに取り込まれた学年暦・公開交通/食堂情報
settings.readcit.settings.* / cit.services.list()本人の表示・通知・有効タブ設定。認証情報は含まない
storage.* / files.storage / cloud.storage端末保存・専用ファイル・本人専用Cloud KV拡張機能ごとに隔離。任意の他ユーザー情報は取得不可
network.fetch + files.storagenetwork.uploadFile() / network.downloadFile()宣言したHTTPSホスト・拡張機能専用領域のみ。利用者操作が必須
network.fetchnetwork.fetch/get/post/put/patch/deletemanifestで列挙したHTTPSホストのみ
camera.use / location.use / notifications.scheduleカメラ・現在地・ローカル通知宣言に加えて、必要な場合はユーザー操作とOS許可が必要
files.user / files.selection.read / photos.userファイル選択・選択内容の読取・写真選択利用者が選択した項目のみ

動かない場合の確認順

  1. app.hostVersion() と capabilities.has() でホスト対応状況を確認します。
  2. APIの権限をmanifestに宣言し、開発版を再ビルド・再アップロードします。
  3. 端末側で対象データが一度取得済みか、設定やOS権限が許可されているかを確認します。
  4. 例外は握りつぶさず、エラーの name と code を記録して原因別に案内します。
try {
  const status = await network.status();
  const next = await cit.timetable.next();
  // UIへ結果を反映
} catch (error) {
  console.error(error.name, error.code, error.message);
  // PermissionError / UnsupportedError / data_unavailable などを個別に扱う
}

エラーコードはSDKの型定義と詳細仕様書を正としてください。未実装APIはCapabilityとして公開されず、代替動作を推測して実行しません。

ホストAPIの主な追加履歴

Host API追加内容
v34ネイティブ複数選択UIとState同期 interactive.multiSelect()
v33ボタン操作を必須にした専用領域とのHTTPSファイル転送 network.uploadFile() / network.downloadFile()
v32選択変更をTypeScript Stateへ同期する interactive.select()
v31本人が有効にしている学内サービス名の一覧 cit.services.list()
v30拡張機能専用ファイルの複製・移動
v29縦・横スクロールコンテナ
v28ネットワーク接続状態の変更購読
v24–v27位置情報、接続状態、レイアウト、文字スタイル
v21–v23本人専用Cloud KV、テキストUI、複数行入力
v16–v20時間割・課題・ToDo・学年暦・バス・食堂データAPI
v9–v15実行型SDK、端末保存、ファイル、クリップボード、設定、通知など

各バージョンの厳密な制約と未実装範囲は詳細API仕様書を参照してください。

公開していないAPI

添付の構想すべてが実装済みではありません。サーバーFunctions/KV/DB/Cron、ユーザー間共有・グループ・Realtime・Push、WebSocket、OAuth/OIDC、拡張機能間Intents、OSウィジェット/App Intents、地図UI、画像変換、音声録音、モーションセンサー、汎用ドラッグ&ドロップ、任意Canvas/グラフ、PDFのページ操作、転送進捗は未実装または未接続です。

これらは使用できるAPIや権限として公開していません。APIの詳しい型・挙動・制限は詳細API仕様(Markdown)を確認してください。

Portalパスワード、OTP秘密鍵、認証Cookie、CIT Hubセッショントークン、他ユーザーの個人データ、別拡張機能のprivate storage、端末固有識別子、無音撮影、無制限ファイルアクセス、任意ネイティブコード、無制限バックグラウンド実行はAPIとして提供しません。