feat/orm-diffs
Laurin Weger 3 days ago
parent cce7dbfbe9
commit 2bdaa84438
No known key found for this signature in database
GPG Key ID: 9B372BB0B792770F
  1. 10
      engine/verifier/src/orm/handle_frontend_update.rs
  2. 1
      engine/verifier/src/orm/initialize.rs
  3. 20
      sdk/js/alien-deepsignals/test-map-type.js
  4. 28
      sdk/js/alien-deepsignals/test-set-map.js
  5. 25
      sdk/js/alien-deepsignals/test-set-paths.js
  6. 9
      sdk/js/examples/multi-framework-signals/src/app/pages/index.astro
  7. 136
      sdk/js/examples/multi-framework-signals/src/frontends/react/HelloWorld.tsx
  8. 7
      sdk/js/examples/multi-framework-signals/src/frontends/svelte/HelloWorld.svelte
  9. 21
      sdk/js/examples/multi-framework-signals/src/frontends/vue/HelloWorld.vue

@ -302,10 +302,7 @@ fn create_sparql_update_query_for_diff(
remove_statement,
wheres.join(" .\n ")
));
log_info!(
"[create_sparql_update_query_for_diff] Added delete query #{}",
sparql_sub_queries.len()
);
log_info!("[create_sparql_update_query_for_diff] Added delete query.");
// var_counter += 1; // Not necessary because not used afterwards.
}
// The actual INSERT.
@ -315,10 +312,7 @@ fn create_sparql_update_query_for_diff(
add_statement,
where_statements.join(". \n ")
));
log_info!(
"[create_sparql_update_query_for_diff] Added insert query #{}",
sparql_sub_queries.len()
);
log_info!("[create_sparql_update_query_for_diff] Added insert query.");
}
}

@ -62,7 +62,6 @@ impl Verifier {
.push(orm_subscription);
let orm_objects = self.create_orm_object_for_shape(nuri, session_id, &shape_type)?;
// log_debug!("create_orm_object_for_shape return {:?}", orm_objects);
let _ = tx
.send(AppResponse::V0(AppResponseV0::OrmInitial(orm_objects)))

@ -0,0 +1,20 @@
import { deepSignal } from './dist/index.js';
const root = deepSignal({
mySet: new Set([
{ "@id": "obj1", value: 10 },
{ "@id": "obj2", value: 20 }
])
});
const result = root.mySet.values().map(entry => entry);
console.log('Type:', typeof result);
console.log('Constructor:', result.constructor.name);
console.log('Result:', result);
console.log('Has next?:', typeof result.next);
console.log('Is iterable?:', Symbol.iterator in result);
// Convert to array
const arr = Array.from(result);
console.log('Array:', arr);
console.log('First entry:', arr[0]);

@ -0,0 +1,28 @@
import { deepSignal, subscribeDeepMutations } from './dist/index.js';
const root = deepSignal({
mySet: new Set([
{ "@id": "obj1", value: 10 },
{ "@id": "obj2", value: 20 }
])
});
subscribeDeepMutations(root, (patches) => {
console.log('Patches:', JSON.stringify(patches, null, 2));
});
// Use .map() to get entries
const entries = root.mySet.values().map(entry => {
console.log('Entry:', entry);
return entry;
});
console.log('Got entries:', entries.length);
console.log('Modifying first entry...');
// Modify the first one
entries[0].value = 100;
setTimeout(() => {
console.log('Done');
}, 100);

@ -0,0 +1,25 @@
import { deepSignal, subscribeDeepMutations } from './dist/index.js';
const root = deepSignal({
mySet: new Set([
{ "@id": "obj1", value: 10 }
])
});
subscribeDeepMutations(root, (patches) => {
console.log('Patches:', JSON.stringify(patches, null, 2));
});
// Get the first entry from the set
const entries = root.mySet.values();
const firstEntry = entries.next().value;
console.log('First entry:', firstEntry);
console.log('Modifying value...');
// Modify it
firstEntry.value = 20;
setTimeout(() => {
console.log('Done');
}, 100);

@ -30,6 +30,7 @@ const title = "Multi-framework app";
initNg(ng, event.session);
window.ng = ng;
window.session = event.session;
},
true,
[]
@ -37,15 +38,15 @@ const title = "Multi-framework app";
</script>
<Layout title={title}>
<!-- <Highlight vue>
<Highlight vue>
<VueRoot client:only />
</Highlight> -->
</Highlight>
<Highlight react>
<ReactRoot client:only="react" />
</Highlight>
<!--
<Highlight svelte>
<SvelteRoot client:only />
</Highlight> -->
</Highlight>
</Layout>

@ -3,31 +3,102 @@ import { useShape } from "@ng-org/signals/react";
import flattenObject from "../utils/flattenObject";
import { TestObjectShapeType } from "../../shapes/orm/testShape.shapeTypes";
import { BasicShapeType } from "../../shapes/orm/basic.shapeTypes";
import type { ShapeType } from "@ng-org/shex-orm";
import type { Basic } from "../../shapes/orm/basic.typings";
const sparqlExampleData = `
PREFIX ex: <http://example.org/>
INSERT DATA {
<urn:test:obj1> a ex:TestObject ;
ex:stringValue "hello world" ;
ex:numValue 42 ;
ex:boolValue true ;
ex:arrayValue 1,2,3 ;
ex:objectValue <urn:test:id3> ;
ex:anotherObject <urn:test:id1>, <urn:test:id2> ;
ex:numOrStr "either" ;
ex:lit1Or2 "lit1" ;
ex:unrelated "some value" ;
ex:anotherUnrelated 4242 .
<urn:test:id3>
ex:nestedString "nested" ;
ex:nestedNum 7 ;
ex:nestedArray 5,6 .
<urn:test:id1>
ex:prop1 "one" ;
ex:prop2 1 .
<urn:test:id2>
ex:prop1 "two" ;
ex:prop2 2 .
<urn:test:obj2> a ex:TestObject ;
ex:stringValue "hello world #2" ;
ex:numValue 422 ;
ex:boolValue false ;
ex:arrayValue 4,5,6 ;
ex:objectValue <urn:test:id6> ;
ex:anotherObject <urn:test:id4>, <urn:test:id5> ;
ex:numOrStr 4 ;
ex:lit1Or2 "lit2" ;
ex:unrelated "some value2" ;
ex:anotherUnrelated 42422 .
<urn:test:id6>
ex:nestedString "nested2" ;
ex:nestedNum 72 ;
ex:nestedArray 7,8,9 .
<urn:test:id4>
ex:prop1 "one2" ;
ex:prop2 12 .
<urn:test:id5>
ex:prop1 "two2" ;
ex:prop2 22 .
<urn:basicObject4>
a <http://example.org/Basic> ;
ex:basicString "string of object 1" .
<urn:basicObject5>
a <http://example.org/Basic> ;
ex:basicString "string of object 2" .
}
`;
export function HelloWorldReact() {
const state = [...(useShape(BasicShapeType)?.entries() || [])][0];
const state = useShape(BasicShapeType);
// @ts-expect-error
window.reactState = state;
console.log("react state", state);
if (!state) return <>Loading state</>;
if (!state) return <div>Loading...</div>;
// Create a table from the state object: One column for keys, one for values, one with an input to change the value.
return (
<div>
<p>Rendered in React</p>
{/* <button
<button
onClick={() => {
state.boolValue = !state.boolValue;
state.numValue += 2;
window.ng.sparql_update(
window.session.session_id,
sparqlExampleData,
"did:ng:" + window.session.private_store_id
);
}}
>
click me to change multiple props
</button> */}
Add example data
</button>
<table border={1} cellPadding={5}>
<div>
{state.values()?.map((ormObj) => (
<table border={1} cellPadding={5} key={ormObj["@id"]}>
<thead>
<tr>
<th>Key</th>
@ -52,18 +123,27 @@ export function HelloWorldReact() {
current[keys[keys.length - 1]] = value;
};
const getNestedValue = (obj: any, path: string) => {
const getNestedValue = (
obj: any,
path: string
) => {
return path
.split(".")
.reduce((current, key) => current[key], obj);
.reduce(
(current, key) => current[key],
obj
);
};
return flattenObject(state).map(([key, value]) => (
return flattenObject(ormObj).map(
([key, value]) => (
<tr key={key}>
<td>{key}</td>
<td>
{value instanceof Set
? Array.from(value).join(", ")
? Array.from(value).join(
", "
)
: Array.isArray(value)
? `[${value.join(", ")}]`
: JSON.stringify(value)}
@ -81,7 +161,8 @@ export function HelloWorldReact() {
);
}}
/>
) : typeof value === "number" ? (
) : typeof value ===
"number" ? (
<input
type="number"
value={value}
@ -89,11 +170,15 @@ export function HelloWorldReact() {
setNestedValue(
state,
key,
Number(e.target.value)
Number(
e.target
.value
)
);
}}
/>
) : typeof value === "boolean" ? (
) : typeof value ===
"boolean" ? (
<input
type="checkbox"
checked={value}
@ -114,10 +199,15 @@ export function HelloWorldReact() {
state,
key
);
setNestedValue(state, key, [
setNestedValue(
state,
key,
[
...currentArray,
currentArray.length + 1,
]);
currentArray.length +
1,
]
);
}}
>
Add
@ -130,7 +220,8 @@ export function HelloWorldReact() {
key
);
if (
currentArray.length > 0
currentArray.length >
0
) {
setNestedValue(
state,
@ -188,10 +279,13 @@ export function HelloWorldReact() {
)}
</td>
</tr>
));
)
);
})()}
</tbody>
</table>
))}
</div>
</div>
);
}

@ -19,9 +19,9 @@
}
cur[keys[keys.length - 1]] = value;
}
const flatEntries = $derived(
const flattenedObjects = $derived(
$shapeObject
? $shapeObject.entries().map((o) => flattenObject(o)[0] || ({} as any))
? $shapeObject.values().map((o) => flattenObject(o)[0] || ({} as any))
: []
);
$effect(() => {
@ -32,6 +32,8 @@
{#if $shapeObject}
<div>
<p>Rendered in Svelte</p>
{#each flattenedObjects as flatEntries}
<table border="1" cellpadding="5">
<thead>
<tr>
@ -118,6 +120,7 @@
{/each}
</tbody>
</table>
{/each}
</div>
{:else}
<p>Loading state</p>

@ -5,24 +5,21 @@ import flattenObject from "../utils/flattenObject";
import { TestObjectShapeType } from "../../shapes/orm/testShape.shapeTypes";
// Acquire deep signal object (proxy) for a shape; scope second arg left empty string for parity
const shapeObj = useShape(TestObjectShapeType);
const shapeObjects = useShape(TestObjectShapeType);
// Expose for devtools exploration
// @ts-ignore
window.vueState = shapeObj;
window.vueState = shapeObjects;
const flatEntries = computed(() => flattenObject(shapeObj));
</script>
<template>
<div class="vue">
<p>Rendered in Vue</p>
<template v-if="shapeObj && 'type' in shapeObj">
<!-- Direct property access -->
<input type="text" v-model="shapeObj.type" />
<input type="text" v-model="shapeObj.objectValue.nestedString" />
<template v-if="shapeObjects">
<template v-for="obj in shapeObjects" :key="obj">
<template v-for="flatEntries in [flattenObject(obj)]">
<!-- Property access through object recursion -->
<table
border="1"
@ -65,7 +62,7 @@ const flatEntries = computed(() => flattenObject(shapeObj));
<template v-if="path.indexOf('.') === -1">
<input
type="text"
v-model="shapeObj[key]"
v-model="obj[key]"
/>
</template>
<template v-else>
@ -87,7 +84,7 @@ const flatEntries = computed(() => flattenObject(shapeObj));
<template v-if="path.indexOf('.') === -1">
<input
type="number"
v-model="shapeObj[key]"
v-model="obj[key]"
/>
</template>
<template v-else>
@ -108,7 +105,7 @@ const flatEntries = computed(() => flattenObject(shapeObj));
<template v-if="path.indexOf('.') === -1">
<input
type="checkbox"
v-model="shapeObj[key]"
v-model="obj[key]"
/>
</template>
<template v-else>
@ -215,6 +212,8 @@ const flatEntries = computed(() => flattenObject(shapeObj));
</tbody>
</table>
</template>
</template>
</template>
<template v-else>
<p>Loading state</p>
</template>

Loading…
Cancel
Save