@secondlayer/shared 4.3.4 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -841,8 +841,12 @@ interface SubgraphSyncInfo {
841
841
  interface SubgraphDetail {
842
842
  name: string;
843
843
  version: string;
844
+ schemaHash?: string;
844
845
  status: string;
845
846
  lastProcessedBlock: number;
847
+ description?: string;
848
+ sources?: Record<string, unknown>;
849
+ definition?: Record<string, unknown>;
846
850
  health: {
847
851
  totalProcessed: number
848
852
  totalErrors: number
@@ -856,9 +860,14 @@ interface SubgraphDetail {
856
860
  columns: Record<string, {
857
861
  type: string
858
862
  nullable?: boolean
863
+ indexed?: boolean
864
+ searchable?: boolean
865
+ default?: string | number | boolean
859
866
  }>
860
867
  rowCount: number
861
868
  example: string
869
+ indexes?: string[][]
870
+ uniqueKeys?: string[][]
862
871
  }>;
863
872
  createdAt: string;
864
873
  updatedAt: string;
@@ -1036,6 +1045,46 @@ declare function validateSubscriptionFilterForTable(input: {
1036
1045
  filter?: unknown
1037
1046
  tables: SubscriptionSchemaTables
1038
1047
  }): string[];
1048
+ type SubgraphSpecFormat = "openapi" | "agent" | "markdown";
1049
+ interface SubgraphSpecOptions {
1050
+ serverUrl?: string;
1051
+ generatedAt?: string;
1052
+ }
1053
+ interface SubgraphAgentSchema {
1054
+ name: string;
1055
+ version: string;
1056
+ description?: string;
1057
+ schemaHash?: string;
1058
+ generatedAt: string;
1059
+ serverUrl: string;
1060
+ sources?: Record<string, unknown>;
1061
+ tables: Record<string, {
1062
+ endpoint: string
1063
+ countEndpoint: string
1064
+ rowCount: number
1065
+ columns: SubgraphDetail["tables"][string]["columns"]
1066
+ indexes?: string[][]
1067
+ uniqueKeys?: string[][]
1068
+ query: {
1069
+ parameters: string[]
1070
+ sortable: string[]
1071
+ selectable: string[]
1072
+ searchable: string[]
1073
+ filters: string[]
1074
+ }
1075
+ examples: {
1076
+ list: Record<string, unknown>
1077
+ count: {
1078
+ count: number
1079
+ }
1080
+ curl: string
1081
+ }
1082
+ }>;
1083
+ }
1084
+ declare function generateSubgraphAgentSchema(detail: SubgraphDetail, options?: SubgraphSpecOptions): SubgraphAgentSchema;
1085
+ declare function generateSubgraphOpenApi(detail: SubgraphDetail, options?: SubgraphSpecOptions): Record<string, unknown>;
1086
+ declare function generateSubgraphMarkdown(detail: SubgraphDetail, options?: SubgraphSpecOptions): string;
1087
+ declare function generateSubgraphSpec(detail: SubgraphDetail, format: SubgraphSpecFormat, options?: SubgraphSpecOptions): Record<string, unknown> | SubgraphAgentSchema | string;
1039
1088
  declare namespace exports_hmac {
1040
1089
  export { verifySignatureHeader, verifySignature, signPayload, generateSecret, createSignatureHeader };
1041
1090
  }
@@ -1064,4 +1113,4 @@ declare function createSignatureHeader(payload: string, secret: string, timestam
1064
1113
  * Returns true if valid, false otherwise
1065
1114
  */
1066
1115
  declare function verifySignatureHeader(payload: string, header: string, secret: string, toleranceSeconds?: number): boolean;
1067
- export { validateSubscriptionFilterForTable, sql, parseJsonb, logger, jsonb, getTargetDb, getSourceDb, getRawClient, getErrorMessage, getEnv, getDb, formatSubscriptionSchemaErrors, exports_hmac as crypto, closeDb, WaitlistTable, VersionConflictError, ValidationError, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionRequestSchema, UpdateSubscriptionRequest, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateProfileRequestSchema, UpdateProfileRequest, UpdateIndexProgress, UpdateEvent, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TransactionsTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantSuspendedError, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionSummary, SubscriptionStatusSchema, SubscriptionStatus, SubscriptionSchemaTables, SubscriptionSchemaTable, SubscriptionSchemaColumn, SubscriptionRuntimeSchema, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionFormatSchema, SubscriptionFormat, SubscriptionFilterSchema, SubscriptionFilterPrimitiveSchema, SubscriptionFilterPrimitive, SubscriptionFilterOperatorSchema, SubscriptionFilterOperator, SubscriptionFilterClauseSchema, SubscriptionFilterClause, SubscriptionFilter, SubscriptionDetail, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphSyncInfo, SubgraphSummary, SubgraphQueryParams, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGapsResponse, SubgraphGapRange, SubgraphGapEntry, SubgraphGap, SubgraphDetail, Subgraph, StxTransferFilterSchema, StxTransferFilter, StxMintFilterSchema, StxMintFilter, StxLockFilterSchema, StxLockFilter, StxBurnFilterSchema, StxBurnFilter, SessionsTable, Session, SecondLayerError, SUBSCRIPTION_STATUSES, SUBSCRIPTION_RUNTIMES, SUBSCRIPTION_FORMATS, SUBSCRIPTION_FILTER_OPERATORS, RotateSecretResponse, ReplaySubscriptionRequestSchema, ReplaySubscriptionRequest, ReplayResult, ReindexResponse, RateLimitError, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, PrintEventFilterSchema, PrintEventFilter, ParsedUpdateSubscriptionRequest, ParsedReplaySubscriptionRequest, ParsedCreateSubscriptionRequest, OutboxStatus, NotFoundError, NftTransferFilterSchema, NftTransferFilter, NftMintFilterSchema, NftMintFilter, NftBurnFilterSchema, NftBurnFilter, MagicLinksTable, MagicLink, KeyRotatedError, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, FtTransferFilterSchema, FtTransferFilter, FtMintFilterSchema, FtMintFilter, FtBurnFilterSchema, FtBurnFilter, ForbiddenError, EventsTable, EventFilterSchema, EventFilter, Event, ErrorCodes, ErrorCode, Env, DeploySubgraphResponse, DeploySubgraphRequestSchema, DeploySubgraphRequest, DeliveryRow, DeadRow, DatabaseError, Database, CreateSubscriptionResponse, CreateSubscriptionRequestSchema, CreateSubscriptionRequest, ContractDeployFilterSchema, ContractDeployFilter, ContractCallFilterSchema, ContractCallFilter, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, CODE_TO_STATUS, BlocksTable, Block, AuthorizationError, AuthenticationError, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
1116
+ export { validateSubscriptionFilterForTable, sql, parseJsonb, logger, jsonb, getTargetDb, getSourceDb, getRawClient, getErrorMessage, getEnv, getDb, generateSubgraphSpec, generateSubgraphOpenApi, generateSubgraphMarkdown, generateSubgraphAgentSchema, formatSubscriptionSchemaErrors, exports_hmac as crypto, closeDb, WaitlistTable, VersionConflictError, ValidationError, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionRequestSchema, UpdateSubscriptionRequest, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateProfileRequestSchema, UpdateProfileRequest, UpdateIndexProgress, UpdateEvent, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TransactionsTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantSuspendedError, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionSummary, SubscriptionStatusSchema, SubscriptionStatus, SubscriptionSchemaTables, SubscriptionSchemaTable, SubscriptionSchemaColumn, SubscriptionRuntimeSchema, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionFormatSchema, SubscriptionFormat, SubscriptionFilterSchema, SubscriptionFilterPrimitiveSchema, SubscriptionFilterPrimitive, SubscriptionFilterOperatorSchema, SubscriptionFilterOperator, SubscriptionFilterClauseSchema, SubscriptionFilterClause, SubscriptionFilter, SubscriptionDetail, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphSyncInfo, SubgraphSummary, SubgraphSpecOptions, SubgraphSpecFormat, SubgraphQueryParams, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGapsResponse, SubgraphGapRange, SubgraphGapEntry, SubgraphGap, SubgraphDetail, SubgraphAgentSchema, Subgraph, StxTransferFilterSchema, StxTransferFilter, StxMintFilterSchema, StxMintFilter, StxLockFilterSchema, StxLockFilter, StxBurnFilterSchema, StxBurnFilter, SessionsTable, Session, SecondLayerError, SUBSCRIPTION_STATUSES, SUBSCRIPTION_RUNTIMES, SUBSCRIPTION_FORMATS, SUBSCRIPTION_FILTER_OPERATORS, RotateSecretResponse, ReplaySubscriptionRequestSchema, ReplaySubscriptionRequest, ReplayResult, ReindexResponse, RateLimitError, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, PrintEventFilterSchema, PrintEventFilter, ParsedUpdateSubscriptionRequest, ParsedReplaySubscriptionRequest, ParsedCreateSubscriptionRequest, OutboxStatus, NotFoundError, NftTransferFilterSchema, NftTransferFilter, NftMintFilterSchema, NftMintFilter, NftBurnFilterSchema, NftBurnFilter, MagicLinksTable, MagicLink, KeyRotatedError, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, FtTransferFilterSchema, FtTransferFilter, FtMintFilterSchema, FtMintFilter, FtBurnFilterSchema, FtBurnFilter, ForbiddenError, EventsTable, EventFilterSchema, EventFilter, Event, ErrorCodes, ErrorCode, Env, DeploySubgraphResponse, DeploySubgraphRequestSchema, DeploySubgraphRequest, DeliveryRow, DeadRow, DatabaseError, Database, CreateSubscriptionResponse, CreateSubscriptionRequestSchema, CreateSubscriptionRequest, ContractDeployFilterSchema, ContractDeployFilter, ContractCallFilterSchema, ContractCallFilter, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, CODE_TO_STATUS, BlocksTable, Block, AuthorizationError, AuthenticationError, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
package/dist/src/index.js CHANGED
@@ -596,6 +596,348 @@ function validateSubscriptionFilterForTable(input) {
596
596
  }
597
597
  return errors;
598
598
  }
599
+ // src/subgraphs/spec.ts
600
+ var SYSTEM_COLUMNS = ["_id", "_block_height", "_tx_id", "_created_at"];
601
+ var BASE_QUERY_PARAMS = ["_limit", "_offset", "_sort", "_order", "_fields"];
602
+ var COMPARISON_OPS = ["neq", "gt", "gte", "lt", "lte"];
603
+ function generatedAt(options) {
604
+ return options.generatedAt ?? new Date().toISOString();
605
+ }
606
+ function normalizeServerUrl(serverUrl) {
607
+ return (serverUrl ?? "https://api.secondlayer.tools").replace(/\/+$/, "");
608
+ }
609
+ function tablePath(subgraphName, tableName) {
610
+ return `/api/subgraphs/${subgraphName}/${tableName}`;
611
+ }
612
+ function countPath(subgraphName, tableName) {
613
+ return `${tablePath(subgraphName, tableName)}/count`;
614
+ }
615
+ function isTextLike(type) {
616
+ return type === "text" || type === "principal" || type === "timestamp";
617
+ }
618
+ function isComparable(type) {
619
+ return type === "uint" || type === "int" || type === "bigint" || type === "serial" || type === "timestamp";
620
+ }
621
+ function exampleForColumn(type) {
622
+ switch (type) {
623
+ case "uint":
624
+ case "int":
625
+ case "bigint":
626
+ return "1000";
627
+ case "serial":
628
+ return 1;
629
+ case "principal":
630
+ return "SP000000000000000000002Q6VF78";
631
+ case "timestamp":
632
+ return "2026-01-01T00:00:00.000Z";
633
+ case "boolean":
634
+ return true;
635
+ case "jsonb":
636
+ return { example: true };
637
+ default:
638
+ return "example";
639
+ }
640
+ }
641
+ function openApiSchemaForColumn(col) {
642
+ let schema;
643
+ switch (col.type) {
644
+ case "uint":
645
+ case "int":
646
+ case "bigint":
647
+ schema = { type: "string", pattern: "^-?\\d+(\\.\\d+)?$" };
648
+ break;
649
+ case "serial":
650
+ schema = { type: "integer" };
651
+ break;
652
+ case "principal":
653
+ case "text":
654
+ schema = { type: "string" };
655
+ break;
656
+ case "timestamp":
657
+ schema = { type: "string", format: "date-time" };
658
+ break;
659
+ case "boolean":
660
+ schema = { type: "boolean" };
661
+ break;
662
+ case "jsonb":
663
+ schema = { type: "object", additionalProperties: true };
664
+ break;
665
+ default:
666
+ schema = {};
667
+ break;
668
+ }
669
+ if (col.nullable) {
670
+ const type = schema.type;
671
+ if (typeof type === "string")
672
+ schema.type = [type, "null"];
673
+ }
674
+ return schema;
675
+ }
676
+ function columnEntries(table) {
677
+ return Object.entries(table.columns);
678
+ }
679
+ function selectableColumns(table) {
680
+ return columnEntries(table).map(([name2]) => name2);
681
+ }
682
+ function searchableColumns(table) {
683
+ return columnEntries(table).filter(([, col]) => col.searchable).map(([name2]) => name2);
684
+ }
685
+ function filterNames(table) {
686
+ const result = [];
687
+ for (const [name2, col] of columnEntries(table)) {
688
+ result.push(name2);
689
+ result.push(`${name2}.neq`);
690
+ if (isComparable(col.type)) {
691
+ for (const op of COMPARISON_OPS.filter((op2) => op2 !== "neq")) {
692
+ result.push(`${name2}.${op}`);
693
+ }
694
+ }
695
+ if (isTextLike(col.type))
696
+ result.push(`${name2}.like`);
697
+ }
698
+ return result;
699
+ }
700
+ function queryParameters(table) {
701
+ const params = [...BASE_QUERY_PARAMS];
702
+ if (searchableColumns(table).length > 0)
703
+ params.push("_search");
704
+ return params;
705
+ }
706
+ function rowExample(table) {
707
+ const row = {};
708
+ for (const [name2, col] of columnEntries(table)) {
709
+ row[name2] = exampleForColumn(col.type);
710
+ }
711
+ return row;
712
+ }
713
+ function openApiParameter(name2, description, schema = { type: "string" }) {
714
+ return {
715
+ name: name2,
716
+ in: "query",
717
+ required: false,
718
+ description,
719
+ schema
720
+ };
721
+ }
722
+ function tableParameters(table) {
723
+ const parameters = [
724
+ openApiParameter("_limit", "Maximum rows to return.", {
725
+ type: "integer",
726
+ default: 50,
727
+ minimum: 1,
728
+ maximum: 1000
729
+ }),
730
+ openApiParameter("_offset", "Rows to skip for pagination.", {
731
+ type: "integer",
732
+ default: 0,
733
+ minimum: 0
734
+ }),
735
+ openApiParameter("_sort", "Column to sort by.", {
736
+ type: "string",
737
+ enum: selectableColumns(table)
738
+ }),
739
+ openApiParameter("_order", "Sort direction.", {
740
+ type: "string",
741
+ enum: ["asc", "desc"],
742
+ default: "asc"
743
+ }),
744
+ openApiParameter("_fields", "Comma-separated columns to include.", {
745
+ type: "string"
746
+ })
747
+ ];
748
+ if (searchableColumns(table).length > 0) {
749
+ parameters.push(openApiParameter("_search", "Search across searchable columns.", {
750
+ type: "string"
751
+ }));
752
+ }
753
+ for (const [name2, col] of columnEntries(table)) {
754
+ parameters.push(openApiParameter(name2, `Filter ${name2} by equality.`, {
755
+ type: "string"
756
+ }));
757
+ parameters.push(openApiParameter(`${name2}.neq`, `Filter ${name2} by inequality.`, {
758
+ type: "string"
759
+ }));
760
+ if (isComparable(col.type)) {
761
+ for (const op of ["gt", "gte", "lt", "lte"]) {
762
+ parameters.push(openApiParameter(`${name2}.${op}`, `Filter ${name2} with ${op}.`, {
763
+ type: "string"
764
+ }));
765
+ }
766
+ }
767
+ if (isTextLike(col.type)) {
768
+ parameters.push(openApiParameter(`${name2}.like`, `Case-insensitive contains filter for ${name2}.`, {
769
+ type: "string"
770
+ }));
771
+ }
772
+ }
773
+ return parameters;
774
+ }
775
+ function generateSubgraphAgentSchema(detail, options = {}) {
776
+ const serverUrl = normalizeServerUrl(options.serverUrl);
777
+ const tables = {};
778
+ for (const [tableName, table] of Object.entries(detail.tables)) {
779
+ const path = tablePath(detail.name, tableName);
780
+ tables[tableName] = {
781
+ endpoint: `${serverUrl}${path}`,
782
+ countEndpoint: `${serverUrl}${countPath(detail.name, tableName)}`,
783
+ rowCount: table.rowCount,
784
+ columns: table.columns,
785
+ ...table.indexes ? { indexes: table.indexes } : {},
786
+ ...table.uniqueKeys ? { uniqueKeys: table.uniqueKeys } : {},
787
+ query: {
788
+ parameters: queryParameters(table),
789
+ sortable: selectableColumns(table),
790
+ selectable: selectableColumns(table),
791
+ searchable: searchableColumns(table),
792
+ filters: filterNames(table)
793
+ },
794
+ examples: {
795
+ list: rowExample(table),
796
+ count: { count: table.rowCount },
797
+ curl: `curl '${serverUrl}${path}?_limit=10&_sort=_block_height&_order=desc'`
798
+ }
799
+ };
800
+ }
801
+ return {
802
+ name: detail.name,
803
+ version: detail.version,
804
+ ...detail.description ? { description: detail.description } : {},
805
+ ...detail.schemaHash ? { schemaHash: detail.schemaHash } : {},
806
+ generatedAt: generatedAt(options),
807
+ serverUrl,
808
+ ...detail.sources ? { sources: detail.sources } : {},
809
+ tables
810
+ };
811
+ }
812
+ function generateSubgraphOpenApi(detail, options = {}) {
813
+ const serverUrl = normalizeServerUrl(options.serverUrl);
814
+ const paths = {};
815
+ const schemas = {};
816
+ for (const [tableName, table] of Object.entries(detail.tables)) {
817
+ const schemaName = `${tableName}Row`;
818
+ const properties = {};
819
+ const required = [];
820
+ for (const [columnName, column] of columnEntries(table)) {
821
+ properties[columnName] = openApiSchemaForColumn(column);
822
+ if (!column.nullable)
823
+ required.push(columnName);
824
+ }
825
+ schemas[schemaName] = {
826
+ type: "object",
827
+ properties,
828
+ required,
829
+ example: rowExample(table)
830
+ };
831
+ paths[tablePath(detail.name, tableName)] = {
832
+ get: {
833
+ summary: `Query ${detail.name}.${tableName}`,
834
+ operationId: `query_${detail.name.replace(/-/g, "_")}_${tableName}`,
835
+ parameters: tableParameters(table),
836
+ responses: {
837
+ "200": {
838
+ description: "Rows returned from the subgraph table.",
839
+ content: {
840
+ "application/json": {
841
+ schema: {
842
+ type: "object",
843
+ properties: {
844
+ data: {
845
+ type: "array",
846
+ items: { $ref: `#/components/schemas/${schemaName}` }
847
+ },
848
+ meta: {
849
+ type: "object",
850
+ properties: {
851
+ total: { type: "integer" },
852
+ limit: { type: "integer" },
853
+ offset: { type: "integer" }
854
+ }
855
+ }
856
+ }
857
+ }
858
+ }
859
+ }
860
+ }
861
+ }
862
+ }
863
+ };
864
+ paths[countPath(detail.name, tableName)] = {
865
+ get: {
866
+ summary: `Count ${detail.name}.${tableName}`,
867
+ operationId: `count_${detail.name.replace(/-/g, "_")}_${tableName}`,
868
+ parameters: tableParameters(table),
869
+ responses: {
870
+ "200": {
871
+ description: "Row count for the filtered table query.",
872
+ content: {
873
+ "application/json": {
874
+ schema: {
875
+ type: "object",
876
+ properties: { count: { type: "integer" } },
877
+ required: ["count"],
878
+ example: { count: table.rowCount }
879
+ }
880
+ }
881
+ }
882
+ }
883
+ }
884
+ }
885
+ };
886
+ }
887
+ return {
888
+ openapi: "3.1.0",
889
+ info: {
890
+ title: `${detail.name} Subgraph API`,
891
+ version: detail.version,
892
+ ...detail.description ? { description: detail.description } : {}
893
+ },
894
+ servers: [{ url: serverUrl }],
895
+ paths,
896
+ components: { schemas },
897
+ "x-secondlayer-subgraph": detail.name,
898
+ "x-secondlayer-version": detail.version,
899
+ "x-secondlayer-schema-hash": detail.schemaHash,
900
+ "x-secondlayer-generated-at": generatedAt(options),
901
+ "x-secondlayer-sources": detail.sources ?? {},
902
+ "x-secondlayer-tables": Object.keys(detail.tables)
903
+ };
904
+ }
905
+ function generateSubgraphMarkdown(detail, options = {}) {
906
+ const agent = generateSubgraphAgentSchema(detail, options);
907
+ const lines = [
908
+ `# ${detail.name} Subgraph API`,
909
+ "",
910
+ `Version: ${detail.version}`,
911
+ detail.schemaHash ? `Schema hash: ${detail.schemaHash}` : undefined,
912
+ `Server: ${agent.serverUrl}`,
913
+ "",
914
+ detail.description
915
+ ].filter((line) => line !== undefined && line !== "");
916
+ for (const [tableName, table] of Object.entries(agent.tables)) {
917
+ lines.push("", `## ${tableName}`, "", `GET ${table.endpoint}`, `GET ${table.countEndpoint}`, "", `Rows: ${table.rowCount}`, "", "### Columns", "", "| Column | Type | Attributes |", "| --- | --- | --- |");
918
+ for (const [columnName, col] of Object.entries(table.columns)) {
919
+ const attrs = [
920
+ SYSTEM_COLUMNS.includes(columnName) ? "system" : undefined,
921
+ col.nullable ? "nullable" : undefined,
922
+ col.indexed ? "indexed" : undefined,
923
+ col.searchable ? "searchable" : undefined
924
+ ].filter(Boolean).join(", ");
925
+ lines.push(`| \`${columnName}\` | \`${col.type}\` | ${attrs || "-"} |`);
926
+ }
927
+ lines.push("", "### Query", "", `Parameters: ${table.query.parameters.map((p) => `\`${p}\``).join(", ")}`, `Filters: ${table.query.filters.map((p) => `\`${p}\``).join(", ")}`, "", "### Example", "", "```bash", table.examples.curl, "```");
928
+ }
929
+ return `${lines.join(`
930
+ `)}
931
+ `;
932
+ }
933
+ function generateSubgraphSpec(detail, format, options = {}) {
934
+ if (format === "openapi")
935
+ return generateSubgraphOpenApi(detail, options);
936
+ if (format === "agent")
937
+ return generateSubgraphAgentSchema(detail, options);
938
+ return generateSubgraphMarkdown(detail, options);
939
+ }
940
+
599
941
  // src/crypto/hmac.ts
600
942
  var exports_hmac = {};
601
943
  __export(exports_hmac, {
@@ -661,6 +1003,10 @@ export {
661
1003
  getErrorMessage,
662
1004
  getEnv,
663
1005
  getDb,
1006
+ generateSubgraphSpec,
1007
+ generateSubgraphOpenApi,
1008
+ generateSubgraphMarkdown,
1009
+ generateSubgraphAgentSchema,
664
1010
  formatSubscriptionSchemaErrors,
665
1011
  exports_hmac as crypto,
666
1012
  closeDb,
@@ -709,5 +1055,5 @@ export {
709
1055
  AuthenticationError
710
1056
  };
711
1057
 
712
- //# debugId=710A523C096CF83964756E2164756E21
1058
+ //# debugId=F03F167A347C5EE364756E2164756E21
713
1059
  //# sourceMappingURL=index.js.map