semanticdb-v2 2.0.0-alpha.1

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 (306) hide show
  1. package/README.md +448 -0
  2. package/dist/cache/expiry.d.ts +5 -0
  3. package/dist/cache/expiry.js +1 -0
  4. package/dist/cache/identity.d.ts +3 -0
  5. package/dist/cache/identity.js +1 -0
  6. package/dist/cache/index.d.ts +3 -0
  7. package/dist/cache/redis-query-cache.d.ts +37 -0
  8. package/dist/cache/redis-query-cache.js +1 -0
  9. package/dist/cache/serialization.d.ts +3 -0
  10. package/dist/cache/serialization.js +1 -0
  11. package/dist/cache/types.d.ts +27 -0
  12. package/dist/calendar/constants.d.ts +7 -0
  13. package/dist/calendar/constants.js +1 -0
  14. package/dist/calendar/index.d.ts +6 -0
  15. package/dist/calendar/provider-relation-store.d.ts +9 -0
  16. package/dist/calendar/provider-relation-store.js +1 -0
  17. package/dist/calendar/resolver.d.ts +10 -0
  18. package/dist/calendar/resolver.js +1 -0
  19. package/dist/calendar/system-schemas.d.ts +3 -0
  20. package/dist/calendar/system-schemas.js +1 -0
  21. package/dist/calendar/types.d.ts +31 -0
  22. package/dist/compatibility/index.d.ts +2 -0
  23. package/dist/compatibility/logicform.d.ts +13 -0
  24. package/dist/compatibility/logicform.js +1 -0
  25. package/dist/compiler/compile-cte.d.ts +12 -0
  26. package/dist/compiler/compile-cte.js +1 -0
  27. package/dist/compiler/compile-plan.d.ts +5 -0
  28. package/dist/compiler/compile-plan.js +1 -0
  29. package/dist/compiler/index.d.ts +4 -0
  30. package/dist/compiler/shorten-sql.d.ts +2 -0
  31. package/dist/compiler/shorten-sql.js +2 -0
  32. package/dist/compiler/types.d.ts +5 -0
  33. package/dist/custom-functions/custom-functions.d.ts +6 -0
  34. package/dist/custom-functions/custom-functions.js +1 -0
  35. package/dist/custom-functions/index.d.ts +3 -0
  36. package/dist/custom-functions/operator-adapter.d.ts +12 -0
  37. package/dist/custom-functions/operator-adapter.js +1 -0
  38. package/dist/custom-functions/types.d.ts +62 -0
  39. package/dist/errors.d.ts +5 -0
  40. package/dist/errors.js +1 -0
  41. package/dist/executor/compatibility.d.ts +6 -0
  42. package/dist/executor/compatibility.js +1 -0
  43. package/dist/executor/components.d.ts +9 -0
  44. package/dist/executor/components.js +1 -0
  45. package/dist/executor/connection-registry.d.ts +12 -0
  46. package/dist/executor/connection-registry.js +1 -0
  47. package/dist/executor/evaluate.d.ts +4 -0
  48. package/dist/executor/evaluate.js +1 -0
  49. package/dist/executor/execute-query.d.ts +13 -0
  50. package/dist/executor/execute-query.js +1 -0
  51. package/dist/executor/execute.d.ts +4 -0
  52. package/dist/executor/execute.js +1 -0
  53. package/dist/executor/fetch-entities.d.ts +26 -0
  54. package/dist/executor/fetch-entities.js +1 -0
  55. package/dist/executor/index.d.ts +3 -0
  56. package/dist/executor/result-hydrator/entity-loader.d.ts +6 -0
  57. package/dist/executor/result-hydrator/entity-loader.js +1 -0
  58. package/dist/executor/result-hydrator/format-values.d.ts +4 -0
  59. package/dist/executor/result-hydrator/format-values.js +1 -0
  60. package/dist/executor/result-hydrator/hydrate-result.d.ts +4 -0
  61. package/dist/executor/result-hydrator/hydrate-result.js +1 -0
  62. package/dist/executor/result-hydrator/index.d.ts +2 -0
  63. package/dist/executor/result-hydrator/missing-entity.d.ts +3 -0
  64. package/dist/executor/result-hydrator/missing-entity.js +1 -0
  65. package/dist/executor/result-hydrator/populate-entities.d.ts +3 -0
  66. package/dist/executor/result-hydrator/populate-entities.js +1 -0
  67. package/dist/executor/result-hydrator/types.d.ts +14 -0
  68. package/dist/executor/row-identity.d.ts +4 -0
  69. package/dist/executor/row-identity.js +1 -0
  70. package/dist/executor/types.d.ts +118 -0
  71. package/dist/index.d.ts +26 -0
  72. package/dist/index.js +1 -0
  73. package/dist/logicform-types.d.ts +125 -0
  74. package/dist/logicform-types.js +1 -0
  75. package/dist/normalizer/core.d.ts +19 -0
  76. package/dist/normalizer/core.js +1 -0
  77. package/dist/normalizer/default-pred-name.d.ts +6 -0
  78. package/dist/normalizer/default-pred-name.js +1 -0
  79. package/dist/normalizer/entity-id.d.ts +4 -0
  80. package/dist/normalizer/entity-id.js +1 -0
  81. package/dist/normalizer/groupby.d.ts +4 -0
  82. package/dist/normalizer/groupby.js +1 -0
  83. package/dist/normalizer/index.d.ts +3 -0
  84. package/dist/normalizer/normalize-logicform.d.ts +4 -0
  85. package/dist/normalizer/normalize-logicform.js +1 -0
  86. package/dist/normalizer/pagination.d.ts +2 -0
  87. package/dist/normalizer/pagination.js +1 -0
  88. package/dist/normalizer/pred-query-name.d.ts +1 -0
  89. package/dist/normalizer/pred-query-name.js +1 -0
  90. package/dist/normalizer/preds.d.ts +4 -0
  91. package/dist/normalizer/preds.js +1 -0
  92. package/dist/normalizer/query.d.ts +5 -0
  93. package/dist/normalizer/query.js +1 -0
  94. package/dist/normalizer/version.d.ts +3 -0
  95. package/dist/normalizer/version.js +1 -0
  96. package/dist/operators/builtins/abs.d.ts +2 -0
  97. package/dist/operators/builtins/abs.js +1 -0
  98. package/dist/operators/builtins/accumulate.d.ts +2 -0
  99. package/dist/operators/builtins/accumulate.js +1 -0
  100. package/dist/operators/builtins/add.d.ts +2 -0
  101. package/dist/operators/builtins/add.js +1 -0
  102. package/dist/operators/builtins/arithmetic.d.ts +3 -0
  103. package/dist/operators/builtins/arithmetic.js +1 -0
  104. package/dist/operators/builtins/average-per-period.d.ts +2 -0
  105. package/dist/operators/builtins/average-per-period.js +1 -0
  106. package/dist/operators/builtins/avg.d.ts +2 -0
  107. package/dist/operators/builtins/avg.js +1 -0
  108. package/dist/operators/builtins/case.d.ts +2 -0
  109. package/dist/operators/builtins/case.js +1 -0
  110. package/dist/operators/builtins/concat.d.ts +2 -0
  111. package/dist/operators/builtins/concat.js +1 -0
  112. package/dist/operators/builtins/count-distinct.d.ts +2 -0
  113. package/dist/operators/builtins/count-distinct.js +1 -0
  114. package/dist/operators/builtins/count.d.ts +2 -0
  115. package/dist/operators/builtins/count.js +1 -0
  116. package/dist/operators/builtins/date-bucket.d.ts +2 -0
  117. package/dist/operators/builtins/date-bucket.js +1 -0
  118. package/dist/operators/builtins/divide.d.ts +2 -0
  119. package/dist/operators/builtins/divide.js +1 -0
  120. package/dist/operators/builtins/index.d.ts +2 -0
  121. package/dist/operators/builtins/index.js +1 -0
  122. package/dist/operators/builtins/max.d.ts +2 -0
  123. package/dist/operators/builtins/max.js +1 -0
  124. package/dist/operators/builtins/min.d.ts +2 -0
  125. package/dist/operators/builtins/min.js +1 -0
  126. package/dist/operators/builtins/multiply.d.ts +2 -0
  127. package/dist/operators/builtins/multiply.js +1 -0
  128. package/dist/operators/builtins/newly.d.ts +2 -0
  129. package/dist/operators/builtins/newly.js +1 -0
  130. package/dist/operators/builtins/period-boundary.d.ts +2 -0
  131. package/dist/operators/builtins/period-boundary.js +1 -0
  132. package/dist/operators/builtins/period-difference.d.ts +2 -0
  133. package/dist/operators/builtins/period-difference.js +1 -0
  134. package/dist/operators/builtins/period-growth.d.ts +2 -0
  135. package/dist/operators/builtins/period-growth.js +1 -0
  136. package/dist/operators/builtins/period-name.d.ts +1 -0
  137. package/dist/operators/builtins/period-name.js +1 -0
  138. package/dist/operators/builtins/period-shift.d.ts +6 -0
  139. package/dist/operators/builtins/period-shift.js +1 -0
  140. package/dist/operators/builtins/rank.d.ts +2 -0
  141. package/dist/operators/builtins/rank.js +1 -0
  142. package/dist/operators/builtins/row-number.d.ts +2 -0
  143. package/dist/operators/builtins/row-number.js +1 -0
  144. package/dist/operators/builtins/share-of-total.d.ts +2 -0
  145. package/dist/operators/builtins/share-of-total.js +1 -0
  146. package/dist/operators/builtins/sql.d.ts +3 -0
  147. package/dist/operators/builtins/sql.js +1 -0
  148. package/dist/operators/builtins/substring.d.ts +2 -0
  149. package/dist/operators/builtins/substring.js +1 -0
  150. package/dist/operators/builtins/subtract.d.ts +2 -0
  151. package/dist/operators/builtins/subtract.js +1 -0
  152. package/dist/operators/builtins/sum.d.ts +2 -0
  153. package/dist/operators/builtins/sum.js +1 -0
  154. package/dist/operators/builtins/time-range.d.ts +13 -0
  155. package/dist/operators/builtins/time-range.js +1 -0
  156. package/dist/operators/groupby.d.ts +3 -0
  157. package/dist/operators/groupby.js +1 -0
  158. package/dist/operators/index.d.ts +7 -0
  159. package/dist/operators/index.js +1 -0
  160. package/dist/operators/registry.d.ts +10 -0
  161. package/dist/operators/registry.js +1 -0
  162. package/dist/operators/sql-expression.d.ts +1 -0
  163. package/dist/operators/sql-expression.js +1 -0
  164. package/dist/operators/types.d.ts +277 -0
  165. package/dist/permissions/index.d.ts +3 -0
  166. package/dist/permissions/permissions.d.ts +10 -0
  167. package/dist/permissions/permissions.js +1 -0
  168. package/dist/permissions/types.d.ts +12 -0
  169. package/dist/physical/clickhouse-provider.d.ts +44 -0
  170. package/dist/physical/clickhouse-provider.js +1 -0
  171. package/dist/physical/connection.d.ts +32 -0
  172. package/dist/physical/connection.js +1 -0
  173. package/dist/physical/display-query.d.ts +4 -0
  174. package/dist/physical/display-query.js +1 -0
  175. package/dist/physical/doris-provider.d.ts +9 -0
  176. package/dist/physical/doris-provider.js +1 -0
  177. package/dist/physical/index.d.ts +18 -0
  178. package/dist/physical/mysql-compatible-sql.d.ts +6 -0
  179. package/dist/physical/mysql-compatible-sql.js +1 -0
  180. package/dist/physical/mysql-protocol-provider.d.ts +34 -0
  181. package/dist/physical/mysql-protocol-provider.js +1 -0
  182. package/dist/physical/mysql-provider.d.ts +8 -0
  183. package/dist/physical/mysql-provider.js +1 -0
  184. package/dist/physical/oracle-provider.d.ts +53 -0
  185. package/dist/physical/oracle-provider.js +1 -0
  186. package/dist/physical/postgresql-provider.d.ts +37 -0
  187. package/dist/physical/postgresql-provider.js +1 -0
  188. package/dist/physical/provider.d.ts +40 -0
  189. package/dist/physical/snowflake-provider.d.ts +45 -0
  190. package/dist/physical/snowflake-provider.js +1 -0
  191. package/dist/physical/starrocks-provider.d.ts +9 -0
  192. package/dist/physical/starrocks-provider.js +1 -0
  193. package/dist/planner/build-lineage.d.ts +5 -0
  194. package/dist/planner/build-lineage.js +1 -0
  195. package/dist/planner/create-logical-plan.d.ts +15 -0
  196. package/dist/planner/create-logical-plan.js +1 -0
  197. package/dist/planner/index.d.ts +7 -0
  198. package/dist/planner/select-schema-mapping.d.ts +14 -0
  199. package/dist/planner/select-schema-mapping.js +1 -0
  200. package/dist/planner/semantics/index.d.ts +5 -0
  201. package/dist/planner/semantics/lifecycle/classification.d.ts +7 -0
  202. package/dist/planner/semantics/lifecycle/classification.js +1 -0
  203. package/dist/planner/semantics/lifecycle/index.d.ts +3 -0
  204. package/dist/planner/semantics/lifecycle/query-policy.d.ts +3 -0
  205. package/dist/planner/semantics/lifecycle/query-policy.js +1 -0
  206. package/dist/planner/semantics/lifecycle/rule.d.ts +2 -0
  207. package/dist/planner/semantics/lifecycle/rule.js +1 -0
  208. package/dist/planner/semantics/observation/classification.d.ts +3 -0
  209. package/dist/planner/semantics/observation/classification.js +1 -0
  210. package/dist/planner/semantics/observation/index.d.ts +4 -0
  211. package/dist/planner/semantics/observation/operator-policy.d.ts +11 -0
  212. package/dist/planner/semantics/observation/operator-policy.js +1 -0
  213. package/dist/planner/semantics/observation/rule.d.ts +2 -0
  214. package/dist/planner/semantics/observation/rule.js +1 -0
  215. package/dist/planner/semantics/observation/types.d.ts +3 -0
  216. package/dist/planner/semantics/registry-defaults.d.ts +2 -0
  217. package/dist/planner/semantics/registry-defaults.js +1 -0
  218. package/dist/planner/semantics/registry.d.ts +32 -0
  219. package/dist/planner/semantics/registry.js +1 -0
  220. package/dist/planner/types.d.ts +202 -0
  221. package/dist/planner/types.js +1 -0
  222. package/dist/plugins/hierarchy/compatibility.d.ts +2 -0
  223. package/dist/plugins/hierarchy/compatibility.js +1 -0
  224. package/dist/plugins/hierarchy/entity-identity.d.ts +2 -0
  225. package/dist/plugins/hierarchy/entity-identity.js +1 -0
  226. package/dist/plugins/hierarchy/index.d.ts +3 -0
  227. package/dist/plugins/hierarchy/index.js +1 -0
  228. package/dist/plugins/hierarchy/operator.d.ts +2 -0
  229. package/dist/plugins/hierarchy/operator.js +1 -0
  230. package/dist/plugins/hierarchy/resolve-schema.d.ts +2 -0
  231. package/dist/plugins/hierarchy/resolve-schema.js +1 -0
  232. package/dist/plugins/hierarchy/types.d.ts +28 -0
  233. package/dist/plugins/index.d.ts +5 -0
  234. package/dist/plugins/index.js +1 -0
  235. package/dist/plugins/types.d.ts +20 -0
  236. package/dist/schema/entity-identity.d.ts +5 -0
  237. package/dist/schema/entity-identity.js +1 -0
  238. package/dist/schema/index.d.ts +4 -0
  239. package/dist/schema/resolve-property-path.d.ts +15 -0
  240. package/dist/schema/resolve-property-path.js +1 -0
  241. package/dist/schema/schema-registry.d.ts +4 -0
  242. package/dist/schema/schema-registry.js +1 -0
  243. package/dist/schema-mappings/freshness.d.ts +7 -0
  244. package/dist/schema-mappings/freshness.js +1 -0
  245. package/dist/schema-mappings/index.d.ts +4 -0
  246. package/dist/schema-mappings/registry.d.ts +9 -0
  247. package/dist/schema-mappings/registry.js +1 -0
  248. package/dist/schema-mappings/types.d.ts +46 -0
  249. package/dist/semantic-types/builtins/boolean.d.ts +2 -0
  250. package/dist/semantic-types/builtins/boolean.js +1 -0
  251. package/dist/semantic-types/builtins/category.d.ts +2 -0
  252. package/dist/semantic-types/builtins/category.js +1 -0
  253. package/dist/semantic-types/builtins/currency.d.ts +2 -0
  254. package/dist/semantic-types/builtins/currency.js +1 -0
  255. package/dist/semantic-types/builtins/date.d.ts +2 -0
  256. package/dist/semantic-types/builtins/date.js +1 -0
  257. package/dist/semantic-types/builtins/duration.d.ts +2 -0
  258. package/dist/semantic-types/builtins/duration.js +1 -0
  259. package/dist/semantic-types/builtins/end-date.d.ts +2 -0
  260. package/dist/semantic-types/builtins/end-date.js +1 -0
  261. package/dist/semantic-types/builtins/entity.d.ts +2 -0
  262. package/dist/semantic-types/builtins/entity.js +1 -0
  263. package/dist/semantic-types/builtins/file.d.ts +2 -0
  264. package/dist/semantic-types/builtins/file.js +1 -0
  265. package/dist/semantic-types/builtins/human-name.d.ts +2 -0
  266. package/dist/semantic-types/builtins/human-name.js +1 -0
  267. package/dist/semantic-types/builtins/id.d.ts +2 -0
  268. package/dist/semantic-types/builtins/id.js +1 -0
  269. package/dist/semantic-types/builtins/image.d.ts +2 -0
  270. package/dist/semantic-types/builtins/image.js +1 -0
  271. package/dist/semantic-types/builtins/index.d.ts +2 -0
  272. package/dist/semantic-types/builtins/index.js +1 -0
  273. package/dist/semantic-types/builtins/int.d.ts +2 -0
  274. package/dist/semantic-types/builtins/int.js +1 -0
  275. package/dist/semantic-types/builtins/name.d.ts +2 -0
  276. package/dist/semantic-types/builtins/name.js +1 -0
  277. package/dist/semantic-types/builtins/number.d.ts +2 -0
  278. package/dist/semantic-types/builtins/number.js +1 -0
  279. package/dist/semantic-types/builtins/object.d.ts +3 -0
  280. package/dist/semantic-types/builtins/object.js +1 -0
  281. package/dist/semantic-types/builtins/order.d.ts +2 -0
  282. package/dist/semantic-types/builtins/order.js +1 -0
  283. package/dist/semantic-types/builtins/percentage.d.ts +2 -0
  284. package/dist/semantic-types/builtins/percentage.js +1 -0
  285. package/dist/semantic-types/builtins/start-date.d.ts +2 -0
  286. package/dist/semantic-types/builtins/start-date.js +1 -0
  287. package/dist/semantic-types/builtins/string.d.ts +2 -0
  288. package/dist/semantic-types/builtins/string.js +1 -0
  289. package/dist/semantic-types/builtins/timestamp.d.ts +2 -0
  290. package/dist/semantic-types/builtins/timestamp.js +1 -0
  291. package/dist/semantic-types/index.d.ts +9 -0
  292. package/dist/semantic-types/index.js +1 -0
  293. package/dist/semantic-types/primal-types/date.d.ts +2 -0
  294. package/dist/semantic-types/primal-types/date.js +1 -0
  295. package/dist/semantic-types/primal-types/index.d.ts +2 -0
  296. package/dist/semantic-types/primal-types/index.js +1 -0
  297. package/dist/semantic-types/registry.d.ts +14 -0
  298. package/dist/semantic-types/registry.js +1 -0
  299. package/dist/semantic-types/resolve-schema.d.ts +4 -0
  300. package/dist/semantic-types/resolve-schema.js +1 -0
  301. package/dist/semantic-types/types.d.ts +90 -0
  302. package/dist/semantic-types/validate-resolved-schema.d.ts +6 -0
  303. package/dist/semantic-types/validate-resolved-schema.js +1 -0
  304. package/dist/utils/clone.d.ts +1 -0
  305. package/dist/utils/clone.js +1 -0
  306. package/package.json +62 -0
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const newlyOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as s}from"../../errors.js";import{resolvePropertyPath as w}from"../../schema/resolve-property-path.js";import{clone as y}from"../../utils/clone.js";import{resolvePredTimeRange as l,withTimeCondition as f}from"./time-range.js";import{groupbyPropertyReference as _,groupbyOutputName as E}from"../groupby.js";const g=t=>{const e=y(t);return delete e.having,delete e.sort,delete e.limit,delete e.page,e},i=t=>{const e=y(t);return delete e.query,e.pred&&typeof e.pred=="object"&&(e.pred=i(e.pred)),e.components&&(e.components=e.components.map(i)),e},N={name:"$newly",defaultName:({operandName:t,locale:e})=>e.toLowerCase().startsWith("en")?`New ${t}`:`\u65B0\u589E${t}`,kind:"component",createComponent({logicform:t,pred:e,schema:m,resolveSchema:a}){if(!e.pred||typeof e.pred!="object"||Array.isArray(e.pred))throw new s("INVALID_NEWLY_INPUT","$newly pred must be a nested metric");if((t.groupby??[]).some(n=>{const o=_(n);return o?w(m,o,a).property.type==="timestamp":!1}))throw new s("NEWLY_TIME_GROUPBY_UNSUPPORTED","$newly does not support grouping by the timestamp property");const r=l(t.query,e,m,a,"$newly");if(r.start===void 0||r.end===void 0)throw new s("NEWLY_RANGE_REQUIRED","$newly requires both start and end timestamp bounds");const u=i(e.pred),d=(n,o)=>{const p=g(t);return p.query=f(r.queryWithoutTime,r.propertyName,{$lte:n}),p.preds=[{...u,name:o}],p},c=(t.groupby??[]).map(E);return{kind:"cte",components:[{name:"end",component:{kind:"query",logicform:d(r.end,"__newly_end__")}},{name:"start",component:{kind:"query",logicform:d(r.start,"__newly_start__")},joinKeys:c}],toSQL:({values:n})=>`${n.end} - COALESCE(${n.start}, 0)`}},getOutputProperty({name:t,inputProperty:e}){if(!e)throw new Error("$newly requires a nested metric");return{...e,name:t,isArray:!1}}};export{N as newlyOperator};
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const periodBoundaryOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as n}from"../../errors.js";import{clone as u}from"../../utils/clone.js";import{resolvePredTimeRange as c,withTimeCondition as _}from"./time-range.js";const l=r=>{const e=u(r);return delete e.having,delete e.sort,delete e.limit,delete e.page,e},s=r=>{const e=u(r);return delete e.query,e.pred&&typeof e.pred=="object"&&(e.pred=s(e.pred)),e.components&&(e.components=e.components.map(s)),e},b={name:"$periodBoundary",defaultName:({operandName:r,args:e,locale:a})=>a.toLowerCase().startsWith("en")?`${r} at period ${e.boundary==="start"?"start":"end"}`:`${r}${e.boundary==="start"?"\u671F\u521D\u503C":"\u671F\u672B\u503C"}`,kind:"component",observationPolicy({pred:r}){const e=r.args?.boundary;if(e!=="start"&&e!=="end")throw new n("INVALID_PERIOD_BOUNDARY_ARGS","$periodBoundary args.boundary must be start or end",{boundary:e});return{boundary:e,implicit:!1}},createComponent({logicform:r,pred:e,outputName:a,schema:i,resolveSchema:y}){if(!e.pred||typeof e.pred!="object"||Array.isArray(e.pred))throw new n("INVALID_PERIOD_BOUNDARY_INPUT","$periodBoundary pred must be a nested metric");const o=e.args?.boundary;if(o!=="start"&&o!=="end")throw new n("INVALID_PERIOD_BOUNDARY_ARGS","$periodBoundary args.boundary must be start or end");const t=c(r.query,e,i,y,"$periodBoundary"),p=o==="start"?t.start:t.end;if(p===void 0)throw new n("PERIOD_BOUNDARY_RANGE_REQUIRED",`$periodBoundary cannot resolve the ${o} of the timestamp query`);const m={version:r.version,schema:i.id,query:{[t.propertyName]:{$lte:p}},preds:[{operator:"$max",pred:t.propertyName,name:"__period_boundary_date__"}]},d=l(r);return d.query=_(t.queryWithoutTime,t.propertyName,m),d.preds=[{...s(e.pred),name:a}],{kind:"query",logicform:d}},getOutputProperty({name:r,inputProperty:e}){if(!e)throw new Error("$periodBoundary requires a nested metric");return{...e,name:r,isArray:!1}}};export{b as periodBoundaryOperator};
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const periodDifferenceOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ import{clone as n}from"../../utils/clone.js";import{combineQueries as m,collectPredQueries as a,buildPeriodShiftComponent as _}from"./period-shift.js";import{periodComparisonName as d}from"./period-name.js";const y=r=>{const e=n(r);return delete e.having,delete e.sort,delete e.limit,delete e.page,e},$=({logicform:r,pred:e,schema:t,resolveSchema:u})=>{if(!e.pred||typeof e.pred!="object"||Array.isArray(e.pred))throw new Error("$periodDifference pred must be a nested metric");const i=n(e.pred);i.name="__period_difference_current__";const o=y(r);o.preds=[i];const c=m([r.query,...a(e)]);c&&(o.query=c);const f={pred:n(e.pred),...e.args?{args:e.args}:{}},s=_({logicform:r,pred:f,outputName:"__period_difference_previous__",schema:t,resolveSchema:u});if(s.kind!=="query")throw new Error("$periodDifference period shift must produce a query component");return{kind:"cte",components:[{name:"current",component:{kind:"query",logicform:o}},{name:"previous",component:s}],toSQL:({values:p})=>`${p.current} - ${p.previous}`}},h={name:"$periodDifference",defaultName:({operandName:r,args:e,locale:t})=>t.toLowerCase().startsWith("en")?`${r} ${d(e,t)} difference`:`${r}${d(e,t)}\u5DEE\u503C`,kind:"component",createComponent:$,getOutputProperty({name:r,inputProperty:e}){if(!e)throw new Error("$periodDifference requires a nested metric");return{...e,name:r,isArray:!1}}};export{h as periodDifferenceOperator};
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const periodGrowthOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ import{clone as n}from"../../utils/clone.js";import{combineQueries as a,collectPredQueries as h,buildPeriodShiftComponent as w}from"./period-shift.js";import{periodComparisonName as d}from"./period-name.js";const y=r=>{const e=n(r);return delete e.having,delete e.sort,delete e.limit,delete e.page,e},_=({logicform:r,pred:e,schema:t,resolveSchema:c})=>{if(!e.pred||typeof e.pred!="object"||Array.isArray(e.pred))throw new Error("$periodGrowth pred must be a nested metric");const i=n(e.pred);i.name="__period_growth_current__";const o=y(r);o.preds=[i];const p=a([r.query,...h(e)]);p&&(o.query=p);const m={pred:n(e.pred),...e.args?{args:e.args}:{}},s=w({logicform:r,pred:m,outputName:"__period_growth_previous__",schema:t,resolveSchema:c});if(s.kind!=="query")throw new Error("$periodGrowth period shift must produce a query component");return{kind:"cte",components:[{name:"current",component:{kind:"query",logicform:o}},{name:"previous",component:s}],toSQL:({values:u})=>`${u.current} / NULLIF(ABS(${u.previous}), 0) - 1`}},f={name:"$periodGrowth",defaultName:({operandName:r,args:e,locale:t})=>t.toLowerCase().startsWith("en")?`${r} ${d(e,t)} growth`:`${r}${d(e,t)}\u589E\u957F\u7387`,kind:"component",createComponent:_,getOutputProperty({name:r}){return{name:r,type:"percentage",primal_type:"number",isArray:!1}}};export{f as periodGrowthOperator};
@@ -0,0 +1 @@
1
+ export declare const periodComparisonName: (args: Readonly<Record<string, unknown>>, locale: string) => string;
@@ -0,0 +1 @@
1
+ const s=o=>typeof o=="object"&&o!==null&&!Array.isArray(o),f={second:"\u79D2",minute:"\u5206\u949F",hour:"\u5C0F\u65F6",day:"\u65E5",week:"\u5468",month:"\u6708",quarter:"\u5B63\u5EA6",year:"\u5E74"},u={year:"\u5E74",quarter:"\u5B63\u5EA6",month:"\u6708",week:"\u5468",day:"\u65E5",hour:"\u65F6",minute:"\u5206",second:"\u79D2"},y=(o,a)=>{const e=a.toLowerCase().startsWith("en"),r=o.time;if(!s(r))return e?"period-over-period":"\u540C\u671F";if(typeof r.granularity=="string"&&typeof r.offset=="number"){if(r.offset===-1&&r.granularity==="year")return e?"year-over-year":"\u540C\u6BD4";if(r.offset===-1&&r.granularity==="month")return e?"month-over-month":"\u73AF\u6BD4";if(r.offset===-1&&r.granularity==="week")return e?"week-over-week":"\u5468\u73AF\u6BD4";if(r.offset===0)return e?"current-period":"\u672C\u671F";const t=Math.abs(r.offset),n=r.offset<0?"before":"after";return e?`${t} ${r.granularity}${t===1?"":"s"} ${n}`:`\u8F83${n==="before"?"\u524D":"\u540E"}${t}${f[r.granularity]??"\u671F"}`}const i=Object.entries(r).map(([t,n])=>e?`${t} ${String(n)}`:`${String(n)}${u[t]??t}`).join(e?", ":"");return e?`compared with ${i}`:`\u5BF9\u6BD4${i}`};export{y as periodComparisonName};
@@ -0,0 +1,6 @@
1
+ import type { PredItemType, QueryType } from '../../logicform-types';
2
+ import type { OperatorComponentContext, OperatorDefinition, OperatorExecutionComponent } from '../types';
3
+ export declare const combineQueries: (queries: readonly (QueryType | undefined)[]) => QueryType | undefined;
4
+ export declare const collectPredQueries: (pred: PredItemType) => QueryType[];
5
+ export declare const buildPeriodShiftComponent: ({ logicform, pred, outputName, schema, resolveSchema, }: OperatorComponentContext) => OperatorExecutionComponent;
6
+ export declare const periodShiftOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ import y from"dayjs";import Y from"dayjs/plugin/isoWeek.js";import k from"dayjs/plugin/quarterOfYear.js";import{SemanticDBError as h}from"../../errors.js";import{resolvePropertyPath as A}from"../../schema/resolve-property-path.js";import{clone as I}from"../../utils/clone.js";import{groupbyPropertyReference as E,groupbyOutputName as _}from"../groupby.js";import{periodComparisonName as $}from"./period-name.js";y.extend(Y),y.extend(k);const T=["second","minute","hour","day","week","month","quarter","year"],M=new Set(T),w=["year","quarter","month","week","day","hour","minute","second"],R=r=>Object.prototype.toString.call(r)==="[object Object]",p=r=>{throw new h("INVALID_PERIOD_SHIFT_ARGS",r)},Q=r=>{const t=r.time;R(t)||p("$periodShift requires args.time");const e=t;if("granularity"in e||"offset"in e)return(typeof e.granularity!="string"||!M.has(e.granularity)||!Number.isInteger(e.offset)||Object.keys(e).some(s=>s!=="granularity"&&s!=="offset"))&&p("Relative period shift time requires only granularity and an integer offset"),e;const o=Object.entries(e);(o.length===0||o.some(([s,c])=>!w.includes(s)||!Number.isInteger(c)))&&p("Absolute period shift time requires integer calendar components"),typeof e.year!="number"&&p("Absolute period shift time requires year");const n={quarter:[1,4],month:[1,12],week:[1,53],day:[1,31],hour:[0,23],minute:[0,59],second:[0,59]};for(const[s,[c,u]]of Object.entries(n)){const f=e[s];f!==void 0&&(Number(f)<c||Number(f)>u)&&p(`Invalid absolute period shift ${s}: ${JSON.stringify(f)}`)}return["quarter","month","week"].filter(s=>s in e).length>1&&p("Absolute period shift time cannot mix quarter, month, and week"),"day"in e&&!("month"in e)&&p("Absolute period shift day requires month"),e},j=(r,t,e)=>t==="month"?r.month(e-1):t==="day"?r.date(e):t==="week"?r.isoWeek(e):t==="quarter"?r.quarter(e):r.set(t,e),V=(r,t)=>{if("granularity"in t){const i=t.granularity==="week"?"week":t.granularity;return r.add(t.offset,i)}let e=r;for(const i of w){const o=t[i];typeof o=="number"&&(e=j(e,i,o))}return e},S=(r,t)=>r instanceof Date?t.toDate():typeof r!="string"?r:t.format(r.includes(":")?"YYYY-MM-DD HH:mm:ss":"YYYY-MM-DD"),F=(r,t,e,i,o)=>(r.groupby??[]).filter(n=>{const a=E(n);return a?A(t,a,e).property.primal_type==="date":!1}).map(n=>{const a=n.operator==="$dateBucket"?n.args?.granularity:void 0,s="granularity"in i?i.granularity:a??"day",c="granularity"in i?-i.offset:o.originalAnchor&&o.shiftedAnchor?o.originalAnchor.diff(o.shiftedAnchor,s):0;return{name:_(n),granularity:s,offset:c}}),O=(r,t,e)=>{if(Array.isArray(r))return r.map(n=>O(n,t,e));if(R(r))return Object.fromEntries(Object.entries(r).map(([n,a])=>[n,O(a,t,e)]));if(!(r instanceof Date)&&typeof r!="string")return r;const i=y(r);if(!i.isValid())return r;const o=V(i,t);return e.originalAnchor??=i,e.shiftedAnchor??=o,e.shiftedValues+=1,S(r,o)},G=(r,t,e,i,o)=>{const n=new Set,a=c=>Object.fromEntries(Object.entries(c).map(([u,f])=>{if((u==="$and"||u==="$or")&&Array.isArray(f))return[u,f.map(g=>a(g))];const d=A(t,u,e);return d.property.primal_type!=="date"?[u,f]:(n.add(d.canonicalName),[u,O(f,i,o)])})),s=a(r);if(n.size===0||o.shiftedValues===0)throw new h("PERIOD_SHIFT_TIME_QUERY_REQUIRED","$periodShift requires a concrete date condition in the LogicForm query");if(n.size>1)throw new h("AMBIGUOUS_PERIOD_SHIFT_TIME","$periodShift query contains more than one date property",{properties:[...n]});return s},N=r=>{const t=r.filter(e=>e!==void 0);if(t.length!==0)return t.length===1?t[0]:{$and:t}},l=r=>[...r.query?[r.query]:[],...typeof r.pred=="object"?l(r.pred):[],...(r.components??[]).flatMap(l)],H=(r,t,e)=>{if(!(r instanceof Date)&&typeof r!="string")return r;const i=y(r);if(!i.isValid())return r;if("granularity"in t)return S(r,i.add(-t.offset,t.granularity));if(!e.originalAnchor)return r;let o=i;for(const n of w)if(t[n]!==void 0){const a=n==="month"?e.originalAnchor.month()+1:n==="day"?e.originalAnchor.date():n==="week"?e.originalAnchor.isoWeek():n==="quarter"?e.originalAnchor.quarter():e.originalAnchor.get(n);o=j(o,n,a)}return S(r,o)},P=({logicform:r,pred:t,outputName:e,schema:i,resolveSchema:o})=>{const n=t.pred;(!n||typeof n!="object"||Array.isArray(n))&&p("$periodShift pred must be a nested metric");const a=Q(t.args??{}),s={shiftedValues:0},c=N([r.query,...l(t)]);if(!c)throw new h("PERIOD_SHIFT_TIME_QUERY_REQUIRED","$periodShift requires a date condition in the LogicForm query");const u=G(c,i,o,a,s),f=I(n);f.name=e,delete f.query;const d=I(r);d.query=u,d.preds=[f],delete d.having,delete d.sort,delete d.limit,delete d.page;const g=new Set((r.groupby??[]).filter(b=>{const m=E(b);return m?A(i,m,o).property.primal_type==="date":!1}).map(_));return{kind:"query",logicform:d,groupKeyShifts:F(r,i,o,a,s),mapResult:b=>b.map(m=>{const q={...m};for(const D of g)q[D]=H(q[D],a,s);return q})}},U={name:"$periodShift",defaultName:({operandName:r,args:t,locale:e})=>e.toLowerCase().startsWith("en")?`${r} ${$(t,e)} baseline`:`${r}${$(t,e)}\u57FA\u671F\u503C`,kind:"component",createComponent:P,getOutputProperty({name:r,inputProperty:t}){if(!t)throw new Error("$periodShift requires a nested metric");return{...t,name:r,isArray:!1}}};export{P as buildPeriodShiftComponent,l as collectPredQueries,N as combineQueries,U as periodShiftOperator};
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const rankOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ const n={name:"$rank",defaultName:({operandName:t,locale:r})=>r.toLowerCase().startsWith("en")?`${t} rank`:`${t}\u6392\u540D`,kind:"window",windowFunction:"rank",getOutputProperty({name:t}){return{name:t,type:"int",primal_type:"number",isArray:!1}}};export{n as rankOperator};
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const rowNumberOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ const e={name:"$rowNumber",defaultName:({locale:r})=>r.toLowerCase().startsWith("en")?"Row number":"\u884C\u53F7",kind:"window",windowFunction:"rowNumber",getOutputProperty({name:r}){return{name:r,type:"int",primal_type:"number",isArray:!1}}};export{e as rowNumberOperator};
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const shareOfTotalOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as a}from"../../errors.js";import{clone as f}from"../../utils/clone.js";import{combineQueries as h,collectPredQueries as T}from"./period-shift.js";import{groupbyOutputName as _}from"../groupby.js";const l=t=>{const e=f(t);return delete e.having,delete e.sort,delete e.limit,delete e.page,e},m=t=>{const e=f(t);return delete e.query,e.pred&&typeof e.pred=="object"&&(e.pred=m(e.pred)),e.components&&(e.components=e.components.map(m)),e},g={name:"$shareOfTotal",defaultName:({operandName:t,locale:e})=>e.toLowerCase().startsWith("en")?`${t} share of total`:`${t}\u5360\u6BD4`,kind:"component",createComponent({logicform:t,pred:e}){if(!e.pred||typeof e.pred!="object")throw new a("INVALID_SHARE_OF_TOTAL_INPUT","$shareOfTotal pred must be a nested metric");const r=e.args?.dimension;if(r!==void 0&&typeof r!="string")throw new a("INVALID_SHARE_OF_TOTAL_ARGS","$shareOfTotal args.dimension must be a groupby pred or output name");const n=t.groupby??[],p=r===void 0?n.length-1:n.findIndex(o=>typeof o.pred=="string"&&o.pred===r||_(o)===r);if(r!==void 0&&p<0)throw new a("SHARE_OF_TOTAL_DIMENSION_NOT_FOUND",`$shareOfTotal dimension is not grouped: ${r}`);const d=n.filter((o,O)=>O!==p),y=d.map(_),u=m(e.pred),s=l(t);s.preds=[{...u,name:"__share_numerator__"}];const c=h([t.query,...T(e)]);c&&(s.query=c);const i=l(t);return i.groupby=d,i.preds=[{...u,name:"__share_denominator__"}],{kind:"cte",components:[{name:"numerator",component:{kind:"query",logicform:s}},{name:"denominator",component:{kind:"query",logicform:i},joinKeys:y}],toSQL:({values:o})=>`${o.numerator} / NULLIF(${o.denominator}, 0)`}},getOutputProperty({name:t}){return{name:t,type:"percentage",primal_type:"number",isArray:!1}}};export{g as shareOfTotalOperator};
@@ -0,0 +1,3 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ /** Trusted raw SQL expression with separately bound dynamic parameters. */
3
+ export declare const sqlOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as s}from"../../errors.js";import{bindTrustedSqlExpression as a}from"../sql-expression.js";const i=new Set(["boolean","date","number","object","string"]),p=r=>{if(r===void 0)return[];if(!Array.isArray(r))throw new s("INVALID_SQL_ARGS","$sql args.parameters must be an array");return r},l=(r,e)=>{const t=e.type,n=e.primal_type;if(typeof t!="string"||t.length===0||!i.has(n))throw new s("INVALID_SQL_OUTPUT","$sql requires args.type and a valid args.primal_type");if(e.isArray!==void 0&&typeof e.isArray!="boolean")throw new s("INVALID_SQL_OUTPUT","$sql args.isArray must be boolean");if(e.ref!==void 0&&typeof e.ref!="string")throw new s("INVALID_SQL_OUTPUT","$sql args.ref must be a Schema id");return{name:r,type:t,primal_type:n,isArray:e.isArray===!0,...typeof e.ref=="string"?{ref:e.ref}:{}}},f={name:"$sql",defaultName:({locale:r})=>r.toLowerCase().startsWith("en")?"Calculated value":"\u8BA1\u7B97\u503C",kind:"scalar",requiresProperty:!1,toSQL({args:r,expression:e,expressions:t,sql:n}){if(e||t&&t.length>0)throw new s("INVALID_SQL_INPUT","$sql does not accept pred or components; put the expression in args.sql");return a(r.sql,p(r.parameters),o=>n.value(o))},getOutputProperty({name:r,args:e,inputProperty:t,componentProperties:n}){if(t||n&&n.length>0)throw new s("INVALID_SQL_INPUT","$sql does not accept pred or components; put the expression in args.sql");return l(r,e)}};export{f as sqlOperator};
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const substringOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as n}from"../../errors.js";const u={name:"$substring",defaultName:({operandName:r,locale:t})=>t.toLowerCase().startsWith("en")?`${r} substring`:`${r}\u5B50\u4E32`,kind:"scalar",toSQL({expression:r,args:t,sql:i}){if(!r)throw new n("PRED_PROPERTY_REQUIRED","$substring requires a pred");const{start:e,length:s}=t;if(!Number.isInteger(e)||Number(e)<0||!Number.isInteger(s)||Number(s)<1)throw new n("INVALID_SUBSTRING_ARGS","$substring requires a non-negative integer start and a positive integer length");return i.substring(r,Number(e)+1,Number(s))},getOutputProperty({name:r}){return{name:r,type:"string",primal_type:"string",isArray:!1}}};export{u as substringOperator};
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const subtractOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ import{numericResult as s,requireExpressions as u}from"./arithmetic.js";const i={name:"$subtract",defaultName:({operandName:t,componentNames:r,locale:e})=>e.toLowerCase().startsWith("en")?r.length>=2?`${r[0]} minus ${r[1]}`:`${t} difference`:r.length>=2?`${r[0]}\u51CF\u53BB${r[1]}`:`${t}\u5DEE\u503C`,kind:"scalar",requiresProperty:!1,toSQL(t){const[r,e]=u("$subtract",t,2);return`(${r} - ${e})`},getOutputProperty({name:t,componentProperties:r}){const e=r?.[0];return e?{...e,name:t,isArray:!1}:s(t)}};export{i as subtractOperator};
@@ -0,0 +1,2 @@
1
+ import type { OperatorDefinition } from '../types';
2
+ export declare const sumOperator: OperatorDefinition;
@@ -0,0 +1 @@
1
+ const s={name:"$sum",defaultName:({operandName:r,locale:t})=>t.toLowerCase().startsWith("en")?`Total ${r}`:`${r}\u5408\u8BA1`,kind:"aggregate",toSQL(r){const{column:t,sql:e}=r;if(!t)throw new Error("$sum requires a column");return e.aggregateFunction("sum",t)},getOutputProperty({name:r,property:t,inputProperty:e}){const o=t??e;if(!o)throw new Error("$sum requires a property");return{name:r,type:o.type,primal_type:o.primal_type,isArray:!1}}};export{s as sumOperator};
@@ -0,0 +1,13 @@
1
+ import type { PredItemType, QueryType } from '../../logicform-types';
2
+ import type { ResolvedSemanticProperty, ResolvedSemanticSchema } from '../../semantic-types/index';
3
+ export interface ResolvedTimeRange {
4
+ readonly property: ResolvedSemanticProperty;
5
+ readonly propertyName: string;
6
+ readonly start?: string | number | Date;
7
+ readonly end?: string | number | Date;
8
+ readonly queryWithoutTime?: QueryType;
9
+ }
10
+ export declare const requireTimestampProperty: (schema: ResolvedSemanticSchema, operator: string) => ResolvedSemanticProperty;
11
+ export declare const resolveTimeRange: (query: QueryType, schema: ResolvedSemanticSchema, resolveSchema: (schemaId: string) => ResolvedSemanticSchema, operator: string) => ResolvedTimeRange;
12
+ export declare const resolvePredTimeRange: (logicformQuery: QueryType | undefined, pred: PredItemType, schema: ResolvedSemanticSchema, resolveSchema: (schemaId: string) => ResolvedSemanticSchema, operator: string) => ResolvedTimeRange;
13
+ export declare const withTimeCondition: (query: QueryType | undefined, propertyName: string, condition: unknown) => QueryType;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as y}from"../../errors.js";import{resolvePropertyPath as R}from"../../schema/resolve-property-path.js";import{combineQueries as U,collectPredQueries as I}from"./period-shift.js";const _=t=>typeof t=="object"&&t!==null&&!Array.isArray(t)&&!(t instanceof Date),h=t=>typeof t=="string"||typeof t=="number"||t instanceof Date,T=(t,e)=>{const r=t.properties.find(({type:s})=>s==="timestamp");if(!r)throw new y("TIMESTAMP_PROPERTY_REQUIRED",`${e} requires a timestamp property in the Schema`);return r},w=(t,e)=>{if(h(t)){e.start??=t,e.end??=t;return}if(!_(t))return;const r=t.$eq;h(r)&&(e.start??=r,e.end??=r);const s=t.$gte??t.$gt,i=t.$lte??t.$lt;h(s)&&(e.start??=s),h(i)&&(e.end??=i);for(const o of["$and","$or"]){const a=t[o];if(Array.isArray(a))for(const u of a)w(u,e)}},A=(t,e,r,s)=>{const i=T(e,s),o=new Set,a={},u=(E,c)=>{for(const[n,f]of Object.entries(E)){if((n==="$and"||n==="$or")&&Array.isArray(f)){for(const m of f)u(m,c||n==="$or");continue}if(n.startsWith("$"))continue;const p=R(e,n,r);if(p.property.type==="timestamp"){if(c)throw new y("AMBIGUOUS_TIME_QUERY",`${s} does not support timestamp conditions inside $or`);o.add(p.canonicalName),w(f,a)}}};if(u(t,!1),o.size!==1)throw new y(o.size===0?"TIME_QUERY_REQUIRED":"AMBIGUOUS_TIME_QUERY",`${s} requires a concrete condition on the Schema timestamp property`);const $=[...o][0];if(!$||$!==i.name)throw new y("AMBIGUOUS_TIME_QUERY",`${s} requires the Schema timestamp property: ${i.name}`);const l=E=>{const c=[];for(const[n,f]of Object.entries(E)){if((n==="$and"||n==="$or")&&Array.isArray(f)){const p=f.map(m=>l(m)).filter(m=>m!==void 0);p.length>0&&c.push([n,p]);continue}!n.startsWith("$")&&R(e,n,r).property.type==="timestamp"||c.push([n,f])}return c.length>0?Object.fromEntries(c):void 0},d=l(t);return{property:i,propertyName:$,...a.start!==void 0?{start:a.start}:{},...a.end!==void 0?{end:a.end}:{},...d?{queryWithoutTime:d}:{}}},M=(t,e,r,s,i)=>{const o=U([t,...I(e)]);if(!o)throw new y("TIME_QUERY_REQUIRED",`${i} requires a timestamp query`);return A(o,r,s,i)},Q=(t,e,r)=>U([t,{[e]:r}]);export{T as requireTimestampProperty,M as resolvePredTimeRange,A as resolveTimeRange,Q as withTimeCondition};
@@ -0,0 +1,3 @@
1
+ import type { PredItemType } from '../logicform-types';
2
+ export declare const groupbyOutputName: (group: PredItemType) => string;
3
+ export declare const groupbyPropertyReference: (group: PredItemType) => string | undefined;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as r}from"../errors.js";const t=e=>{if(e.name)return e.name;throw new r("MISSING_PRED_NAME","A normalized groupby PredItem must have a name")},n=e=>typeof e.pred=="string"?e.pred:void 0;export{t as groupbyOutputName,n as groupbyPropertyReference};
@@ -0,0 +1,7 @@
1
+ import type { SemanticDBPlugin } from '../plugins/index';
2
+ import { OperatorRegistry } from './registry';
3
+ export { OperatorRegistry } from './registry';
4
+ export { bindTrustedSqlExpression } from './sql-expression';
5
+ export type { OperatorDefinition, OperatorDefaultNameContext, OperatorComponentContext, OperatorCteCalculation, OperatorCteComponent, OperatorCteSqlContext, OperatorExecutionComponent, OperatorGroupKeyShift, OperatorJavaScriptCalculation, OperatorQueryComponent, OperatorEvaluateContext, OperatorOutputPropertyContext, OperatorObservationPolicy, OperatorObservationPolicyContext, OperatorNormalizePredContext, OperatorPlanExpressionContext, OperatorPeriodEvaluationContext, OperatorPlanInputContext, OperatorPlannedInput, OperatorRewriteLogicformContext, OperatorValidatePlanContext, OperatorSqlCapabilities, OperatorSqlContext, ResultProperty, ResultPropertyTemporalMetadata, } from './types';
6
+ export declare const builtinOperators: readonly import("./types").OperatorDefinition[];
7
+ export declare const createOperatorRegistry: (plugins?: readonly SemanticDBPlugin[]) => OperatorRegistry;
@@ -0,0 +1 @@
1
+ import{builtinOperators as t}from"./builtins/index.js";import{builtinPlugins as o,resolvePlugins as a}from"../plugins/index.js";import{OperatorRegistry as e}from"./registry.js";const p=Object.freeze([...t,...o.flatMap(({operators:r})=>r??[])]),s=(r=[])=>new e([...t,...a(r).flatMap(({operators:i})=>i??[])]);export{e as OperatorRegistry,p as builtinOperators,s as createOperatorRegistry};
@@ -0,0 +1,10 @@
1
+ import type { OperatorDefinition, OperatorPeriodEvaluationContext } from './types';
2
+ export declare class OperatorRegistry {
3
+ #private;
4
+ constructor(definitions?: readonly OperatorDefinition[]);
5
+ register(definition: OperatorDefinition): this;
6
+ get(name: string): OperatorDefinition;
7
+ requiresPerPeriodEvaluation(name: string, context: OperatorPeriodEvaluationContext): boolean;
8
+ has(name: string): boolean;
9
+ definitions(): readonly OperatorDefinition[];
10
+ }
@@ -0,0 +1 @@
1
+ import{SemanticDBError as r}from"../errors.js";class n{#e=new Map;constructor(e=[]){for(const t of e)this.register(t)}register(e){if(!e.name)throw new r("INVALID_OPERATOR","Operator name must not be empty");if(typeof e.defaultName!="function")throw new r("INVALID_OPERATOR",`Operator must implement defaultName: ${e.name}`);if(this.#e.has(e.name))throw new r("OPERATOR_ALREADY_REGISTERED",`Operator is already registered: ${e.name}`,{operator:e.name});const t=e;if(!(t.kind==="scalar"&&(typeof t.toSQL=="function"||typeof t.evaluate=="function")||t.kind==="aggregate"&&typeof t.toSQL=="function"||t.kind==="component"&&typeof t.createComponent=="function"||t.kind==="window"&&typeof t.windowFunction=="string"||t.kind==="logical"&&typeof t.planExpression=="function"))throw new r("INVALID_OPERATOR",`Operator kind and implementation do not match: ${e.name}`);return this.#e.set(e.name,e),this}get(e){const t=this.#e.get(e);if(!t)throw new r("OPERATOR_NOT_FOUND",`Operator is not registered: ${e}`,{operator:e});return t}requiresPerPeriodEvaluation(e,t){return this.get(e).requiresPerPeriodEvaluation?.(t)??!1}has(e){return this.#e.has(e)}definitions(){return[...this.#e.values()]}}export{n as OperatorRegistry};
@@ -0,0 +1 @@
1
+ export declare const bindTrustedSqlExpression: (expression: unknown, parameters: readonly unknown[], bind: (value: unknown) => string, subject?: string) => string;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as a}from"../errors.js";const f=(o,s,c,i="$sql")=>{if(typeof o!="string"||o.trim().length===0)throw new a("INVALID_SQL_ARGS",`${i} requires a non-empty args.sql expression`);let r="",l=0,n;for(let t=0;t<o.length;t+=1){const e=o[t];if(!e)continue;if(n){r+=e,e===n&&(o[t+1]===n?(r+=n,t+=1):n=void 0);continue}if(e==="'"||e==='"'||e==="`"){n=e,r+=e;continue}const S=o.slice(t,t+2);if(e===";"||S==="--"||S==="/*")throw new a("INVALID_SQL_EXPRESSION",`${i} accepts one expression and does not allow statements or SQL comments`);if(e==="?"){if(l>=s.length)throw new a("INVALID_SQL_PARAMETERS",`${i} contains more placeholders than args.parameters values`);r+=c(s[l]),l+=1;continue}r+=e}if(n)throw new a("INVALID_SQL_EXPRESSION",`${i} contains an unterminated quote`);if(l!==s.length)throw new a("INVALID_SQL_PARAMETERS",`${i} args.parameters contains more values than SQL placeholders`);return r};export{f as bindTrustedSqlExpression};
@@ -0,0 +1,277 @@
1
+ import type { PrimalType, ResolvedSemanticProperty, ResolvedSemanticSchema, TimeGranularity, ComparableCategoryDefinition } from '../semantic-types/index';
2
+ import type { LogicformType, PredItemType } from '../logicform-types';
3
+ import type { DataRow } from '../physical/index';
4
+ import type { Expression } from '../planner/index';
5
+ export interface OperatorSqlCapabilities {
6
+ /** Produce a dialect-specific aggregate function around an expression. */
7
+ aggregateFunction(name: string, expression?: string): string;
8
+ /** Quote an identifier or an alias according to the active dialect. */
9
+ quoteIdentifier(identifier: string): string;
10
+ concat(expressions: readonly string[]): string;
11
+ substring(expression: string, start: number, length: number): string;
12
+ dateBucket(expression: string, granularity: TimeGranularity): string;
13
+ /** Bind a literal as a SQL parameter. */
14
+ value(value: unknown): string;
15
+ /** Compile a field-local LogicForm condition against an expression. */
16
+ condition(expression: string, condition: unknown): string;
17
+ }
18
+ /** Context passed to an operator that pushes its computation into SQL. */
19
+ export interface OperatorSqlContext {
20
+ readonly sql: OperatorSqlCapabilities;
21
+ /** SQL for the nested input expression, when this operator has one. */
22
+ readonly expression?: string;
23
+ /** SQL expressions produced by a multi-input operator's structural components. */
24
+ readonly expressions?: readonly string[];
25
+ /** Quoted physical column for a leaf-property operator. */
26
+ readonly column?: string;
27
+ /** Operator-specific LogicForm arguments. */
28
+ readonly args: Readonly<Record<string, unknown>>;
29
+ }
30
+ /** Context passed to an operator evaluated after the provider returns rows. */
31
+ export interface OperatorEvaluateContext {
32
+ /** Value produced by the nested expression, or undefined for a propertyless operator. */
33
+ readonly input: unknown;
34
+ /** Operator-specific LogicForm arguments. */
35
+ readonly args: Readonly<Record<string, unknown>>;
36
+ }
37
+ /** A logical output column produced by one LogicForm projection. */
38
+ export interface ResultProperty {
39
+ readonly name: string;
40
+ readonly type: string;
41
+ readonly primal_type: PrimalType;
42
+ readonly isArray: boolean;
43
+ /** Referenced Schema for object-valued result columns. */
44
+ readonly ref?: string;
45
+ readonly granularity?: TimeGranularity;
46
+ readonly comparable?: ComparableCategoryDefinition;
47
+ /** Runtime temporal semantics for this output column, when applicable. */
48
+ readonly temporal?: ResultPropertyTemporalMetadata;
49
+ }
50
+ export interface ResultPropertyTemporalMetadata {
51
+ readonly kind: 'period-boundary' | 'period-shift' | 'date-bucket' | 'lifecycle';
52
+ readonly boundary?: 'start' | 'end';
53
+ readonly sourceProperty?: string;
54
+ readonly requestedRange?: {
55
+ readonly gte?: string;
56
+ readonly lte?: string;
57
+ };
58
+ readonly effectiveRange?: {
59
+ readonly gte?: string;
60
+ readonly lte?: string;
61
+ };
62
+ readonly resolvedAt?: string;
63
+ readonly shiftedBy?: {
64
+ readonly granularity: TimeGranularity;
65
+ readonly offset: number;
66
+ };
67
+ readonly resolvedAtByGroup?: readonly {
68
+ readonly group: Readonly<Record<string, unknown>>;
69
+ readonly date: string;
70
+ }[];
71
+ }
72
+ export interface OperatorOutputPropertyContext {
73
+ /** Final alias assigned to this operator's single output column. */
74
+ readonly name: string;
75
+ /** Original Schema property when the operator starts from a physical property. */
76
+ readonly property?: ResolvedSemanticProperty;
77
+ /** Semantic metadata produced by a nested expression. */
78
+ readonly inputProperty?: ResultProperty;
79
+ /** Semantic metadata produced by structural components. */
80
+ readonly componentProperties?: readonly ResultProperty[];
81
+ /** Operator-specific LogicForm arguments. */
82
+ readonly args: Readonly<Record<string, unknown>>;
83
+ }
84
+ /** Context used by operators whose value must be evaluated per time bucket. */
85
+ export interface OperatorPeriodEvaluationContext {
86
+ readonly logicform: LogicformType;
87
+ readonly pred: PredItemType;
88
+ readonly schema: ResolvedSemanticSchema;
89
+ readonly inputProperty?: ResolvedSemanticProperty;
90
+ }
91
+ export interface OperatorDefaultNameContext {
92
+ /** Name produced by the direct pred, structural components, or localized row label. */
93
+ readonly operandName: string;
94
+ /** Name of a direct or nested pred input. */
95
+ readonly inputName?: string;
96
+ /** Names of structural component inputs. */
97
+ readonly componentNames: readonly string[];
98
+ /** Operator-specific LogicForm arguments. */
99
+ readonly args: Readonly<Record<string, unknown>>;
100
+ /** Requested locale. Each operator owns its own localized default names. */
101
+ readonly locale: string;
102
+ }
103
+ export interface OperatorPlanInputContext {
104
+ /** Canonical property or relation reference supplied as this operator's direct pred. */
105
+ readonly reference: string;
106
+ readonly args: Readonly<Record<string, unknown>>;
107
+ readonly schema: ResolvedSemanticSchema;
108
+ readonly resolveSchema?: (schemaId: string) => ResolvedSemanticSchema;
109
+ }
110
+ export interface OperatorPlannedInput {
111
+ /** Property reference the generic expression planner should consume. */
112
+ readonly reference: string;
113
+ /** Provider-independent arguments resolved from semantic metadata. */
114
+ readonly args: Readonly<Record<string, unknown>>;
115
+ }
116
+ export interface OperatorNormalizePredContext {
117
+ readonly pred: PredItemType;
118
+ readonly schema: ResolvedSemanticSchema;
119
+ }
120
+ export interface OperatorPlanExpressionContext {
121
+ readonly pred: PredItemType;
122
+ readonly input?: Expression;
123
+ readonly inputProperty?: ResultProperty;
124
+ readonly components: readonly Expression[];
125
+ readonly args: Readonly<Record<string, unknown>>;
126
+ readonly resolveKey: (reference: string) => Expression;
127
+ readonly getOperator: (name: string) => OperatorDefinition;
128
+ readonly planQuery: (query: Readonly<Record<string, unknown>>) => Readonly<Record<string, unknown>>;
129
+ }
130
+ export interface OperatorObservationPolicyContext {
131
+ readonly pred: PredItemType;
132
+ }
133
+ export interface OperatorObservationPolicy {
134
+ readonly boundary: 'start' | 'end';
135
+ readonly implicit: boolean;
136
+ }
137
+ export interface OperatorValidatePlanContext {
138
+ readonly pred: PredItemType;
139
+ readonly groupByNames: readonly string[];
140
+ readonly resolveGroupName: (reference: string) => string | undefined;
141
+ readonly getOperator: (name: string) => OperatorDefinition;
142
+ }
143
+ export interface OperatorRewriteLogicformContext {
144
+ readonly logicform: LogicformType;
145
+ readonly schema: ResolvedSemanticSchema;
146
+ }
147
+ export interface OperatorComponentContext {
148
+ /** Fully normalized LogicForm containing this top-level operator projection. */
149
+ readonly logicform: LogicformType;
150
+ /** Caller-authored normalized LogicForm before executor row policies were added. */
151
+ readonly sourceLogicform?: LogicformType;
152
+ /** The operator projection for which the component is being built. */
153
+ readonly pred: PredItemType;
154
+ /** Final output alias assigned by the planner. */
155
+ readonly outputName: string;
156
+ readonly schema: ResolvedSemanticSchema;
157
+ /** Resolve Schemas referenced by object relation paths used by this component. */
158
+ readonly resolveSchema: (schemaId: string) => ResolvedSemanticSchema;
159
+ }
160
+ export interface OperatorGroupKeyShift {
161
+ readonly name: string;
162
+ readonly granularity: TimeGranularity;
163
+ readonly offset: number;
164
+ }
165
+ export interface OperatorQueryComponent {
166
+ readonly kind: 'query';
167
+ /** Internal LogicForm executed by the normal planner/compiler/provider pipeline. */
168
+ readonly logicform: LogicformType;
169
+ /** Apply permissions and normalize this dynamically generated LogicForm before planning. */
170
+ readonly prepare?: boolean;
171
+ /** Optional result-key mapping used before component rows are merged. */
172
+ readonly mapResult?: (rows: readonly DataRow[]) => DataRow[];
173
+ /** SQL-side transformations that align this component's group keys with the base component. */
174
+ readonly groupKeyShifts?: readonly OperatorGroupKeyShift[];
175
+ }
176
+ export interface OperatorCteSqlContext {
177
+ readonly values: Readonly<Record<string, string>>;
178
+ readonly quoteIdentifier: (identifier: string) => string;
179
+ }
180
+ export interface OperatorCteComponent {
181
+ readonly name: string;
182
+ readonly component: OperatorQueryComponent;
183
+ /** Group output names used to join this component back to the first component. */
184
+ readonly joinKeys?: readonly string[];
185
+ }
186
+ export interface OperatorCteCalculation {
187
+ readonly kind: 'cte';
188
+ readonly components: readonly OperatorCteComponent[];
189
+ readonly outputName?: string;
190
+ readonly toSQL: (context: OperatorCteSqlContext) => string;
191
+ readonly exposeComponents?: boolean;
192
+ }
193
+ export interface OperatorJavaScriptCalculation {
194
+ readonly kind: 'js';
195
+ readonly components: readonly OperatorCteComponent[];
196
+ readonly outputName: string;
197
+ readonly mergeRow: (values: DataRow) => unknown;
198
+ readonly exposeComponents?: boolean;
199
+ }
200
+ export type OperatorExecutionComponent = OperatorQueryComponent | OperatorCteCalculation | OperatorJavaScriptCalculation;
201
+ /**
202
+ * Extension contract for one LogicForm operator.
203
+ *
204
+ * `kind` is the semantic category used by planning and execution. Its variant
205
+ * requires the corresponding SQL, JavaScript, window, or component contract.
206
+ * The planner recursively connects nested `pred` expressions and uses
207
+ * `getOutputProperty` to describe the resulting one-column logical schema.
208
+ */
209
+ interface OperatorDefinitionBase {
210
+ /** Public registry key, normally using the `$name` convention. */
211
+ readonly name: string;
212
+ /** Produce the normalized output name when the PredItem does not declare one. */
213
+ readonly defaultName: (context: OperatorDefaultNameContext) => string;
214
+ /** Logical property names read in addition to the direct input property. */
215
+ readonly dependencies?: readonly string[];
216
+ /** Set to false for operators such as `$count` that do not require a property. */
217
+ readonly requiresProperty?: boolean;
218
+ /** Output metadata hook. It must describe exactly one result column. */
219
+ readonly getOutputProperty?: (context: OperatorOutputPropertyContext) => ResultProperty;
220
+ /** Resolve Schema-dependent input and arguments before creating a logical expression. */
221
+ readonly planInput?: (context: OperatorPlanInputContext) => OperatorPlannedInput;
222
+ /** Validate or canonicalize this operator after its nested inputs are normalized. */
223
+ readonly normalizePred?: (context: OperatorNormalizePredContext) => PredItemType;
224
+ /** Build a provider-independent expression for operators with custom planning semantics. */
225
+ readonly planExpression?: (context: OperatorPlanExpressionContext) => Expression | undefined;
226
+ /** Resolve observation temporal semantics for this operator, when applicable. */
227
+ readonly observationPolicy?: (context: OperatorObservationPolicyContext) => OperatorObservationPolicy | undefined;
228
+ /** Validate this operator against the completed group key set. */
229
+ readonly validatePlan?: (context: OperatorValidatePlanContext) => void;
230
+ /** Expand high-level operator semantics into ordinary nested LogicForms before planning. */
231
+ readonly rewriteLogicform?: (context: OperatorRewriteLogicformContext) => LogicformType | undefined;
232
+ /** Whether this operator requires one evaluation per time bucket. */
233
+ readonly requiresPerPeriodEvaluation?: (context: OperatorPeriodEvaluationContext) => boolean;
234
+ }
235
+ export type OperatorWindowFunction = 'rank' | 'rowNumber';
236
+ export type OperatorDefinition = OperatorDefinitionBase & ({
237
+ readonly kind: 'scalar';
238
+ /** Convert the operator and its input expression into SQL. */
239
+ readonly toSQL: (context: OperatorSqlContext) => string;
240
+ readonly evaluate?: (context: OperatorEvaluateContext) => unknown;
241
+ readonly createComponent?: never;
242
+ readonly windowFunction?: never;
243
+ } | {
244
+ readonly kind: 'scalar';
245
+ readonly toSQL?: (context: OperatorSqlContext) => string;
246
+ /** JavaScript evaluator for this operator. */
247
+ readonly evaluate: (context: OperatorEvaluateContext) => unknown;
248
+ readonly createComponent?: never;
249
+ readonly windowFunction?: never;
250
+ } | {
251
+ readonly kind: 'aggregate';
252
+ readonly toSQL: (context: OperatorSqlContext) => string;
253
+ readonly evaluate?: (context: OperatorEvaluateContext) => unknown;
254
+ readonly createComponent?: never;
255
+ readonly windowFunction?: never;
256
+ } | {
257
+ readonly kind: 'component';
258
+ readonly toSQL?: never;
259
+ readonly evaluate?: never;
260
+ readonly createComponent: (context: OperatorComponentContext) => OperatorExecutionComponent;
261
+ readonly windowFunction?: never;
262
+ } | {
263
+ readonly kind: 'window';
264
+ readonly toSQL?: never;
265
+ readonly evaluate?: never;
266
+ readonly createComponent?: never;
267
+ /** Plan this operator as a SQL window expression. */
268
+ readonly windowFunction: OperatorWindowFunction;
269
+ } | {
270
+ readonly kind: 'logical';
271
+ readonly toSQL?: never;
272
+ readonly evaluate?: never;
273
+ readonly createComponent?: never;
274
+ readonly windowFunction?: never;
275
+ readonly planExpression: (context: OperatorPlanExpressionContext) => Expression;
276
+ });
277
+ export {};
@@ -0,0 +1,3 @@
1
+ export { applyPermissions, assertLogicformAllowed, getSchemaPermissions, isColumnAllowed, validatePermissions, } from './permissions';
2
+ export type { PermissionSchemaResolver, } from './permissions';
3
+ export type { ColumnPermissions, Permissions, SchemaPermissions, } from './types';
@@ -0,0 +1,10 @@
1
+ import type { LogicformType } from '../logicform-types';
2
+ import type { ResolvedSemanticProperty, ResolvedSemanticSchema } from '../semantic-types/index';
3
+ import type { Permissions, SchemaPermissions } from './types';
4
+ import type { SemanticDBPlugin } from '../plugins/index';
5
+ export type PermissionSchemaResolver = (schemaId: string) => ResolvedSemanticSchema;
6
+ export declare const getSchemaPermissions: (permissions: Permissions | undefined, schemaId: string) => SchemaPermissions | undefined;
7
+ export declare const isColumnAllowed: (permissions: Permissions | undefined, schemaId: string, property: Pick<ResolvedSemanticProperty, "id" | "name">) => boolean;
8
+ export declare const assertLogicformAllowed: (logicform: LogicformType, permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver, plugins?: readonly SemanticDBPlugin[]) => void;
9
+ export declare const applyPermissions: (logicform: LogicformType, permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver, authorize?: boolean, appliedSchemas?: ReadonlySet<string>, plugins?: readonly SemanticDBPlugin[]) => LogicformType;
10
+ export declare const validatePermissions: (permissions: Permissions | undefined, resolveSchema: PermissionSchemaResolver) => void;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as A}from"../errors.js";import{isLogicform as D}from"../logicform-types.js";import{resolvePropertyPath as _}from"../schema/resolve-property-path.js";import{isConcreteEntityId as L,resolveEntityFilterProperty as C}from"../schema/entity-identity.js";import{clone as E}from"../utils/clone.js";const q=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),u=(t,e)=>{if(t){if(!q(t,e))throw new A("TABLE_PERMISSION_DENIED",`Schema is not included in the table permissions: ${e}`,{schemaId:e});return t[e]}},M=(t,e,r)=>{const n=u(t,e)?.columnPermissions?.whitelist;return!n||n.includes(r.name)||n.includes(r.id)},p=(t,e,r)=>{if(!M(t,e.id,r))throw new A("COLUMN_PERMISSION_DENIED",`Property is not included in the column permissions: ${e.id}.${r.name}`,{schemaId:e.id,property:r.name,propertyId:r.id})},Q=(t,e,r,n)=>{const f=_(e,t,n);for(const o of f.relations)u(r,o.targetSchema.id),p(r,o.sourceSchema,o.property);p(r,f.schema,f.property)},U=t=>typeof t=="object"&&t!==null&&!Array.isArray(t)&&typeof t.schema=="string"&&typeof t.query=="object"&&t.query!==null&&!Array.isArray(t.query),F=(t,e,r,n)=>{if(typeof t!="object"||t===null||Array.isArray(t)||!q(t,"$recursive"))return;const f=t.$recursive,o=typeof f=="object"&&f!==null&&!Array.isArray(f)?f:{},s=typeof o.schema=="string"?o.schema:e.property.ref??e.schema.id,c=n(s);if(u(r,s)?.rowPermissions!==void 0)throw new A("RECURSIVE_ROW_PERMISSION_UNSUPPORTED",`$recursive cannot safely apply row permissions for Schema ${s}`,{schemaId:s});const i=o.idProperty??o.id_property,w=i===void 0?c.properties.find(({type:d})=>d==="ID"):c.properties.find(({id:d,name:b})=>d===i||b===i),a=o.parentProperty??o.parent_property??c.parentProperty??"pid",P=c.properties.find(({id:d,name:b})=>d===a||b===a);w&&p(r,c,w),P&&p(r,c,P)},N=(t,e,r,n)=>{if(D(t)){O(t,e,r,n);return}if(Array.isArray(t)){for(const f of t)N(f,e,r,n);return}if(!(typeof t!="object"||t===null||t instanceof Date))for(const f of Object.values(t))N(f,e,r,n)},m=(t,e,r,n,f)=>{if(t)for(const[o,s]of Object.entries(t)){if(o==="$and"||o==="$or"){if(Array.isArray(s))for(const y of s)m(y,e,r,n,f);continue}const c=_(e,o,n);if(Q(o,e,r,n),F(s,c,r,n),U(s)){if(c.property.ref!==s.schema)continue;const y=n(s.schema);u(r,y.id),L(s.entity_id)&&p(r,y,C(y,f)),m(s.query,y,r,n,f);continue}N(s,r,n,f)}},j=(t,e,r,n,f)=>{const o=t.schema?n(t.schema):e;t.schema&&u(r,t.schema),typeof t.pred=="string"?Q(t.pred,o,r,n):t.pred&&j(t.pred,o,r,n,f);for(const s of t.components??[])j(s,o,r,n,f);m(t.query,o,r,n,f)},O=(t,e,r,n=[])=>{if(t.logicforms){for(const o of t.logicforms)O(o,e,r,n);return}if(!t.schema){if(t.from){O(t.from,e,r,n);return}throw new A("LOGICFORM_SCHEMA_REQUIRED","A physical LogicForm must define schema")}const f=r(t.schema);if(u(e,f.id),L(t.entity_id)&&p(e,f,C(f,n)),t.from){O(t.from,e,r,n);return}m(t.query,f,e,r,n);for(const o of t.preds??[])j(o,f,e,r,n);for(const o of t.groupby??[])j(o,f,e,r,n)},R=(t,e)=>{if(Array.isArray(t))return t.map(f=>R(f,e));if(typeof t!="object"||t===null||t instanceof Date)return t;const r=Object.entries(t).map(([f,o])=>[f,R(o,e)]),n=Object.fromEntries(r);return U(t)&&!q(t,"version")&&(n.version=e),n},T=(t,e,r)=>{const n=[],f=c=>{n.push(_(e,c,r))},o=c=>{if(c)for(const[y,i]of Object.entries(c))if((y==="$and"||y==="$or")&&Array.isArray(i))for(const w of i)o(w);else y.startsWith("$")||f(y)},s=c=>{typeof c.pred=="string"?f(c.pred):c.pred&&s(c.pred);for(const y of c.components??[])s(y);o(c.query)};o(t.query);for(const c of t.preds??[])s(c);for(const c of t.groupby??[])s(c);return n},V=(t,e,r)=>{if(!t.schema)return[];const n=r(t.schema),f=new Set,o=[];for(const s of T(t,n,r)){if(s.relations.length===0)continue;let c=-1;if(s.relations.forEach(({targetSchema:a},P)=>{e[a.id]?.rowPermissions!==void 0&&(c=P)}),c<0)continue;const y=s.relations.slice(0,c+1),i=y.map(({property:a})=>a.name).join("_");if(f.has(i))continue;f.add(i);let w={};for(const a of[...y].reverse())w={[a.property.name]:{schema:a.targetSchema.id,query:w}};o.push(w)}return o},I=(t,e,r,n,f,o)=>D(t)?h(t,e,r,n,f,o):Array.isArray(t)?t.map(s=>I(s,e,r,n,f,o)):typeof t!="object"||t===null||t instanceof Date?t:Object.fromEntries(Object.entries(t).map(([s,c])=>[s,I(c,e,r,n,f,o)])),$=(t,e,r,n,f,o)=>({...t,...t.query?{query:I(t.query,e,r,n,f,o)}:{},...t.pred&&typeof t.pred=="object"?{pred:$(t.pred,e,r,n,f,o)}:{},...t.components?{components:t.components.map(s=>$(s,e,r,n,f,o))}:{}}),h=(t,e,r,n=!0,f=new Set,o=[])=>{if(!e)return E(t);if(t.logicforms){const d=E(t);return d.logicforms=t.logicforms.map(b=>h(b,e,r,n,new Set,o)),d}if(!t.schema){const d=E(t);return d.from&&(d.from=h(d.from,e,r,n,new Set,o)),d}n&&O(t,e,r,o);const s=u(e,t.schema),c=f.has(t.schema),y=new Set(f).add(t.schema),i=E(t);i.query&&(i.query=I(i.query,e,r,n,new Set,o)),i.preds&&(i.preds=i.preds.map(d=>$(d,e,r,n,new Set,o))),i.from&&(i.from=h(i.from,e,r,n,new Set,o));const w=c||t.from?void 0:s?.rowPermissions,a=(t.from?[]:V(t,e,r)).map(d=>I(R(d,t.version),e,r,!1,y,o));w&&a.push(I(R(E(w),t.version),e,r,!1,y,o));const P=[i.query,...a].filter(d=>d!==void 0&&Object.keys(d).length>0);return P.length===1?i.query=P[0]:P.length>1?i.query={$and:P}:delete i.query,i},k=(t,e)=>{if(t)for(const[r,n]of Object.entries(t)){const f=e(r),o=n.columnPermissions?.whitelist;if(o&&(!Array.isArray(o)||o.some(s=>typeof s!="string")))throw new A("INVALID_COLUMN_PERMISSIONS",`Column permissions whitelist must be an array of strings: ${r}`,{schemaId:r});for(const s of o??[])if(!f.properties.some(({id:c,name:y})=>c===s||y===s))throw new A("INVALID_COLUMN_PERMISSION",`Column permission property not found: ${r}.${s}`,{schemaId:r,property:s})}};export{h as applyPermissions,O as assertLogicformAllowed,u as getSchemaPermissions,M as isColumnAllowed,k as validatePermissions};
@@ -0,0 +1,12 @@
1
+ import type { QueryType } from '../logicform-types';
2
+ export interface ColumnPermissions {
3
+ readonly whitelist: readonly string[];
4
+ }
5
+ export interface SchemaPermissions {
6
+ readonly rowPermissions?: QueryType;
7
+ readonly columnPermissions?: ColumnPermissions;
8
+ }
9
+ /**
10
+ * Schema-keyed execution permissions. When present, the keys are the table allowlist.
11
+ */
12
+ export type Permissions = Readonly<Record<string, SchemaPermissions>>;
@@ -0,0 +1,44 @@
1
+ import type { CoreComputeProvider, DataRow, ProviderExecutionRequest } from './provider';
2
+ interface ClickHouseResultLike {
3
+ json<T>(): Promise<T>;
4
+ }
5
+ export interface ClickHouseClientLike {
6
+ query(options: {
7
+ query: string;
8
+ format: 'JSONEachRow';
9
+ query_params: Readonly<Record<string, unknown>>;
10
+ abort_signal?: AbortSignal;
11
+ }): Promise<ClickHouseResultLike>;
12
+ close(): Promise<void>;
13
+ }
14
+ export interface ClickHouseProviderOptions {
15
+ readonly url?: string;
16
+ readonly username?: string;
17
+ readonly password?: string;
18
+ readonly database?: string;
19
+ readonly client?: ClickHouseClientLike;
20
+ }
21
+ export declare class ClickHouseProvider implements CoreComputeProvider {
22
+ readonly kind: "clickhouse";
23
+ private readonly client;
24
+ constructor(options?: ClickHouseProviderOptions);
25
+ quoteIdentifier(identifier: string): string;
26
+ tableAlias(expression: string, alias: string): string;
27
+ paginate(sql: string, pageSize: number, offset: number): string;
28
+ parameter(index: number, value: unknown): string;
29
+ displayQuery(sql: string, parameters: readonly unknown[]): string;
30
+ dateBucket(expression: string, level: string): string;
31
+ dateShift(expression: string, granularity: string, offset: number): string;
32
+ aggregateFunction(name: string, expression?: string): string;
33
+ concat(expressions: readonly string[]): string;
34
+ substring(expression: string, start: number, length: number): string;
35
+ regex(expression: string, pattern: string, options?: string): string;
36
+ arrayContains(arrayExpression: string, valueExpression: string): string;
37
+ expandArray(arrayExpression: string, alias: string, column: string): {
38
+ joinSql: string;
39
+ valueExpression: string;
40
+ };
41
+ execute(request: ProviderExecutionRequest): Promise<DataRow[]>;
42
+ close(): Promise<void>;
43
+ }
44
+ export {};
@@ -0,0 +1 @@
1
+ import{createClient as i}from"@clickhouse/client";import{displayClickHouseQuery as s}from"./display-query.js";const u=a=>a===null?"Nullable(String)":typeof a=="boolean"?"Bool":typeof a=="number"?"Float64":a instanceof Date?"DateTime64(3)":"String",c=a=>a instanceof Date?a.toISOString().replace("T"," ").replace("Z",""):a;class l{kind="clickhouse";client;constructor(e={}){this.client=e.client??i({url:e.url??"http://localhost:8123",username:e.username??"default",password:e.password??"",database:e.database??"default"})}quoteIdentifier(e){return`\`${e.replaceAll("`","``")}\``}tableAlias(e,r){return`${e} AS ${this.quoteIdentifier(r)}`}paginate(e,r,t){return`${e} LIMIT ${r}${t>0?` OFFSET ${t}`:""}`}parameter(e,r){return`{p${e}:${u(r)}}`}displayQuery(e,r){return s(e,r)}dateBucket(e,r){const n={hour:"toStartOfHour",day:"toStartOfDay",week:"toStartOfWeek",month:"toStartOfMonth",quarter:"toStartOfQuarter",year:"toStartOfYear"}[r];if(!n)throw new Error(`Unsupported ClickHouse date level: ${r}`);return`${n}(${e})`}dateShift(e,r,t){if(!new Set(["second","minute","hour","day","week","month","quarter","year"]).has(r)||!Number.isInteger(t))throw new Error(`Unsupported ClickHouse date shift: ${r}/${t}`);return`dateAdd('${r}', ${t}, ${e})`}aggregateFunction(e,r="*"){if(!/^[A-Za-z][A-Za-z0-9_]*$/.test(e))throw new Error(`Unsupported ClickHouse aggregate function: ${e}`);return`${e.toUpperCase()}(${r})`}concat(e){return`concat(${e.join(", ")})`}substring(e,r,t){return`substring(${e}, ${r}, ${t})`}regex(e,r,t){if(t&&t!=="i")throw new Error(`Unsupported ClickHouse regex options: ${t}`);const n=t==="i"?`concat('(?i)', ${r})`:r;return`match(${e}, ${n})`}arrayContains(e,r){return`has(${e}, ${r})`}expandArray(e,r,t){const n=this.quoteIdentifier(r);return{joinSql:`ARRAY JOIN ${e} AS ${n}`,valueExpression:n}}async execute(e){e.signal?.throwIfAborted();const r=Object.fromEntries(e.parameters.map((n,o)=>[`p${o}`,c(n)]));return(await this.client.query({query:e.sql,format:"JSONEachRow",query_params:r,...e.signal?{abort_signal:e.signal}:{}})).json()}async close(){await this.client.close()}}export{l as ClickHouseProvider};