@undefineds.co/drizzle-solid 0.2.13 → 0.3.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.
Files changed (180) hide show
  1. package/README.md +141 -250
  2. package/dist/core/ast-to-sparql.d.ts +1 -1
  3. package/dist/core/ast-to-sparql.js +1 -1
  4. package/dist/core/comunica-patch.d.ts +1 -6
  5. package/dist/core/comunica-patch.d.ts.map +1 -1
  6. package/dist/core/comunica-patch.js +16 -19
  7. package/dist/core/comunica-patch.js.map +1 -1
  8. package/dist/core/execution/sparql-strategy.d.ts +9 -37
  9. package/dist/core/execution/sparql-strategy.d.ts.map +1 -1
  10. package/dist/core/execution/sparql-strategy.js +44 -148
  11. package/dist/core/execution/sparql-strategy.js.map +1 -1
  12. package/dist/core/execution/strategy-factory.d.ts +7 -20
  13. package/dist/core/execution/strategy-factory.d.ts.map +1 -1
  14. package/dist/core/execution/strategy-factory.js +2 -17
  15. package/dist/core/execution/strategy-factory.js.map +1 -1
  16. package/dist/core/pod-database.d.ts +3 -3
  17. package/dist/core/pod-database.d.ts.map +1 -1
  18. package/dist/core/pod-database.js +37 -37
  19. package/dist/core/pod-database.js.map +1 -1
  20. package/dist/core/pod-dialect.d.ts +2 -0
  21. package/dist/core/pod-dialect.d.ts.map +1 -1
  22. package/dist/core/pod-dialect.js +4 -2
  23. package/dist/core/pod-dialect.js.map +1 -1
  24. package/dist/core/query-builders/select-query-builder.d.ts +2 -2
  25. package/dist/core/query-builders/select-query-builder.d.ts.map +1 -1
  26. package/dist/core/query-builders/select-query-builder.js +10 -10
  27. package/dist/core/query-builders/select-query-builder.js.map +1 -1
  28. package/dist/core/schema/columns.d.ts +6 -6
  29. package/dist/core/schema/columns.d.ts.map +1 -1
  30. package/dist/core/schema/columns.js +18 -18
  31. package/dist/core/schema/columns.js.map +1 -1
  32. package/dist/core/schema/defs.d.ts +4 -4
  33. package/dist/core/schema/defs.d.ts.map +1 -1
  34. package/dist/core/schema/pod-table.js +2 -2
  35. package/dist/core/schema/pod-table.js.map +1 -1
  36. package/dist/core/services/pod-services.d.ts +7 -5
  37. package/dist/core/services/pod-services.d.ts.map +1 -1
  38. package/dist/core/services/pod-services.js +7 -5
  39. package/dist/core/services/pod-services.js.map +1 -1
  40. package/dist/core/shape/generator.js +3 -3
  41. package/dist/core/shape/generator.js.map +1 -1
  42. package/dist/core/shape/manager.js +5 -5
  43. package/dist/core/shape/manager.js.map +1 -1
  44. package/dist/core/sparql/builder/expression-builder.d.ts +5 -5
  45. package/dist/core/sparql/builder/expression-builder.d.ts.map +1 -1
  46. package/dist/core/sparql/builder/expression-builder.js +15 -15
  47. package/dist/core/sparql/builder/expression-builder.js.map +1 -1
  48. package/dist/core/sparql/builder/select-builder.d.ts +1 -1
  49. package/dist/core/sparql/builder/select-builder.js +1 -1
  50. package/dist/core/sparql/builder/update-builder.d.ts +1 -1
  51. package/dist/core/sparql/builder/update-builder.d.ts.map +1 -1
  52. package/dist/core/sparql/builder/update-builder.js +4 -4
  53. package/dist/core/sparql/builder/update-builder.js.map +1 -1
  54. package/dist/core/sparql/helpers.js +3 -3
  55. package/dist/core/sparql/helpers.js.map +1 -1
  56. package/dist/core/sparql-engine.d.ts +16 -0
  57. package/dist/core/sparql-engine.d.ts.map +1 -0
  58. package/dist/core/sparql-engine.js +128 -0
  59. package/dist/core/sparql-engine.js.map +1 -0
  60. package/dist/core/sparql-executor.d.ts +3 -1
  61. package/dist/core/sparql-executor.d.ts.map +1 -1
  62. package/dist/core/sparql-executor.js +3 -4
  63. package/dist/core/sparql-executor.js.map +1 -1
  64. package/dist/core/triple/handlers/inverse.js +4 -4
  65. package/dist/core/triple/handlers/inverse.js.map +1 -1
  66. package/dist/core/triple/handlers/uri.d.ts +1 -1
  67. package/dist/core/triple/handlers/uri.js +3 -3
  68. package/dist/core/triple/handlers/uri.js.map +1 -1
  69. package/dist/core/uri/resolver.d.ts +9 -9
  70. package/dist/core/uri/resolver.d.ts.map +1 -1
  71. package/dist/core/uri/resolver.js +51 -51
  72. package/dist/core/uri/resolver.js.map +1 -1
  73. package/dist/core/uri/types.d.ts +10 -10
  74. package/dist/core/uri/types.d.ts.map +1 -1
  75. package/dist/driver.d.ts +10 -1
  76. package/dist/driver.d.ts.map +1 -1
  77. package/dist/driver.js +1 -5
  78. package/dist/driver.js.map +1 -1
  79. package/dist/esm/core/ast-to-sparql.d.ts +1 -1
  80. package/dist/esm/core/ast-to-sparql.js +1 -1
  81. package/dist/esm/core/comunica-patch.d.ts +1 -6
  82. package/dist/esm/core/comunica-patch.d.ts.map +1 -1
  83. package/dist/esm/core/comunica-patch.js +13 -20
  84. package/dist/esm/core/comunica-patch.js.map +1 -1
  85. package/dist/esm/core/execution/sparql-strategy.d.ts +9 -37
  86. package/dist/esm/core/execution/sparql-strategy.d.ts.map +1 -1
  87. package/dist/esm/core/execution/sparql-strategy.js +44 -148
  88. package/dist/esm/core/execution/sparql-strategy.js.map +1 -1
  89. package/dist/esm/core/execution/strategy-factory.d.ts +7 -20
  90. package/dist/esm/core/execution/strategy-factory.d.ts.map +1 -1
  91. package/dist/esm/core/execution/strategy-factory.js +2 -17
  92. package/dist/esm/core/execution/strategy-factory.js.map +1 -1
  93. package/dist/esm/core/pod-database.d.ts +3 -3
  94. package/dist/esm/core/pod-database.d.ts.map +1 -1
  95. package/dist/esm/core/pod-database.js +37 -37
  96. package/dist/esm/core/pod-database.js.map +1 -1
  97. package/dist/esm/core/pod-dialect.d.ts +2 -0
  98. package/dist/esm/core/pod-dialect.d.ts.map +1 -1
  99. package/dist/esm/core/pod-dialect.js +4 -2
  100. package/dist/esm/core/pod-dialect.js.map +1 -1
  101. package/dist/esm/core/query-builders/select-query-builder.d.ts +2 -2
  102. package/dist/esm/core/query-builders/select-query-builder.d.ts.map +1 -1
  103. package/dist/esm/core/query-builders/select-query-builder.js +10 -10
  104. package/dist/esm/core/query-builders/select-query-builder.js.map +1 -1
  105. package/dist/esm/core/schema/columns.d.ts +6 -6
  106. package/dist/esm/core/schema/columns.d.ts.map +1 -1
  107. package/dist/esm/core/schema/columns.js +18 -18
  108. package/dist/esm/core/schema/columns.js.map +1 -1
  109. package/dist/esm/core/schema/defs.d.ts +4 -4
  110. package/dist/esm/core/schema/defs.d.ts.map +1 -1
  111. package/dist/esm/core/schema/pod-table.js +2 -2
  112. package/dist/esm/core/schema/pod-table.js.map +1 -1
  113. package/dist/esm/core/services/pod-services.d.ts +7 -5
  114. package/dist/esm/core/services/pod-services.d.ts.map +1 -1
  115. package/dist/esm/core/services/pod-services.js +7 -5
  116. package/dist/esm/core/services/pod-services.js.map +1 -1
  117. package/dist/esm/core/shape/generator.js +3 -3
  118. package/dist/esm/core/shape/generator.js.map +1 -1
  119. package/dist/esm/core/shape/manager.js +5 -5
  120. package/dist/esm/core/shape/manager.js.map +1 -1
  121. package/dist/esm/core/sparql/builder/expression-builder.d.ts +5 -5
  122. package/dist/esm/core/sparql/builder/expression-builder.d.ts.map +1 -1
  123. package/dist/esm/core/sparql/builder/expression-builder.js +15 -15
  124. package/dist/esm/core/sparql/builder/expression-builder.js.map +1 -1
  125. package/dist/esm/core/sparql/builder/select-builder.d.ts +1 -1
  126. package/dist/esm/core/sparql/builder/select-builder.js +1 -1
  127. package/dist/esm/core/sparql/builder/update-builder.d.ts +1 -1
  128. package/dist/esm/core/sparql/builder/update-builder.d.ts.map +1 -1
  129. package/dist/esm/core/sparql/builder/update-builder.js +4 -4
  130. package/dist/esm/core/sparql/builder/update-builder.js.map +1 -1
  131. package/dist/esm/core/sparql/helpers.js +3 -3
  132. package/dist/esm/core/sparql/helpers.js.map +1 -1
  133. package/dist/esm/core/sparql-engine.d.ts +16 -0
  134. package/dist/esm/core/sparql-engine.d.ts.map +1 -0
  135. package/dist/esm/core/sparql-engine.js +89 -0
  136. package/dist/esm/core/sparql-engine.js.map +1 -0
  137. package/dist/esm/core/sparql-executor.d.ts +3 -1
  138. package/dist/esm/core/sparql-executor.d.ts.map +1 -1
  139. package/dist/esm/core/sparql-executor.js +3 -4
  140. package/dist/esm/core/sparql-executor.js.map +1 -1
  141. package/dist/esm/core/triple/handlers/inverse.js +4 -4
  142. package/dist/esm/core/triple/handlers/inverse.js.map +1 -1
  143. package/dist/esm/core/triple/handlers/uri.d.ts +1 -1
  144. package/dist/esm/core/triple/handlers/uri.js +3 -3
  145. package/dist/esm/core/triple/handlers/uri.js.map +1 -1
  146. package/dist/esm/core/uri/resolver.d.ts +9 -9
  147. package/dist/esm/core/uri/resolver.d.ts.map +1 -1
  148. package/dist/esm/core/uri/resolver.js +51 -51
  149. package/dist/esm/core/uri/resolver.js.map +1 -1
  150. package/dist/esm/core/uri/types.d.ts +10 -10
  151. package/dist/esm/core/uri/types.d.ts.map +1 -1
  152. package/dist/esm/driver.d.ts +10 -1
  153. package/dist/esm/driver.d.ts.map +1 -1
  154. package/dist/esm/driver.js +1 -5
  155. package/dist/esm/driver.js.map +1 -1
  156. package/dist/esm/index.d.ts +2 -0
  157. package/dist/esm/index.d.ts.map +1 -1
  158. package/dist/esm/index.js +3 -1
  159. package/dist/esm/index.js.map +1 -1
  160. package/dist/esm/pod.d.ts +68 -0
  161. package/dist/esm/pod.d.ts.map +1 -0
  162. package/dist/esm/pod.js +146 -0
  163. package/dist/esm/pod.js.map +1 -0
  164. package/dist/esm/utils/webid-resolver.d.ts +1 -2
  165. package/dist/esm/utils/webid-resolver.d.ts.map +1 -1
  166. package/dist/esm/utils/webid-resolver.js +36 -30
  167. package/dist/esm/utils/webid-resolver.js.map +1 -1
  168. package/dist/index.d.ts +2 -0
  169. package/dist/index.d.ts.map +1 -1
  170. package/dist/index.js +12 -4
  171. package/dist/index.js.map +1 -1
  172. package/dist/pod.d.ts +68 -0
  173. package/dist/pod.d.ts.map +1 -0
  174. package/dist/pod.js +153 -0
  175. package/dist/pod.js.map +1 -0
  176. package/dist/utils/webid-resolver.d.ts +1 -2
  177. package/dist/utils/webid-resolver.d.ts.map +1 -1
  178. package/dist/utils/webid-resolver.js +36 -30
  179. package/dist/utils/webid-resolver.js.map +1 -1
  180. package/package.json +11 -3
package/README.md CHANGED
@@ -1,123 +1,101 @@
1
1
  # drizzle-solid
2
2
 
3
- `drizzle-solid` is a Drizzle-aligned adapter for application-owned data in Solid Pods.
3
+ `drizzle-solid` is a Drizzle-aligned data layer for application-owned data in Solid Pods.
4
4
 
5
- It helps you define typed models, map them to RDF resources/documents/IRIs, and read or write them with a familiar query builder — without pretending Solid is a relational database.
5
+ 这次变化的重点不是强迫你把构造函数名字从 `drizzle()` 换成别的东西,而是把语义讲清楚:
6
6
 
7
- The library is intentionally **document-first**, **IRI-native**, **Pod-aware**, and **SPARQL-native**.
7
+ - `table` 更接近 **resource layout / collection definition**
8
+ - `link` 字段更接近 **RDF link / IRI link**
9
+ - 实体最终身份更接近 **IRI / @id**,而不只是本地主键
10
+ - 读取和写入不再默认共享 SQL 式语义
8
11
 
9
- ## What it helps with
12
+ ## Scope
10
13
 
11
- - Defining typed application data for Solid Pods
12
- - Mapping fields to RDF predicates and resource layouts
13
- - Using a Drizzle-style CRUD/query builder over Pod data
14
- - Performing exact entity operations through full IRIs
15
- - Building discovery, federation, and notification flows on top of Solid-native storage
14
+ Current v1 solves one problem well:
16
15
 
17
- ## Design principles
16
+ - persist application-owned data into Solid Pods with typed schemas
17
+ - keep Pod layout explicit through `base` and `subjectTemplate`
18
+ - make full IRIs part of the public API instead of hiding them behind local-only IDs
19
+ - give Drizzle users a migration-friendly surface without pretending Solid is a SQL database
20
+ - support adjacent Solid flows such as discovery, notifications, and federation where they fit the Pod model
18
21
 
19
- - **Document-first**: model around Solid resources and document boundaries
20
- - **IRI-native**: treat IRIs as first-class identity, not as an afterthought over local IDs
21
- - **Pod-aware**: keep resource layout, links, network, and access constraints explicit
22
- - **Drizzle-aligned**: stay close to Drizzle's builder surface and ergonomics where it makes sense
23
- - **SPARQL-native**: the native query model is SPARQL/Solid, not SQL emulation
22
+ Not in v1:
24
23
 
25
- ## What it is
26
-
27
- - A typed persistence layer for application-owned data in Solid Pods
28
- - A Drizzle-style API surface over RDF resources and documents
29
- - A practical bridge for teams migrating Drizzle mental models into Solid-native data flows
30
-
31
- ## What it isn't
32
-
33
- - Not a general-purpose SQL ORM
34
- - Not a universal abstraction over arbitrary RDF on the open web
35
- - Not a graph database or SPARQL engine replacement
36
- - Not a black box that hides Pod boundaries, permissions, or network behavior
37
- - Not a promise that every SQL/driver-specific Drizzle feature maps cleanly to Solid
38
-
39
- ## Core concepts
40
-
41
- ### Resource
42
-
43
- A resource is the persisted unit in a Pod, usually a Turtle or JSON-LD document addressed by URL.
44
-
45
- ### Document
46
-
47
- A document may contain one entity or many entities. Document layout is part of application design, not an implementation detail.
48
-
49
- ### Entity
50
-
51
- An entity is a typed RDF subject stored in a document. It is closer to a linked-data subject than to a relational row.
52
-
53
- ### IRI
24
+ - full SQL/database feature parity
25
+ - raw SQL as the primary abstraction
26
+ - hiding Pod boundaries, permissions, or network behavior
27
+ - implicit scan-based `updateMany/deleteMany` on backends that do not support set-based mutation
28
+ - universal querying over arbitrary open-world RDF as the main goal
54
29
 
55
- IRIs are native identity. `drizzle-solid` keeps the full subject IRI available and provides explicit IRI APIs for exact operations.
30
+ ## Constructor Choice
56
31
 
57
- ### Link
32
+ 仓库文档与 examples 默认先用 `pod(session, config?)` 讲主线语义:
58
33
 
59
- Links between entities are represented as IRIs and may cross documents or Pods.
34
+ - `pod(session, config?)`
35
+ - `drizzle(session, config?)`
60
36
 
61
- ### Model
37
+ 建议这样理解:
62
38
 
63
- `drizzle-solid` supports two modeling styles:
39
+ - `pod()` 是语义优先的正式入口,方便把 API 组织成 `collection()` / `entity()` / `bind()`
40
+ - `drizzle()` 是同一运行时上的 Drizzle-aligned 入口,适合迁移或保留 builder/query 代码形状
41
+ - 重要的不是“入口名”,而是下面这些语义:`base`、`subjectTemplate`、`IRI`、exact-target mutation
64
42
 
65
- - `podTable(...)`: schema plus concrete storage location
66
- - `solidSchema(...)` + `db.createTable(...)`: reusable schema separated from where data is stored
43
+ ## Public Surface
67
44
 
68
- ### Pod client
45
+ 当前公开表面可以分成两层:
69
46
 
70
- `drizzle(session)` creates the database client bound to an authenticated Solid session.
47
+ ### Semantic-first surface
71
48
 
72
- ## Modeling vs persistence
49
+ - `pod(session, config?)`
50
+ - `client.bind(schema, options)`
51
+ - `client.collection(table)`
52
+ - `client.entity(table, iri)`
53
+ - `client.sparql(query)`
73
54
 
74
- A Solid application usually needs to answer two different questions:
55
+ ### Drizzle-aligned surface
75
56
 
76
- 1. **What is the shape of my data?**
77
- 2. **Where does that data live in Pods?**
57
+ - `drizzle(session, config?)`
58
+ - `podTable(name, columns, config)`
59
+ - `solidSchema(...)`
60
+ - `select / insert / update / delete`
61
+ - `db.query.*` read facade
78
62
 
79
- `drizzle-solid` keeps those concerns explicit.
63
+ ## Install
80
64
 
81
- - Use `podTable(...)` when your app owns the storage location and you want one place to define shape + location.
82
- - Use `solidSchema(...)` when the same schema should be reused across different Pod locations, profiles, or discovered data sources.
83
- - Use `db.createTable(schema, { base, ... })` when you want to bind a reusable schema to a concrete place at runtime.
65
+ ```bash
66
+ yarn add @undefineds.co/drizzle-solid drizzle-orm
67
+ # optional, when your app wants the default SPARQL client engine
68
+ yarn add @comunica/query-sparql-solid
69
+ ```
84
70
 
85
- This keeps Solid's persistence model visible instead of flattening everything into table-only abstractions.
71
+ ```bash
72
+ npm install @undefineds.co/drizzle-solid drizzle-orm
73
+ npm install @comunica/query-sparql-solid
74
+ ```
86
75
 
87
- ## Why document-first
76
+ `@comunica/query-sparql-solid` is an optional peer dependency.
88
77
 
89
- Solid stores data in resources, not in tables.
78
+ Install it in the consuming app when you need built-in SPARQL query execution, LDP-backed query fallback, or direct SPARQL workflows.
90
79
 
91
- That means application design starts with questions like:
80
+ Current public compatibility stance:
92
81
 
93
- - which entities belong in the same document
94
- - which entities should be split into separate resources
95
- - which resources should be public, private, or shared
96
- - how links should work across documents and Pods
82
+ - officially supported: `@comunica/query-sparql-solid` `4.x`
83
+ - not currently in the supported matrix: `3.x`
97
84
 
98
- `drizzle-solid` follows that reality. It provides a structured API, but keeps resource identity and document layout as part of the model.
85
+ If another in-process runtime already carries Comunica (for example `xpod`), inject that engine instead of forcing a second copy. See `docs/api/README.md` and `docs/guides/installation.md`.
99
86
 
100
87
  ## Quick start
101
88
 
102
- ### Install
89
+ 仓库里的主线 quick start 默认使用 `pod(session)`,因为它会把 `collection()` / `entity()` / `bind()` 语义直接写在代码里。
103
90
 
104
- ```bash
105
- yarn add @undefineds.co/drizzle-solid
106
- # or
107
- npm install @undefineds.co/drizzle-solid
108
- ```
109
-
110
- > In this repository, the examples import `drizzle-solid` through a local TypeScript path alias. In external applications, import the published package name: `@undefineds.co/drizzle-solid`.
111
-
112
- ### Define a model and run CRUD
91
+ 如果你已有大量 Drizzle 风格代码,`drizzle(session)` 仍然是正式可用入口。
113
92
 
114
93
  ```ts
115
94
  import {
116
- drizzle,
95
+ pod,
117
96
  podTable,
118
97
  string,
119
98
  datetime,
120
- eq,
121
99
  } from '@undefineds.co/drizzle-solid';
122
100
 
123
101
  const posts = podTable('posts', {
@@ -131,115 +109,84 @@ const posts = podTable('posts', {
131
109
  type: 'http://schema.org/CreativeWork',
132
110
  });
133
111
 
134
- const db = drizzle(session);
135
- await db.init([posts]);
112
+ const client = pod(session);
113
+ await client.init(posts);
114
+
115
+ const postsCollection = client.collection(posts);
136
116
 
137
- await db.insert(posts).values({
117
+ const created = await postsCollection.create({
138
118
  id: 'post-1',
139
119
  title: 'Hello Solid',
140
120
  content: 'Stored as RDF in a Pod document.',
141
121
  createdAt: new Date(),
142
122
  });
143
123
 
144
- const rows = await db.select()
145
- .from(posts)
146
- .where(eq(posts.id, 'post-1'));
124
+ const first = await postsCollection.first({
125
+ where: { id: 'post-1' },
126
+ });
147
127
 
148
- await db.update(posts)
149
- .set({ title: 'Updated title' })
150
- .where(eq(posts.id, 'post-1'));
128
+ const postIri = created?.['@id'] ?? postsCollection.iriFor({
129
+ id: 'post-1',
130
+ title: 'Hello Solid',
131
+ content: 'Stored as RDF in a Pod document.',
132
+ createdAt: new Date(),
133
+ });
151
134
 
152
- await db.delete(posts)
153
- .where(eq(posts.id, 'post-1'));
135
+ const post = client.entity(posts, postIri);
136
+ await post.update({ title: 'Updated title' });
137
+ await post.delete();
154
138
  ```
155
139
 
156
- ### Reusable schema + runtime binding
140
+ > 如果你保持 `drizzle(session)` 作为入口,语义并不会变:`base`、`subjectTemplate`、`IRI`、精确写目标这些约束仍然完全成立。
157
141
 
158
- ```ts
159
- import {
160
- drizzle,
161
- solidSchema,
162
- id,
163
- string,
164
- } from '@undefineds.co/drizzle-solid';
142
+ ## Reusable schema + runtime binding
165
143
 
166
- const profileSchema = solidSchema({
167
- id: id(),
168
- name: string('name').predicate('http://xmlns.com/foaf/0.1/name'),
169
- bio: string('bio').predicate('http://schema.org/description'),
170
- }, {
171
- type: 'http://xmlns.com/foaf/0.1/Person',
172
- });
144
+ Use `solidSchema(...)` when you want to separate the reusable data shape from where that data lives in a Pod.
173
145
 
174
- const db = drizzle(session);
146
+ 如果你使用 `pod()` façade:
175
147
 
176
- const profileTable = db.createTable(profileSchema, {
148
+ ```ts
149
+ const client = pod(session);
150
+ const profileTable = client.bind(profileSchema, {
177
151
  base: 'https://alice.example/profile/card',
178
152
  });
179
153
  ```
180
154
 
181
- ## Exact IRI operations
182
-
183
- For detail-page flows, remote links, shared resources, or exact mutation targets, use the IRI APIs:
184
-
185
- - `db.findByIri(table, iri)`
186
- - `db.updateByIri(table, iri, data)`
187
- - `db.deleteByIri(table, iri)`
188
- - `db.subscribeByIri(table, iri, options)`
155
+ 如果你保持 `drizzle()` 入口:
189
156
 
190
157
  ```ts
191
- const agent = await db.findByIri(agentTable, 'https://alice.example/data/agents.ttl#assistant');
192
-
193
- await db.updateByIri(
194
- agentTable,
195
- 'https://alice.example/data/agents.ttl#assistant',
196
- { description: 'Updated through explicit IRI' },
197
- );
198
-
199
- await db.deleteByIri(
200
- agentTable,
201
- 'https://alice.example/data/agents.ttl#assistant',
202
- );
158
+ const db = drizzle(session);
159
+ const profileTable = db.createTable(profileSchema, {
160
+ base: 'https://alice.example/profile/card',
161
+ });
203
162
  ```
204
163
 
205
- ## Subject templates and identity
164
+ ## Identity and placement
206
165
 
207
- `subjectTemplate` controls how record identity maps to Pod resources.
166
+ `subjectTemplate` defines how application identity maps onto Pod resources.
208
167
 
209
168
  Common patterns:
210
169
 
211
- - `#{id}`: fragment mode, many entities in one RDF file
212
- - `{id}.ttl`: document mode, one file per entity
213
- - `{id}.ttl#it`: document mode with stable in-document fragment
214
- - `{chatId}/{yyyy}/{MM}/{dd}/messages.ttl#{id}`: multi-variable, date-partitioned layouts
170
+ - `#{id}`: many entities inside one document
171
+ - `{id}.ttl`: one document per entity
172
+ - `{id}.ttl#it`: one document per entity with stable in-document fragment
173
+ - `{chatId}/messages.ttl#{id}`: multi-variable layouts and partitioned resources
215
174
 
216
- Example:
175
+ 这不是命名细节,而是持久化语义本身。
217
176
 
218
- ```ts
219
- const Message = podTable('Message', {
220
- id: string('id').primaryKey(),
221
- chatId: string('chatId').predicate('http://example.org/chatId'),
222
- content: string('content').predicate('http://schema.org/text'),
223
- timestamp: datetime('timestamp').predicate('http://schema.org/dateCreated'),
224
- }, {
225
- base: 'https://alice.example/data/chats/',
226
- subjectTemplate: '{chatId}/messages.ttl#{id}',
227
- type: 'http://schema.org/Message',
228
- });
229
- ```
177
+ ## Exact-target mutation semantics
230
178
 
231
- For reads, the library can often work from:
179
+ Reads and writes do not intentionally behave the same way.
232
180
 
233
- - a full IRI
234
- - all template variables
235
- - a narrower partial condition that scans a smaller bounded area
181
+ - list / filter reads can stay collection-oriented
182
+ - writes should prefer exact-target semantics
183
+ - incomplete `where(...)` information should not silently degrade into scan + mutate
184
+ - if a subject can only be resolved by multiple template variables, mutation should use an explicit IRI or provide all required variables
236
185
 
237
- Read-path and write-path semantics are intentionally different:
186
+ 所以最重要的变化不是“要不要换成 `pod()`”,而是:
238
187
 
239
- - **Read queries** (`select`, `db.query.*`) may use partial template information for list/filter flows when the resolver can keep the scan bounded.
240
- - **Mutations** (`update`, `delete`) require deterministic targets by default. If `where()` cannot uniquely resolve the subject from the template, the dialect throws and tells you to use `updateByIri()` / `deleteByIri()` (or to provide the missing template variables).
241
- - **No implicit scan-based `updateMany/deleteMany` fallback** is performed on backends that do not natively support set-based mutation.
242
- - **Capability-based enhancement**: if a backend explicitly supports filter-based multi-row mutation in the future (for example, an xpod capability), `drizzle-solid` can expose that path there without pretending every Solid server supports it.
188
+ - 什么时候你只是在做集合读取
189
+ - 什么时候你已经需要一个确定的实体目标
243
190
 
244
191
  ## Server support
245
192
 
@@ -247,118 +194,62 @@ Read-path and write-path semantics are intentionally different:
247
194
 
248
195
  | Capability | Community Solid Server | xpod |
249
196
  | --- | --- | --- |
250
- | Basic CRUD | ✅ LDP mode | ✅ LDP mode |
251
- | SPARQL SELECT pushdown | Client-side / resolver-driven | ✅ `/-/sparql` sidecar |
252
- | SPARQL UPDATE | ⚠️ Limited / write path stays LDP-oriented | ✅ Better server-side support |
253
- | Filter / aggregation pushdown | Fallbacks and client execution | ✅ Single-Pod pushdown |
197
+ | Basic CRUD | ✅ | ✅ |
198
+ | Document notifications | | ✅ |
199
+ | Drizzle-style read facade | | ✅ |
200
+ | SPARQL pushdown | ⚠️ Limited / often client-assisted | ✅ Better in-process support |
201
+ | Filter / aggregation pushdown | ❌ Mostly fallback execution | ✅ Better server-side support |
254
202
  | Federated queries | ⚠️ Client-side federation | ⚠️ Client-side federation |
255
- | Notifications | | ✅ |
256
- | In-process test runtime | ⚠️ External CSS setup | ✅ via `@undefineds.co/xpod` |
257
-
258
- ### Community Solid Server (CSS)
259
-
260
- On plain CSS, `drizzle-solid` keeps working, but many queries are resolved through client-side execution and Solid-aware fallbacks. This is the compatibility baseline.
261
-
262
- ### xpod
203
+ | In-process local runtime | ⚠️ External setup | ✅ via `@undefineds.co/xpod` |
263
204
 
264
- `xpod` adds a Solid-compatible SPARQL sidecar and is the recommended development/runtime target when you want stronger query pushdown and a lower-friction local setup.
265
-
266
- See `docs/xpod-features.md` for more detail.
205
+ If `xpod` already ships its own Comunica stack, `drizzle-solid` can reuse that copy instead of requiring another app-level install.
267
206
 
268
207
  ## Verified examples
269
208
 
270
- The canonical examples in `examples/` are verified in the test suite.
271
-
272
- - `examples/01-quick-start.ts` — CRUD quick start
273
- - `examples/02-relational-query.ts` — relational query API surface
274
- - `examples/03-zero-config-discovery.ts` — zero-config discovery flow
275
- - `examples/04-notifications.ts` — Solid notifications
276
- - `examples/05-data-discovery.ts` — discovery API
277
- - `examples/06-federated-query.ts` — federated query across Pods
278
- - `examples/07-hooks-and-profile.ts` — hooks and profile management
279
- - `examples/08-iri-based-operations.ts` — explicit IRI operations
280
- - `examples/08-schema-inheritance.ts` — schema inheritance
281
- - `examples/09-multi-variable-templates.ts` — multi-variable subject templates
282
-
283
- The example manifest lives at `examples/manifest.json`, and the integration verification lives at `tests/integration/css/examples-verification.test.ts`.
284
-
285
- ## Query surface and SQL scope
286
-
287
- `drizzle-solid` aims to stay close to Drizzle's public builder surface where that maps cleanly to Solid.
209
+ The canonical examples in `examples/` are part of the real integration verification flow:
288
210
 
289
- Current supported surface includes:
211
+ - `examples/01-quick-start.ts`
212
+ - `examples/02-relational-query.ts`
213
+ - `examples/03-zero-config-discovery.ts`
214
+ - `examples/04-notifications.ts`
215
+ - `examples/05-data-discovery.ts`
216
+ - `examples/06-federated-query.ts`
217
+ - `examples/07-hooks-and-profile.ts`
218
+ - `examples/08-iri-based-operations.ts`
219
+ - `examples/08-schema-inheritance.ts`
220
+ - `examples/09-multi-variable-templates.ts`
290
221
 
291
- - CRUD builders: `select`, `insert`, `update`, `delete`
292
- - Read-oriented query facade: `db.query.*.findMany`, `findFirst`, `findById`, `findByIRI`, `count`
293
- - Conditions: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `like`, `ilike`, `inArray`, `exists`, `and`, `or`, `not`
294
- - Query features: joins, ordering, limits, offsets, distinct
295
- - Aggregations: `count`, `sum`, `avg`, `min`, `max`
296
- - Batch and `returning()` support where implemented by the dialect
297
- - Raw **SPARQL** workflows where you need explicit graph-native control
298
-
299
- Not the mainline contract:
300
-
301
- - raw SQL as the primary abstraction
302
- - transaction semantics identical to SQL databases
303
- - implicit scan-based `updateMany/deleteMany` on backends that do not support set-based mutation
304
- - driver-specific DDL, auto-increment, foreign keys, or SQL engine behaviors
222
+ See `examples/manifest.json` and `tests/integration/css/examples-verification.test.ts`.
305
223
 
306
- The migration goal is API familiarity with low migration cost, but the execution model remains Solid/SPARQL-native rather than semantics-faking SQL emulation.
224
+ ## Migration
307
225
 
308
- ## Discovery, interoperability, and federation
226
+ If you already know `drizzle-orm`, start here:
309
227
 
310
- The library also includes higher-level Solid workflows:
228
+ - `docs/guides/migrating-from-drizzle-orm.md`
311
229
 
312
- - data discovery and interop metadata
313
- - TypeIndex-driven location discovery
314
- - shape-aware table generation
315
- - federated queries across discovered Pod locations
316
- - notifications for resource/entity updates
230
+ 那份指南重点解释的是:
317
231
 
318
- Useful starting points:
232
+ - `table/row` → `resource/document/entity/IRI`
233
+ - `link` / relation fields → RDF link / IRI link
234
+ - `where`-style mutation → exact-target mutation
235
+ - `toSQL()` / raw SQL 主心智 → `toSPARQL()` / SPARQL 主心智
319
236
 
320
- - `docs/guides/data-discovery.md`
321
- - `docs/guides/notifications.md`
322
- - `docs/guides/css-notifications.md`
323
- - `docs/federated-queries.md`
324
- - `docs/guides/multi-variable-templates.md`
237
+ 而不是要求你第一步先改掉构造函数名。
325
238
 
326
239
  ## Documentation map
327
240
 
328
- - `examples/README.md` — curated walkthroughs and runnable examples
329
- - `docs/quick-start-local.md` — local setup guide
241
+ - `docs/api/README.md` — current public API and constructor positioning
242
+ - `docs/guides/installation.md` — installation and SPARQL engine setup
243
+ - `docs/guides/migrating-from-drizzle-orm.md` — migration guide for Drizzle users
244
+ - `examples/README.md` — curated runnable examples
330
245
  - `docs/guides/data-discovery.md` — discovery workflows
331
- - `docs/guides/issue-handling.md` — issue reproduction and regression workflow
332
- - `docs/guides/testing.md` — test conventions and coverage strategy
333
- - `ACTION-PLAN.md` — current parity and implementation plan
334
-
335
- ## Planned scope
336
-
337
- ### Current direction
338
-
339
- The current focus is:
340
-
341
- - typed models for application-owned Pod data
342
- - explicit document and subject placement
343
- - Drizzle-aligned query ergonomics
344
- - practical CRUD, discovery, federation, and notification flows
345
-
346
- ### Likely next steps
347
-
348
- - better modeling ergonomics around reusable schemas and links
349
- - clearer guidance around multi-resource layouts and identity strategies
350
- - continued Drizzle parity on Solid-relevant behaviors
351
- - stronger documentation around Solid-native tradeoffs and migration paths
352
-
353
- ### Out of scope
354
-
355
- - hiding Solid behind a fake SQL database mental model
356
- - universal querying over arbitrary open-world RDF as the primary goal
357
- - promising full relational/database feature parity where Solid semantics differ
246
+ - `docs/guides/notifications.md` — notification flows
247
+ - `docs/xpod-features.md` — xpod runtime notes
248
+ - `ACTION-PLAN.md` — parity and implementation plan
358
249
 
359
250
  ## Contributing
360
251
 
361
- Before contributing:
252
+ Before pushing:
362
253
 
363
254
  ```bash
364
255
  yarn build
@@ -23,7 +23,7 @@ export declare class ASTToSPARQLConverter {
23
23
  private prefixes;
24
24
  constructor(podUrl: string, webId?: string | undefined, uriResolver?: UriResolver);
25
25
  /**
26
- * Set table registry for URI reference resolution
26
+ * Set table registry for URI link resolution
27
27
  */
28
28
  setTableRegistry(tableRegistry: Map<string, PodTable[]>, tableNameRegistry: Map<string, PodTable>, baseUri?: string): void;
29
29
  convertSelect(ast: any, table: PodTable, targetGraph?: string, fromSources?: string[], allowGraphVariable?: boolean): SPARQLQuery;
@@ -26,7 +26,7 @@ class ASTToSPARQLConverter {
26
26
  this.expressionBuilder = new expression_builder_1.ExpressionBuilder(this.uriResolver);
27
27
  }
28
28
  /**
29
- * Set table registry for URI reference resolution
29
+ * Set table registry for URI link resolution
30
30
  */
31
31
  setTableRegistry(tableRegistry, tableNameRegistry, baseUri) {
32
32
  this.tableContext = { tableRegistry, tableNameRegistry, baseUri };
@@ -1,7 +1,2 @@
1
- type NodeCreateRequire = (filename: string) => NodeRequire;
2
- declare const resolveCreateRequire: () => NodeCreateRequire | null;
3
- declare const createRequireFn: NodeCreateRequire | null;
4
- declare const moduleFilename: string;
5
- declare const requireModule: NodeRequire | null;
6
- declare const patchActionObserverHttp: (moduleName: string) => boolean;
1
+ export declare const applyComunicaPatches: (requireModule?: NodeRequire | null) => boolean;
7
2
  //# sourceMappingURL=comunica-patch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"comunica-patch.d.ts","sourceRoot":"","sources":["../../src/core/comunica-patch.ts"],"names":[],"mappings":"AAGA,KAAK,iBAAiB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,WAAW,CAAC;AAE3D,QAAA,MAAM,oBAAoB,QAAO,iBAAiB,GAAG,IAoBpD,CAAC;AAEF,QAAA,MAAM,eAAe,0BAAyB,CAAC;AAC/C,QAAA,MAAM,cAAc,QAIR,CAAC;AAEb,QAAA,MAAM,aAAa,oBAEX,CAAC;AAGT,QAAA,MAAM,uBAAuB,GAAI,YAAY,MAAM,YAkClD,CAAC"}
1
+ {"version":3,"file":"comunica-patch.d.ts","sourceRoot":"","sources":["../../src/core/comunica-patch.ts"],"names":[],"mappings":"AAkEA,eAAO,MAAM,oBAAoB,GAAI,gBAAe,WAAW,GAAG,IAA2B,KAAG,OAe/F,CAAC"}
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  // Comunica 兼容性补丁
3
3
  // 修复 ActionObserverHttp 中 observedActors 未定义的问题
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.applyComunicaPatches = void 0;
4
6
  const resolveCreateRequire = () => {
5
7
  if (typeof window !== 'undefined') {
6
8
  return null;
@@ -26,11 +28,10 @@ const moduleFilename = typeof __filename === 'string'
26
28
  : (typeof process !== 'undefined' && typeof process.cwd === 'function'
27
29
  ? process.cwd()
28
30
  : '/');
29
- const requireModule = createRequireFn
31
+ const defaultRequireModule = createRequireFn
30
32
  ? createRequireFn(moduleFilename)
31
33
  : null;
32
- // 直接修补所有 Comunica ActionObserverHttp
33
- const patchActionObserverHttp = (moduleName) => {
34
+ const patchActionObserverHttp = (requireModule, moduleName) => {
34
35
  if (!requireModule) {
35
36
  return false;
36
37
  }
@@ -39,15 +40,9 @@ const patchActionObserverHttp = (moduleName) => {
39
40
  if (comunica && comunica.ActionObserverHttp) {
40
41
  const originalOnRun = comunica.ActionObserverHttp.prototype.onRun;
41
42
  comunica.ActionObserverHttp.prototype.onRun = function (actor, _action, _output) {
42
- // 确保 observedActors 存在且是数组
43
- if (!this.observedActors) {
43
+ if (!this.observedActors || !Array.isArray(this.observedActors)) {
44
44
  this.observedActors = [];
45
45
  }
46
- // observedActors 应该是一个数组,如果不是则初始化为空数组
47
- if (!Array.isArray(this.observedActors)) {
48
- this.observedActors = [];
49
- }
50
- // 调用原始方法
51
46
  return originalOnRun.call(this, actor, _action, _output);
52
47
  };
53
48
  console.log(`[Patch] Successfully patched ActionObserverHttp.onRun in ${moduleName}`);
@@ -55,22 +50,24 @@ const patchActionObserverHttp = (moduleName) => {
55
50
  }
56
51
  return false;
57
52
  }
58
- catch (error) {
59
- // 静默忽略模块不存在的错误
53
+ catch {
60
54
  return false;
61
55
  }
62
56
  };
63
- // 修补所有可能的 ActionObserverHttp 实例
64
- // 包括顶层和 @comunica/query-sparql-solid 嵌套的 node_modules
65
- if (requireModule) {
57
+ const applyComunicaPatches = (requireModule = defaultRequireModule) => {
58
+ if (!requireModule) {
59
+ return false;
60
+ }
66
61
  const modules = [
67
- // 顶层模块
68
62
  '@comunica/actor-query-result-serialize-sparql-json',
69
63
  '@comunica/actor-query-result-serialize-stats',
70
- // 嵌套在 @comunica/query-sparql-solid 下的模块 (Comunica v4)
71
64
  '@comunica/query-sparql-solid/node_modules/@comunica/actor-query-result-serialize-sparql-json',
72
65
  '@comunica/query-sparql-solid/node_modules/@comunica/actor-query-result-serialize-stats'
73
66
  ];
74
- modules.forEach(patchActionObserverHttp);
75
- }
67
+ return modules
68
+ .map((moduleName) => patchActionObserverHttp(requireModule, moduleName))
69
+ .some(Boolean);
70
+ };
71
+ exports.applyComunicaPatches = applyComunicaPatches;
72
+ (0, exports.applyComunicaPatches)();
76
73
  //# sourceMappingURL=comunica-patch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"comunica-patch.js","sourceRoot":"","sources":["../../src/core/comunica-patch.ts"],"names":[],"mappings":";AAAA,iBAAiB;AACjB,gDAAgD;AAIhD,MAAM,oBAAoB,GAAG,GAA6B,EAAE;IAC1D,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAA4B,CAAC;QAC/D,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAsD,CAAC;QAC7F,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,CAAC,aAAa,KAAK,UAAU,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,SAAS,CAAC,aAAa,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,oBAAoB,EAAE,CAAC;AAC/C,MAAM,cAAc,GAAG,OAAO,UAAU,KAAK,QAAQ;IACnD,CAAC,CAAC,UAAU;IACZ,CAAC,CAAC,CAAC,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,UAAU;QAClE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;QACf,CAAC,CAAC,GAAG,CAAC,CAAC;AAEb,MAAM,aAAa,GAAG,eAAe;IACnC,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC;IACjC,CAAC,CAAC,IAAI,CAAC;AAET,yCAAyC;AACzC,MAAM,uBAAuB,GAAG,CAAC,UAAkB,EAAE,EAAE;IACrD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QAE3C,IAAI,QAAQ,IAAI,QAAQ,CAAC,kBAAkB,EAAE,CAAC;YAC5C,MAAM,aAAa,GAAG,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,KAAK,CAAC;YAElE,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,KAAK,GAAG,UAAS,KAAU,EAAE,OAAY,EAAE,OAAY;gBAC3F,2BAA2B;gBAC3B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;oBACzB,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;gBAC3B,CAAC;gBAED,sCAAsC;gBACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;oBACxC,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;gBAC3B,CAAC;gBAED,SAAS;gBACT,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC3D,CAAC,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,4DAA4D,UAAU,EAAE,CAAC,CAAC;YACtF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAe;QACf,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,gCAAgC;AAChC,sDAAsD;AACtD,IAAI,aAAa,EAAE,CAAC;IAClB,MAAM,OAAO,GAAG;QACd,OAAO;QACP,oDAAoD;QACpD,8CAA8C;QAC9C,sDAAsD;QACtD,8FAA8F;QAC9F,wFAAwF;KACzF,CAAC;IAEF,OAAO,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"comunica-patch.js","sourceRoot":"","sources":["../../src/core/comunica-patch.ts"],"names":[],"mappings":";AAAA,iBAAiB;AACjB,gDAAgD;;;AAIhD,MAAM,oBAAoB,GAAG,GAA6B,EAAE;IAC1D,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAA4B,CAAC;QAC/D,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAsD,CAAC;QAC7F,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,CAAC,aAAa,KAAK,UAAU,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,SAAS,CAAC,aAAa,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,oBAAoB,EAAE,CAAC;AAC/C,MAAM,cAAc,GAAG,OAAO,UAAU,KAAK,QAAQ;IACnD,CAAC,CAAC,UAAU;IACZ,CAAC,CAAC,CAAC,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,UAAU;QAClE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;QACf,CAAC,CAAC,GAAG,CAAC,CAAC;AAEb,MAAM,oBAAoB,GAAG,eAAe;IAC1C,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC;IACjC,CAAC,CAAC,IAAI,CAAC;AAET,MAAM,uBAAuB,GAAG,CAAC,aAAiC,EAAE,UAAkB,EAAE,EAAE;IACxF,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QAE3C,IAAI,QAAQ,IAAI,QAAQ,CAAC,kBAAkB,EAAE,CAAC;YAC5C,MAAM,aAAa,GAAG,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,KAAK,CAAC;YAElE,QAAQ,CAAC,kBAAkB,CAAC,SAAS,CAAC,KAAK,GAAG,UAAS,KAAU,EAAE,OAAY,EAAE,OAAY;gBAC3F,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;oBAChE,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;gBAC3B,CAAC;gBAED,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC3D,CAAC,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,4DAA4D,UAAU,EAAE,CAAC,CAAC;YACtF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEK,MAAM,oBAAoB,GAAG,CAAC,gBAAoC,oBAAoB,EAAW,EAAE;IACxG,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAG;QACd,oDAAoD;QACpD,8CAA8C;QAC9C,8FAA8F;QAC9F,wFAAwF;KACzF,CAAC;IAEF,OAAO,OAAO;SACX,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,uBAAuB,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;SACvE,IAAI,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC,CAAC;AAfW,QAAA,oBAAoB,wBAe/B;AAEF,IAAA,4BAAoB,GAAE,CAAC"}