@rocicorp/zero 0.22.2025081301 → 0.23.2025081400
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/analyze-query/src/bin-analyze.js +5 -8
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/{chunk-C3ZE2IHA.js → chunk-JHJ3MBXW.js} +8 -6
- package/out/chunk-JHJ3MBXW.js.map +7 -0
- package/out/chunk-MKB4RXL3.js +15 -0
- package/out/chunk-MKB4RXL3.js.map +7 -0
- package/out/{chunk-LENWM5WE.js → chunk-O536GEIT.js} +410 -218
- package/out/chunk-O536GEIT.js.map +7 -0
- package/out/chunk-SGW2EIVJ.js +192 -0
- package/out/chunk-SGW2EIVJ.js.map +7 -0
- package/out/{chunk-N2EOVSVB.js → chunk-ZKRMVMWK.js} +209 -153
- package/out/chunk-ZKRMVMWK.js.map +7 -0
- package/out/expo.js +356 -0
- package/out/expo.js.map +7 -0
- package/out/{inspector-AF3UI76B.js → inspector-J5P4DOGH.js} +122 -26
- package/out/inspector-J5P4DOGH.js.map +7 -0
- package/out/{inspector-ENPS6L3H.js → inspector-YIRP3TTL.js} +1 -1
- package/out/{inspector-ENPS6L3H.js.map → inspector-YIRP3TTL.js.map} +1 -1
- package/out/react.js +7 -4
- package/out/react.js.map +2 -2
- package/out/replicache/src/kv/sqlite-store.d.ts +117 -0
- package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -0
- package/out/shared/src/binary-search.js +31 -0
- package/out/shared/src/binary-search.js.map +1 -0
- package/out/shared/src/centroid.d.ts +10 -0
- package/out/shared/src/centroid.d.ts.map +1 -0
- package/out/shared/src/centroid.js +28 -0
- package/out/shared/src/centroid.js.map +1 -0
- package/out/shared/src/logging-test-utils.d.ts +12 -0
- package/out/shared/src/logging-test-utils.d.ts.map +1 -0
- package/out/shared/src/logging-test-utils.js +21 -0
- package/out/shared/src/logging-test-utils.js.map +1 -0
- package/out/shared/src/objects.d.ts +3 -1
- package/out/shared/src/objects.d.ts.map +1 -1
- package/out/shared/src/objects.js.map +1 -1
- package/out/shared/src/tdigest-schema.d.ts +8 -0
- package/out/shared/src/tdigest-schema.d.ts.map +1 -0
- package/out/shared/src/tdigest-schema.js +7 -0
- package/out/shared/src/tdigest-schema.js.map +1 -0
- package/out/shared/src/tdigest.d.ts +53 -0
- package/out/shared/src/tdigest.d.ts.map +1 -0
- package/out/shared/src/tdigest.js +304 -0
- package/out/shared/src/tdigest.js.map +1 -0
- package/out/solid.js +13 -9
- package/out/solid.js.map +2 -2
- package/out/zero/package.json +9 -4
- package/out/zero/src/expo.d.ts +2 -0
- package/out/zero/src/expo.d.ts.map +1 -0
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +3 -2
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +18 -297
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +43 -5
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/observability/events.d.ts +15 -0
- package/out/zero-cache/src/observability/events.d.ts.map +1 -0
- package/out/zero-cache/src/observability/events.js +93 -0
- package/out/zero-cache/src/observability/events.js.map +1 -0
- package/out/zero-cache/src/server/anonymous-otel-start.d.ts +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +40 -18
- package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +4 -4
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/main.js +4 -4
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/server/replicator.js +7 -6
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.d.ts.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +3 -2
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/syncer.js +5 -5
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +46 -35
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +7 -2
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts +28 -2
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.d.ts +5 -1
- package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +10 -8
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +17 -3
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts +12 -0
- package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/replication-status.js +92 -0
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -0
- package/out/zero-cache/src/services/replicator/replicator.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +2 -2
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/statz.d.ts.map +1 -1
- package/out/zero-cache/src/services/statz.js +0 -23
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +2 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +10 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +77 -8
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/pg.d.ts +9 -0
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +78 -1
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-client/src/client/context.d.ts +11 -11
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.d.ts +6 -6
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.d.ts +10 -1
- package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/types.d.ts +10 -0
- package/out/zero-client/src/client/inspector/types.d.ts.map +1 -1
- package/out/zero-client/src/client/measure-push-operator.d.ts +17 -0
- package/out/zero-client/src/client/measure-push-operator.d.ts.map +1 -0
- package/out/zero-client/src/client/options.d.ts +2 -2
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.d.ts +18 -5
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.d.ts +4 -4
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/mod.d.ts +1 -1
- package/out/zero-client/src/mod.d.ts.map +1 -1
- package/out/zero-events/src/index.d.ts +29 -0
- package/out/zero-events/src/index.d.ts.map +1 -0
- package/out/zero-events/src/index.js +28 -0
- package/out/zero-events/src/index.js.map +1 -0
- package/out/zero-events/src/status.d.ts +113 -0
- package/out/zero-events/src/status.d.ts.map +1 -0
- package/out/zero-events/src/status.js +72 -0
- package/out/zero-events/src/status.js.map +1 -0
- package/out/zero-expo/src/mod.d.ts +2 -0
- package/out/zero-expo/src/mod.d.ts.map +1 -0
- package/out/zero-expo/src/store.d.ts +4 -0
- package/out/zero-expo/src/store.d.ts.map +1 -0
- package/out/zero-protocol/src/down.d.ts +18 -2
- package/out/zero-protocol/src/down.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-down.d.ts +64 -6
- package/out/zero-protocol/src/inspect-down.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-down.js +18 -3
- package/out/zero-protocol/src/inspect-down.js.map +1 -1
- package/out/zero-protocol/src/inspect-up.d.ts +25 -6
- package/out/zero-protocol/src/inspect-up.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-up.js +8 -3
- package/out/zero-protocol/src/inspect-up.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.js +3 -1
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/up.d.ts +7 -2
- package/out/zero-protocol/src/up.d.ts.map +1 -1
- package/out/zero-react/src/components/inspector.d.ts +1 -1
- package/out/zero-react/src/components/inspector.d.ts.map +1 -1
- package/out/zero-react/src/components/zero-inspector.d.ts +1 -1
- package/out/zero-react/src/components/zero-inspector.d.ts.map +1 -1
- package/out/zero-react/src/zero-provider.d.ts +4 -4
- package/out/zero-react/src/zero-provider.d.ts.map +1 -1
- package/out/zero-schema/src/permissions.d.ts +15 -0
- package/out/zero-schema/src/permissions.d.ts.map +1 -1
- package/out/zero-schema/src/table-schema.d.ts +1 -8
- package/out/zero-schema/src/table-schema.d.ts.map +1 -1
- package/out/zero-schema/src/table-schema.js.map +1 -1
- package/out/zero-solid/src/use-zero.d.ts +4 -4
- package/out/zero-solid/src/use-zero.d.ts.map +1 -1
- package/out/zero.js +5 -3
- package/out/zql/src/builder/builder.d.ts +3 -2
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +9 -8
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/ivm/operator.d.ts +1 -1
- package/out/zql/src/ivm/operator.d.ts.map +1 -1
- package/out/zql/src/ivm/operator.js +0 -1
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/query/metrics-delegate.d.ts +14 -0
- package/out/zql/src/query/metrics-delegate.d.ts.map +1 -0
- package/out/zql/src/query/metrics-delegate.js +2 -0
- package/out/zql/src/query/metrics-delegate.js.map +1 -0
- package/out/zql/src/query/query-delegate.d.ts +7 -2
- package/out/zql/src/query/query-delegate.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +17 -14
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zqlite/src/query-delegate.d.ts +7 -6
- package/out/zqlite/src/query-delegate.d.ts.map +1 -1
- package/out/zqlite/src/query-delegate.js +5 -2
- package/out/zqlite/src/query-delegate.js.map +1 -1
- package/package.json +9 -4
- package/out/chunk-C3ZE2IHA.js.map +0 -7
- package/out/chunk-LENWM5WE.js.map +0 -7
- package/out/chunk-N2EOVSVB.js.map +0 -7
- package/out/inspector-AF3UI76B.js.map +0 -7
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../ast-to-zql/src/ast-to-zql.ts", "../../zero-client/src/client/inspector/inspector.ts"],
|
|
4
|
+
"sourcesContent": ["import {unreachable} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport type {\n AST,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralReference,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../zero-protocol/src/ast.ts';\nimport {SUBQ_PREFIX} from '../../zql/src/query/query-impl.ts';\n\n/**\n * Converts an AST to the equivalent query builder code.\n * This is useful for debugging and understanding queries.\n *\n * @example\n * ```\n * const ast = query.issue.where('id', '=', 123)[astSymbol];\n * console.log(astToZQL(ast)); // outputs: .where('id', '=', 123)\n * ```\n */\nexport function astToZQL(ast: AST): string {\n let code = '';\n\n // Handle where conditions\n if (ast.where) {\n code += transformCondition(ast.where, '.where', new Set());\n }\n\n // Handle related subqueries\n if (ast.related && ast.related.length > 0) {\n for (const related of ast.related) {\n if (related.hidden) {\n const nestedRelated = related.subquery.related?.[0];\n if (nestedRelated) {\n code += transformRelated(nestedRelated);\n }\n } else {\n code += transformRelated(related);\n }\n }\n }\n\n // Handle orderBy\n if (ast.orderBy && ast.orderBy.length > 0) {\n code += transformOrder(ast.orderBy);\n }\n\n // Handle limit\n if (ast.limit !== undefined) {\n code += `.limit(${ast.limit})`;\n }\n\n // Handle start\n if (ast.start) {\n const {row, exclusive} = ast.start;\n code += `.start(${JSON.stringify(row)}${\n exclusive ? '' : ', { inclusive: true }'\n })`;\n }\n\n return code;\n}\n\ntype Args = Set<string>;\n\ntype Prefix = '.where' | 'cmp';\n\nfunction transformCondition(\n condition: Condition,\n prefix: Prefix,\n args: Args,\n): string {\n switch (condition.type) {\n case 'simple':\n return transformSimpleCondition(condition, prefix);\n case 'and':\n case 'or':\n return transformLogicalCondition(condition, prefix, args);\n case 'correlatedSubquery':\n return transformExistsCondition(condition, prefix, args);\n default:\n unreachable(condition);\n }\n}\n\nfunction transformSimpleCondition(\n condition: SimpleCondition,\n prefix: Prefix,\n): string {\n const {left, op, right} = condition;\n\n const leftCode = transformValuePosition(left);\n const rightCode = transformValuePosition(right);\n\n // Handle the shorthand form for equals\n if (op === '=') {\n return `${prefix}(${leftCode}, ${rightCode})`;\n }\n\n return `${prefix}(${leftCode}, '${op}', ${rightCode})`;\n}\n\nfunction transformLogicalCondition(\n condition: Conjunction | Disjunction,\n prefix: Prefix,\n args: Args,\n): string {\n const {type, conditions} = condition;\n\n // For single condition, no need for logical operator\n if (conditions.length === 1) {\n return transformCondition(conditions[0], prefix, args);\n }\n\n // Generate multiple where calls for top-level AND conditions\n if (type === 'and') {\n const parts = conditions.map(c => transformCondition(c, prefix, args));\n // Simply concatenate the where conditions\n if (prefix === '.where') {\n return parts.join('');\n }\n args.add('and');\n return 'and(' + parts.join(', ') + ')';\n }\n\n args = new Set<string>();\n\n // Handle nested conditions with a callback for OR conditions and nested ANDs/ORs\n const conditionsCode = conditions\n .map(c => transformCondition(c, 'cmp', args))\n .join(', ');\n\n args.add('cmp');\n args.add(type);\n const argsCode = [...args].sort().join(', ');\n\n return `.where(({${argsCode}}) => ${type}(${conditionsCode}))`;\n}\n\nfunction transformExistsCondition(\n condition: CorrelatedSubqueryCondition,\n prefix: '.where' | 'cmp',\n args: Set<string>,\n): string {\n const {related, op} = condition;\n const relationship = extractRelationshipName(related);\n\n const nextSubquery = getNextExistsSubquery(related);\n\n // Check if subquery has additional properties\n const hasSubQueryProps =\n nextSubquery.where ||\n (nextSubquery.related && nextSubquery.related.length > 0) ||\n nextSubquery.orderBy ||\n nextSubquery.limit;\n\n if (op === 'EXISTS') {\n if (!hasSubQueryProps) {\n if (prefix === '.where') {\n return `.whereExists('${relationship}')`;\n }\n args.add('exists');\n return `exists('${relationship}')`;\n }\n\n if (prefix === '.where') {\n return `.whereExists('${relationship}', q => q${astToZQL(nextSubquery)})`;\n }\n prefix satisfies 'cmp';\n args.add('exists');\n return `exists('${relationship}', q => q${astToZQL(nextSubquery)})`;\n }\n\n op satisfies 'NOT EXISTS';\n\n if (hasSubQueryProps) {\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}', q => q${astToZQL(\n nextSubquery,\n )})))`;\n }\n prefix satisfies 'cmp';\n args.add('not');\n args.add('exists');\n return `not(exists('${relationship}', q => q${astToZQL(nextSubquery)}))`;\n }\n\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}')))`;\n }\n args.add('not');\n args.add('exists');\n\n return `not(exists('${relationship}')))`;\n}\n\n// If the `exists` is applied against a junction edge, both hops will have the same alias and both hops will be exists conditions.\nfunction getNextExistsSubquery(related: CorrelatedSubquery): AST {\n if (\n related.subquery.where?.type === 'correlatedSubquery' &&\n related.subquery.where.related.subquery.alias?.includes(\n SUBQ_PREFIX + 'zhidden_',\n )\n ) {\n return getNextExistsSubquery(related.subquery.where.related);\n }\n\n return related.subquery;\n}\n\nfunction extractRelationshipName(related: CorrelatedSubquery): string {\n const alias = must(related.subquery.alias);\n return alias.startsWith(SUBQ_PREFIX)\n ? alias.substring(SUBQ_PREFIX.length)\n : alias;\n}\n\nfunction transformRelated(related: CorrelatedSubquery): string {\n const {alias} = related.subquery;\n if (!alias) return '';\n\n const relationship = alias;\n let code = `.related('${relationship}'`;\n\n // If the subquery has additional filters or configurations\n if (\n related.subquery.where ||\n (related.subquery.related && related.subquery.related.length > 0) ||\n related.subquery.orderBy ||\n related.subquery.limit\n ) {\n code += ', q => q' + astToZQL(related.subquery);\n }\n\n code += ')';\n return code;\n}\n\nfunction transformOrder(orderBy: Ordering): string {\n let code = '';\n for (const [field, direction] of orderBy) {\n code += `.orderBy('${field}', '${direction}')`;\n }\n return code;\n}\n\nfunction transformValuePosition(value: ValuePosition): string {\n switch (value.type) {\n case 'literal':\n return transformLiteral(value);\n case 'column':\n return `'${value.name}'`;\n case 'static':\n return transformParameter(value);\n default:\n unreachable(value);\n }\n}\n\nfunction transformLiteral(literal: LiteralReference): string {\n if (literal.value === null) {\n return 'null';\n }\n if (Array.isArray(literal.value)) {\n return JSON.stringify(literal.value);\n }\n if (typeof literal.value === 'string') {\n return `'${literal.value.replace(/'/g, \"\\\\'\")}'`;\n }\n return String(literal.value);\n}\n\nfunction transformParameter(param: Parameter): string {\n const fieldStr = Array.isArray(param.field)\n ? `[${param.field.map(f => `'${f}'`).join(', ')}]`\n : `'${param.field}'`;\n\n return `authParam(${fieldStr})`;\n}\n", "import {astToZQL} from '../../../../ast-to-zql/src/ast-to-zql.ts';\nimport type {BTreeRead} from '../../../../replicache/src/btree/read.ts';\nimport {type Read} from '../../../../replicache/src/dag/store.ts';\nimport {readFromHash} from '../../../../replicache/src/db/read.ts';\nimport * as FormatVersion from '../../../../replicache/src/format-version-enum.ts';\nimport {getClientGroup} from '../../../../replicache/src/persist/client-groups.ts';\nimport {\n getClient,\n getClients,\n type ClientMap,\n} from '../../../../replicache/src/persist/clients.ts';\nimport type {ReplicacheImpl} from '../../../../replicache/src/replicache-impl.ts';\nimport {withRead} from '../../../../replicache/src/with-transactions.ts';\nimport {assert} from '../../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../../shared/src/json.ts';\nimport {mapValues} from '../../../../shared/src/objects.ts';\nimport {TDigest, type ReadonlyTDigest} from '../../../../shared/src/tdigest.ts';\nimport * as valita from '../../../../shared/src/valita.ts';\nimport type {AST} from '../../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../../zero-protocol/src/data.ts';\nimport {\n inspectMetricsDownSchema,\n inspectQueriesDownSchema,\n inspectVersionDownSchema,\n type InspectDownBody,\n type InspectQueryRow,\n type ServerMetrics as ServerMetricsJSON,\n} from '../../../../zero-protocol/src/inspect-down.ts';\nimport type {\n InspectQueriesUpBody,\n InspectUpBody,\n InspectUpMessage,\n} from '../../../../zero-protocol/src/inspect-up.ts';\nimport type {Schema} from '../../../../zero-schema/src/builder/schema-builder.ts';\nimport type {\n ClientMetricMap,\n MetricMap,\n ServerMetricMap,\n} from '../../../../zql/src/query/metrics-delegate.ts';\nimport {normalizeTTL, type TTL} from '../../../../zql/src/query/ttl.ts';\nimport {nanoid} from '../../util/nanoid.ts';\nimport {ENTITIES_KEY_PREFIX} from '../keys.ts';\nimport type {MutatorDefs} from '../replicache-types.ts';\nimport type {\n ClientGroup as ClientGroupInterface,\n Client as ClientInterface,\n Inspector as InspectorInterface,\n Query as QueryInterface,\n} from './types.ts';\n\ntype Rep = ReplicacheImpl<MutatorDefs>;\n\ntype GetWebSocket = () => Promise<WebSocket>;\n\ntype Metrics = {\n readonly [K in keyof MetricMap]: ReadonlyTDigest;\n};\n\ntype ClientMetrics = {\n readonly [K in keyof ClientMetricMap]: ReadonlyTDigest;\n};\n\ntype ServerMetrics = {\n readonly [K in keyof ServerMetricMap]: ReadonlyTDigest;\n};\n\nexport interface InspectorClientMetricsDelegate {\n getQueryMetrics(hash: string): ClientMetrics | undefined;\n readonly metrics: ClientMetrics;\n}\n\nexport async function newInspector(\n rep: Rep,\n clientMetricsDelegate: InspectorClientMetricsDelegate,\n schema: Schema,\n socket: GetWebSocket,\n): Promise<InspectorInterface> {\n const clientGroupID = await rep.clientGroupID;\n return new Inspector(\n rep,\n clientMetricsDelegate,\n schema,\n rep.clientID,\n clientGroupID,\n socket,\n );\n}\n\nclass Inspector implements InspectorInterface {\n readonly #rep: Rep;\n readonly client: Client;\n readonly clientGroup: ClientGroup;\n readonly #schema: Schema;\n readonly socket: GetWebSocket;\n readonly #metricsDelegate: InspectorClientMetricsDelegate;\n\n constructor(\n rep: ReplicacheImpl,\n clientMetricsDelegate: InspectorClientMetricsDelegate,\n schema: Schema,\n clientID: string,\n clientGroupID: string,\n socket: GetWebSocket,\n ) {\n this.#rep = rep;\n this.#schema = schema;\n this.client = new Client(\n rep,\n clientMetricsDelegate,\n schema,\n socket,\n clientID,\n clientGroupID,\n );\n this.clientGroup = this.client.clientGroup;\n this.socket = socket;\n this.#metricsDelegate = clientMetricsDelegate;\n }\n\n async metrics(): Promise<Metrics> {\n const clientMetrics = this.#metricsDelegate.metrics;\n const serverMetricsJSON = await rpc(\n await this.socket(),\n {op: 'metrics'},\n inspectMetricsDownSchema,\n );\n return mergeMetrics(clientMetrics, serverMetricsJSON);\n }\n\n clients(): Promise<ClientInterface[]> {\n return withDagRead(this.#rep, dagRead =>\n clients(\n this.#rep,\n this.#metricsDelegate,\n this.socket,\n this.#schema,\n dagRead,\n ),\n );\n }\n\n clientsWithQueries(): Promise<ClientInterface[]> {\n return withDagRead(this.#rep, dagRead =>\n clientsWithQueries(\n this.#rep,\n this.#metricsDelegate,\n this.socket,\n this.#schema,\n dagRead,\n ),\n );\n }\n\n async serverVersion(): Promise<string> {\n return rpc(await this.socket(), {op: 'version'}, inspectVersionDownSchema);\n }\n}\n\nfunction rpc<T extends InspectDownBody>(\n socket: WebSocket,\n arg: Omit<InspectUpBody, 'id'>,\n downSchema: valita.Type<T>,\n): Promise<T['value']> {\n return new Promise((resolve, reject) => {\n const id = nanoid();\n const f = (ev: MessageEvent) => {\n const msg = JSON.parse(ev.data);\n if (msg[0] === 'inspect') {\n const body = msg[1];\n if (body.id !== id) {\n return;\n }\n const res = valita.test(body, downSchema);\n if (res.ok) {\n resolve(res.value.value);\n } else {\n reject(res.error);\n }\n socket.removeEventListener('message', f);\n }\n };\n socket.addEventListener('message', f);\n socket.send(\n JSON.stringify(['inspect', {...arg, id}] satisfies InspectUpMessage),\n );\n });\n}\n\nclass Client implements ClientInterface {\n readonly #rep: Rep;\n readonly id: string;\n readonly clientGroup: ClientGroup;\n readonly #socket: GetWebSocket;\n readonly #clientMetricsDelegate: InspectorClientMetricsDelegate;\n\n constructor(\n rep: Rep,\n clientMetricsDelegate: InspectorClientMetricsDelegate,\n schema: Schema,\n socket: GetWebSocket,\n id: string,\n clientGroupID: string,\n ) {\n this.#rep = rep;\n this.#socket = socket;\n this.id = id;\n this.clientGroup = new ClientGroup(\n rep,\n clientMetricsDelegate,\n socket,\n schema,\n clientGroupID,\n );\n this.#clientMetricsDelegate = clientMetricsDelegate;\n }\n\n async queries(): Promise<QueryInterface[]> {\n const rows: InspectQueryRow[] = await rpc(\n await this.#socket(),\n {op: 'queries', clientID: this.id} as InspectQueriesUpBody,\n inspectQueriesDownSchema,\n );\n return rows.map(row => new Query(row, this.#clientMetricsDelegate));\n }\n\n map(): Promise<Map<string, ReadonlyJSONValue>> {\n return withDagRead(this.#rep, async dagRead => {\n const tree = await getBTree(dagRead, this.id);\n const map = new Map<string, ReadonlyJSONValue>();\n for await (const [key, value] of tree.scan('')) {\n map.set(key, value);\n }\n return map;\n });\n }\n\n rows(tableName: string): Promise<Row[]> {\n return withDagRead(this.#rep, async dagRead => {\n const prefix = ENTITIES_KEY_PREFIX + tableName;\n const tree = await getBTree(dagRead, this.id);\n const rows: Row[] = [];\n for await (const [key, value] of tree.scan(prefix)) {\n if (!key.startsWith(prefix)) {\n break;\n }\n rows.push(value as Row);\n }\n return rows;\n });\n }\n}\n\nclass ClientGroup implements ClientGroupInterface {\n readonly #rep: Rep;\n readonly id: string;\n readonly #schema: Schema;\n readonly #socket: GetWebSocket;\n readonly #metricsDelegate: InspectorClientMetricsDelegate;\n\n constructor(\n rep: Rep,\n metricsDelegate: InspectorClientMetricsDelegate,\n socket: GetWebSocket,\n schema: Schema,\n id: string,\n ) {\n this.#rep = rep;\n this.#metricsDelegate = metricsDelegate;\n this.#socket = socket;\n this.#schema = schema;\n this.id = id;\n }\n\n clients(): Promise<ClientInterface[]> {\n return withDagRead(this.#rep, dagRead =>\n clients(\n this.#rep,\n this.#metricsDelegate,\n this.#socket,\n this.#schema,\n dagRead,\n ([_, v]) => v.clientGroupID === this.id,\n ),\n );\n }\n\n clientsWithQueries(): Promise<ClientInterface[]> {\n return withDagRead(this.#rep, dagRead =>\n clientsWithQueries(\n this.#rep,\n this.#metricsDelegate,\n this.#socket,\n this.#schema,\n dagRead,\n ([_, v]) => v.clientGroupID === this.id,\n ),\n );\n }\n\n async queries(): Promise<QueryInterface[]> {\n const rows: InspectQueryRow[] = await rpc(\n await this.#socket(),\n {op: 'queries'},\n inspectQueriesDownSchema,\n );\n return rows.map(row => new Query(row, this.#metricsDelegate));\n }\n}\n\nasync function withDagRead<T>(\n rep: Rep,\n f: (dagRead: Read) => Promise<T>,\n): Promise<T> {\n await rep.refresh();\n await rep.persist();\n return withRead(rep.perdag, f);\n}\n\nasync function getBTree(dagRead: Read, clientID: string): Promise<BTreeRead> {\n const client = await getClient(clientID, dagRead);\n assert(client, `Client not found: ${clientID}`);\n const {clientGroupID} = client;\n const clientGroup = await getClientGroup(clientGroupID, dagRead);\n assert(clientGroup, `Client group not found: ${clientGroupID}`);\n const dbRead = await readFromHash(\n clientGroup.headHash,\n dagRead,\n FormatVersion.Latest,\n );\n return dbRead.map;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype MapEntry<T extends ReadonlyMap<any, any>> =\n T extends ReadonlyMap<infer K, infer V> ? readonly [K, V] : never;\n\nasync function clients(\n rep: Rep,\n metricsDelegate: InspectorClientMetricsDelegate,\n socket: GetWebSocket,\n schema: Schema,\n dagRead: Read,\n predicate: (entry: MapEntry<ClientMap>) => boolean = () => true,\n): Promise<ClientInterface[]> {\n const clients = await getClients(dagRead);\n return [...clients.entries()]\n .filter(predicate)\n .map(\n ([clientID, {clientGroupID}]) =>\n new Client(\n rep,\n metricsDelegate,\n schema,\n socket,\n clientID,\n clientGroupID,\n ),\n );\n}\n\nasync function clientsWithQueries(\n rep: Rep,\n metricsDelegate: InspectorClientMetricsDelegate,\n socket: GetWebSocket,\n schema: Schema,\n dagRead: Read,\n predicate: (entry: MapEntry<ClientMap>) => boolean = () => true,\n): Promise<ClientInterface[]> {\n const allClients = await clients(\n rep,\n metricsDelegate,\n socket,\n schema,\n dagRead,\n predicate,\n );\n const clientsWithQueries: ClientInterface[] = [];\n await Promise.all(\n allClients.map(async client => {\n const queries = await client.queries();\n if (queries.length > 0) {\n clientsWithQueries.push(client);\n }\n }),\n );\n return clientsWithQueries;\n}\n\nclass Query implements QueryInterface {\n readonly ast: AST | null;\n readonly name: string | null;\n readonly args: ReadonlyArray<ReadonlyJSONValue> | null;\n readonly got: boolean;\n readonly ttl: TTL;\n readonly inactivatedAt: Date | null;\n readonly rowCount: number;\n readonly deleted: boolean;\n readonly id: string;\n readonly zql: string | null;\n readonly clientID: string;\n readonly metrics: Metrics | null;\n\n constructor(\n row: InspectQueryRow,\n metricsDelegate: InspectorClientMetricsDelegate,\n ) {\n const {ast, queryID, inactivatedAt} = row;\n // Use own properties to make this more useful in dev tools. For example, in\n // Chrome dev tools, if you do console.table(queries) you'll see the\n // properties in the table, if these were getters you would not see them in the table.\n this.clientID = row.clientID;\n this.id = queryID;\n this.inactivatedAt =\n inactivatedAt === null ? null : new Date(inactivatedAt);\n this.ttl = normalizeTTL(row.ttl);\n this.ast = ast;\n this.name = row.name;\n this.args = row.args;\n this.got = row.got;\n this.rowCount = row.rowCount;\n this.deleted = row.deleted;\n this.zql = ast ? ast.table + astToZQL(ast) : null;\n\n // Merge client and server metrics\n const clientMetrics = metricsDelegate.getQueryMetrics(queryID);\n const serverMetrics = row.metrics;\n\n this.metrics = mergeMetrics(clientMetrics, serverMetrics);\n }\n}\n\nfunction mergeMetrics(\n clientMetrics: ClientMetrics | undefined,\n serverMetrics: ServerMetricsJSON | null | undefined,\n): Metrics {\n return {\n ...(clientMetrics ?? newClientMetrics()),\n ...(serverMetrics\n ? convertServerMetrics(serverMetrics)\n : newServerMetrics()),\n };\n}\n\nfunction newClientMetrics(): ClientMetrics {\n return {\n 'query-materialization-client': new TDigest(),\n 'query-materialization-end-to-end': new TDigest(),\n 'query-update-client': new TDigest(),\n };\n}\n\nfunction newServerMetrics(): ServerMetrics {\n return {\n 'query-materialization-server': new TDigest(),\n };\n}\n\nfunction convertServerMetrics(metrics: ServerMetricsJSON): ServerMetrics {\n return mapValues(metrics, v => TDigest.fromJSON(v));\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["clients", "clientsWithQueries"]
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../zero-react/src/components/inspector.tsx"],
|
|
4
|
-
"sourcesContent": ["import type {CustomMutatorDefs} from '../../../zero-client/src/client/custom.ts';\nimport type {Zero} from '../../../zero-client/src/client/zero.ts';\nimport type {Schema} from '../../../zero-schema/src/builder/schema-builder.ts';\nimport {MarkIcon} from './mark-icon.tsx';\n\nexport default function Inspector<\n S extends Schema,\n MD extends CustomMutatorDefs
|
|
4
|
+
"sourcesContent": ["import type {CustomMutatorDefs} from '../../../zero-client/src/client/custom.ts';\nimport type {Zero} from '../../../zero-client/src/client/zero.ts';\nimport type {Schema} from '../../../zero-schema/src/builder/schema-builder.ts';\nimport {MarkIcon} from './mark-icon.tsx';\n\nexport default function Inspector<\n S extends Schema,\n MD extends CustomMutatorDefs | undefined = undefined,\n>({zero, onClose}: {zero: Zero<S, MD>; onClose: () => void}) {\n return (\n <dialog\n open\n style={{\n alignItems: 'center',\n backgroundColor: 'white',\n borderRadius: '8px 0 0 0',\n bottom: 0,\n boxShadow: '0 4px 8px rgba(0, 0, 0, 0.1)',\n color: 'black',\n display: 'flex',\n height: 'fit-content',\n marginRight: 0,\n opacity: 0.95,\n padding: '0.25em 0.5em',\n position: 'fixed',\n width: 'fit-content',\n zIndex: 1000,\n }}\n >\n <MarkIcon style={{margin: '0.5em'}} />\n <div>Zero v{zero.version}</div>\n <button onClick={onClose} style={{padding: '0.5em'}}>\n \u2716\uFE0E\n </button>\n </dialog>\n );\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;AA6BM,cACA,YADA;AAxBS,SAAR,UAGL,EAAC,MAAM,QAAO,GAA6C;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAI;AAAA,MACJ,OAAO;AAAA,QACL,YAAY;AAAA,QACZ,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,OAAO;AAAA,QACP,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,SAAS;AAAA,QACT,SAAS;AAAA,QACT,UAAU;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,MACV;AAAA,MAEA;AAAA,4BAAC,YAAS,OAAO,EAAC,QAAQ,QAAO,GAAG;AAAA,QACpC,qBAAC,SAAI;AAAA;AAAA,UAAO,KAAK;AAAA,WAAQ;AAAA,QACzB,oBAAC,YAAO,SAAS,SAAS,OAAO,EAAC,SAAS,QAAO,GAAG,0BAErD;AAAA;AAAA;AAAA,EACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/out/react.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Zero
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZKRMVMWK.js";
|
|
4
|
+
import "./chunk-MKB4RXL3.js";
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_TTL_MS
|
|
7
|
+
} from "./chunk-O536GEIT.js";
|
|
4
8
|
import {
|
|
5
|
-
DEFAULT_TTL_MS,
|
|
6
9
|
hasOwn
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-SGW2EIVJ.js";
|
|
8
11
|
import {
|
|
9
12
|
MarkIcon
|
|
10
13
|
} from "./chunk-O7W55FT4.js";
|
|
@@ -13,7 +16,7 @@ import "./chunk-424PT5DM.js";
|
|
|
13
16
|
// ../zero-react/src/components/zero-inspector.tsx
|
|
14
17
|
import { lazy, Suspense, useState } from "react";
|
|
15
18
|
import { jsx } from "react/jsx-runtime";
|
|
16
|
-
var Inspector = lazy(() => import("./inspector-
|
|
19
|
+
var Inspector = lazy(() => import("./inspector-YIRP3TTL.js"));
|
|
17
20
|
function ZeroInspector({ zero }) {
|
|
18
21
|
const [show, setShow] = useState(false);
|
|
19
22
|
return show ? /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { children: "Loading Inspector..." }), children: /* @__PURE__ */ jsx(
|
package/out/react.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../zero-react/src/components/zero-inspector.tsx", "../../zero-react/src/use-query.tsx", "../../shared/src/deep-clone.ts", "../../zero-react/src/zero-provider.tsx", "../../zero-react/src/use-zero-online.tsx"],
|
|
4
|
-
"sourcesContent": ["import {lazy, Suspense, useState} from 'react';\nimport type {CustomMutatorDefs} from '../../../zero-client/src/client/custom.ts';\nimport type {Zero} from '../../../zero-client/src/client/zero.ts';\nimport type {Schema} from '../../../zero-schema/src/builder/schema-builder.ts';\nimport {MarkIcon} from './mark-icon.tsx';\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst Inspector = lazy(() => import('./inspector.tsx'));\n\nexport function ZeroInspector<\n S extends Schema,\n MD extends CustomMutatorDefs<S> | undefined = undefined,\n>({zero}: {zero: Zero<S, MD>}): JSX.Element {\n const [show, setShow] = useState(false);\n return show ? (\n <Suspense fallback={<div>Loading Inspector...</div>}>\n <Inspector\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n zero={zero as any}\n onClose={() => setShow(false)}\n />\n </Suspense>\n ) : (\n <button\n onClick={() => setShow(!show)}\n style={{\n position: 'fixed',\n bottom: 0,\n right: 0,\n zIndex: 1000,\n padding: '5px',\n color: 'white',\n backgroundColor: '#333',\n borderTopLeftRadius: '8px',\n opacity: 0.95,\n }}\n >\n <MarkIcon\n style={{\n width: '20px',\n height: '20px',\n fill: 'currentColor',\n }}\n />\n </button>\n );\n}\n", "import {useSyncExternalStore} from 'react';\nimport {deepClone} from '../../shared/src/deep-clone.ts';\nimport type {Immutable} from '../../shared/src/immutable.ts';\nimport type {ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {Zero} from '../../zero-client/src/client/zero.ts';\nimport type {Schema} from '../../zero-schema/src/builder/schema-builder.ts';\nimport type {Format} from '../../zql/src/ivm/view.ts';\nimport {AbstractQuery} from '../../zql/src/query/query-impl.ts';\nimport {type HumanReadable, type Query} from '../../zql/src/query/query.ts';\nimport {DEFAULT_TTL_MS, type TTL} from '../../zql/src/query/ttl.ts';\nimport type {ResultType, TypedView} from '../../zql/src/query/typed-view.ts';\nimport {useZero} from './zero-provider.tsx';\n\nexport type QueryResultDetails = Readonly<{\n type: ResultType;\n}>;\n\nexport type QueryResult<TReturn> = readonly [\n HumanReadable<TReturn>,\n QueryResultDetails,\n];\n\nexport type UseQueryOptions = {\n enabled?: boolean | undefined;\n /**\n * Time to live (TTL) in seconds. Controls how long query results are cached\n * after the query is removed. During this time, Zero continues to sync the query.\n * Default is 'never'.\n */\n ttl?: TTL | undefined;\n};\n\nexport function useQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n query: Query<TSchema, TTable, TReturn>,\n options?: UseQueryOptions | boolean,\n): QueryResult<TReturn> {\n let enabled = true;\n let ttl: TTL = DEFAULT_TTL_MS;\n if (typeof options === 'boolean') {\n enabled = options;\n } else if (options) {\n ({enabled = true, ttl = DEFAULT_TTL_MS} = options);\n }\n\n const view = viewStore.getView(\n useZero(),\n query as AbstractQuery<TSchema, TTable, TReturn>,\n enabled,\n ttl,\n );\n // https://react.dev/reference/react/useSyncExternalStore\n return useSyncExternalStore(\n view.subscribeReactInternals,\n view.getSnapshot,\n view.getSnapshot,\n );\n}\n\nconst emptyArray: unknown[] = [];\nconst disabledSubscriber = () => () => {};\n\nconst resultTypeUnknown = {type: 'unknown'} as const;\nconst resultTypeComplete = {type: 'complete'} as const;\n\nconst emptySnapshotSingularUnknown = [undefined, resultTypeUnknown] as const;\nconst emptySnapshotSingularComplete = [undefined, resultTypeComplete] as const;\nconst emptySnapshotPluralUnknown = [emptyArray, resultTypeUnknown] as const;\nconst emptySnapshotPluralComplete = [emptyArray, resultTypeComplete] as const;\n\nfunction getDefaultSnapshot<TReturn>(singular: boolean): QueryResult<TReturn> {\n return (\n singular ? emptySnapshotSingularUnknown : emptySnapshotPluralUnknown\n ) as QueryResult<TReturn>;\n}\n\n/**\n * Returns a new snapshot or one of the empty predefined ones. Returning the\n * predefined ones is important to prevent unnecessary re-renders in React.\n */\nfunction getSnapshot<TReturn>(\n singular: boolean,\n data: HumanReadable<TReturn>,\n resultType: string,\n): QueryResult<TReturn> {\n if (singular && data === undefined) {\n return (resultType === 'complete'\n ? emptySnapshotSingularComplete\n : emptySnapshotSingularUnknown) as unknown as QueryResult<TReturn>;\n }\n\n if (!singular && (data as unknown[]).length === 0) {\n return (\n resultType === 'complete'\n ? emptySnapshotPluralComplete\n : emptySnapshotPluralUnknown\n ) as QueryResult<TReturn>;\n }\n\n return [\n data,\n resultType === 'complete' ? resultTypeComplete : resultTypeUnknown,\n ];\n}\n\ndeclare const TESTING: boolean;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ViewWrapperAny = ViewWrapper<any, any, any>;\n\nconst allViews = new WeakMap<ViewStore, Map<string, ViewWrapperAny>>();\n\nexport function getAllViewsSizeForTesting(store: ViewStore): number {\n if (TESTING) {\n return allViews.get(store)?.size ?? 0;\n }\n return 0;\n}\n\n/**\n * A global store of all active views.\n *\n * React subscribes and unsubscribes to these views\n * via `useSyncExternalStore`.\n *\n * Managing views through `useEffect` or `useLayoutEffect` causes\n * inconsistencies because effects run after render.\n *\n * For example, if useQuery used use*Effect in the component below:\n * ```ts\n * function Foo({issueID}) {\n * const issue = useQuery(z.query.issue.where('id', issueID).one());\n * if (issue?.id !== undefined && issue.id !== issueID) {\n * console.log('MISMATCH!', issue.id, issueID);\n * }\n * }\n * ```\n *\n * `MISMATCH` will be printed whenever the `issueID` prop changes.\n *\n * This is because the component will render once with\n * the old state returned from `useQuery`. Then the effect inside\n * `useQuery` will run. The component will render again with the new\n * state. This inconsistent transition can cause unexpected results.\n *\n * Emulating `useEffect` via `useState` and `if` causes resource leaks.\n * That is:\n *\n * ```ts\n * function useQuery(q) {\n * const [oldHash, setOldHash] = useState();\n * if (hash(q) !== oldHash) {\n * // make new view\n * }\n *\n * useEffect(() => {\n * return () => view.destroy();\n * }, []);\n * }\n * ```\n *\n * I'm not sure why but in strict mode the cleanup function\n * fails to be called for the first instance of the view and only\n * cleans up later instances.\n *\n * Swapping `useState` to `useRef` has similar problems.\n */\nexport class ViewStore {\n #views = new Map<string, ViewWrapperAny>();\n\n constructor() {\n if (TESTING) {\n allViews.set(this, this.#views);\n }\n }\n\n getView<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n >(\n zero: Zero<TSchema>,\n query: Query<TSchema, TTable, TReturn>,\n enabled: boolean,\n ttl: TTL,\n ): {\n getSnapshot: () => QueryResult<TReturn>;\n subscribeReactInternals: (internals: () => void) => () => void;\n updateTTL: (ttl: TTL) => void;\n } {\n const {format} = query;\n if (!enabled) {\n return {\n getSnapshot: () => getDefaultSnapshot(format.singular),\n subscribeReactInternals: disabledSubscriber,\n updateTTL: () => {},\n };\n }\n\n const hash = query.hash() + zero.clientID;\n let existing = this.#views.get(hash);\n if (!existing) {\n query = query.delegate(zero.queryDelegate);\n existing = new ViewWrapper(\n query,\n format,\n ttl,\n view => {\n const lastView = this.#views.get(hash);\n // I don't think this can happen\n // but lets guard against it so we don't\n // leak resources.\n if (lastView && lastView !== view) {\n throw new Error('View already exists');\n }\n this.#views.set(hash, view);\n },\n () => {\n this.#views.delete(hash);\n },\n ) as ViewWrapper<TSchema, TTable, TReturn>;\n this.#views.set(hash, existing);\n } else {\n existing.updateTTL(ttl);\n }\n return existing as ViewWrapper<TSchema, TTable, TReturn>;\n }\n}\n\nconst viewStore = new ViewStore();\n\n/**\n * This wraps and ref counts a view.\n *\n * The only signal we have from React as to whether or not it is\n * done with a view is when it calls `unsubscribe`.\n *\n * In non-strict-mode we can clean up the view as soon\n * as the listener count goes to 0.\n *\n * In strict-mode, the listener count will go to 0 then a\n * new listener for the same view is immediately added back.\n *\n * This is why the `onMaterialized` and `onDematerialized` callbacks exist --\n * they allow a view which React is still referencing to be added\n * back into the store when React re-subscribes to it.\n *\n * This wrapper also exists to deal with the various\n * `useSyncExternalStore` caveats that cause excessive\n * re-renders and materializations.\n *\n * See: https://react.dev/reference/react/useSyncExternalStore#caveats\n * Especially:\n * 1. The store snapshot returned by getSnapshot must be immutable. If the underlying store has mutable data, return a new immutable snapshot if the data has changed. Otherwise, return a cached last snapshot.\n * 2. If a different subscribe function is passed during a re-render, React will re-subscribe to the store using the newly passed subscribe function. You can prevent this by declaring subscribe outside the component.\n */\nclass ViewWrapper<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n> {\n #view: TypedView<HumanReadable<TReturn>> | undefined;\n readonly #onDematerialized;\n readonly #onMaterialized;\n readonly #query: Query<TSchema, TTable, TReturn>;\n readonly #format: Format;\n #snapshot: QueryResult<TReturn>;\n #reactInternals: Set<() => void>;\n #ttl: TTL;\n\n constructor(\n query: Query<TSchema, TTable, TReturn>,\n format: Format,\n ttl: TTL,\n onMaterialized: (view: ViewWrapper<TSchema, TTable, TReturn>) => void,\n onDematerialized: () => void,\n ) {\n this.#query = query;\n this.#format = format;\n this.#ttl = ttl;\n this.#onMaterialized = onMaterialized;\n this.#onDematerialized = onDematerialized;\n this.#snapshot = getDefaultSnapshot(format.singular);\n this.#reactInternals = new Set();\n this.#materializeIfNeeded();\n }\n\n #onData = (\n snap: Immutable<HumanReadable<TReturn>>,\n resultType: ResultType,\n ) => {\n const data =\n snap === undefined\n ? snap\n : (deepClone(snap as ReadonlyJSONValue) as HumanReadable<TReturn>);\n this.#snapshot = getSnapshot(this.#format.singular, data, resultType);\n for (const internals of this.#reactInternals) {\n internals();\n }\n };\n\n #materializeIfNeeded = () => {\n if (this.#view) {\n return;\n }\n\n this.#view = this.#query.materialize(this.#ttl);\n this.#view.addListener(this.#onData);\n\n this.#onMaterialized(this);\n };\n\n getSnapshot = () => this.#snapshot;\n\n subscribeReactInternals = (internals: () => void): (() => void) => {\n this.#reactInternals.add(internals);\n this.#materializeIfNeeded();\n return () => {\n this.#reactInternals.delete(internals);\n\n // only schedule a cleanup task if we have no listeners left\n if (this.#reactInternals.size === 0) {\n setTimeout(() => {\n // Someone re-registered a listener on this view before the timeout elapsed.\n // This happens often in strict-mode which forces a component\n // to mount, unmount, remount.\n if (this.#reactInternals.size > 0) {\n return;\n }\n // We already destroyed the view\n if (this.#view === undefined) {\n return;\n }\n this.#view?.destroy();\n this.#view = undefined;\n this.#onDematerialized();\n }, 10);\n }\n };\n };\n\n updateTTL(ttl: TTL): void {\n this.#ttl = ttl;\n this.#view?.updateTTL(ttl);\n }\n}\n", "import {hasOwn} from './has-own.ts';\nimport type {JSONValue, ReadonlyJSONValue} from './json.ts';\n\nexport function deepClone(value: ReadonlyJSONValue): JSONValue {\n const seen: Array<ReadonlyJSONValue> = [];\n return internalDeepClone(value, seen);\n}\n\nexport function internalDeepClone(\n value: ReadonlyJSONValue,\n seen: Array<ReadonlyJSONValue>,\n): JSONValue {\n switch (typeof value) {\n case 'boolean':\n case 'number':\n case 'string':\n case 'undefined':\n return value;\n case 'object': {\n if (value === null) {\n return null;\n }\n if (seen.includes(value)) {\n throw new Error('Cyclic object');\n }\n seen.push(value);\n if (Array.isArray(value)) {\n const rv = value.map(v => internalDeepClone(v, seen));\n seen.pop();\n return rv;\n }\n\n const obj: JSONValue = {};\n\n for (const k in value) {\n if (hasOwn(value, k)) {\n const v = (value as Record<string, ReadonlyJSONValue>)[k];\n if (v !== undefined) {\n obj[k] = internalDeepClone(v, seen);\n }\n }\n }\n seen.pop();\n return obj;\n }\n\n default:\n throw new Error(`Invalid type: ${typeof value}`);\n }\n}\n", "import {\n createContext,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n} from 'react';\nimport {Zero} from '../../zero-client/src/client/zero.ts';\nimport type {Schema} from '../../zero-schema/src/builder/schema-builder.ts';\nimport type {CustomMutatorDefs} from '../../zero-client/src/client/custom.ts';\nimport type {ZeroOptions} from '../../zero-client/src/client/options.ts';\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst ZeroContext = createContext<unknown | undefined>(undefined);\n\nexport function useZero<\n S extends Schema,\n MD extends CustomMutatorDefs<S> | undefined = undefined,\n>(): Zero<S, MD> {\n const zero = useContext(ZeroContext);\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero as Zero<S, MD>;\n}\n\nexport function createUseZero<\n S extends Schema,\n MD extends CustomMutatorDefs<S> | undefined = undefined,\n>() {\n return () => useZero<S, MD>();\n}\n\nexport type ZeroProviderProps<\n S extends Schema,\n MD extends CustomMutatorDefs<S> | undefined = undefined,\n> = (ZeroOptions<S, MD> | {zero: Zero<S, MD>}) & {\n init?: (zero: Zero<S, MD>) => void;\n children: ReactNode;\n};\n\nexport function ZeroProvider<\n S extends Schema,\n MD extends CustomMutatorDefs<S> | undefined = undefined,\n>({children, init, ...props}: ZeroProviderProps<S, MD>) {\n const [zero, setZero] = useState<Zero<S, MD> | undefined>(\n 'zero' in props ? props.zero : undefined,\n );\n\n // If Zero is not passed in, we construct it, but only client-side.\n // Zero doesn't really work SSR today so this is usually the right thing.\n // When we support Zero SSR this will either become a breaking change or\n // more likely server support will be opt-in with a new prop on this\n // component.\n useEffect(() => {\n if ('zero' in props) {\n setZero(props.zero);\n return;\n }\n\n const z = new Zero(props);\n init?.(z);\n setZero(z);\n\n return () => {\n void z.close();\n setZero(undefined);\n };\n }, [init, ...Object.values(props)]);\n\n return (\n zero && <ZeroContext.Provider value={zero}>{children}</ZeroContext.Provider>\n );\n}\n", "import {useSyncExternalStore} from 'react';\nimport {useZero} from './zero-provider.tsx';\n\n/**\n * Hook to subscribe to the online status of the Zero instance.\n *\n * This is useful when you want to update state based on the online status.\n *\n * @returns The online status of the Zero instance.\n */\nexport function useZeroOnline(): boolean {\n const zero = useZero();\n return useSyncExternalStore(\n zero.onOnline,\n () => zero.online,\n () => zero.online,\n );\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import {lazy, Suspense, useState} from 'react';\nimport type {CustomMutatorDefs} from '../../../zero-client/src/client/custom.ts';\nimport type {Zero} from '../../../zero-client/src/client/zero.ts';\nimport type {Schema} from '../../../zero-schema/src/builder/schema-builder.ts';\nimport {MarkIcon} from './mark-icon.tsx';\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst Inspector = lazy(() => import('./inspector.tsx'));\n\nexport function ZeroInspector<\n S extends Schema,\n MD extends CustomMutatorDefs | undefined = undefined,\n>({zero}: {zero: Zero<S, MD>}): JSX.Element {\n const [show, setShow] = useState(false);\n return show ? (\n <Suspense fallback={<div>Loading Inspector...</div>}>\n <Inspector\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n zero={zero as any}\n onClose={() => setShow(false)}\n />\n </Suspense>\n ) : (\n <button\n onClick={() => setShow(!show)}\n style={{\n position: 'fixed',\n bottom: 0,\n right: 0,\n zIndex: 1000,\n padding: '5px',\n color: 'white',\n backgroundColor: '#333',\n borderTopLeftRadius: '8px',\n opacity: 0.95,\n }}\n >\n <MarkIcon\n style={{\n width: '20px',\n height: '20px',\n fill: 'currentColor',\n }}\n />\n </button>\n );\n}\n", "import {useSyncExternalStore} from 'react';\nimport {deepClone} from '../../shared/src/deep-clone.ts';\nimport type {Immutable} from '../../shared/src/immutable.ts';\nimport type {ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {Zero} from '../../zero-client/src/client/zero.ts';\nimport type {Schema} from '../../zero-schema/src/builder/schema-builder.ts';\nimport type {Format} from '../../zql/src/ivm/view.ts';\nimport {AbstractQuery} from '../../zql/src/query/query-impl.ts';\nimport {type HumanReadable, type Query} from '../../zql/src/query/query.ts';\nimport {DEFAULT_TTL_MS, type TTL} from '../../zql/src/query/ttl.ts';\nimport type {ResultType, TypedView} from '../../zql/src/query/typed-view.ts';\nimport {useZero} from './zero-provider.tsx';\n\nexport type QueryResultDetails = Readonly<{\n type: ResultType;\n}>;\n\nexport type QueryResult<TReturn> = readonly [\n HumanReadable<TReturn>,\n QueryResultDetails,\n];\n\nexport type UseQueryOptions = {\n enabled?: boolean | undefined;\n /**\n * Time to live (TTL) in seconds. Controls how long query results are cached\n * after the query is removed. During this time, Zero continues to sync the query.\n * Default is 'never'.\n */\n ttl?: TTL | undefined;\n};\n\nexport function useQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n query: Query<TSchema, TTable, TReturn>,\n options?: UseQueryOptions | boolean,\n): QueryResult<TReturn> {\n let enabled = true;\n let ttl: TTL = DEFAULT_TTL_MS;\n if (typeof options === 'boolean') {\n enabled = options;\n } else if (options) {\n ({enabled = true, ttl = DEFAULT_TTL_MS} = options);\n }\n\n const view = viewStore.getView(\n useZero(),\n query as AbstractQuery<TSchema, TTable, TReturn>,\n enabled,\n ttl,\n );\n // https://react.dev/reference/react/useSyncExternalStore\n return useSyncExternalStore(\n view.subscribeReactInternals,\n view.getSnapshot,\n view.getSnapshot,\n );\n}\n\nconst emptyArray: unknown[] = [];\nconst disabledSubscriber = () => () => {};\n\nconst resultTypeUnknown = {type: 'unknown'} as const;\nconst resultTypeComplete = {type: 'complete'} as const;\n\nconst emptySnapshotSingularUnknown = [undefined, resultTypeUnknown] as const;\nconst emptySnapshotSingularComplete = [undefined, resultTypeComplete] as const;\nconst emptySnapshotPluralUnknown = [emptyArray, resultTypeUnknown] as const;\nconst emptySnapshotPluralComplete = [emptyArray, resultTypeComplete] as const;\n\nfunction getDefaultSnapshot<TReturn>(singular: boolean): QueryResult<TReturn> {\n return (\n singular ? emptySnapshotSingularUnknown : emptySnapshotPluralUnknown\n ) as QueryResult<TReturn>;\n}\n\n/**\n * Returns a new snapshot or one of the empty predefined ones. Returning the\n * predefined ones is important to prevent unnecessary re-renders in React.\n */\nfunction getSnapshot<TReturn>(\n singular: boolean,\n data: HumanReadable<TReturn>,\n resultType: string,\n): QueryResult<TReturn> {\n if (singular && data === undefined) {\n return (resultType === 'complete'\n ? emptySnapshotSingularComplete\n : emptySnapshotSingularUnknown) as unknown as QueryResult<TReturn>;\n }\n\n if (!singular && (data as unknown[]).length === 0) {\n return (\n resultType === 'complete'\n ? emptySnapshotPluralComplete\n : emptySnapshotPluralUnknown\n ) as QueryResult<TReturn>;\n }\n\n return [\n data,\n resultType === 'complete' ? resultTypeComplete : resultTypeUnknown,\n ];\n}\n\ndeclare const TESTING: boolean;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ViewWrapperAny = ViewWrapper<any, any, any>;\n\nconst allViews = new WeakMap<ViewStore, Map<string, ViewWrapperAny>>();\n\nexport function getAllViewsSizeForTesting(store: ViewStore): number {\n if (TESTING) {\n return allViews.get(store)?.size ?? 0;\n }\n return 0;\n}\n\n/**\n * A global store of all active views.\n *\n * React subscribes and unsubscribes to these views\n * via `useSyncExternalStore`.\n *\n * Managing views through `useEffect` or `useLayoutEffect` causes\n * inconsistencies because effects run after render.\n *\n * For example, if useQuery used use*Effect in the component below:\n * ```ts\n * function Foo({issueID}) {\n * const issue = useQuery(z.query.issue.where('id', issueID).one());\n * if (issue?.id !== undefined && issue.id !== issueID) {\n * console.log('MISMATCH!', issue.id, issueID);\n * }\n * }\n * ```\n *\n * `MISMATCH` will be printed whenever the `issueID` prop changes.\n *\n * This is because the component will render once with\n * the old state returned from `useQuery`. Then the effect inside\n * `useQuery` will run. The component will render again with the new\n * state. This inconsistent transition can cause unexpected results.\n *\n * Emulating `useEffect` via `useState` and `if` causes resource leaks.\n * That is:\n *\n * ```ts\n * function useQuery(q) {\n * const [oldHash, setOldHash] = useState();\n * if (hash(q) !== oldHash) {\n * // make new view\n * }\n *\n * useEffect(() => {\n * return () => view.destroy();\n * }, []);\n * }\n * ```\n *\n * I'm not sure why but in strict mode the cleanup function\n * fails to be called for the first instance of the view and only\n * cleans up later instances.\n *\n * Swapping `useState` to `useRef` has similar problems.\n */\nexport class ViewStore {\n #views = new Map<string, ViewWrapperAny>();\n\n constructor() {\n if (TESTING) {\n allViews.set(this, this.#views);\n }\n }\n\n getView<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n >(\n zero: Zero<TSchema>,\n query: Query<TSchema, TTable, TReturn>,\n enabled: boolean,\n ttl: TTL,\n ): {\n getSnapshot: () => QueryResult<TReturn>;\n subscribeReactInternals: (internals: () => void) => () => void;\n updateTTL: (ttl: TTL) => void;\n } {\n const {format} = query;\n if (!enabled) {\n return {\n getSnapshot: () => getDefaultSnapshot(format.singular),\n subscribeReactInternals: disabledSubscriber,\n updateTTL: () => {},\n };\n }\n\n const hash = query.hash() + zero.clientID;\n let existing = this.#views.get(hash);\n if (!existing) {\n query = query.delegate(zero.queryDelegate);\n existing = new ViewWrapper(\n query,\n format,\n ttl,\n view => {\n const lastView = this.#views.get(hash);\n // I don't think this can happen\n // but lets guard against it so we don't\n // leak resources.\n if (lastView && lastView !== view) {\n throw new Error('View already exists');\n }\n this.#views.set(hash, view);\n },\n () => {\n this.#views.delete(hash);\n },\n ) as ViewWrapper<TSchema, TTable, TReturn>;\n this.#views.set(hash, existing);\n } else {\n existing.updateTTL(ttl);\n }\n return existing as ViewWrapper<TSchema, TTable, TReturn>;\n }\n}\n\nconst viewStore = new ViewStore();\n\n/**\n * This wraps and ref counts a view.\n *\n * The only signal we have from React as to whether or not it is\n * done with a view is when it calls `unsubscribe`.\n *\n * In non-strict-mode we can clean up the view as soon\n * as the listener count goes to 0.\n *\n * In strict-mode, the listener count will go to 0 then a\n * new listener for the same view is immediately added back.\n *\n * This is why the `onMaterialized` and `onDematerialized` callbacks exist --\n * they allow a view which React is still referencing to be added\n * back into the store when React re-subscribes to it.\n *\n * This wrapper also exists to deal with the various\n * `useSyncExternalStore` caveats that cause excessive\n * re-renders and materializations.\n *\n * See: https://react.dev/reference/react/useSyncExternalStore#caveats\n * Especially:\n * 1. The store snapshot returned by getSnapshot must be immutable. If the underlying store has mutable data, return a new immutable snapshot if the data has changed. Otherwise, return a cached last snapshot.\n * 2. If a different subscribe function is passed during a re-render, React will re-subscribe to the store using the newly passed subscribe function. You can prevent this by declaring subscribe outside the component.\n */\nclass ViewWrapper<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n> {\n #view: TypedView<HumanReadable<TReturn>> | undefined;\n readonly #onDematerialized;\n readonly #onMaterialized;\n readonly #query: Query<TSchema, TTable, TReturn>;\n readonly #format: Format;\n #snapshot: QueryResult<TReturn>;\n #reactInternals: Set<() => void>;\n #ttl: TTL;\n\n constructor(\n query: Query<TSchema, TTable, TReturn>,\n format: Format,\n ttl: TTL,\n onMaterialized: (view: ViewWrapper<TSchema, TTable, TReturn>) => void,\n onDematerialized: () => void,\n ) {\n this.#query = query;\n this.#format = format;\n this.#ttl = ttl;\n this.#onMaterialized = onMaterialized;\n this.#onDematerialized = onDematerialized;\n this.#snapshot = getDefaultSnapshot(format.singular);\n this.#reactInternals = new Set();\n this.#materializeIfNeeded();\n }\n\n #onData = (\n snap: Immutable<HumanReadable<TReturn>>,\n resultType: ResultType,\n ) => {\n const data =\n snap === undefined\n ? snap\n : (deepClone(snap as ReadonlyJSONValue) as HumanReadable<TReturn>);\n this.#snapshot = getSnapshot(this.#format.singular, data, resultType);\n for (const internals of this.#reactInternals) {\n internals();\n }\n };\n\n #materializeIfNeeded = () => {\n if (this.#view) {\n return;\n }\n\n this.#view = this.#query.materialize(this.#ttl);\n this.#view.addListener(this.#onData);\n\n this.#onMaterialized(this);\n };\n\n getSnapshot = () => this.#snapshot;\n\n subscribeReactInternals = (internals: () => void): (() => void) => {\n this.#reactInternals.add(internals);\n this.#materializeIfNeeded();\n return () => {\n this.#reactInternals.delete(internals);\n\n // only schedule a cleanup task if we have no listeners left\n if (this.#reactInternals.size === 0) {\n setTimeout(() => {\n // Someone re-registered a listener on this view before the timeout elapsed.\n // This happens often in strict-mode which forces a component\n // to mount, unmount, remount.\n if (this.#reactInternals.size > 0) {\n return;\n }\n // We already destroyed the view\n if (this.#view === undefined) {\n return;\n }\n this.#view?.destroy();\n this.#view = undefined;\n this.#onDematerialized();\n }, 10);\n }\n };\n };\n\n updateTTL(ttl: TTL): void {\n this.#ttl = ttl;\n this.#view?.updateTTL(ttl);\n }\n}\n", "import {hasOwn} from './has-own.ts';\nimport type {JSONValue, ReadonlyJSONValue} from './json.ts';\n\nexport function deepClone(value: ReadonlyJSONValue): JSONValue {\n const seen: Array<ReadonlyJSONValue> = [];\n return internalDeepClone(value, seen);\n}\n\nexport function internalDeepClone(\n value: ReadonlyJSONValue,\n seen: Array<ReadonlyJSONValue>,\n): JSONValue {\n switch (typeof value) {\n case 'boolean':\n case 'number':\n case 'string':\n case 'undefined':\n return value;\n case 'object': {\n if (value === null) {\n return null;\n }\n if (seen.includes(value)) {\n throw new Error('Cyclic object');\n }\n seen.push(value);\n if (Array.isArray(value)) {\n const rv = value.map(v => internalDeepClone(v, seen));\n seen.pop();\n return rv;\n }\n\n const obj: JSONValue = {};\n\n for (const k in value) {\n if (hasOwn(value, k)) {\n const v = (value as Record<string, ReadonlyJSONValue>)[k];\n if (v !== undefined) {\n obj[k] = internalDeepClone(v, seen);\n }\n }\n }\n seen.pop();\n return obj;\n }\n\n default:\n throw new Error(`Invalid type: ${typeof value}`);\n }\n}\n", "import {\n createContext,\n useContext,\n useEffect,\n useState,\n type ReactNode,\n} from 'react';\nimport {Zero} from '../../zero-client/src/client/zero.ts';\nimport type {Schema} from '../../zero-schema/src/builder/schema-builder.ts';\nimport type {CustomMutatorDefs} from '../../zero-client/src/client/custom.ts';\nimport type {ZeroOptions} from '../../zero-client/src/client/options.ts';\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst ZeroContext = createContext<unknown | undefined>(undefined);\n\nexport function useZero<\n S extends Schema,\n MD extends CustomMutatorDefs | undefined = undefined,\n>(): Zero<S, MD> {\n const zero = useContext(ZeroContext);\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero as Zero<S, MD>;\n}\n\nexport function createUseZero<\n S extends Schema,\n MD extends CustomMutatorDefs | undefined = undefined,\n>() {\n return () => useZero<S, MD>();\n}\n\nexport type ZeroProviderProps<\n S extends Schema,\n MD extends CustomMutatorDefs | undefined = undefined,\n> = (ZeroOptions<S, MD> | {zero: Zero<S, MD>}) & {\n init?: (zero: Zero<S, MD>) => void;\n children: ReactNode;\n};\n\nexport function ZeroProvider<\n S extends Schema,\n MD extends CustomMutatorDefs | undefined = undefined,\n>({children, init, ...props}: ZeroProviderProps<S, MD>) {\n const [zero, setZero] = useState<Zero<S, MD> | undefined>(\n 'zero' in props ? props.zero : undefined,\n );\n\n // If Zero is not passed in, we construct it, but only client-side.\n // Zero doesn't really work SSR today so this is usually the right thing.\n // When we support Zero SSR this will either become a breaking change or\n // more likely server support will be opt-in with a new prop on this\n // component.\n useEffect(() => {\n if ('zero' in props) {\n setZero(props.zero);\n return;\n }\n\n const z = new Zero(props);\n init?.(z);\n setZero(z);\n\n return () => {\n void z.close();\n setZero(undefined);\n };\n }, [init, ...Object.values(props)]);\n\n return (\n zero && <ZeroContext.Provider value={zero}>{children}</ZeroContext.Provider>\n );\n}\n", "import {useSyncExternalStore} from 'react';\nimport {useZero} from './zero-provider.tsx';\n\n/**\n * Hook to subscribe to the online status of the Zero instance.\n *\n * This is useful when you want to update state based on the online status.\n *\n * @returns The online status of the Zero instance.\n */\nexport function useZeroOnline(): boolean {\n const zero = useZero();\n return useSyncExternalStore(\n zero.onOnline,\n () => zero.online,\n () => zero.online,\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["useState", "jsx", "useState", "useSyncExternalStore", "useSyncExternalStore"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { ReadonlyJSONValue } from '../../../shared/src/json.ts';
|
|
2
|
+
import type { Read, Store, Write } from './store.ts';
|
|
3
|
+
/**
|
|
4
|
+
* A SQLite prepared statement.
|
|
5
|
+
*
|
|
6
|
+
* `run` executes the statement with optional parameters.
|
|
7
|
+
* `all` executes the statement and returns the result rows.
|
|
8
|
+
* `finalize` releases the statement.
|
|
9
|
+
*/
|
|
10
|
+
export interface PreparedStatement {
|
|
11
|
+
run(...params: unknown[]): void;
|
|
12
|
+
all<T>(...params: unknown[]): T[];
|
|
13
|
+
finalize(): void;
|
|
14
|
+
}
|
|
15
|
+
export interface SQLiteDatabase {
|
|
16
|
+
/**
|
|
17
|
+
* Close the database connection.
|
|
18
|
+
*/
|
|
19
|
+
close(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Destroy or delete the database (e.g. delete file).
|
|
22
|
+
*/
|
|
23
|
+
destroy(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Prepare a SQL string, returning a statement you can execute.
|
|
26
|
+
* E.g. `const stmt = db.prepare("SELECT * FROM todos WHERE id=?");`
|
|
27
|
+
*/
|
|
28
|
+
prepare(sql: string): PreparedStatement;
|
|
29
|
+
}
|
|
30
|
+
type SQLiteTransactionPreparedStatements = {
|
|
31
|
+
begin: PreparedStatement;
|
|
32
|
+
beginImmediate: PreparedStatement;
|
|
33
|
+
commit: PreparedStatement;
|
|
34
|
+
rollback: PreparedStatement;
|
|
35
|
+
};
|
|
36
|
+
type SQLiteRWPreparedStatements = {
|
|
37
|
+
get: PreparedStatement;
|
|
38
|
+
put: PreparedStatement;
|
|
39
|
+
del: PreparedStatement;
|
|
40
|
+
};
|
|
41
|
+
type SQLitePreparedStatements = SQLiteTransactionPreparedStatements & SQLiteRWPreparedStatements;
|
|
42
|
+
/**
|
|
43
|
+
* A SQLite-based Store implementation.
|
|
44
|
+
*
|
|
45
|
+
* This store provides a generic SQLite implementation that can be used with different
|
|
46
|
+
* SQLite providers (expo-sqlite, better-sqlite3, etc). It implements the Store
|
|
47
|
+
* interface using a single 'entry' table with key-value pairs.
|
|
48
|
+
*
|
|
49
|
+
* The store uses a single RWLock to prevent concurrent read and write operations.
|
|
50
|
+
*
|
|
51
|
+
* The store also uses a pool of read connections to allow concurrent reads with separate transactions.
|
|
52
|
+
*/
|
|
53
|
+
export declare class SQLiteStore implements Store {
|
|
54
|
+
#private;
|
|
55
|
+
constructor(name: string, dbm: SQLiteDatabaseManager, opts: SQLiteDatabaseManagerOptions);
|
|
56
|
+
read(): Promise<Read>;
|
|
57
|
+
write(): Promise<Write>;
|
|
58
|
+
close(): Promise<void>;
|
|
59
|
+
get closed(): boolean;
|
|
60
|
+
}
|
|
61
|
+
declare class SQLiteStoreRWBase {
|
|
62
|
+
#private;
|
|
63
|
+
protected readonly _preparedStatements: SQLitePreparedStatements;
|
|
64
|
+
constructor(preparedStatements: SQLitePreparedStatements, release: () => void);
|
|
65
|
+
has(key: string): Promise<boolean>;
|
|
66
|
+
get(key: string): Promise<ReadonlyJSONValue | undefined>;
|
|
67
|
+
protected _release(): void;
|
|
68
|
+
get closed(): boolean;
|
|
69
|
+
}
|
|
70
|
+
export declare class SQLiteStoreRead extends SQLiteStoreRWBase implements Read {
|
|
71
|
+
constructor(preparedStatements: SQLitePreparedStatements, release: () => void);
|
|
72
|
+
release(): void;
|
|
73
|
+
}
|
|
74
|
+
export declare class SQLiteStoreWrite extends SQLiteStoreRWBase implements Write {
|
|
75
|
+
#private;
|
|
76
|
+
constructor(preparedStatements: SQLitePreparedStatements, release: () => void);
|
|
77
|
+
put(key: string, value: ReadonlyJSONValue): Promise<void>;
|
|
78
|
+
del(key: string): Promise<void>;
|
|
79
|
+
commit(): Promise<void>;
|
|
80
|
+
release(): void;
|
|
81
|
+
}
|
|
82
|
+
export interface GenericSQLiteDatabaseManager {
|
|
83
|
+
open(fileName: string): SQLiteDatabase;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates a function that returns new SQLite store instances.
|
|
87
|
+
* This is the main entry point for using the SQLite store implementation.
|
|
88
|
+
*
|
|
89
|
+
* @param dbm The SQLite database manager implementation
|
|
90
|
+
* @returns A function that creates new store instances
|
|
91
|
+
*/
|
|
92
|
+
export declare function createSQLiteStore(dbm: SQLiteDatabaseManager): (name: string, opts: SQLiteDatabaseManagerOptions) => SQLiteStore;
|
|
93
|
+
export type SQLiteDatabaseManagerOptions = {
|
|
94
|
+
/**
|
|
95
|
+
* The number of read connections to keep open.
|
|
96
|
+
*
|
|
97
|
+
* This must be greater than 1 to support concurrent reads.
|
|
98
|
+
*/
|
|
99
|
+
readPoolSize: number;
|
|
100
|
+
busyTimeout?: number | undefined;
|
|
101
|
+
journalMode?: 'WAL' | 'DELETE' | undefined;
|
|
102
|
+
synchronous?: 'NORMAL' | 'FULL' | undefined;
|
|
103
|
+
readUncommitted?: boolean | undefined;
|
|
104
|
+
};
|
|
105
|
+
export declare class SQLiteDatabaseManager {
|
|
106
|
+
#private;
|
|
107
|
+
constructor(dbm: GenericSQLiteDatabaseManager);
|
|
108
|
+
clearAllStoresForTesting(): void;
|
|
109
|
+
open(name: string, opts: Omit<SQLiteDatabaseManagerOptions, 'poolSize'>): {
|
|
110
|
+
db: SQLiteDatabase;
|
|
111
|
+
preparedStatements: SQLitePreparedStatements;
|
|
112
|
+
};
|
|
113
|
+
close(name: string): void;
|
|
114
|
+
destroy(name: string): void;
|
|
115
|
+
}
|
|
116
|
+
export {};
|
|
117
|
+
//# sourceMappingURL=sqlite-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/kv/sqlite-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is a binary search that returns the index of the first element in the
|
|
3
|
+
* array that is greater than or equal to the given value.
|
|
4
|
+
*
|
|
5
|
+
* Typical usage:
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* const haystack = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
9
|
+
* const needle = 3;
|
|
10
|
+
* const index = binarySearch(haystack.length, i => needle - haystack[i]);
|
|
11
|
+
* const found = index < haystack.length && haystack[index] === needle;
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function binarySearch(high, compare) {
|
|
15
|
+
let low = 0;
|
|
16
|
+
while (low < high) {
|
|
17
|
+
const mid = low + ((high - low) >> 1);
|
|
18
|
+
const i = compare(mid);
|
|
19
|
+
if (i === 0) {
|
|
20
|
+
return mid;
|
|
21
|
+
}
|
|
22
|
+
if (i > 0) {
|
|
23
|
+
low = mid + 1;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
high = mid;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return low;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=binary-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary-search.js","sourceRoot":"","sources":["../../../../shared/src/binary-search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAA8B;IACvE,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,OAAO,GAAG,GAAG,IAAI,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACZ,OAAO,GAAG,CAAC;QACb,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class Centroid {
|
|
2
|
+
mean: number;
|
|
3
|
+
weight: number;
|
|
4
|
+
constructor(mean: number, weight: number);
|
|
5
|
+
add(r: Centroid): void;
|
|
6
|
+
}
|
|
7
|
+
/** CentroidList is sorted by the mean of the centroid, ascending. */
|
|
8
|
+
export type CentroidList = Centroid[];
|
|
9
|
+
export declare function sortCentroidList(centroids: CentroidList): void;
|
|
10
|
+
//# sourceMappingURL=centroid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"centroid.d.ts","sourceRoot":"","sources":["../../../../shared/src/centroid.ts"],"names":[],"mappings":"AAIA,qBAAa,QAAQ;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;gBAEH,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAKxC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI;CAYvB;AAED,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG,QAAQ,EAAE,CAAC;AAEtC,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI,CAE9D"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Apache License 2.0
|
|
2
|
+
// https://github.com/influxdata/tdigest
|
|
3
|
+
// Centroid average position of all points in a shape
|
|
4
|
+
export class Centroid {
|
|
5
|
+
mean;
|
|
6
|
+
weight;
|
|
7
|
+
constructor(mean, weight) {
|
|
8
|
+
this.mean = mean;
|
|
9
|
+
this.weight = weight;
|
|
10
|
+
}
|
|
11
|
+
add(r) {
|
|
12
|
+
if (r.weight < 0) {
|
|
13
|
+
throw new Error('centroid weight cannot be less than zero');
|
|
14
|
+
}
|
|
15
|
+
if (this.weight !== 0) {
|
|
16
|
+
this.weight += r.weight;
|
|
17
|
+
this.mean += (r.weight * (r.mean - this.mean)) / this.weight;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
this.weight = r.weight;
|
|
21
|
+
this.mean = r.mean;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function sortCentroidList(centroids) {
|
|
26
|
+
centroids.sort((a, b) => a.mean - b.mean);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=centroid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"centroid.js","sourceRoot":"","sources":["../../../../shared/src/centroid.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,wCAAwC;AAExC,qDAAqD;AACrD,MAAM,OAAO,QAAQ;IACnB,IAAI,CAAS;IACb,MAAM,CAAS;IAEf,YAAY,IAAY,EAAE,MAAc;QACtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,GAAG,CAAC,CAAW;QACb,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC;YACxB,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;YACvB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;CACF;AAKD,MAAM,UAAU,gBAAgB,CAAC,SAAuB;IACtD,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Context, LogContext, type LogLevel, type LogSink } from '@rocicorp/logger';
|
|
2
|
+
export declare class TestLogSink implements LogSink {
|
|
3
|
+
messages: [LogLevel, Context | undefined, unknown[]][];
|
|
4
|
+
flushCallCount: number;
|
|
5
|
+
log(level: LogLevel, context: Context | undefined, ...args: unknown[]): void;
|
|
6
|
+
flush(): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare class SilentLogSink implements LogSink {
|
|
9
|
+
log(_l: LogLevel, _c: Context | undefined, ..._args: unknown[]): void;
|
|
10
|
+
}
|
|
11
|
+
export declare function createSilentLogContext(): LogContext<unknown[], unknown[], unknown[], unknown[]>;
|
|
12
|
+
//# sourceMappingURL=logging-test-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-test-utils.d.ts","sourceRoot":"","sources":["../../../../shared/src/logging-test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,UAAU,EACV,KAAK,QAAQ,EACb,KAAK,OAAO,EACb,MAAM,kBAAkB,CAAC;AAE1B,qBAAa,WAAY,YAAW,OAAO;IACzC,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,CAAM;IAC5D,cAAc,SAAK;IAEnB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI5E,KAAK;CAIN;AAED,qBAAa,aAAc,YAAW,OAAO;IAC3C,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,GAAG,SAAS,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI;CAGtE;AAED,wBAAgB,sBAAsB,2DAErC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { LogContext, } from '@rocicorp/logger';
|
|
2
|
+
export class TestLogSink {
|
|
3
|
+
messages = [];
|
|
4
|
+
flushCallCount = 0;
|
|
5
|
+
log(level, context, ...args) {
|
|
6
|
+
this.messages.push([level, context, args]);
|
|
7
|
+
}
|
|
8
|
+
flush() {
|
|
9
|
+
this.flushCallCount++;
|
|
10
|
+
return Promise.resolve();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class SilentLogSink {
|
|
14
|
+
log(_l, _c, ..._args) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function createSilentLogContext() {
|
|
19
|
+
return new LogContext('error', undefined, new SilentLogSink());
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=logging-test-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-test-utils.js","sourceRoot":"","sources":["../../../../shared/src/logging-test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,GAGX,MAAM,kBAAkB,CAAC;AAE1B,MAAM,OAAO,WAAW;IACtB,QAAQ,GAAiD,EAAE,CAAC;IAC5D,cAAc,GAAG,CAAC,CAAC;IAEnB,GAAG,CAAC,KAAe,EAAE,OAA4B,EAAE,GAAG,IAAe;QACnE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,aAAa;IACxB,GAAG,CAAC,EAAY,EAAE,EAAuB,EAAE,GAAG,KAAgB;QAC5D,OAAO;IACT,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,IAAI,UAAU,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,aAAa,EAAE,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export declare function mapValues<T, U>(input:
|
|
1
|
+
export declare function mapValues<T extends Record<string, unknown>, U>(input: T, mapper: (value: T[keyof T]) => U): {
|
|
2
|
+
[K in keyof T]: U;
|
|
3
|
+
};
|
|
2
4
|
export declare function mapEntries<T, U>(input: Record<string, T>, mapper: (key: string, val: T) => [key: string, val: U]): Record<string, U>;
|
|
3
5
|
export declare function mapAllEntries<T, U>(input: Record<string, T>, mapper: (entries: [key: string, val: T][]) => [key: string, val: U][]): Record<string, U>;
|
|
4
6
|
//# sourceMappingURL=objects.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objects.d.ts","sourceRoot":"","sources":["../../../../shared/src/objects.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"objects.d.ts","sourceRoot":"","sources":["../../../../shared/src/objects.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,EAC5D,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAC/B;KAAE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC;CAAC,CAIrB;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACxB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GACrD,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAYnB;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACxB,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GACpE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAQnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objects.js","sourceRoot":"","sources":["../../../../shared/src/objects.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS,CACvB,
|
|
1
|
+
{"version":3,"file":"objects.js","sourceRoot":"","sources":["../../../../shared/src/objects.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS,CACvB,KAAQ,EACR,MAAgC;IAEhC,OAAO,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAe,CAAC,CAAC,CAE9D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,KAAwB,EACxB,MAAsD;IAEtD,wDAAwD;IACxD,qEAAqE;IACrE,MAAM,MAAM,GAAsB,EAAE,CAAC;IAErC,4EAA4E;IAC5E,+DAA+D;IAC/D,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,KAAwB,EACxB,MAAqE;IAErE,wDAAwD;IACxD,qEAAqE;IACrE,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as v from './valita.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Valita schema for TDigest JSON representation.
|
|
4
|
+
* Matches the structure returned by TDigest.toJSON().
|
|
5
|
+
*/
|
|
6
|
+
export declare const tdigestSchema: v.VariadicTupleType<[v.Type<number>], v.Type<number>, []>;
|
|
7
|
+
export type TDigestJSON = v.Infer<typeof tdigestSchema>;
|
|
8
|
+
//# sourceMappingURL=tdigest-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tdigest-schema.d.ts","sourceRoot":"","sources":["../../../../shared/src/tdigest-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC;AAEjC;;;GAGG;AACH,eAAO,MAAM,aAAa,2DAAoD,CAAC;AAE/E,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as v from "./valita.js";
|
|
2
|
+
/**
|
|
3
|
+
* Valita schema for TDigest JSON representation.
|
|
4
|
+
* Matches the structure returned by TDigest.toJSON().
|
|
5
|
+
*/
|
|
6
|
+
export const tdigestSchema = v.tuple([v.number()]).concat(v.array(v.number()));
|
|
7
|
+
//# sourceMappingURL=tdigest-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tdigest-schema.js","sourceRoot":"","sources":["../../../../shared/src/tdigest-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC;AAEjC;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Centroid, type CentroidList } from './centroid.ts';
|
|
2
|
+
import type { TDigestJSON } from './tdigest-schema.ts';
|
|
3
|
+
export interface ReadonlyTDigest {
|
|
4
|
+
readonly count: () => number;
|
|
5
|
+
readonly quantile: (q: number) => number;
|
|
6
|
+
readonly cdf: (x: number) => number;
|
|
7
|
+
}
|
|
8
|
+
export declare class TDigest {
|
|
9
|
+
#private;
|
|
10
|
+
readonly compression: number;
|
|
11
|
+
constructor(compression?: number);
|
|
12
|
+
/**
|
|
13
|
+
* fromJSON creates a TDigest from a JSON-serializable representation.
|
|
14
|
+
* The data should be an object with compression and centroids array.
|
|
15
|
+
*/
|
|
16
|
+
static fromJSON(data: Readonly<TDigestJSON>): TDigest;
|
|
17
|
+
reset(): void;
|
|
18
|
+
add(mean: number, weight?: number): void;
|
|
19
|
+
/** AddCentroidList can quickly add multiple centroids. */
|
|
20
|
+
addCentroidList(centroidList: CentroidList): void;
|
|
21
|
+
/**
|
|
22
|
+
* AddCentroid adds a single centroid.
|
|
23
|
+
* Weights which are not a number or are <= 0 are ignored, as are NaN means.
|
|
24
|
+
*/
|
|
25
|
+
addCentroid(c: Centroid): void;
|
|
26
|
+
/**
|
|
27
|
+
* Merges the supplied digest into this digest. Functionally equivalent to
|
|
28
|
+
* calling t.AddCentroidList(t2.Centroids(nil)), but avoids making an extra
|
|
29
|
+
* copy of the CentroidList.
|
|
30
|
+
**/
|
|
31
|
+
merge(t2: TDigest): void;
|
|
32
|
+
/**
|
|
33
|
+
* Centroids returns a copy of processed centroids.
|
|
34
|
+
* Useful when aggregating multiple t-digests.
|
|
35
|
+
*
|
|
36
|
+
* Centroids are appended to the passed CentroidList; if you're re-using a
|
|
37
|
+
* buffer, be sure to pass cl[:0].
|
|
38
|
+
*/
|
|
39
|
+
centroids(cl?: CentroidList): CentroidList;
|
|
40
|
+
count(): number;
|
|
41
|
+
/**
|
|
42
|
+
* toJSON returns a JSON-serializable representation of the digest.
|
|
43
|
+
* This processes the digest and returns an object with compression and centroid data.
|
|
44
|
+
*/
|
|
45
|
+
toJSON(): TDigestJSON;
|
|
46
|
+
quantile(q: number): number;
|
|
47
|
+
/**
|
|
48
|
+
* CDF returns the cumulative distribution function for a given value x.
|
|
49
|
+
*/
|
|
50
|
+
cdf(x: number): number;
|
|
51
|
+
}
|
|
52
|
+
export declare function byteSizeForCompression(comp: number): number;
|
|
53
|
+
//# sourceMappingURL=tdigest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tdigest.d.ts","sourceRoot":"","sources":["../../../../shared/src/tdigest.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,QAAQ,EAAoB,KAAK,YAAY,EAAC,MAAM,eAAe,CAAC;AAC5E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAID,qBAAa,OAAO;;IAClB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAYjB,WAAW,GAAE,MAAa;IAOtC;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO;IAWrD,KAAK,IAAI,IAAI;IAUb,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU;IAIpC,0DAA0D;IAC1D,eAAe,CAAC,YAAY,EAAE,YAAY;IAM1C;;;OAGG;IACH,WAAW,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI;IAqB9B;;;;QAII;IACJ,KAAK,CAAC,EAAE,EAAE,OAAO;IA4CjB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,GAAE,YAAiB,GAAG,YAAY;IAK9C,KAAK,IAAI,MAAM;IAQf;;;OAGG;IACH,MAAM,IAAI,WAAW;IAqCrB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IA6C3B;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;CAyFvB;AAID,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoB3D"}
|