this.me 2.9.51 → 3.0.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 CHANGED
@@ -5,62 +5,102 @@
5
5
 
6
6
  <strong>.me</strong> is your identity that lives on your machine, under your control. It holds attributes, relationships, and keys that define who you are—and crucially, <strong>how you relate to others</strong>.
7
7
 
8
- Each <strong>.me</strong> instance can pair with other authorities or identities using its <strong>cryptographic keys</strong>, establishing <strong>trust through signatures and endorsements</strong>.
8
+ # Getting Started:
9
9
 
10
- Instead of logging in through third-party services, you can validate your identity or vouch for someone else’s using these key exchanges. This enables a decentralized trust model where relationships are verifiable, persistent, and portable.
10
+ You can use **this.me** both in the browser and in Node environments. The library automatically detects the environment and provides a single global instance of `me` once initialized.
11
11
 
12
- # Getting Started:
13
- 1. ##### **Install `this.me`:**
14
- Open your terminal and run the following command to install the `this.me` package:
15
- ```js
16
- npm i -g this.me
17
- ```
12
+ ### **1. Installation**
18
13
 
19
- 2. **Run this command on your terminal:**
14
+ If you are using npm:
20
15
 
21
- ```bash
22
- me
23
- ```
16
+ ```bash
17
+ npm install this.me
18
+ ```
24
19
 
25
- The **Me** class represents a **persistent identity**, stored as an encrypted file (username.me) in ~/.this/me. This file contains:
26
- - An identifier (username)
27
- - Keys (private/public — currently placeholders)
28
- - User-defined attributes
29
- - Relationships and other social elements (reactions, attributies, properties, endorsements...)
20
+ Or load it directly in the browser (after building):
30
21
 
31
- It can be **created**, **read** (if you have the correct hash), **modified in memory**, and then **saved again** in encrypted form.
22
+ ```html
23
+ <script src="this.me.umd.js"></script>
24
+ <script>
25
+ // Global instance automatically attached to `window.me`
26
+ console.log(me); // Ready to use after initialization
27
+ </script>
28
+ ```
32
29
 
33
- # Command Line Options:
30
+ ---
34
31
 
35
- **Run this commands on your terminal:**
32
+ ### **2. Initialization**
36
33
 
37
- ```bash
38
- me create
34
+ You need to initialize the `.me` instance before using it:
35
+
36
+ ```js
37
+ import me from "this.me";
38
+
39
+ await me.init({
40
+ monadEndpoint: "http://localhost:7777" // optional, defaults to 7777
41
+ });
39
42
  ```
40
43
 
41
- - **Description**: Creates a new .me identity.
42
- - **Flow**: Prompts for username and hash (secret key), then saves an encrypted file at ~/.this/me/username.me.
44
+ Once initialized, the `me` instance will maintain its state (status, loaded identities, etc.) globally.
43
45
 
44
- ------
46
+ ---
45
47
 
46
- ```bash
47
- me show [username]
48
+ ### **3. Checking Daemon Status**
49
+
50
+ You can verify if the local daemon is running:
51
+
52
+ ```js
53
+ const status = await me.status();
54
+ console.log("Daemon active:", status.active);
48
55
  ```
49
56
 
50
- - **Description**: Shows the decrypted contents of an identity.
51
- - **Flow**:
52
- - If [username] is not provided, it prompts for it.
53
- - Always prompts for the hash to unlock the identity.
54
- - If successful, prints the identity as JSON.
57
+ The floating components or any GUI indicators (green/red) can rely directly on `me.status()`.
55
58
 
56
- ------
59
+ ---
57
60
 
58
- ```bash
59
- me list
61
+ ### **4. Listing Identities**
62
+
63
+ ```js
64
+ const list = await me.listUs();
65
+ console.log(list);
66
+ /*
67
+ [
68
+ { alias: "suign", path: "/Users/abellae/.this/me/suign" }
69
+ ]
70
+ */
71
+ ```
72
+
73
+ ---
74
+
75
+ ### **5. Loading an Identity**
76
+
77
+ ```js
78
+ await me.load("abellae", "mySecretHash");
79
+ console.log(me.active); // true if identity is successfully loaded
60
80
  ```
61
81
 
62
- - **Description**: Lists all local .me identities.
63
- - **Flow**: Reads the ~/.this/me directory and prints all .me files (usernames).
82
+ After loading, you can use all available methods (`be`, `have`, `do`, etc.).
83
+
84
+ ---
85
+
86
+ ### **6. Example in the Browser Console**
87
+
88
+ If you include the UMD bundle:
89
+
90
+ ```html
91
+ <script src="this.me.umd.js"></script>
92
+ <script>
93
+ (async () => {
94
+ await me.init();
95
+ console.log(await me.status());
96
+ console.log(await me.listUs());
97
+ })();
98
+ </script>
99
+ ```
100
+
101
+ - `me` is a **singleton instance** that lives in memory once initialized.
102
+ - Works in both browser and Node.
103
+ - Provides methods for status, identity management, and attribute handling.
64
104
 
65
105
  ------
66
106
 
@@ -118,18 +158,6 @@ Once unlocked, you can:
118
158
 
119
159
  ------
120
160
 
121
- #### Locking the identity
122
-
123
- You can clear the identity from memory with:
124
-
125
- ```js
126
- me.lock();
127
- ```
128
-
129
- This keeps the encrypted file on disk but removes all data from RAM.
130
-
131
- ------
132
-
133
161
  ### **Summary**
134
162
 
135
163
  - Your identity is encrypted on your own machine.
@@ -150,25 +178,6 @@ Let me know if you’d like a diagram or visual flow to go with this explanation
150
178
  3. **Local Ownership**
151
179
  All sensitive data (including private keys) stays on the user's machine.
152
180
 
153
- ---
154
- ### 📁 File Structure
155
- * `~/.this/me/username.me.json` — Encrypted identity file
156
- * `.me` includes:
157
-
158
- * `username`
159
- * `publicKey`, `privateKey` (encrypted)
160
- * `attributes`, `relationships`, `reactions`, `properties`, `relationships`
161
- * `endorsements`
162
-
163
- ---
164
- ### 🔐 Cryptographic Model
165
- * Identity is unlocked using a user-defined `hash` (password).
166
- * This hash decrypts the local `.me` file.
167
- * The identity includes:
168
-
169
- * A **key pair** (public/private) for signing and verification.
170
- * Optional **endorsements** signed by Cleaker or other authorities.
171
-
172
181
  ---
173
182
  ### 🛡️ Security Model
174
183
  * No private key ever leaves the local `.me` file.
@@ -180,17 +189,6 @@ Let me know if you’d like a diagram or visual flow to go with this explanation
180
189
  * `.me` can be restored using a seed phrase or backup.
181
190
  * New devices can be authorized using signatures from old devices.
182
191
 
183
- ---
184
- ## ⚖️ Responsibilities
185
- * **this.me**
186
- * Local file management, encryption, signing.
187
- * CLI + API for usage.
188
-
189
- * **Cleaker / Authorities**
190
-
191
- * Store trusted records of `username` + `publicKey`
192
- * Provide validation/endorsement services.
193
-
194
192
  ---
195
193
  ## 🌍 Use Cases
196
194
  * Digital signature of documents
@@ -199,9 +197,6 @@ Let me know if you’d like a diagram or visual flow to go with this explanation
199
197
  * Group identity and shared contexts (`me && you && them in context/friends`)
200
198
 
201
199
  ---
202
- By default, **this.me** uses the **local file system (~/.this/me/)** to store and manage identity data.
203
- No external service is required.
204
-
205
200
  <img src="https://suign.github.io/assets/imgs/monads.png" alt="Cleak Me Please" width="244">Hello, I am **.me**
206
201
 
207
202
  ### ❯ add.me
@@ -0,0 +1,55 @@
1
+ "use strict";class c{constructor(t,s){this.me=t,this.url=s,this.ws=null,this.reconnectInterval=1e4,this.isConnected=!1,this.connect()}connect(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{console.log("[this.me][WS] Connected to daemon"),this.isConnected=!0,this.me.state?.status&&(this.me.state.status.active=!0,this.me.state.status.error=!1),this.#t()},this.ws.onmessage=t=>{try{const s=JSON.parse(t.data);this.#s(s)}catch{console.warn("[this.me][WS] Invalid message:",t.data)}},this.ws.onclose=()=>{console.warn("[this.me][WS] Disconnected, retrying in 10s"),this.isConnected=!1,this.me.state?.status&&(this.me.state.status.active=!1,this.me.state.status.error=!0),this.#t(),setTimeout(()=>this.connect(),this.reconnectInterval)},this.ws.onerror=t=>{console.error("[this.me][WS] Error:",t),this.ws.close()}}#s(t){switch(t.type){case"status":this.me.state.status={active:t.data.active,error:!1,data:t.data};break;case"listUs":this.me.state.listUs=t.data;break;case"update":console.log("[this.me][WS] Update event:",t.data);break;default:console.warn("[this.me][WS] Unknown message type:",t.type)}this.#t()}send(t,s){this.isConnected&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify({type:t,data:s}))}#t(){this.me.subscribers?.size&&this.me.subscribers.forEach(t=>t(this.me.state))}}class u{constructor(t="http://localhost:7777/graphql"){this.endpoint=t,this.state={status:{active:!1,error:!1,loading:!0,data:null},listUs:[],activeMe:null},this.subscribers=new Set,this.status(),this.socket=null}async init(){return this.#s({status:{...this.state.status,loading:!0}}),(await this.status()).active&&(await this.startSocket(),await new Promise(s=>{let a=!1;const e=this.subscribe(i=>{!a&&i.status.active!==void 0&&(a=!0,e(),s())});setTimeout(()=>{a||(a=!0,e(),s())},2e3)})),this.#s({status:{...this.state.status,loading:!1}}),this.state.status}async startSocket(){if(this.state.status.active){if(this.socket){console.warn("[this.me] WebSocket already running");return}this.socket=new c(this.endpoint.replace("/graphql","")),this.socket.on("status",t=>{this._updateFromSocket({status:{active:!0,error:!1,data:t}})}),this.socket.on("listUs",t=>{this._updateFromSocket({listUs:t})}),this.socket.on("update",t=>{console.log("[this.me] update event",t)})}}_updateFromSocket(t){this.#s(t)}setEndpoint(t){typeof t=="string"&&t.trim()!==""&&(this.endpoint=t)}getState(){return this.state}#s(t){this.state={...this.state,...t},this.subscribers.forEach(s=>s(this.state))}subscribe(t){return this.subscribers.add(t),()=>this.subscribers.delete(t)}async#t(t,s={}){const a=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({query:t,variables:s})});if(!a.ok)throw new Error(`GraphQL error: ${a.status}`);const{data:e,errors:i}=await a.json();if(i)throw new Error(i.map(o=>o.message).join(", "));return e}async status(){const t=`
2
+ query {
3
+ status {
4
+ active
5
+ version
6
+ uptime
7
+ }
8
+ }
9
+ `;try{const s=await this.#t(t),a=s.status?{active:s.status.active,version:s.status.version,uptime:s.status.uptime}:{active:!1,version:null,uptime:null};return this.#s({status:{active:a.active,error:!1,data:a}}),a}catch{const s={active:!1,version:null,uptime:null};return this.#s({status:{active:!1,error:!0,data:null}}),s}}async listUs(){const t=`
10
+ query {
11
+ listUs {
12
+ alias
13
+ path
14
+ }
15
+ }
16
+ `;try{const s=await this.#t(t),a=Array.isArray(s.listUs)?s.listUs.map(({alias:e,path:i})=>({alias:e,path:i})):[];return this.#s({listUs:a}),a}catch{return this.#s({listUs:[]}),[]}}async loadMe(t,s){const a=`
17
+ mutation($alias: String!, $hash: String!) {
18
+ loadMe(alias: $alias, hash: $hash)
19
+ }
20
+ `;try{const i=!!(await this.#t(a,{alias:t,hash:s})).loadMe;return i&&this.#s({activeMe:t}),i}catch{return!1}}async be(t,s,a){const e=`
21
+ mutation($alias: String!, $key: String!, $value: String!) {
22
+ be(alias: $alias, key: $key, value: $value)
23
+ }
24
+ `;try{return!!(await this.#t(e,{alias:t,key:s,value:a})).be}catch{return!1}}async have(t,s,a){const e=`
25
+ mutation($alias: String!, $key: String!, $value: String!) {
26
+ have(alias: $alias, key: $key, value: $value)
27
+ }
28
+ `;try{return!!(await this.#t(e,{alias:t,key:s,value:a})).have}catch{return!1}}async do_(t,s,a){const e=`
29
+ mutation($alias: String!, $key: String!, $value: String!) {
30
+ do(alias: $alias, key: $key, value: $value)
31
+ }
32
+ `;try{return!!(await this.#t(e,{alias:t,key:s,value:a})).do}catch{return!1}}async at(t,s,a){const e=`
33
+ mutation($alias: String!, $key: String!, $value: String!) {
34
+ at(alias: $alias, key: $key, value: $value)
35
+ }
36
+ `;try{return!!(await this.#t(e,{alias:t,key:s,value:a})).at}catch{return!1}}async relate(t,s,a){const e=`
37
+ mutation($alias: String!, $key: String!, $value: String!) {
38
+ relate(alias: $alias, key: $key, value: $value)
39
+ }
40
+ `;try{return!!(await this.#t(e,{alias:t,key:s,value:a})).relate}catch{return!1}}async react(t,s,a){const e=`
41
+ mutation($alias: String!, $key: String!, $value: String!) {
42
+ react(alias: $alias, key: $key, value: $value)
43
+ }
44
+ `;try{return!!(await this.#t(e,{alias:t,key:s,value:a})).react}catch{return!1}}async communication(t,s,a){const e=`
45
+ mutation($alias: String!, $key: String!, $value: String!) {
46
+ communication(alias: $alias, key: $key, value: $value)
47
+ }
48
+ `;try{return!!(await this.#t(e,{alias:t,key:s,value:a})).communication}catch{return!1}}async me(t){const s=`
49
+ query($alias: String!) {
50
+ me(alias: $alias) {
51
+ alias
52
+ publicKey
53
+ }
54
+ }
55
+ `;try{const a=await this.#t(s,{alias:t});if(a.me&&typeof a.me=="object"){const{alias:e,publicKey:i}=a.me;return e&&i?{alias:e,publicKey:i}:null}return null}catch{return null}}}const n=new u;typeof window<"u"&&(window.me=n,console.log("[this.me] Global instance available as window.me"));module.exports=n;
@@ -0,0 +1,324 @@
1
+ class o {
2
+ constructor(t, s) {
3
+ this.me = t, this.url = s, this.ws = null, this.reconnectInterval = 1e4, this.isConnected = !1, this.connect();
4
+ }
5
+ connect() {
6
+ this.ws = new WebSocket(this.url), this.ws.onopen = () => {
7
+ console.log("[this.me][WS] Connected to daemon"), this.isConnected = !0, this.me.state?.status && (this.me.state.status.active = !0, this.me.state.status.error = !1), this.#t();
8
+ }, this.ws.onmessage = (t) => {
9
+ try {
10
+ const s = JSON.parse(t.data);
11
+ this.#s(s);
12
+ } catch {
13
+ console.warn("[this.me][WS] Invalid message:", t.data);
14
+ }
15
+ }, this.ws.onclose = () => {
16
+ console.warn("[this.me][WS] Disconnected, retrying in 10s"), this.isConnected = !1, this.me.state?.status && (this.me.state.status.active = !1, this.me.state.status.error = !0), this.#t(), setTimeout(() => this.connect(), this.reconnectInterval);
17
+ }, this.ws.onerror = (t) => {
18
+ console.error("[this.me][WS] Error:", t), this.ws.close();
19
+ };
20
+ }
21
+ #s(t) {
22
+ switch (t.type) {
23
+ case "status":
24
+ this.me.state.status = {
25
+ active: t.data.active,
26
+ error: !1,
27
+ data: t.data
28
+ };
29
+ break;
30
+ case "listUs":
31
+ this.me.state.listUs = t.data;
32
+ break;
33
+ case "update":
34
+ console.log("[this.me][WS] Update event:", t.data);
35
+ break;
36
+ default:
37
+ console.warn("[this.me][WS] Unknown message type:", t.type);
38
+ }
39
+ this.#t();
40
+ }
41
+ send(t, s) {
42
+ this.isConnected && this.ws.readyState === WebSocket.OPEN && this.ws.send(JSON.stringify({ type: t, data: s }));
43
+ }
44
+ #t() {
45
+ this.me.subscribers?.size && this.me.subscribers.forEach((t) => t(this.me.state));
46
+ }
47
+ }
48
+ class c {
49
+ constructor(t = "http://localhost:7777/graphql") {
50
+ this.endpoint = t, this.state = {
51
+ status: { active: !1, error: !1, loading: !0, data: null },
52
+ listUs: [],
53
+ activeMe: null
54
+ }, this.subscribers = /* @__PURE__ */ new Set(), this.status(), this.socket = null;
55
+ }
56
+ /** 🔹 Init
57
+ * Manually initializes the daemon state (status + listUs).
58
+ * Useful if you need to re-check after user actions.
59
+ */
60
+ async init() {
61
+ return this.#s({
62
+ status: { ...this.state.status, loading: !0 }
63
+ }), (await this.status()).active && (await this.startSocket(), await new Promise((s) => {
64
+ let a = !1;
65
+ const e = this.subscribe((i) => {
66
+ !a && i.status.active !== void 0 && (a = !0, e(), s());
67
+ });
68
+ setTimeout(() => {
69
+ a || (a = !0, e(), s());
70
+ }, 2e3);
71
+ })), this.#s({
72
+ status: { ...this.state.status, loading: !1 }
73
+ }), this.state.status;
74
+ }
75
+ async startSocket() {
76
+ if (this.state.status.active) {
77
+ if (this.socket) {
78
+ console.warn("[this.me] WebSocket already running");
79
+ return;
80
+ }
81
+ this.socket = new o(this.endpoint.replace("/graphql", "")), this.socket.on("status", (t) => {
82
+ this._updateFromSocket({
83
+ status: { active: !0, error: !1, data: t }
84
+ });
85
+ }), this.socket.on("listUs", (t) => {
86
+ this._updateFromSocket({ listUs: t });
87
+ }), this.socket.on("update", (t) => {
88
+ console.log("[this.me] update event", t);
89
+ });
90
+ }
91
+ }
92
+ _updateFromSocket(t) {
93
+ this.#s(t);
94
+ }
95
+ setEndpoint(t) {
96
+ typeof t == "string" && t.trim() !== "" && (this.endpoint = t);
97
+ }
98
+ getState() {
99
+ return this.state;
100
+ }
101
+ #s(t) {
102
+ this.state = { ...this.state, ...t }, this.subscribers.forEach((s) => s(this.state));
103
+ }
104
+ subscribe(t) {
105
+ return this.subscribers.add(t), () => this.subscribers.delete(t);
106
+ }
107
+ async #t(t, s = {}) {
108
+ const a = await fetch(this.endpoint, {
109
+ method: "POST",
110
+ headers: { "Content-Type": "application/json" },
111
+ body: JSON.stringify({ query: t, variables: s })
112
+ });
113
+ if (!a.ok) throw new Error(`GraphQL error: ${a.status}`);
114
+ const { data: e, errors: i } = await a.json();
115
+ if (i) throw new Error(i.map((r) => r.message).join(", "));
116
+ return e;
117
+ }
118
+ // 🔹 Daemon-level helpers
119
+ /** 🔹 Daemon status
120
+ * Retrieves the current status of the daemon.
121
+ * Use to check if the service is active and get version/uptime info.
122
+ */
123
+ async status() {
124
+ const t = `
125
+ query {
126
+ status {
127
+ active
128
+ version
129
+ uptime
130
+ }
131
+ }
132
+ `;
133
+ try {
134
+ const s = await this.#t(t), a = s.status ? {
135
+ active: s.status.active,
136
+ version: s.status.version,
137
+ uptime: s.status.uptime
138
+ } : { active: !1, version: null, uptime: null };
139
+ return this.#s({ status: { active: a.active, error: !1, data: a } }), a;
140
+ } catch {
141
+ const s = { active: !1, version: null, uptime: null };
142
+ return this.#s({ status: { active: !1, error: !0, data: null } }), s;
143
+ }
144
+ }
145
+ /** 🔹 List all identities
146
+ * Fetches all available identities (users).
147
+ * Use to display or manage the list of identities.
148
+ */
149
+ async listUs() {
150
+ const t = `
151
+ query {
152
+ listUs {
153
+ alias
154
+ path
155
+ }
156
+ }
157
+ `;
158
+ try {
159
+ const s = await this.#t(t), a = Array.isArray(s.listUs) ? s.listUs.map(({ alias: e, path: i }) => ({ alias: e, path: i })) : [];
160
+ return this.#s({ listUs: a }), a;
161
+ } catch {
162
+ return this.#s({ listUs: [] }), [];
163
+ }
164
+ }
165
+ /** 🔹 Load an identity
166
+ * Loads a specific identity by alias and hash.
167
+ * Use to activate or switch to a particular identity.
168
+ */
169
+ async loadMe(t, s) {
170
+ const a = `
171
+ mutation($alias: String!, $hash: String!) {
172
+ loadMe(alias: $alias, hash: $hash)
173
+ }
174
+ `;
175
+ try {
176
+ const i = !!(await this.#t(a, { alias: t, hash: s })).loadMe;
177
+ return i && this.#s({ activeMe: t }), i;
178
+ } catch {
179
+ return !1;
180
+ }
181
+ }
182
+ // 🔹 Me-level operations
183
+ /** 🔹 Be operation
184
+ * Performs a 'be' mutation for given alias, key, and value.
185
+ * Use to set or update identity attributes.
186
+ */
187
+ async be(t, s, a) {
188
+ const e = `
189
+ mutation($alias: String!, $key: String!, $value: String!) {
190
+ be(alias: $alias, key: $key, value: $value)
191
+ }
192
+ `;
193
+ try {
194
+ return !!(await this.#t(e, { alias: t, key: s, value: a })).be;
195
+ } catch {
196
+ return !1;
197
+ }
198
+ }
199
+ /** 🔹 Have operation
200
+ * Performs a 'have' mutation for given alias, key, and value.
201
+ * Use to declare possession or ownership related to identity.
202
+ */
203
+ async have(t, s, a) {
204
+ const e = `
205
+ mutation($alias: String!, $key: String!, $value: String!) {
206
+ have(alias: $alias, key: $key, value: $value)
207
+ }
208
+ `;
209
+ try {
210
+ return !!(await this.#t(e, { alias: t, key: s, value: a })).have;
211
+ } catch {
212
+ return !1;
213
+ }
214
+ }
215
+ /** 🔹 Do operation
216
+ * Performs a 'do' mutation for given alias, key, and value.
217
+ * Use to record actions or activities for the identity.
218
+ */
219
+ async do_(t, s, a) {
220
+ const e = `
221
+ mutation($alias: String!, $key: String!, $value: String!) {
222
+ do(alias: $alias, key: $key, value: $value)
223
+ }
224
+ `;
225
+ try {
226
+ return !!(await this.#t(e, { alias: t, key: s, value: a })).do;
227
+ } catch {
228
+ return !1;
229
+ }
230
+ }
231
+ /** 🔹 At operation
232
+ * Performs an 'at' mutation for given alias, key, and value.
233
+ * Use to set location or context related data for the identity.
234
+ */
235
+ async at(t, s, a) {
236
+ const e = `
237
+ mutation($alias: String!, $key: String!, $value: String!) {
238
+ at(alias: $alias, key: $key, value: $value)
239
+ }
240
+ `;
241
+ try {
242
+ return !!(await this.#t(e, { alias: t, key: s, value: a })).at;
243
+ } catch {
244
+ return !1;
245
+ }
246
+ }
247
+ /** 🔹 Relate operation
248
+ * Performs a 'relate' mutation for given alias, key, and value.
249
+ * Use to define relationships or connections for the identity.
250
+ */
251
+ async relate(t, s, a) {
252
+ const e = `
253
+ mutation($alias: String!, $key: String!, $value: String!) {
254
+ relate(alias: $alias, key: $key, value: $value)
255
+ }
256
+ `;
257
+ try {
258
+ return !!(await this.#t(e, { alias: t, key: s, value: a })).relate;
259
+ } catch {
260
+ return !1;
261
+ }
262
+ }
263
+ /** 🔹 React operation
264
+ * Performs a 'react' mutation for given alias, key, and value.
265
+ * Use to record reactions or responses by the identity.
266
+ */
267
+ async react(t, s, a) {
268
+ const e = `
269
+ mutation($alias: String!, $key: String!, $value: String!) {
270
+ react(alias: $alias, key: $key, value: $value)
271
+ }
272
+ `;
273
+ try {
274
+ return !!(await this.#t(e, { alias: t, key: s, value: a })).react;
275
+ } catch {
276
+ return !1;
277
+ }
278
+ }
279
+ /** 🔹 Communication operation
280
+ * Performs a 'communication' mutation for given alias, key, and value.
281
+ * Use to log communications or messages for the identity.
282
+ */
283
+ async communication(t, s, a) {
284
+ const e = `
285
+ mutation($alias: String!, $key: String!, $value: String!) {
286
+ communication(alias: $alias, key: $key, value: $value)
287
+ }
288
+ `;
289
+ try {
290
+ return !!(await this.#t(e, { alias: t, key: s, value: a })).communication;
291
+ } catch {
292
+ return !1;
293
+ }
294
+ }
295
+ /** 🔹 Get identity info
296
+ * Queries detailed information about a specific identity by alias.
297
+ * Use to retrieve public data like alias and publicKey.
298
+ */
299
+ async me(t) {
300
+ const s = `
301
+ query($alias: String!) {
302
+ me(alias: $alias) {
303
+ alias
304
+ publicKey
305
+ }
306
+ }
307
+ `;
308
+ try {
309
+ const a = await this.#t(s, { alias: t });
310
+ if (a.me && typeof a.me == "object") {
311
+ const { alias: e, publicKey: i } = a.me;
312
+ return e && i ? { alias: e, publicKey: i } : null;
313
+ }
314
+ return null;
315
+ } catch {
316
+ return null;
317
+ }
318
+ }
319
+ }
320
+ const u = new c();
321
+ typeof window < "u" && (window.me = u, console.log("[this.me] Global instance available as window.me"));
322
+ export {
323
+ u as default
324
+ };
@@ -0,0 +1,55 @@
1
+ (function(n,r){typeof exports=="object"&&typeof module<"u"?module.exports=r():typeof define=="function"&&define.amd?define(r):(n=typeof globalThis<"u"?globalThis:n||self,n.Me=r())})(this,function(){"use strict";class n{constructor(t,s){this.me=t,this.url=s,this.ws=null,this.reconnectInterval=1e4,this.isConnected=!1,this.connect()}connect(){this.ws=new WebSocket(this.url),this.ws.onopen=()=>{console.log("[this.me][WS] Connected to daemon"),this.isConnected=!0,this.me.state?.status&&(this.me.state.status.active=!0,this.me.state.status.error=!1),this.#t()},this.ws.onmessage=t=>{try{const s=JSON.parse(t.data);this.#s(s)}catch{console.warn("[this.me][WS] Invalid message:",t.data)}},this.ws.onclose=()=>{console.warn("[this.me][WS] Disconnected, retrying in 10s"),this.isConnected=!1,this.me.state?.status&&(this.me.state.status.active=!1,this.me.state.status.error=!0),this.#t(),setTimeout(()=>this.connect(),this.reconnectInterval)},this.ws.onerror=t=>{console.error("[this.me][WS] Error:",t),this.ws.close()}}#s(t){switch(t.type){case"status":this.me.state.status={active:t.data.active,error:!1,data:t.data};break;case"listUs":this.me.state.listUs=t.data;break;case"update":console.log("[this.me][WS] Update event:",t.data);break;default:console.warn("[this.me][WS] Unknown message type:",t.type)}this.#t()}send(t,s){this.isConnected&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify({type:t,data:s}))}#t(){this.me.subscribers?.size&&this.me.subscribers.forEach(t=>t(this.me.state))}}class r{constructor(t="http://localhost:7777/graphql"){this.endpoint=t,this.state={status:{active:!1,error:!1,loading:!0,data:null},listUs:[],activeMe:null},this.subscribers=new Set,this.status(),this.socket=null}async init(){return this.#s({status:{...this.state.status,loading:!0}}),(await this.status()).active&&(await this.startSocket(),await new Promise(s=>{let e=!1;const a=this.subscribe(i=>{!e&&i.status.active!==void 0&&(e=!0,a(),s())});setTimeout(()=>{e||(e=!0,a(),s())},2e3)})),this.#s({status:{...this.state.status,loading:!1}}),this.state.status}async startSocket(){if(this.state.status.active){if(this.socket){console.warn("[this.me] WebSocket already running");return}this.socket=new n(this.endpoint.replace("/graphql","")),this.socket.on("status",t=>{this._updateFromSocket({status:{active:!0,error:!1,data:t}})}),this.socket.on("listUs",t=>{this._updateFromSocket({listUs:t})}),this.socket.on("update",t=>{console.log("[this.me] update event",t)})}}_updateFromSocket(t){this.#s(t)}setEndpoint(t){typeof t=="string"&&t.trim()!==""&&(this.endpoint=t)}getState(){return this.state}#s(t){this.state={...this.state,...t},this.subscribers.forEach(s=>s(this.state))}subscribe(t){return this.subscribers.add(t),()=>this.subscribers.delete(t)}async#t(t,s={}){const e=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({query:t,variables:s})});if(!e.ok)throw new Error(`GraphQL error: ${e.status}`);const{data:a,errors:i}=await e.json();if(i)throw new Error(i.map(u=>u.message).join(", "));return a}async status(){const t=`
2
+ query {
3
+ status {
4
+ active
5
+ version
6
+ uptime
7
+ }
8
+ }
9
+ `;try{const s=await this.#t(t),e=s.status?{active:s.status.active,version:s.status.version,uptime:s.status.uptime}:{active:!1,version:null,uptime:null};return this.#s({status:{active:e.active,error:!1,data:e}}),e}catch{const s={active:!1,version:null,uptime:null};return this.#s({status:{active:!1,error:!0,data:null}}),s}}async listUs(){const t=`
10
+ query {
11
+ listUs {
12
+ alias
13
+ path
14
+ }
15
+ }
16
+ `;try{const s=await this.#t(t),e=Array.isArray(s.listUs)?s.listUs.map(({alias:a,path:i})=>({alias:a,path:i})):[];return this.#s({listUs:e}),e}catch{return this.#s({listUs:[]}),[]}}async loadMe(t,s){const e=`
17
+ mutation($alias: String!, $hash: String!) {
18
+ loadMe(alias: $alias, hash: $hash)
19
+ }
20
+ `;try{const i=!!(await this.#t(e,{alias:t,hash:s})).loadMe;return i&&this.#s({activeMe:t}),i}catch{return!1}}async be(t,s,e){const a=`
21
+ mutation($alias: String!, $key: String!, $value: String!) {
22
+ be(alias: $alias, key: $key, value: $value)
23
+ }
24
+ `;try{return!!(await this.#t(a,{alias:t,key:s,value:e})).be}catch{return!1}}async have(t,s,e){const a=`
25
+ mutation($alias: String!, $key: String!, $value: String!) {
26
+ have(alias: $alias, key: $key, value: $value)
27
+ }
28
+ `;try{return!!(await this.#t(a,{alias:t,key:s,value:e})).have}catch{return!1}}async do_(t,s,e){const a=`
29
+ mutation($alias: String!, $key: String!, $value: String!) {
30
+ do(alias: $alias, key: $key, value: $value)
31
+ }
32
+ `;try{return!!(await this.#t(a,{alias:t,key:s,value:e})).do}catch{return!1}}async at(t,s,e){const a=`
33
+ mutation($alias: String!, $key: String!, $value: String!) {
34
+ at(alias: $alias, key: $key, value: $value)
35
+ }
36
+ `;try{return!!(await this.#t(a,{alias:t,key:s,value:e})).at}catch{return!1}}async relate(t,s,e){const a=`
37
+ mutation($alias: String!, $key: String!, $value: String!) {
38
+ relate(alias: $alias, key: $key, value: $value)
39
+ }
40
+ `;try{return!!(await this.#t(a,{alias:t,key:s,value:e})).relate}catch{return!1}}async react(t,s,e){const a=`
41
+ mutation($alias: String!, $key: String!, $value: String!) {
42
+ react(alias: $alias, key: $key, value: $value)
43
+ }
44
+ `;try{return!!(await this.#t(a,{alias:t,key:s,value:e})).react}catch{return!1}}async communication(t,s,e){const a=`
45
+ mutation($alias: String!, $key: String!, $value: String!) {
46
+ communication(alias: $alias, key: $key, value: $value)
47
+ }
48
+ `;try{return!!(await this.#t(a,{alias:t,key:s,value:e})).communication}catch{return!1}}async me(t){const s=`
49
+ query($alias: String!) {
50
+ me(alias: $alias) {
51
+ alias
52
+ publicKey
53
+ }
54
+ }
55
+ `;try{const e=await this.#t(s,{alias:t});if(e.me&&typeof e.me=="object"){const{alias:a,publicKey:i}=e.me;return a&&i?{alias:a,publicKey:i}:null}return null}catch{return null}}}const o=new r;return typeof window<"u"&&(window.me=o,console.log("[this.me] Global instance available as window.me")),o});