@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
183 lines • 7.56 kB
JavaScript
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
import { asArray } from "../../utils/records.js";
import { rstripSlash } from "../../utils/slash.js";
import { apiRequest } from "../api/client.js";
import { ApiError } from "../api/errors.js";
export class TrelloApiError extends ApiError {
endpoint;
constructor(endpoint, status, message) {
super(`Trello API error (${endpoint}): HTTP ${String(status)}: ${message}`, status);
this.endpoint = endpoint;
this.name = 'TrelloApiError';
}
}
export class HttpTrelloTransport {
fetch = globalThis.fetch.bind(globalThis);
apiKey;
apiToken;
baseUrl;
timeout;
constructor(opts) {
this.apiKey = opts.apiKey;
this.apiToken = opts.apiToken;
this.baseUrl = rstripSlash(opts.baseUrl ?? 'https://api.trello.com/1');
this.timeout = opts.timeout;
}
async call(method, path, params, body) {
// auth first, so a caller's params can overwrite key/token
return apiRequest(method, `${this.baseUrl}${path}`, {
fetchFn: this.fetch,
timeout: this.timeout,
params: { key: this.apiKey, token: this.apiToken, ...params },
...(body !== undefined
? { json: body, headers: { 'Content-Type': 'application/json; charset=utf-8' } }
: {}),
errorOf: (response, text) => new TrelloApiError(path, response.status, text),
});
}
}
function asObject(value, endpoint) {
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
throw new TrelloApiError(endpoint, 0, 'unexpected response shape');
}
return value;
}
export async function listWorkspaces(transport) {
const result = await transport.call('GET', '/members/me/organizations');
return asArray(result);
}
export async function listWorkspaceBoards(transport, workspaceId) {
const result = await transport.call('GET', `/organizations/${workspaceId}/boards`, {
filter: 'open',
});
return asArray(result);
}
export async function getBoard(transport, boardId) {
const result = await transport.call('GET', `/boards/${boardId}`);
return asObject(result, `/boards/${boardId}`);
}
export async function listBoardLists(transport, boardId) {
const result = await transport.call('GET', `/boards/${boardId}/lists`, { filter: 'open' });
return asArray(result);
}
export async function getList(transport, listId) {
const result = await transport.call('GET', `/lists/${listId}`);
return asObject(result, `/lists/${listId}`);
}
export async function listBoardMembers(transport, boardId) {
const result = await transport.call('GET', `/boards/${boardId}/members`);
return asArray(result);
}
export async function listBoardLabels(transport, boardId) {
const result = await transport.call('GET', `/boards/${boardId}/labels`);
return asArray(result);
}
export async function listListCards(transport, listId) {
const result = await transport.call('GET', `/lists/${listId}/cards`, {
members: 'true',
member_fields: 'id,username,fullName',
});
return asArray(result);
}
/** The cards Trello's search names for `query`, ids only. */
export async function searchCards(transport, query, limit) {
const result = await transport.call('GET', '/search', {
query,
modelTypes: 'cards',
card_fields: 'id',
cards_limit: String(limit),
partial: 'false',
});
const cards = asObject(result, '/search').cards;
const valid = Array.isArray(cards) &&
cards.every((card) => card !== null &&
typeof card === 'object' &&
typeof card.id === 'string');
if (!valid)
throw new TrelloApiError('/search', 0, 'unexpected response shape');
return cards;
}
export async function getCard(transport, cardId) {
const result = await transport.call('GET', `/cards/${cardId}`, {
members: 'true',
member_fields: 'id,username,fullName',
});
return asObject(result, `/cards/${cardId}`);
}
export async function listCardComments(transport, cardId) {
const result = await transport.call('GET', `/cards/${cardId}/actions`, {
filter: 'commentCard',
});
return asArray(result);
}
export async function cardCreate(transport, input) {
const params = { idList: input.listId, name: input.name };
if (input.desc !== undefined && input.desc !== null && input.desc !== '') {
params.desc = input.desc;
}
const result = await transport.call('POST', '/cards', params);
const created = asObject(result, '/cards');
const id = created.id;
if (typeof id !== 'string')
throw new TrelloApiError('/cards', 0, 'card create returned no id');
return getCard(transport, id);
}
export async function cardUpdate(transport, input) {
const params = {};
if (input.name !== undefined && input.name !== null)
params.name = input.name;
if (input.desc !== undefined && input.desc !== null)
params.desc = input.desc;
if (input.closed !== undefined && input.closed !== null) {
params.closed = input.closed ? 'true' : 'false';
}
if (input.due !== undefined && input.due !== null)
params.due = input.due;
if (input.dueComplete !== undefined && input.dueComplete !== null) {
params.dueComplete = input.dueComplete ? 'true' : 'false';
}
if (Object.keys(params).length === 0) {
throw new Error('no updates provided');
}
await transport.call('PUT', `/cards/${input.cardId}`, params);
return getCard(transport, input.cardId);
}
export async function cardMove(transport, cardId, listId) {
await transport.call('PUT', `/cards/${cardId}`, { idList: listId });
return getCard(transport, cardId);
}
export async function cardAssign(transport, cardId, memberId) {
await transport.call('POST', `/cards/${cardId}/idMembers`, { value: memberId });
return getCard(transport, cardId);
}
export async function cardAddLabel(transport, cardId, labelId) {
await transport.call('POST', `/cards/${cardId}/idLabels`, { value: labelId });
return getCard(transport, cardId);
}
export async function cardRemoveLabel(transport, cardId, labelId) {
await transport.call('DELETE', `/cards/${cardId}/idLabels/${labelId}`);
return getCard(transport, cardId);
}
export async function commentCreate(transport, cardId, text) {
const result = await transport.call('POST', `/cards/${cardId}/actions/comments`, { text });
return asObject(result, `/cards/${cardId}/actions/comments`);
}
export async function commentUpdate(transport, cardId, commentId, text) {
const result = await transport.call('PUT', `/cards/${cardId}/actions/${commentId}/comments`, {
text,
});
return asObject(result, `/cards/${cardId}/actions/${commentId}/comments`);
}
//# sourceMappingURL=client.js.map