@gjsify/react-native 0.52.0 → 0.53.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
@@ -93,7 +93,7 @@ NAME, with its own sentence, or by being absent from the list its route maps. Re
93
93
  only the first answered ACCEPTED for `box-none` until #1648 (ADR 0039 § Amendment).
94
94
  What is still not answered is the TYPE grain — `acceptsPropValue('Text',
95
95
  'selectable', 'yes')` is `true` while a render refuses the string — because that is a
96
- predicate rather than a list; `status/open-todos.md` carries what it would take.
96
+ predicate rather than a list; `status/open-todos/README.md` carries what it would take.
97
97
 
98
98
  ## `<TextInput>`'s ref is a handle, not the widget
99
99
 
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{PrimitiveError as e}from"../primitives/errors.js";import"../generated/unsupported-async-storage.js";import t from"gi://Gio?version=2.0";import n from"gi://GLib?version=2.0";const r=`async-storage.json`,i=new TextDecoder,a=new TextEncoder;let o=null,s=null;function storeFile(){if(s!==null)return s;let i=t.Application.get_default()?.applicationId??null;if(i===null||i===``)throw new e(`AsyncStorage`,`the store’s location`,"needs the application id, and there is no Gio.Application yet. `GLib.get_prgname()` would name the INTERPRETER, so the store would land in a directory called after gjs or node and a later run under the real application would find it empty. Build the application first — `registerRootComponent(App, { applicationId })` does — or read this from a component rather than at module scope");return s=t.File.new_for_path(n.build_filenamev([n.get_user_data_dir(),i,r])),s}function load(){if(o!==null)return o;let t=storeFile(),n=new Map,a=null;if(t.query_exists(null))try{let[,e]=t.load_contents(null);a=e}catch(n){throw new e(`AsyncStorage`,`reading ${t.get_path()??r}`,`failed: ${n instanceof Error?n.message:String(n)}. Starting from an empty store would look like a first launch, so this is loud instead`)}if(a!==null){let o=i.decode(a),s;try{s=JSON.parse(o)}catch(n){throw new e(`AsyncStorage`,`parsing ${t.get_path()??r}`,`failed: ${n instanceof Error?n.message:String(n)}. The file is not this store’s JSON any more. Move it aside to start over — deleting it silently is not this layer’s decision to make`)}if(typeof s!=`object`||!s||Array.isArray(s))throw new e(`AsyncStorage`,`reading ${t.get_path()??r}`,`found ${Array.isArray(s)?`an array`:typeof s} where this store keeps a JSON object of string values`);for(let[e,t]of Object.entries(s))typeof t==`string`&&n.set(e,t)}return o=n,n}function flush(){let n=storeFile(),r=n.get_parent();if(r!==null&&!r.query_exists(null))try{r.make_directory_with_parents(null)}catch(t){throw new e(`AsyncStorage`,`creating ${r.get_path()??`<data dir>`}`,`failed: ${t instanceof Error?t.message:String(t)}`)}let i={};for(let[e,t]of load())i[e]=t;n.replace_contents(a.encode(JSON.stringify(i,null,2)),null,!1,t.FileCreateFlags.REPLACE_DESTINATION,null)}const requireKey=(t,n)=>{if(typeof n!=`string`)throw new e(`AsyncStorage`,t,`takes a string key, and received ${typeof n}`);return n},requireValue=(t,n)=>{if(typeof n!=`string`)throw new e(`AsyncStorage`,t,`takes a string value — AsyncStorage stores strings, which is upstream’s own contract — and received ${typeof n}. Use JSON.stringify`);return n},c={async getItem(e){return load().get(requireKey(`getItem`,e))??null},async setItem(e,t){load().set(requireKey(`setItem`,e),requireValue(`setItem`,t)),flush()},async removeItem(e){load().delete(requireKey(`removeItem`,e)),flush()},async mergeItem(e,t){let n=requireKey(`mergeItem`,e),r=parseObject(`mergeItem`,requireValue(`mergeItem`,t)),i=load().get(n),a=i===void 0?r:{...parseObject(`mergeItem`,i),...r};load().set(n,JSON.stringify(a)),flush()},async clear(){load().clear(),flush()},async getAllKeys(){return[...load().keys()]},async multiGet(e){let t=load();return e.map(e=>[requireKey(`multiGet`,e),t.get(e)??null])},async multiSet(e){let t=load();for(let[n,r]of e)t.set(requireKey(`multiSet`,n),requireValue(`multiSet`,r));flush()},async multiRemove(e){let t=load();for(let n of e)t.delete(requireKey(`multiRemove`,n));flush()},async multiMerge(e){let t=load();for(let[n,r]of e){let e=requireKey(`multiMerge`,n),i=parseObject(`multiMerge`,requireValue(`multiMerge`,r)),a=t.get(e),o=a===void 0?i:{...parseObject(`multiMerge`,a),...i};t.set(e,JSON.stringify(o))}flush()},async flushGetRequests(){}};function parseObject(t,n){let r;try{r=JSON.parse(n)}catch(n){throw new e(`AsyncStorage`,t,`needs both sides to be JSON objects, and one of them does not parse: ${n instanceof Error?n.message:String(n)}`)}if(typeof r!=`object`||!r||Array.isArray(r))throw new e(`AsyncStorage`,t,`merges JSON OBJECTS, and found ${Array.isArray(r)?`an array`:typeof r}. Overwriting instead would be silent data loss`);return r}function useAsyncStorage(e){return{getItem:()=>c.getItem(e),setItem:t=>c.setItem(e,t),mergeItem:t=>c.mergeItem(e,t),removeItem:()=>c.removeItem(e)}}const resetAsyncStorage=()=>{o=null,s=null},useStoreFile=e=>{s=t.File.new_for_path(e),o=null};export{c as AsyncStorage,c as default,resetAsyncStorage,useAsyncStorage,useStoreFile};
1
+ import"../_virtual/_rolldown/runtime.js";import{PrimitiveError as e}from"../primitives/errors.js";import"../generated/unsupported-async-storage.js";import t from"gi://Gio?version=2.0";import n from"gi://GLib?version=2.0";const r=`async-storage.json`,i=new TextDecoder,a=new TextEncoder;let o=null,s=null;function storeFile(){return s===null&&(s=storeFileFor(t.Application.get_default()?.applicationId??null)),s}function storeFileFor(i){if(i===null||i===``)throw new e(`AsyncStorage`,`the store’s location`,"needs the application id, and there is no Gio.Application yet. `GLib.get_prgname()` would name the INTERPRETER, so the store would land in a directory called after gjs or node and a later run under the real application would find it empty. Build the application first — `registerRootComponent(App, { applicationId })` does — or read this from a component rather than at module scope");return t.File.new_for_path(n.build_filenamev([n.get_user_data_dir(),i,r]))}function load(){if(o!==null)return o;let t=storeFile(),n=new Map,a=null;if(t.query_exists(null))try{let[,e]=t.load_contents(null);a=e}catch(n){throw new e(`AsyncStorage`,`reading ${t.get_path()??r}`,`failed: ${n instanceof Error?n.message:String(n)}. Starting from an empty store would look like a first launch, so this is loud instead`)}if(a!==null){let o=i.decode(a),s;try{s=JSON.parse(o)}catch(n){throw new e(`AsyncStorage`,`parsing ${t.get_path()??r}`,`failed: ${n instanceof Error?n.message:String(n)}. The file is not this store’s JSON any more. Move it aside to start over — deleting it silently is not this layer’s decision to make`)}if(typeof s!=`object`||!s||Array.isArray(s))throw new e(`AsyncStorage`,`reading ${t.get_path()??r}`,`found ${Array.isArray(s)?`an array`:typeof s} where this store keeps a JSON object of string values`);for(let[e,t]of Object.entries(s))typeof t==`string`&&n.set(e,t)}return o=n,n}function flush(){let n=storeFile(),r=n.get_parent();if(r!==null&&!r.query_exists(null))try{r.make_directory_with_parents(null)}catch(t){throw new e(`AsyncStorage`,`creating ${r.get_path()??`<data dir>`}`,`failed: ${t instanceof Error?t.message:String(t)}`)}let i={};for(let[e,t]of load())i[e]=t;n.replace_contents(a.encode(JSON.stringify(i,null,2)),null,!1,t.FileCreateFlags.REPLACE_DESTINATION,null)}const requireKey=(t,n)=>{if(typeof n!=`string`)throw new e(`AsyncStorage`,t,`takes a string key, and received ${typeof n}`);return n},requireValue=(t,n)=>{if(typeof n!=`string`)throw new e(`AsyncStorage`,t,`takes a string value — AsyncStorage stores strings, which is upstream’s own contract — and received ${typeof n}. Use JSON.stringify`);return n},c={async getItem(e){return load().get(requireKey(`getItem`,e))??null},async setItem(e,t){load().set(requireKey(`setItem`,e),requireValue(`setItem`,t)),flush()},async removeItem(e){load().delete(requireKey(`removeItem`,e)),flush()},async mergeItem(e,t){let n=requireKey(`mergeItem`,e),r=parseObject(`mergeItem`,requireValue(`mergeItem`,t)),i=load().get(n),a=i===void 0?r:{...parseObject(`mergeItem`,i),...r};load().set(n,JSON.stringify(a)),flush()},async clear(){load().clear(),flush()},async getAllKeys(){return[...load().keys()]},async multiGet(e){let t=load();return e.map(e=>[requireKey(`multiGet`,e),t.get(e)??null])},async multiSet(e){let t=load();for(let[n,r]of e)t.set(requireKey(`multiSet`,n),requireValue(`multiSet`,r));flush()},async multiRemove(e){let t=load();for(let n of e)t.delete(requireKey(`multiRemove`,n));flush()},async multiMerge(e){let t=load();for(let[n,r]of e){let e=requireKey(`multiMerge`,n),i=parseObject(`multiMerge`,requireValue(`multiMerge`,r)),a=t.get(e),o=a===void 0?i:{...parseObject(`multiMerge`,a),...i};t.set(e,JSON.stringify(o))}flush()},async flushGetRequests(){}};function parseObject(t,n){let r;try{r=JSON.parse(n)}catch(n){throw new e(`AsyncStorage`,t,`needs both sides to be JSON objects, and one of them does not parse: ${n instanceof Error?n.message:String(n)}`)}if(typeof r!=`object`||!r||Array.isArray(r))throw new e(`AsyncStorage`,t,`merges JSON OBJECTS, and found ${Array.isArray(r)?`an array`:typeof r}. Overwriting instead would be silent data loss`);return r}function useAsyncStorage(e){return{getItem:()=>c.getItem(e),setItem:t=>c.setItem(e,t),mergeItem:t=>c.mergeItem(e,t),removeItem:()=>c.removeItem(e)}}const resetAsyncStorage=()=>{o=null,s=null},useStoreFile=e=>{s=t.File.new_for_path(e),o=null};export{c as AsyncStorage,c as default,resetAsyncStorage,storeFileFor,useAsyncStorage,useStoreFile};
@@ -1,3 +1,14 @@
1
+ import Gio from 'gi://Gio?version=2.0';
2
+ /**
3
+ * Where the store lives for one application id, or a refusal by name when there is none.
4
+ *
5
+ * Split out of `storeFile()` so a spec can hold BOTH outcomes deterministically.
6
+ * `Gio.Application.get_default()` is process-wide state: the first suite that builds an
7
+ * application makes it non-null for every later suite, and `g_application_set_default`
8
+ * cannot clear it from JS (GJS binds it as an instance method), so a vector that reads
9
+ * the ambient default measures a different property depending on suite order.
10
+ */
11
+ export declare function storeFileFor(applicationId: string | null): Gio.File;
1
12
  /**
2
13
  * `AsyncStorage`, over one JSON document.
3
14
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/react-native",
3
- "version": "0.52.0",
3
+ "version": "0.53.0",
4
4
  "description": "The React Native view vocabulary rendered onto GTK4/Adwaita, over @gjsify/gtk-host",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -105,8 +105,8 @@
105
105
  "build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
106
106
  "build:types": "gjsify tsc",
107
107
  "build:test": "gjsify run build:test:gjs",
108
- "build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs --define \"process.env.NODE_ENV='production'\" --exclude-globals navigator",
109
- "build:test:node": "gjsify build src/test.mts --app node --outfile dist/test.node.mjs --define \"process.env.NODE_ENV='production'\" --exclude-globals navigator",
108
+ "build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs --define \"process.env.NODE_ENV='production'\"",
109
+ "build:test:node": "gjsify build src/test.mts --app node --outfile dist/test.node.mjs --define \"process.env.NODE_ENV='production'\"",
110
110
  "test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:gjs",
111
111
  "test:gjs": "gjsify run test.gjs.mjs",
112
112
  "test:gjs-on-node": "gjsify run build:gjsify && gjsify run build:test:node && node dist/test.node.mjs",
@@ -120,8 +120,8 @@
120
120
  "react-native"
121
121
  ],
122
122
  "dependencies": {
123
- "@gjsify/adwaita-app": "^0.52.0",
124
- "@gjsify/gtk-host": "^0.52.0"
123
+ "@gjsify/adwaita-app": "^0.53.0",
124
+ "@gjsify/gtk-host": "^0.53.0"
125
125
  },
126
126
  "peerDependencies": {
127
127
  "@react-navigation/core": "^7.21.13",
@@ -152,9 +152,9 @@
152
152
  "@girs/gdk-4.0": "5.4.0",
153
153
  "@girs/gjs": "5.4.0",
154
154
  "@girs/gtk-4.0": "5.4.0",
155
- "@gjsify/cli": "^0.52.0",
156
- "@gjsify/rolldown-plugin-gjsify": "^0.52.0",
157
- "@gjsify/unit": "^0.52.0",
155
+ "@gjsify/cli": "^0.53.0",
156
+ "@gjsify/rolldown-plugin-gjsify": "^0.53.0",
157
+ "@gjsify/unit": "^0.53.0",
158
158
  "@react-navigation/core": "^7.21.13",
159
159
  "@react-navigation/routers": "^7.6.4",
160
160
  "@types/node": "^25.9.2",