nixamp 0.75.0 → 0.76.1
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/dist/ai-label.js +510 -0
- package/dist/library-mcp.d.ts +6 -6
- package/dist/server.d.ts +3 -0
- package/dist/server.js +53 -0
- package/dist/signup-profiles.d.ts +15 -0
- package/dist/signup-profiles.js +26 -0
- package/dist/station-mcp.d.ts +6 -6
- package/package.json +2 -1
- package/src/ai-label.ts +510 -0
- package/src/server.ts +56 -0
- package/src/signup-profiles.ts +33 -0
- package/web/dist/assets/{ar-DWO4AD-h.js → ar-NhWfdGfS.js} +1 -1
- package/web/dist/assets/{chunk-Q2XQMA4B-DdHrVlSJ.css → chunk-Q2XQMA4B-DR1XNWCJ.css} +1 -1
- package/web/dist/assets/{chunk-Q2XQMA4B-BaoaSqsD.js → chunk-Q2XQMA4B-OBCD3Aev.js} +1 -1
- package/web/dist/assets/{cs-BYkdeLUB.js → cs-D1orW8p8.js} +1 -1
- package/web/dist/assets/{da-D1-4-VhC.js → da-C9c7DdFK.js} +1 -1
- package/web/dist/assets/{de-CaklUWbI.js → de-DsPQqmTX.js} +1 -1
- package/web/dist/assets/{es-CG6nwbN9.js → es-STqShmKZ.js} +1 -1
- package/web/dist/assets/{fi-DWfrod_V.js → fi-v5vNrYcE.js} +1 -1
- package/web/dist/assets/{fr-CpWd4lRG.js → fr-lKpl6rLi.js} +1 -1
- package/web/dist/assets/{hi-BIwcJMqA.js → hi-C1w6fo1p.js} +1 -1
- package/web/dist/assets/{hls-OR5FY6YP-B-70I17r.js → hls-OR5FY6YP-B2RNEz5K.js} +1 -1
- package/web/dist/assets/{hu-yaKuIx_R.js → hu-DFUXXymd.js} +1 -1
- package/web/dist/assets/{id-B20X5Jpx.js → id-BQiiFqsd.js} +1 -1
- package/web/dist/assets/{it-C_0lQi83.js → it-CxVVOs4D.js} +1 -1
- package/web/dist/assets/main-DuUFn357.js +26 -0
- package/web/dist/assets/{mpegts-7CN75AI2-D-bdbDNw.js → mpegts-7CN75AI2-1Qj6py7N.js} +1 -1
- package/web/dist/assets/{mpegts-C_-pZIIG.js → mpegts-BcF3gJrf.js} +1 -1
- package/web/dist/assets/music-Day-DtFd.js +1 -0
- package/web/dist/assets/{nl-vH0eIRvu.js → nl-Bg9nYWdM.js} +1 -1
- package/web/dist/assets/{radio-dUHZb5wV.js → radio-Dx44o-ug.js} +1 -1
- package/web/dist/assets/{ru-CyWPMStM.js → ru-Cq7_qZpi.js} +1 -1
- package/web/dist/assets/{station-KW1WLKF4.js → station-UibBpdBh.js} +1 -1
- package/web/dist/assets/{sv-pXXM1l8a.js → sv-zqKojzxL.js} +1 -1
- package/web/dist/assets/{uk-DcNuaLei.js → uk-BRjxYLjm.js} +1 -1
- package/web/dist/assets/{vi-QYkJg9a4.js → vi-Bq9TGPGs.js} +1 -1
- package/web/dist/assets/{vod-CdMhdfvg.js → vod-CkR6hzN7.js} +1 -1
- package/web/dist/assets/{watch-fq5gXk7x.js → watch-BO-wMY8T.js} +1 -1
- package/web/dist/assets/{zh-9sYPz_Vm.js → zh-B6Rlwv_6.js} +1 -1
- package/web/dist/index.html +13 -3
- package/web/dist/music.html +1 -1
- package/web/dist/radio.html +3 -3
- package/web/dist/station.html +3 -3
- package/web/dist/sw.js +29 -29
- package/web/dist/vod.html +3 -3
- package/web/dist/watch.html +3 -3
- package/web/dist/assets/main-reQmYdJ0.js +0 -22
- package/web/dist/assets/music-C8ITlUNF.js +0 -1
package/dist/server.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { Handles } from "./handles.ts";
|
|
|
12
12
|
import { OpenDirs } from "./opendirs.ts";
|
|
13
13
|
import { Servers } from "./servers.ts";
|
|
14
14
|
import { AccountProfiles } from "./profiles.ts";
|
|
15
|
+
import { type ProfileStore } from "@profullstack/profile";
|
|
15
16
|
import { NixampLinks } from "./nixamp-link.ts";
|
|
16
17
|
import { SignIn } from "./oauth.ts";
|
|
17
18
|
import { AuthorizationServer } from "./oauth-server.ts";
|
|
@@ -778,6 +779,8 @@ export interface HandlerOptions {
|
|
|
778
779
|
handles?: Handles;
|
|
779
780
|
/** The account's card: a name, a homepage, a photo, a line. One table, read by every site here. */
|
|
780
781
|
accountProfiles?: AccountProfiles;
|
|
782
|
+
/** Name, company, title and LinkedIn from the sign-up form (@profullstack/profile). */
|
|
783
|
+
signupProfiles?: ProfileStore;
|
|
781
784
|
/** nixamp accounts connected to accounts here, where this site is a client of nixamp.com. */
|
|
782
785
|
links?: NixampLinks;
|
|
783
786
|
/** Open directories people have found, which anyone may read. */
|
package/dist/server.js
CHANGED
|
@@ -37,6 +37,8 @@ import { anonymousHandle, Handles } from "./handles.js";
|
|
|
37
37
|
import { OpenDirs } from "./opendirs.js";
|
|
38
38
|
import { Servers } from "./servers.js";
|
|
39
39
|
import { AccountProfiles, hostCard, PHOTO_LIMIT } from "./profiles.js";
|
|
40
|
+
import { createProfileHandlers, saveSignupProfile, validateProfile } from "@profullstack/profile";
|
|
41
|
+
import { SIGNUP_PROFILE_FIELDS, signupProfiles } from "./signup-profiles.js";
|
|
40
42
|
import { NixampLinks, nixampExchange } from "./nixamp-link.js";
|
|
41
43
|
import { handleNixampLinkApi, nixampLinkPath } from "./nixamp-link-api.js";
|
|
42
44
|
import { DeviceGrants } from "./device.js";
|
|
@@ -3428,9 +3430,28 @@ export function createHandler(engine, options) {
|
|
|
3428
3430
|
return;
|
|
3429
3431
|
}
|
|
3430
3432
|
}
|
|
3433
|
+
// The web form sends the profile fields, and then first and last name are
|
|
3434
|
+
// required; a terminal or an older app that sends none is not asked.
|
|
3435
|
+
const asked = signingUp && options.signupProfiles
|
|
3436
|
+
&& SIGNUP_PROFILE_FIELDS.some((field) => field in body);
|
|
3437
|
+
const profile = asked ? validateProfile(body) : null;
|
|
3438
|
+
if (profile && !profile.ok) {
|
|
3439
|
+
json(response, 400, { error: Object.values(profile.errors)[0] ?? "some fields need fixing", errors: profile.errors });
|
|
3440
|
+
return;
|
|
3441
|
+
}
|
|
3431
3442
|
const result = signingUp
|
|
3432
3443
|
? await accounts.signUp(body.email, body.password)
|
|
3433
3444
|
: await accounts.signIn(body.email, body.password);
|
|
3445
|
+
// Kept once the account exists. A profile that does not save is filled
|
|
3446
|
+
// in later from the Account panel, never a sign-up that failed.
|
|
3447
|
+
if (profile && result.ok && result.account && options.signupProfiles) {
|
|
3448
|
+
try {
|
|
3449
|
+
await saveSignupProfile(options.signupProfiles, result.account.id, profile.profile, { email: result.account.email });
|
|
3450
|
+
}
|
|
3451
|
+
catch (error) {
|
|
3452
|
+
console.error("nixamp: sign-up profile not saved:", error.message);
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3434
3455
|
// A handle asked for at sign-up, or one nobody has to think about. Never
|
|
3435
3456
|
// derived from the address: turning anthony@… into "anthony" is the leak
|
|
3436
3457
|
// this whole idea exists to avoid, and it is one nobody would notice
|
|
@@ -4450,6 +4471,37 @@ export function createHandler(engine, options) {
|
|
|
4450
4471
|
//
|
|
4451
4472
|
// A name, a homepage, a photo and a line, said once. A class is made from
|
|
4452
4473
|
// it, a settings page edits it, and an OpenProfile.md fills it in one move.
|
|
4474
|
+
// The account's own profile fields (name, company, title, LinkedIn), from
|
|
4475
|
+
// the shared @profullstack/profile handlers. Under the host card's path
|
|
4476
|
+
// because /api/v1/me/profile is already that card, which strangers see.
|
|
4477
|
+
if (path === "/api/v1/me/profile/fields" && options.signupProfiles && options.accounts) {
|
|
4478
|
+
const accounts = options.accounts;
|
|
4479
|
+
const handlers = createProfileHandlers({
|
|
4480
|
+
store: options.signupProfiles,
|
|
4481
|
+
getUser: () => accounts.whoIs(tokenFrom(request.headers)),
|
|
4482
|
+
});
|
|
4483
|
+
const method = request.method ?? "GET";
|
|
4484
|
+
const handle = method === "GET" ? handlers.GET : method === "PUT" ? handlers.PUT : method === "PATCH" ? handlers.PATCH : null;
|
|
4485
|
+
if (handle === null) {
|
|
4486
|
+
json(response, 405, { error: "GET, PUT or PATCH" });
|
|
4487
|
+
return;
|
|
4488
|
+
}
|
|
4489
|
+
const bare = requestFor(request);
|
|
4490
|
+
bare.headers.delete("content-length");
|
|
4491
|
+
bare.headers.delete("transfer-encoding");
|
|
4492
|
+
let body;
|
|
4493
|
+
if (method !== "GET") {
|
|
4494
|
+
try {
|
|
4495
|
+
body = await readBody(request);
|
|
4496
|
+
}
|
|
4497
|
+
catch {
|
|
4498
|
+
json(response, 413, { error: "too large" });
|
|
4499
|
+
return;
|
|
4500
|
+
}
|
|
4501
|
+
}
|
|
4502
|
+
await answerWith(response, await handle(new Request(bare.url, { method, headers: bare.headers, body })));
|
|
4503
|
+
return;
|
|
4504
|
+
}
|
|
4453
4505
|
if ((path === "/api/v1/me/profile" || path.startsWith("/api/v1/me/profile/")) && options.accountProfiles && options.accounts) {
|
|
4454
4506
|
const profiles = options.accountProfiles;
|
|
4455
4507
|
const who = await options.accounts.whoIs(tokenFrom(request.headers));
|
|
@@ -8459,6 +8511,7 @@ export async function serve(argv, version = "0.1.0") {
|
|
|
8459
8511
|
handles: new Handles(pool),
|
|
8460
8512
|
openDirs: new OpenDirs(pool),
|
|
8461
8513
|
accountProfiles: new AccountProfiles(pool),
|
|
8514
|
+
signupProfiles: signupProfiles(pool),
|
|
8462
8515
|
// The school's side of "Connect nixamp": tokens from nixamp.com,
|
|
8463
8516
|
// kept against the school account. The issuer is this same
|
|
8464
8517
|
// program in production, reached over HTTP like any client.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared profile every Profullstack property asks for at sign-up: first
|
|
3
|
+
* and last name, company domain, job title and LinkedIn, beside the email.
|
|
4
|
+
*
|
|
5
|
+
* Kept by @profullstack/profile in its own `user_profiles` table, keyed by the
|
|
6
|
+
* auth-system user id, and never in `nixamp_profiles`: that one is the host
|
|
7
|
+
* card a classroom shows to strangers, and these fields are the account's own.
|
|
8
|
+
* The table is made on first use, like every other nixamp table, because
|
|
9
|
+
* nixamp carries no migration runner.
|
|
10
|
+
*/
|
|
11
|
+
import { type ProfileStore } from "@profullstack/profile";
|
|
12
|
+
import type { Queryable } from "./follows.ts";
|
|
13
|
+
/** The fields the web sign-up form sends; a client that sends none is not asked for them. */
|
|
14
|
+
export declare const SIGNUP_PROFILE_FIELDS: readonly ["first_name", "last_name", "company_domain", "job_title", "linkedin_url"];
|
|
15
|
+
export declare function signupProfiles(db: Queryable): ProfileStore;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared profile every Profullstack property asks for at sign-up: first
|
|
3
|
+
* and last name, company domain, job title and LinkedIn, beside the email.
|
|
4
|
+
*
|
|
5
|
+
* Kept by @profullstack/profile in its own `user_profiles` table, keyed by the
|
|
6
|
+
* auth-system user id, and never in `nixamp_profiles`: that one is the host
|
|
7
|
+
* card a classroom shows to strangers, and these fields are the account's own.
|
|
8
|
+
* The table is made on first use, like every other nixamp table, because
|
|
9
|
+
* nixamp carries no migration runner.
|
|
10
|
+
*/
|
|
11
|
+
import { createProfileStore, schemaSql } from "@profullstack/profile";
|
|
12
|
+
/** The fields the web sign-up form sends; a client that sends none is not asked for them. */
|
|
13
|
+
export const SIGNUP_PROFILE_FIELDS = ["first_name", "last_name", "company_domain", "job_title", "linkedin_url"];
|
|
14
|
+
export function signupProfiles(db) {
|
|
15
|
+
let ready = null;
|
|
16
|
+
const ensure = () => (ready ??= db.query(schemaSql({ keyType: "text" })).catch((error) => {
|
|
17
|
+
ready = null;
|
|
18
|
+
throw error;
|
|
19
|
+
}));
|
|
20
|
+
return createProfileStore({
|
|
21
|
+
query: async (text, values) => {
|
|
22
|
+
await ensure();
|
|
23
|
+
return db.query(text, values);
|
|
24
|
+
},
|
|
25
|
+
}, { keyType: "text" });
|
|
26
|
+
}
|
package/dist/station-mcp.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ export declare const STATION_TOOLS: ({
|
|
|
2
2
|
name: string;
|
|
3
3
|
description: string;
|
|
4
4
|
inputSchema: {
|
|
5
|
-
required?: undefined;
|
|
6
5
|
type: string;
|
|
7
6
|
properties: {
|
|
8
7
|
server: {
|
|
@@ -73,6 +72,7 @@ export declare const STATION_TOOLS: ({
|
|
|
73
72
|
id?: undefined;
|
|
74
73
|
private?: undefined;
|
|
75
74
|
};
|
|
75
|
+
required?: undefined;
|
|
76
76
|
};
|
|
77
77
|
} | {
|
|
78
78
|
name: string;
|
|
@@ -531,7 +531,6 @@ export declare const STATION_TOOLS: ({
|
|
|
531
531
|
name: string;
|
|
532
532
|
description: string;
|
|
533
533
|
inputSchema: {
|
|
534
|
-
required?: undefined;
|
|
535
534
|
type: string;
|
|
536
535
|
properties: {
|
|
537
536
|
playlist?: undefined;
|
|
@@ -616,12 +615,12 @@ export declare const STATION_TOOLS: ({
|
|
|
616
615
|
id?: undefined;
|
|
617
616
|
private?: undefined;
|
|
618
617
|
};
|
|
618
|
+
required?: undefined;
|
|
619
619
|
};
|
|
620
620
|
} | {
|
|
621
621
|
name: string;
|
|
622
622
|
description: string;
|
|
623
623
|
inputSchema: {
|
|
624
|
-
required?: undefined;
|
|
625
624
|
type: string;
|
|
626
625
|
properties: {
|
|
627
626
|
playlist?: undefined;
|
|
@@ -719,12 +718,12 @@ export declare const STATION_TOOLS: ({
|
|
|
719
718
|
id?: undefined;
|
|
720
719
|
private?: undefined;
|
|
721
720
|
};
|
|
721
|
+
required?: undefined;
|
|
722
722
|
};
|
|
723
723
|
} | {
|
|
724
724
|
name: string;
|
|
725
725
|
description: string;
|
|
726
726
|
inputSchema: {
|
|
727
|
-
required?: undefined;
|
|
728
727
|
type: string;
|
|
729
728
|
properties: {
|
|
730
729
|
playlist?: undefined;
|
|
@@ -863,12 +862,12 @@ export declare const STATION_TOOLS: ({
|
|
|
863
862
|
id?: undefined;
|
|
864
863
|
private?: undefined;
|
|
865
864
|
};
|
|
865
|
+
required?: undefined;
|
|
866
866
|
};
|
|
867
867
|
} | {
|
|
868
868
|
name: string;
|
|
869
869
|
description: string;
|
|
870
870
|
inputSchema: {
|
|
871
|
-
required?: undefined;
|
|
872
871
|
type: string;
|
|
873
872
|
properties: {
|
|
874
873
|
playlist?: undefined;
|
|
@@ -961,12 +960,12 @@ export declare const STATION_TOOLS: ({
|
|
|
961
960
|
license?: undefined;
|
|
962
961
|
private?: undefined;
|
|
963
962
|
};
|
|
963
|
+
required?: undefined;
|
|
964
964
|
};
|
|
965
965
|
} | {
|
|
966
966
|
name: string;
|
|
967
967
|
description: string;
|
|
968
968
|
inputSchema: {
|
|
969
|
-
required?: undefined;
|
|
970
969
|
type: string;
|
|
971
970
|
properties: {
|
|
972
971
|
playlist?: undefined;
|
|
@@ -1061,6 +1060,7 @@ export declare const STATION_TOOLS: ({
|
|
|
1061
1060
|
};
|
|
1062
1061
|
private?: undefined;
|
|
1063
1062
|
};
|
|
1063
|
+
required?: undefined;
|
|
1064
1064
|
};
|
|
1065
1065
|
} | {
|
|
1066
1066
|
name: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nixamp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.76.1",
|
|
4
4
|
"description": "It really whips the terminal's ass. A Winamp-shaped audio player for your terminal.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"@profullstack/hqtui": "^0.5.0",
|
|
50
50
|
"@profullstack/live-translate": "^0.3.0",
|
|
51
51
|
"@profullstack/notifications": "^0.1.0",
|
|
52
|
+
"@profullstack/profile": "0.1.3",
|
|
52
53
|
"@profullstack/synconfig": "^0.1.2",
|
|
53
54
|
"@profullstack/throttle": "^0.3.3",
|
|
54
55
|
"@profullstack/x402-gateway": "^0.11.0",
|