@omelhorsite/sdk 0.1.0 → 0.2.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.
- package/README.md +1 -0
- package/dist/index.js +56 -1
- package/dist/types/client.d.ts +15 -0
- package/dist/types/http.d.ts +18 -0
- package/dist/types/resources/account.d.ts +6 -3
- package/dist/types/resources/index.d.ts +1 -0
- package/dist/types/resources/quotas.d.ts +122 -0
- package/dist/types/resources/tools/index.d.ts +3 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -89,6 +89,7 @@ const rows = await oms.http.get<{ id: string }[]>("/some/new/path");
|
|
|
89
89
|
| `oms.account` | The signed-in user, their profile, their usage report. |
|
|
90
90
|
| `oms.storage` | The virtual filesystem: nodes, uploads, downloads, grants. |
|
|
91
91
|
| `oms.tools` | The metered media tools, each with its own daily quota. |
|
|
92
|
+
| `oms.quotas` | Every ceiling on the account - tools, storage and music - in one call. |
|
|
92
93
|
| `oms.jobs` | Background jobs: list, get, wait, watch. The API has no cancel. |
|
|
93
94
|
| `oms.tickets` | Support tickets and their message threads. |
|
|
94
95
|
| `oms.shortLinks` `oms.notepads` `oms.dynamicQrs` `oms.chests` `oms.forms` `oms.linkTrees` | Everything that ends in a shareable URL. |
|
package/dist/index.js
CHANGED
|
@@ -322,6 +322,7 @@ class ApiClient {
|
|
|
322
322
|
baseUrl;
|
|
323
323
|
fetchImpl;
|
|
324
324
|
tokens;
|
|
325
|
+
sessionCookie;
|
|
325
326
|
baseHeaders;
|
|
326
327
|
timeoutMs;
|
|
327
328
|
retry;
|
|
@@ -332,7 +333,11 @@ class ApiClient {
|
|
|
332
333
|
throw new OmsNetworkError("No fetch implementation available. Pass one to the Oms constructor: new Oms({ fetch }).");
|
|
333
334
|
}
|
|
334
335
|
this.fetchImpl = (input, init) => injected(input, init);
|
|
336
|
+
if (options.sessionCookie && options.tokens) {
|
|
337
|
+
throw new TypeError("Pass either `sessionCookie` or a token, not both: two credentials on one request means the server decides which identity wins, and the caller cannot tell which one it got.");
|
|
338
|
+
}
|
|
335
339
|
this.tokens = options.tokens;
|
|
340
|
+
this.sessionCookie = options.sessionCookie ?? false;
|
|
336
341
|
this.baseHeaders = { ...options.headers ?? {} };
|
|
337
342
|
if (options.clientName)
|
|
338
343
|
this.baseHeaders["X-Oms-Client"] = options.clientName;
|
|
@@ -451,7 +456,7 @@ class ApiClient {
|
|
|
451
456
|
headers,
|
|
452
457
|
signal,
|
|
453
458
|
...body === undefined ? {} : { body },
|
|
454
|
-
credentials: "omit",
|
|
459
|
+
credentials: this.sessionCookie ? "include" : "omit",
|
|
455
460
|
redirect: "follow"
|
|
456
461
|
};
|
|
457
462
|
}
|
|
@@ -10476,6 +10481,45 @@ class NotepadsNamespace extends Resource {
|
|
|
10476
10481
|
}
|
|
10477
10482
|
}
|
|
10478
10483
|
|
|
10484
|
+
// src/resources/quotas.ts
|
|
10485
|
+
var QUOTA_RESOURCES = [
|
|
10486
|
+
"vocal_separation_seconds",
|
|
10487
|
+
"transcription_seconds",
|
|
10488
|
+
"caption_seconds",
|
|
10489
|
+
"jumpstyle_edits",
|
|
10490
|
+
"storage_nodes",
|
|
10491
|
+
"music_storage_bytes"
|
|
10492
|
+
];
|
|
10493
|
+
|
|
10494
|
+
class QuotasNamespace extends Resource {
|
|
10495
|
+
async list(options = {}) {
|
|
10496
|
+
const answer = await this.http.get("/quotas", options);
|
|
10497
|
+
return {
|
|
10498
|
+
authenticated: answer?.authenticated === true,
|
|
10499
|
+
quotas: answer?.quotas ?? []
|
|
10500
|
+
};
|
|
10501
|
+
}
|
|
10502
|
+
async get(resource, options = {}) {
|
|
10503
|
+
return quotaFor(await this.list(options), resource) ?? null;
|
|
10504
|
+
}
|
|
10505
|
+
}
|
|
10506
|
+
function quotaFor(report, resource) {
|
|
10507
|
+
return report.quotas.find((entry) => entry.resource === resource);
|
|
10508
|
+
}
|
|
10509
|
+
function quotaExhausted(entry) {
|
|
10510
|
+
if (entry.unlimited || entry.remaining === null)
|
|
10511
|
+
return false;
|
|
10512
|
+
return entry.remaining <= 0;
|
|
10513
|
+
}
|
|
10514
|
+
function quotaAffords(entry, amount) {
|
|
10515
|
+
if (entry.unlimited)
|
|
10516
|
+
return true;
|
|
10517
|
+
const remaining = entry.remaining ?? (entry.limit === null ? null : Math.max(0, entry.limit - entry.used));
|
|
10518
|
+
if (remaining === null)
|
|
10519
|
+
return true;
|
|
10520
|
+
return amount <= remaining;
|
|
10521
|
+
}
|
|
10522
|
+
|
|
10479
10523
|
// src/resources/storage.ts
|
|
10480
10524
|
class FsGrantsNamespace extends Resource {
|
|
10481
10525
|
async list(params = {}, options = {}) {
|
|
@@ -11389,17 +11433,22 @@ class Oms {
|
|
|
11389
11433
|
forms;
|
|
11390
11434
|
linkTrees;
|
|
11391
11435
|
jobs;
|
|
11436
|
+
quotas;
|
|
11392
11437
|
tools;
|
|
11393
11438
|
local = local;
|
|
11394
11439
|
constructor(options = {}) {
|
|
11395
11440
|
if (options.tokens && options.token !== undefined && options.token !== null) {
|
|
11396
11441
|
throw new TypeError("Pass either `token` or `tokens` to the Oms constructor, not both.");
|
|
11397
11442
|
}
|
|
11443
|
+
if (options.sessionCookie && (options.tokens || options.token !== undefined && options.token !== null)) {
|
|
11444
|
+
throw new TypeError("Pass either `sessionCookie` or a token to the Oms constructor, not both.");
|
|
11445
|
+
}
|
|
11398
11446
|
const tokens2 = options.tokens ?? providerFor(options.token);
|
|
11399
11447
|
this.http = new ApiClient({
|
|
11400
11448
|
...options.baseUrl === undefined ? {} : { baseUrl: options.baseUrl },
|
|
11401
11449
|
...options.fetch === undefined ? {} : { fetch: options.fetch },
|
|
11402
11450
|
...tokens2 === undefined ? {} : { tokens: tokens2 },
|
|
11451
|
+
...options.sessionCookie === undefined ? {} : { sessionCookie: options.sessionCookie },
|
|
11403
11452
|
...options.headers === undefined ? {} : { headers: options.headers },
|
|
11404
11453
|
...options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs },
|
|
11405
11454
|
...options.retry === undefined ? {} : { retry: options.retry },
|
|
@@ -11417,6 +11466,7 @@ class Oms {
|
|
|
11417
11466
|
this.forms = new FormsNamespace(this.http);
|
|
11418
11467
|
this.linkTrees = new LinkTreesNamespace(this.http);
|
|
11419
11468
|
this.jobs = new JobsNamespace(this.http);
|
|
11469
|
+
this.quotas = new QuotasNamespace(this.http);
|
|
11420
11470
|
this.tools = new ToolsNamespace(this.http);
|
|
11421
11471
|
}
|
|
11422
11472
|
get baseUrl() {
|
|
@@ -11459,6 +11509,9 @@ export {
|
|
|
11459
11509
|
readFileInput,
|
|
11460
11510
|
readErrorBody,
|
|
11461
11511
|
randomInt,
|
|
11512
|
+
quotaFor,
|
|
11513
|
+
quotaExhausted,
|
|
11514
|
+
quotaAffords,
|
|
11462
11515
|
qrToSvg,
|
|
11463
11516
|
qrToDataUri,
|
|
11464
11517
|
pollUntilTerminal,
|
|
@@ -11524,6 +11577,8 @@ export {
|
|
|
11524
11577
|
ShortLinksNamespace,
|
|
11525
11578
|
SHORT_LINK_BASE_URL,
|
|
11526
11579
|
Resource,
|
|
11580
|
+
QuotasNamespace,
|
|
11581
|
+
QUOTA_RESOURCES,
|
|
11527
11582
|
POLL_BACKOFF_FACTOR,
|
|
11528
11583
|
PART_URL_WINDOW,
|
|
11529
11584
|
OmsTimeoutError,
|
package/dist/types/client.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { IpLookupNamespace } from "./resources/ipLookup";
|
|
|
21
21
|
import { JobsNamespace } from "./resources/jobs";
|
|
22
22
|
import { LinkTreesNamespace } from "./resources/linkTrees";
|
|
23
23
|
import { NotepadsNamespace } from "./resources/notepads";
|
|
24
|
+
import { QuotasNamespace } from "./resources/quotas";
|
|
24
25
|
import { ShortLinksNamespace } from "./resources/shortLinks";
|
|
25
26
|
import { StorageNamespace } from "./resources/storage";
|
|
26
27
|
import { TicketsNamespace } from "./resources/tickets";
|
|
@@ -48,6 +49,18 @@ export interface OmsOptions {
|
|
|
48
49
|
* passing both throws. Build one with `refreshingTokenProvider`.
|
|
49
50
|
*/
|
|
50
51
|
readonly tokens?: TokenProvider;
|
|
52
|
+
/**
|
|
53
|
+
* Authenticate with the browser's httpOnly session cookie instead of a
|
|
54
|
+
* token. First-party pages only, and never the default: see
|
|
55
|
+
* {@link ApiClientOptions.sessionCookie} for why it has to be asked for
|
|
56
|
+
* by name.
|
|
57
|
+
*
|
|
58
|
+
* ```ts
|
|
59
|
+
* // in the omelhorsite web app, served from the same site as the API
|
|
60
|
+
* const oms = new Oms({ sessionCookie: true });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
readonly sessionCookie?: boolean;
|
|
51
64
|
/** API root. Defaults to `https://backend.omelhorsite.pt`. */
|
|
52
65
|
readonly baseUrl?: string;
|
|
53
66
|
/**
|
|
@@ -110,6 +123,8 @@ export declare class Oms {
|
|
|
110
123
|
readonly linkTrees: LinkTreesNamespace;
|
|
111
124
|
/** Background jobs: listing, polling and watching. There is no cancel. */
|
|
112
125
|
readonly jobs: JobsNamespace;
|
|
126
|
+
/** Every ceiling on the account - tools, storage and music - in one call. */
|
|
127
|
+
readonly quotas: QuotasNamespace;
|
|
113
128
|
/** The metered media tools, each with its own daily quota. */
|
|
114
129
|
readonly tools: ToolsNamespace;
|
|
115
130
|
/**
|
package/dist/types/http.d.ts
CHANGED
|
@@ -40,6 +40,23 @@ export interface ApiClientOptions {
|
|
|
40
40
|
readonly fetch?: FetchLike;
|
|
41
41
|
/** Where the bearer token comes from. */
|
|
42
42
|
readonly tokens?: TokenProvider;
|
|
43
|
+
/**
|
|
44
|
+
* Authenticate with the browser's `oms_session` cookie instead of a token.
|
|
45
|
+
*
|
|
46
|
+
* FOR A FIRST-PARTY PAGE ONLY, and never the default. The cookie is httpOnly
|
|
47
|
+
* precisely so that no JavaScript can read the session token; a page served
|
|
48
|
+
* from omelhorsite.pt asks the browser to attach it, and the token itself
|
|
49
|
+
* stays out of reach of any script on the page.
|
|
50
|
+
*
|
|
51
|
+
* That is also why this has to be asked for by name. Left off, an SDK call is
|
|
52
|
+
* authenticated by the token it was handed and by nothing else, so a page
|
|
53
|
+
* that embeds the SDK cannot act as whoever happens to be signed in. Turning
|
|
54
|
+
* it on is a statement that this code IS the first-party app.
|
|
55
|
+
*
|
|
56
|
+
* Requires a same-site page: the cookie is host-only on the API host, so a
|
|
57
|
+
* page anywhere else gets an unauthenticated request, not an error.
|
|
58
|
+
*/
|
|
59
|
+
readonly sessionCookie?: boolean;
|
|
43
60
|
/** Headers merged into every request, below per-call headers. */
|
|
44
61
|
readonly headers?: Record<string, string>;
|
|
45
62
|
/** Default deadline for one call, retries included. `0` disables it. */
|
|
@@ -85,6 +102,7 @@ export declare class ApiClient {
|
|
|
85
102
|
readonly baseUrl: string;
|
|
86
103
|
private readonly fetchImpl;
|
|
87
104
|
private readonly tokens;
|
|
105
|
+
private readonly sessionCookie;
|
|
88
106
|
private readonly baseHeaders;
|
|
89
107
|
private readonly timeoutMs;
|
|
90
108
|
private readonly retry;
|
|
@@ -126,9 +126,12 @@ export interface AccountStorageUsage {
|
|
|
126
126
|
/**
|
|
127
127
|
* `GET /account/usage`: what the account has spent, per area.
|
|
128
128
|
*
|
|
129
|
-
* This is a bespoke report, not
|
|
130
|
-
*
|
|
131
|
-
* ceiling
|
|
129
|
+
* This is a bespoke report, not a quota answer: it carries breakdowns nothing
|
|
130
|
+
* else has (the biggest files, the extension histogram) and it does NOT carry
|
|
131
|
+
* every ceiling - the row ceiling on the file tree and the music byte ceiling
|
|
132
|
+
* are absent from it. For ceilings, ask `oms.quotas.list()`, which answers all
|
|
133
|
+
* of them in one call; each metered tool also still reports its own through
|
|
134
|
+
* its `quota()`.
|
|
132
135
|
*/
|
|
133
136
|
export interface AccountUsage {
|
|
134
137
|
readonly user: {
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `quotas` namespace: every ceiling on the account, in one call.
|
|
3
|
+
*
|
|
4
|
+
* This exists because the question an agent actually asks is "how much is left
|
|
5
|
+
* of everything", and answering it used to mean knowing which four tools were
|
|
6
|
+
* metered, calling four endpoints, and then knowing that neither storage nor
|
|
7
|
+
* music was in any of those answers. `oms.quotas.list()` is one request and
|
|
8
|
+
* returns every resource the server meters, each in the same shape.
|
|
9
|
+
*
|
|
10
|
+
* The per-tool `quota()` calls have NOT gone anywhere and answer exactly what
|
|
11
|
+
* they always answered - they are published API. Use them when you want one
|
|
12
|
+
* tool and nothing else, or when the credential carries `tools:read` but not
|
|
13
|
+
* `profile`; use this when you want the picture.
|
|
14
|
+
*
|
|
15
|
+
* Two things to read before trusting a number:
|
|
16
|
+
*
|
|
17
|
+
* - **`period` is not decoration.** A `"daily"` resource resets at midnight,
|
|
18
|
+
* server time, and `used` is what today has spent. A `"total"` resource is
|
|
19
|
+
* what is stored RIGHT NOW and only falls when something is deleted; waiting
|
|
20
|
+
* does not give it back.
|
|
21
|
+
* - **Anonymous callers get a shorter list.** Without a credential the server
|
|
22
|
+
* answers with the daily resources only, counted per IP, because an
|
|
23
|
+
* anonymous caller has no file tree and no music library. Never index the
|
|
24
|
+
* array by position - look the resource up by name, or use
|
|
25
|
+
* {@link quotaFor}, which returns `undefined` rather than lying.
|
|
26
|
+
*
|
|
27
|
+
* Needs the `profile` scope for an OAuth token, the same scope
|
|
28
|
+
* `account.usage()` needs, because a quota is account state and it spans tools,
|
|
29
|
+
* storage and music at once.
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* const report = await oms.quotas.list();
|
|
33
|
+
* const music = quotaFor(report, "music_storage_bytes");
|
|
34
|
+
* if (music && !quotaAffords(music, file.size)) throw new Error("no room");
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
import { Resource } from "../http";
|
|
38
|
+
import type { RequestOptions } from "../types";
|
|
39
|
+
/**
|
|
40
|
+
* Every resource the server's catalogue defines today, in the order it answers
|
|
41
|
+
* them: the four metered tools first, then the two storage ceilings.
|
|
42
|
+
*
|
|
43
|
+
* A server that grows a seventh keeps working - {@link QuotaEntry.resource} is
|
|
44
|
+
* widened to `string` on purpose, so an unknown name arrives as data rather
|
|
45
|
+
* than as a type error in a client nobody has rebuilt.
|
|
46
|
+
*/
|
|
47
|
+
export declare const QUOTA_RESOURCES: readonly ["vocal_separation_seconds", "transcription_seconds", "caption_seconds", "jumpstyle_edits", "storage_nodes", "music_storage_bytes"];
|
|
48
|
+
/** One of {@link QUOTA_RESOURCES}. */
|
|
49
|
+
export type QuotaResource = (typeof QUOTA_RESOURCES)[number];
|
|
50
|
+
/**
|
|
51
|
+
* What the numbers count. `"seconds"` of media, `"count"` of whole things
|
|
52
|
+
* (edits, files and folders), `"bytes"` of stored media.
|
|
53
|
+
*/
|
|
54
|
+
export type QuotaUnit = "seconds" | "count" | "bytes";
|
|
55
|
+
/**
|
|
56
|
+
* `"daily"` spends and resets at midnight, server time. `"total"` is what is
|
|
57
|
+
* stored right now and only falls when something is deleted.
|
|
58
|
+
*/
|
|
59
|
+
export type QuotaPeriod = "daily" | "total";
|
|
60
|
+
/** One resource, in the one shape every resource uses. */
|
|
61
|
+
export interface QuotaEntry {
|
|
62
|
+
/** A {@link QuotaResource}, or a name added to the server since this build. */
|
|
63
|
+
readonly resource: QuotaResource | string;
|
|
64
|
+
readonly unit: QuotaUnit | string;
|
|
65
|
+
readonly period: QuotaPeriod | string;
|
|
66
|
+
/** Spent today for a daily resource; stored right now for a total one. */
|
|
67
|
+
readonly used: number;
|
|
68
|
+
/** `null` exactly when {@link unlimited} is `true`. */
|
|
69
|
+
readonly limit: number | null;
|
|
70
|
+
/** `null` exactly when {@link unlimited} is `true`. Never negative. */
|
|
71
|
+
readonly remaining: number | null;
|
|
72
|
+
/** `true` when this account has no ceiling on this resource. */
|
|
73
|
+
readonly unlimited: boolean;
|
|
74
|
+
}
|
|
75
|
+
/** `GET /quotas` in full. */
|
|
76
|
+
export interface QuotaReport {
|
|
77
|
+
/** Whether the caller was recognised. Anonymous callers get a shorter list. */
|
|
78
|
+
readonly authenticated: boolean;
|
|
79
|
+
/** One entry per resource the caller can actually spend. */
|
|
80
|
+
readonly quotas: QuotaEntry[];
|
|
81
|
+
}
|
|
82
|
+
/** The `quotas` namespace, reachable as `oms.quotas`. */
|
|
83
|
+
export declare class QuotasNamespace extends Resource {
|
|
84
|
+
/**
|
|
85
|
+
* `GET /quotas` - every ceiling on the account, in one request.
|
|
86
|
+
*
|
|
87
|
+
* Works anonymously, and then answers with the daily resources only.
|
|
88
|
+
*
|
|
89
|
+
* Every number is computed on the spot - the daily ones are aggregates over
|
|
90
|
+
* today's rows, and the two totals are a subtree row count and a blob-size
|
|
91
|
+
* sum - so this is a call to make BEFORE an expensive upload, not one to
|
|
92
|
+
* poll. The server throttles it at thirty a minute per caller, well above
|
|
93
|
+
* that use and well below a loop.
|
|
94
|
+
*/
|
|
95
|
+
list(options?: RequestOptions): Promise<QuotaReport>;
|
|
96
|
+
/**
|
|
97
|
+
* One resource, or `null` when the caller cannot spend it - which is what an
|
|
98
|
+
* anonymous caller gets for `storage_nodes` and `music_storage_bytes`.
|
|
99
|
+
*
|
|
100
|
+
* Costs the same single request as {@link list}, because the server has no
|
|
101
|
+
* per-resource endpoint. Asking for three resources means calling
|
|
102
|
+
* {@link list} once and using {@link quotaFor} three times, not calling this
|
|
103
|
+
* three times.
|
|
104
|
+
*/
|
|
105
|
+
get(resource: QuotaResource | string, options?: RequestOptions): Promise<QuotaEntry | null>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Finds one resource in a report. Returns `undefined` when it is not there,
|
|
109
|
+
* which is a real answer and not a failure: an anonymous caller has no storage
|
|
110
|
+
* quota because they have no storage.
|
|
111
|
+
*/
|
|
112
|
+
export declare function quotaFor(report: QuotaReport, resource: QuotaResource | string): QuotaEntry | undefined;
|
|
113
|
+
/** True when there is nothing left to spend. Always false when unlimited. */
|
|
114
|
+
export declare function quotaExhausted(entry: QuotaEntry): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Whether `amount` more fits under the ceiling, in the resource's own unit.
|
|
117
|
+
*
|
|
118
|
+
* Always true when unlimited. Uses `remaining` when the server sent one and
|
|
119
|
+
* falls back to `limit - used` when it did not, so it is honest about a report
|
|
120
|
+
* that is missing a field rather than reading `null` as zero.
|
|
121
|
+
*/
|
|
122
|
+
export declare function quotaAffords(entry: QuotaEntry, amount: number): boolean;
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* - it is asynchronous: the create call answers with a row in `"pending"` and
|
|
10
10
|
* the work happens on a sidecar;
|
|
11
11
|
* - it has a daily quota, metered in seconds for the audio and video tools and
|
|
12
|
-
* in edits for jumpstyle, and smaller for an anonymous caller
|
|
12
|
+
* in edits for jumpstyle, and smaller for an anonymous caller - each tool's
|
|
13
|
+
* own `quota()` reads it, and `oms.quotas.list()` reads all of them plus the
|
|
14
|
+
* storage ceilings in one request;
|
|
13
15
|
* - an anonymous caller must pass a Turnstile token
|
|
14
16
|
* ({@link ToolCaptcha.captchaToken}, sent as `cf_turnstile_token`).
|
|
15
17
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omelhorsite/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "TypeScript SDK for the omelhorsite API. Isolate-safe: no node builtins, no environment access, no stdout.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -17,11 +17,12 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"typecheck": "tsc --noEmit -p .",
|
|
20
|
+
"typecheck": "tsc --noEmit -p . && tsc --noEmit -p tsconfig.test.json",
|
|
21
21
|
"check:isolate": "bun run scripts/check-isolate.ts",
|
|
22
22
|
"test": "bun run check:isolate && bun test",
|
|
23
23
|
"build": "bun build src/index.ts --target node --format esm --outdir dist --external uqr && tsc -p tsconfig.build.json",
|
|
24
|
-
"prepublishOnly": "bun run build"
|
|
24
|
+
"prepublishOnly": "bun run build",
|
|
25
|
+
"typecheck:tests": "tsc --noEmit -p tsconfig.test.json"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"typescript": "^5.9.3"
|
|
@@ -31,7 +32,6 @@
|
|
|
31
32
|
},
|
|
32
33
|
"repository": {
|
|
33
34
|
"type": "git",
|
|
34
|
-
"url": "git+https://github.com/afonsopc/omelhorsite.git"
|
|
35
|
-
"directory": "apps/cli/packages/core"
|
|
35
|
+
"url": "git+https://github.com/afonsopc/omelhorsite-sdk.git"
|
|
36
36
|
}
|
|
37
37
|
}
|