open-secrets-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.
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # Open Secrets SDK
2
+
3
+ A decentralized protocol for anonymous confessions, built on Nostr.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install open-secrets-sdk
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Creating a Post
14
+
15
+ ```typescript
16
+ import { createOpenSecretsTags } from 'open-secrets-sdk';
17
+
18
+ const tags = createOpenSecretsTags({
19
+ lang: 'en',
20
+ gender: 'female',
21
+ age: 25,
22
+ country: 'US',
23
+ client: 'my-awesome-app'
24
+ });
25
+
26
+ // Use with nostr-tools
27
+ const event = {
28
+ kind: 1,
29
+ content: "This is my secret...",
30
+ tags: tags,
31
+ created_at: Math.floor(Date.now() / 1000)
32
+ };
33
+ ```
34
+
35
+ ### Parsing metadata
36
+
37
+ ```typescript
38
+ import { parseOpenSecretsTags } from 'open-secrets-sdk';
39
+
40
+ const metadata = parseOpenSecretsTags(event.tags);
41
+ console.log(metadata.gender); // 'female'
42
+ console.log(metadata.client); // 'my-awesome-app'
43
+ ```
44
+
45
+ ### Fetching posts
46
+
47
+ ```typescript
48
+ import { getOpenSecretsFilter } from 'open-secrets-sdk';
49
+
50
+ const filter = getOpenSecretsFilter(100);
51
+ // Query your favorite relays...
52
+ ```
53
+
54
+ ## Protocol Details
55
+
56
+ Open Secrets uses Nostr Kind 1 events with specific tags:
57
+
58
+ - `#t`: `open-secrets` (The gatekeeper tag)
59
+ - `#l`: Used for namespaced metadata (gender, age, country, lang, etc.)
60
+ - `client`: Identifies the originating application.
61
+ - `content-warning`: Standard Nostr tag for NSFW content.
62
+
63
+ ## License
64
+
65
+ MIT
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Open Secrets Protocol SDK
3
+ * A decentralized protocol for anonymous confessions on Nostr.
4
+ */
5
+ declare const OPEN_SECRETS_TAG = "open-secrets";
6
+ declare const OPEN_SECRETS_NAMESPACE = "open-secrets";
7
+ declare const DEFAULT_RELAYS: string[];
8
+ interface OpenSecretsOptions {
9
+ externalId?: string;
10
+ gender?: string;
11
+ age?: string | number;
12
+ country?: string;
13
+ lang?: string;
14
+ client?: string;
15
+ isNsfw?: boolean;
16
+ }
17
+ interface OpenSecretsMetadata {
18
+ externalId?: string;
19
+ gender?: string;
20
+ age?: string;
21
+ country?: string;
22
+ lang?: string;
23
+ client?: string;
24
+ isNsfw: boolean;
25
+ }
26
+ /**
27
+ * Generates the tags for an Open Secrets post (Nostr Kind 1)
28
+ */
29
+ declare function createOpenSecretsTags(options?: OpenSecretsOptions): string[][];
30
+ /**
31
+ * Parses tags from a Nostr event into Open Secrets metadata
32
+ */
33
+ declare function parseOpenSecretsTags(tags: string[][]): OpenSecretsMetadata;
34
+ /**
35
+ * Generates a Nostr filter for fetching Open Secrets posts
36
+ */
37
+ declare function getOpenSecretsFilter(limit?: number): {
38
+ kinds: number[];
39
+ '#t': string[];
40
+ limit: number;
41
+ };
42
+
43
+ export { DEFAULT_RELAYS, OPEN_SECRETS_NAMESPACE, OPEN_SECRETS_TAG, type OpenSecretsMetadata, type OpenSecretsOptions, createOpenSecretsTags, getOpenSecretsFilter, parseOpenSecretsTags };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Open Secrets Protocol SDK
3
+ * A decentralized protocol for anonymous confessions on Nostr.
4
+ */
5
+ declare const OPEN_SECRETS_TAG = "open-secrets";
6
+ declare const OPEN_SECRETS_NAMESPACE = "open-secrets";
7
+ declare const DEFAULT_RELAYS: string[];
8
+ interface OpenSecretsOptions {
9
+ externalId?: string;
10
+ gender?: string;
11
+ age?: string | number;
12
+ country?: string;
13
+ lang?: string;
14
+ client?: string;
15
+ isNsfw?: boolean;
16
+ }
17
+ interface OpenSecretsMetadata {
18
+ externalId?: string;
19
+ gender?: string;
20
+ age?: string;
21
+ country?: string;
22
+ lang?: string;
23
+ client?: string;
24
+ isNsfw: boolean;
25
+ }
26
+ /**
27
+ * Generates the tags for an Open Secrets post (Nostr Kind 1)
28
+ */
29
+ declare function createOpenSecretsTags(options?: OpenSecretsOptions): string[][];
30
+ /**
31
+ * Parses tags from a Nostr event into Open Secrets metadata
32
+ */
33
+ declare function parseOpenSecretsTags(tags: string[][]): OpenSecretsMetadata;
34
+ /**
35
+ * Generates a Nostr filter for fetching Open Secrets posts
36
+ */
37
+ declare function getOpenSecretsFilter(limit?: number): {
38
+ kinds: number[];
39
+ '#t': string[];
40
+ limit: number;
41
+ };
42
+
43
+ export { DEFAULT_RELAYS, OPEN_SECRETS_NAMESPACE, OPEN_SECRETS_TAG, type OpenSecretsMetadata, type OpenSecretsOptions, createOpenSecretsTags, getOpenSecretsFilter, parseOpenSecretsTags };
package/dist/index.js ADDED
@@ -0,0 +1,105 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/index.ts
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
+ DEFAULT_RELAYS: () => DEFAULT_RELAYS,
23
+ OPEN_SECRETS_NAMESPACE: () => OPEN_SECRETS_NAMESPACE,
24
+ OPEN_SECRETS_TAG: () => OPEN_SECRETS_TAG,
25
+ createOpenSecretsTags: () => createOpenSecretsTags,
26
+ getOpenSecretsFilter: () => getOpenSecretsFilter,
27
+ parseOpenSecretsTags: () => parseOpenSecretsTags
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+ var OPEN_SECRETS_TAG = "open-secrets";
31
+ var OPEN_SECRETS_NAMESPACE = "open-secrets";
32
+ var DEFAULT_RELAYS = ["wss://nos.lol", "wss://relay.damus.io", "wss://relay.snort.social"];
33
+ function createOpenSecretsTags(options = {}) {
34
+ const tags = [
35
+ ["t", OPEN_SECRETS_TAG]
36
+ ];
37
+ if (options.lang) {
38
+ tags.push(["l", options.lang]);
39
+ tags.push(["l", `lang:${options.lang}`, OPEN_SECRETS_NAMESPACE]);
40
+ }
41
+ if (options.externalId) {
42
+ tags.push(["i", `supabase:${options.externalId}`]);
43
+ }
44
+ if (options.gender) {
45
+ tags.push(["l", `gender:${options.gender}`, OPEN_SECRETS_NAMESPACE]);
46
+ }
47
+ if (options.age) {
48
+ tags.push(["l", `age:${options.age}`, OPEN_SECRETS_NAMESPACE]);
49
+ }
50
+ if (options.country) {
51
+ tags.push(["l", `country:${options.country}`, OPEN_SECRETS_NAMESPACE]);
52
+ }
53
+ if (options.client) {
54
+ tags.push(["client", options.client]);
55
+ }
56
+ if (options.isNsfw) {
57
+ tags.push(["l", "nsfw:true", OPEN_SECRETS_NAMESPACE]);
58
+ tags.push(["content-warning", "NSFW"]);
59
+ }
60
+ return tags;
61
+ }
62
+ function parseOpenSecretsTags(tags) {
63
+ var _a, _b, _c, _d;
64
+ const getLabel = (prefix) => {
65
+ const tag = tags.find(
66
+ (t) => {
67
+ var _a2;
68
+ return t[0] === "l" && ((_a2 = t[1]) == null ? void 0 : _a2.startsWith(`${prefix}:`)) && t[2] === OPEN_SECRETS_NAMESPACE;
69
+ }
70
+ );
71
+ return tag ? tag[1].split(":")[1] : void 0;
72
+ };
73
+ const langTag = (_a = tags.find((t) => {
74
+ var _a2;
75
+ return t[0] === "l" && ((_a2 = t[1]) == null ? void 0 : _a2.length) === 2;
76
+ })) == null ? void 0 : _a[1];
77
+ return {
78
+ externalId: (_c = (_b = tags.find((t) => {
79
+ var _a2;
80
+ return t[0] === "i" && ((_a2 = t[1]) == null ? void 0 : _a2.startsWith("supabase:"));
81
+ })) == null ? void 0 : _b[1]) == null ? void 0 : _c.split(":")[1],
82
+ gender: getLabel("gender"),
83
+ age: getLabel("age"),
84
+ country: getLabel("country"),
85
+ lang: getLabel("lang") || langTag,
86
+ client: (_d = tags.find((t) => t[0] === "client")) == null ? void 0 : _d[1],
87
+ isNsfw: tags.some((t) => t[0] === "content-warning" || t[0] === "l" && t[1] === "nsfw:true")
88
+ };
89
+ }
90
+ function getOpenSecretsFilter(limit = 100) {
91
+ return {
92
+ kinds: [1],
93
+ "#t": [OPEN_SECRETS_TAG],
94
+ limit
95
+ };
96
+ }
97
+ // Annotate the CommonJS export names for ESM import in node:
98
+ 0 && (module.exports = {
99
+ DEFAULT_RELAYS,
100
+ OPEN_SECRETS_NAMESPACE,
101
+ OPEN_SECRETS_TAG,
102
+ createOpenSecretsTags,
103
+ getOpenSecretsFilter,
104
+ parseOpenSecretsTags
105
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,76 @@
1
+ // src/index.ts
2
+ var OPEN_SECRETS_TAG = "open-secrets";
3
+ var OPEN_SECRETS_NAMESPACE = "open-secrets";
4
+ var DEFAULT_RELAYS = ["wss://nos.lol", "wss://relay.damus.io", "wss://relay.snort.social"];
5
+ function createOpenSecretsTags(options = {}) {
6
+ const tags = [
7
+ ["t", OPEN_SECRETS_TAG]
8
+ ];
9
+ if (options.lang) {
10
+ tags.push(["l", options.lang]);
11
+ tags.push(["l", `lang:${options.lang}`, OPEN_SECRETS_NAMESPACE]);
12
+ }
13
+ if (options.externalId) {
14
+ tags.push(["i", `supabase:${options.externalId}`]);
15
+ }
16
+ if (options.gender) {
17
+ tags.push(["l", `gender:${options.gender}`, OPEN_SECRETS_NAMESPACE]);
18
+ }
19
+ if (options.age) {
20
+ tags.push(["l", `age:${options.age}`, OPEN_SECRETS_NAMESPACE]);
21
+ }
22
+ if (options.country) {
23
+ tags.push(["l", `country:${options.country}`, OPEN_SECRETS_NAMESPACE]);
24
+ }
25
+ if (options.client) {
26
+ tags.push(["client", options.client]);
27
+ }
28
+ if (options.isNsfw) {
29
+ tags.push(["l", "nsfw:true", OPEN_SECRETS_NAMESPACE]);
30
+ tags.push(["content-warning", "NSFW"]);
31
+ }
32
+ return tags;
33
+ }
34
+ function parseOpenSecretsTags(tags) {
35
+ var _a, _b, _c, _d;
36
+ const getLabel = (prefix) => {
37
+ const tag = tags.find(
38
+ (t) => {
39
+ var _a2;
40
+ return t[0] === "l" && ((_a2 = t[1]) == null ? void 0 : _a2.startsWith(`${prefix}:`)) && t[2] === OPEN_SECRETS_NAMESPACE;
41
+ }
42
+ );
43
+ return tag ? tag[1].split(":")[1] : void 0;
44
+ };
45
+ const langTag = (_a = tags.find((t) => {
46
+ var _a2;
47
+ return t[0] === "l" && ((_a2 = t[1]) == null ? void 0 : _a2.length) === 2;
48
+ })) == null ? void 0 : _a[1];
49
+ return {
50
+ externalId: (_c = (_b = tags.find((t) => {
51
+ var _a2;
52
+ return t[0] === "i" && ((_a2 = t[1]) == null ? void 0 : _a2.startsWith("supabase:"));
53
+ })) == null ? void 0 : _b[1]) == null ? void 0 : _c.split(":")[1],
54
+ gender: getLabel("gender"),
55
+ age: getLabel("age"),
56
+ country: getLabel("country"),
57
+ lang: getLabel("lang") || langTag,
58
+ client: (_d = tags.find((t) => t[0] === "client")) == null ? void 0 : _d[1],
59
+ isNsfw: tags.some((t) => t[0] === "content-warning" || t[0] === "l" && t[1] === "nsfw:true")
60
+ };
61
+ }
62
+ function getOpenSecretsFilter(limit = 100) {
63
+ return {
64
+ kinds: [1],
65
+ "#t": [OPEN_SECRETS_TAG],
66
+ limit
67
+ };
68
+ }
69
+ export {
70
+ DEFAULT_RELAYS,
71
+ OPEN_SECRETS_NAMESPACE,
72
+ OPEN_SECRETS_TAG,
73
+ createOpenSecretsTags,
74
+ getOpenSecretsFilter,
75
+ parseOpenSecretsTags
76
+ };
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "open-secrets-sdk",
3
+ "version": "0.1.0",
4
+ "description": "SDK for the Open Secrets protocol on Nostr",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsup src/index.ts --format cjs,esm --dts",
13
+ "dev": "tsup src/index.ts --format cjs,esm --watch --dts",
14
+ "lint": "eslint src"
15
+ },
16
+ "keywords": [
17
+ "nostr",
18
+ "confessions",
19
+ "anonymous",
20
+ "protocol",
21
+ "open-secrets"
22
+ ],
23
+ "author": "",
24
+ "license": "MIT",
25
+ "devDependencies": {
26
+ "tsup": "^8.0.0",
27
+ "typescript": "^5.0.0"
28
+ },
29
+ "peerDependencies": {
30
+ "nostr-tools": "^2.0.0"
31
+ }
32
+ }