@tinybirdco/sdk 0.0.47 → 0.0.48
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/dist/cli/commands/migrate.test.js +187 -7
- package/dist/cli/commands/migrate.test.js.map +1 -1
- package/dist/generator/connection.d.ts.map +1 -1
- package/dist/generator/connection.js +3 -0
- package/dist/generator/connection.js.map +1 -1
- package/dist/generator/connection.test.js +8 -0
- package/dist/generator/connection.test.js.map +1 -1
- package/dist/generator/datasource.d.ts.map +1 -1
- package/dist/generator/datasource.js +3 -0
- package/dist/generator/datasource.js.map +1 -1
- package/dist/generator/datasource.test.js +50 -0
- package/dist/generator/datasource.test.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +3 -0
- package/dist/index.test.js.map +1 -1
- package/dist/migrate/emit-ts.d.ts.map +1 -1
- package/dist/migrate/emit-ts.js +109 -32
- package/dist/migrate/emit-ts.js.map +1 -1
- package/dist/migrate/parse-connection.d.ts.map +1 -1
- package/dist/migrate/parse-connection.js +13 -2
- package/dist/migrate/parse-connection.js.map +1 -1
- package/dist/migrate/parse-datasource.d.ts.map +1 -1
- package/dist/migrate/parse-datasource.js +39 -4
- package/dist/migrate/parse-datasource.js.map +1 -1
- package/dist/migrate/parse-pipe.d.ts.map +1 -1
- package/dist/migrate/parse-pipe.js +3 -2
- package/dist/migrate/parse-pipe.js.map +1 -1
- package/dist/migrate/types.d.ts +3 -0
- package/dist/migrate/types.d.ts.map +1 -1
- package/dist/schema/connection.d.ts +2 -0
- package/dist/schema/connection.d.ts.map +1 -1
- package/dist/schema/connection.js.map +1 -1
- package/dist/schema/datasource.d.ts +3 -1
- package/dist/schema/datasource.d.ts.map +1 -1
- package/dist/schema/datasource.js +8 -1
- package/dist/schema/datasource.js.map +1 -1
- package/dist/schema/datasource.test.js +12 -0
- package/dist/schema/datasource.test.js.map +1 -1
- package/dist/schema/engines.d.ts.map +1 -1
- package/dist/schema/engines.js +3 -0
- package/dist/schema/engines.js.map +1 -1
- package/dist/schema/engines.test.js +16 -0
- package/dist/schema/engines.test.js.map +1 -1
- package/dist/schema/secret.d.ts +6 -0
- package/dist/schema/secret.d.ts.map +1 -0
- package/dist/schema/secret.js +14 -0
- package/dist/schema/secret.js.map +1 -0
- package/dist/schema/secret.test.d.ts +2 -0
- package/dist/schema/secret.test.d.ts.map +1 -0
- package/dist/schema/secret.test.js +14 -0
- package/dist/schema/secret.test.js.map +1 -0
- package/dist/schema/types.d.ts +5 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +6 -0
- package/dist/schema/types.js.map +1 -1
- package/dist/schema/types.test.js +12 -0
- package/dist/schema/types.test.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/migrate.test.ts +279 -7
- package/src/generator/connection.test.ts +13 -0
- package/src/generator/connection.ts +4 -0
- package/src/generator/datasource.test.ts +60 -0
- package/src/generator/datasource.ts +3 -0
- package/src/index.test.ts +4 -0
- package/src/index.ts +3 -0
- package/src/migrate/emit-ts.ts +109 -38
- package/src/migrate/parse-connection.ts +15 -2
- package/src/migrate/parse-datasource.ts +53 -4
- package/src/migrate/parse-pipe.ts +5 -3
- package/src/migrate/types.ts +3 -0
- package/src/schema/connection.ts +2 -0
- package/src/schema/datasource.test.ts +16 -0
- package/src/schema/datasource.ts +13 -2
- package/src/schema/engines.test.ts +18 -0
- package/src/schema/engines.ts +3 -0
- package/src/schema/secret.test.ts +19 -0
- package/src/schema/secret.ts +16 -0
- package/src/schema/types.test.ts +14 -0
- package/src/schema/types.ts +10 -0
|
@@ -15,7 +15,7 @@ const EXPECTED_COMPLEX_OUTPUT = `/**
|
|
|
15
15
|
* Review endpoint output schemas and any defaults before production use.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { defineKafkaConnection, defineDatasource, definePipe, defineMaterializedView, defineCopyPipe, node, t, engine,
|
|
18
|
+
import { defineKafkaConnection, defineDatasource, definePipe, defineMaterializedView, defineCopyPipe, node, t, engine, p } from "@tinybirdco/sdk";
|
|
19
19
|
|
|
20
20
|
// Connections
|
|
21
21
|
|
|
@@ -36,12 +36,12 @@ export const stream = defineKafkaConnection("stream", {
|
|
|
36
36
|
export const events = defineDatasource("events", {
|
|
37
37
|
description: "Events from Kafka stream",
|
|
38
38
|
schema: {
|
|
39
|
-
event_id:
|
|
40
|
-
user_id:
|
|
41
|
-
env:
|
|
42
|
-
is_test:
|
|
43
|
-
updated_at:
|
|
44
|
-
payload:
|
|
39
|
+
event_id: t.string().jsonPath("$.event_id"),
|
|
40
|
+
user_id: t.uint64().jsonPath("$.user.id"),
|
|
41
|
+
env: t.string().default("prod").jsonPath("$.env"),
|
|
42
|
+
is_test: t.bool().default(false).jsonPath("$.meta.is_test"),
|
|
43
|
+
updated_at: t.dateTime().jsonPath("$.updated_at"),
|
|
44
|
+
payload: t.string().default("{}").codec("ZSTD(1)").jsonPath("$.payload"),
|
|
45
45
|
},
|
|
46
46
|
engine: engine.replacingMergeTree({ sortingKey: ["event_id", "user_id"], partitionKey: "toYYYYMM(updated_at)", primaryKey: "event_id", ttl: "updated_at + toIntervalDay(30)", ver: "updated_at", settings: { "index_granularity": 8192, "enable_mixed_granularity_parts": true } }),
|
|
47
47
|
kafka: {
|
|
@@ -615,4 +615,276 @@ IMPORT_FROM_TIMESTAMP 2024-01-01T00:00:00Z
|
|
|
615
615
|
expect(output).toContain('schedule: "@auto"');
|
|
616
616
|
expect(output).toContain('fromTimestamp: "2024-01-01T00:00:00Z"');
|
|
617
617
|
});
|
|
618
|
+
|
|
619
|
+
it("migrates KAFKA_STORE_RAW_VALUE datasource directive", async () => {
|
|
620
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "tinybird-migrate-"));
|
|
621
|
+
tempDirs.push(tempDir);
|
|
622
|
+
|
|
623
|
+
writeFile(
|
|
624
|
+
tempDir,
|
|
625
|
+
"stream.connection",
|
|
626
|
+
`TYPE kafka
|
|
627
|
+
KAFKA_BOOTSTRAP_SERVERS localhost:9092
|
|
628
|
+
`
|
|
629
|
+
);
|
|
630
|
+
|
|
631
|
+
writeFile(
|
|
632
|
+
tempDir,
|
|
633
|
+
"events.datasource",
|
|
634
|
+
`SCHEMA >
|
|
635
|
+
event_id String
|
|
636
|
+
|
|
637
|
+
ENGINE "MergeTree"
|
|
638
|
+
ENGINE_SORTING_KEY "event_id"
|
|
639
|
+
KAFKA_CONNECTION_NAME stream
|
|
640
|
+
KAFKA_TOPIC events_topic
|
|
641
|
+
KAFKA_STORE_RAW_VALUE True
|
|
642
|
+
`
|
|
643
|
+
);
|
|
644
|
+
|
|
645
|
+
const result = await runMigrate({
|
|
646
|
+
cwd: tempDir,
|
|
647
|
+
patterns: ["."],
|
|
648
|
+
strict: true,
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
expect(result.success).toBe(true);
|
|
652
|
+
expect(result.errors).toHaveLength(0);
|
|
653
|
+
|
|
654
|
+
const output = fs.readFileSync(result.outputPath, "utf-8");
|
|
655
|
+
expect(output).toContain("kafka: {");
|
|
656
|
+
expect(output).toContain("connection: stream");
|
|
657
|
+
expect(output).toContain('topic: "events_topic"');
|
|
658
|
+
expect(output).toContain("storeRawValue: true");
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
it("migrates kafka schema registry and engine is deleted directives", async () => {
|
|
662
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "tinybird-migrate-"));
|
|
663
|
+
tempDirs.push(tempDir);
|
|
664
|
+
|
|
665
|
+
writeFile(
|
|
666
|
+
tempDir,
|
|
667
|
+
"stream.connection",
|
|
668
|
+
`TYPE kafka
|
|
669
|
+
KAFKA_BOOTSTRAP_SERVERS kafka.example.com:9092
|
|
670
|
+
KAFKA_SCHEMA_REGISTRY_URL https://registry-user:registry-pass@registry.example.com
|
|
671
|
+
# Optional registry auth details
|
|
672
|
+
`
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
writeFile(
|
|
676
|
+
tempDir,
|
|
677
|
+
"events.datasource",
|
|
678
|
+
`SCHEMA >
|
|
679
|
+
event_id String
|
|
680
|
+
|
|
681
|
+
ENGINE "MergeTree"
|
|
682
|
+
ENGINE_SORTING_KEY "event_id"
|
|
683
|
+
KAFKA_CONNECTION_NAME stream
|
|
684
|
+
KAFKA_TOPIC events_topic
|
|
685
|
+
KAFKA_STORE_RAW_VALUE True
|
|
686
|
+
`
|
|
687
|
+
);
|
|
688
|
+
|
|
689
|
+
writeFile(
|
|
690
|
+
tempDir,
|
|
691
|
+
"events_state.datasource",
|
|
692
|
+
`SCHEMA >
|
|
693
|
+
# logical delete marker
|
|
694
|
+
_is_deleted UInt8,
|
|
695
|
+
event_id String,
|
|
696
|
+
version_ts DateTime
|
|
697
|
+
|
|
698
|
+
ENGINE "ReplacingMergeTree"
|
|
699
|
+
ENGINE_SORTING_KEY "event_id"
|
|
700
|
+
ENGINE_VER "version_ts"
|
|
701
|
+
ENGINE_IS_DELETED "_is_deleted"
|
|
702
|
+
`
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
writeFile(
|
|
706
|
+
tempDir,
|
|
707
|
+
"events_state_mv.pipe",
|
|
708
|
+
`NODE latest
|
|
709
|
+
SQL >
|
|
710
|
+
SELECT
|
|
711
|
+
toUInt8(0) AS _is_deleted,
|
|
712
|
+
event_id,
|
|
713
|
+
now() AS version_ts
|
|
714
|
+
FROM events
|
|
715
|
+
# materialized definition
|
|
716
|
+
TYPE MATERIALIZED
|
|
717
|
+
DATASOURCE events_state
|
|
718
|
+
`
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
const result = await runMigrate({
|
|
722
|
+
cwd: tempDir,
|
|
723
|
+
patterns: ["."],
|
|
724
|
+
strict: true,
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
expect(result.success).toBe(true);
|
|
728
|
+
expect(result.errors).toHaveLength(0);
|
|
729
|
+
|
|
730
|
+
const output = fs.readFileSync(result.outputPath, "utf-8");
|
|
731
|
+
expect(output).toContain(
|
|
732
|
+
'schemaRegistryUrl: "https://registry-user:registry-pass@registry.example.com"'
|
|
733
|
+
);
|
|
734
|
+
expect(output).toContain("storeRawValue: true");
|
|
735
|
+
expect(output).toContain(
|
|
736
|
+
'engine: engine.replacingMergeTree({ sortingKey: "event_id", ver: "version_ts", isDeleted: "_is_deleted" })'
|
|
737
|
+
);
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
it("migrates datasource with mixed explicit and default json paths", async () => {
|
|
741
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "tinybird-migrate-"));
|
|
742
|
+
tempDirs.push(tempDir);
|
|
743
|
+
|
|
744
|
+
writeFile(
|
|
745
|
+
tempDir,
|
|
746
|
+
"mixed_paths.datasource",
|
|
747
|
+
`SCHEMA >
|
|
748
|
+
event_id String \`json:$.payload.id\`,
|
|
749
|
+
event_type String
|
|
750
|
+
|
|
751
|
+
ENGINE "MergeTree"
|
|
752
|
+
ENGINE_SORTING_KEY "event_id"
|
|
753
|
+
`
|
|
754
|
+
);
|
|
755
|
+
|
|
756
|
+
const result = await runMigrate({
|
|
757
|
+
cwd: tempDir,
|
|
758
|
+
patterns: ["."],
|
|
759
|
+
strict: true,
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
expect(result.success).toBe(true);
|
|
763
|
+
expect(result.errors).toHaveLength(0);
|
|
764
|
+
|
|
765
|
+
const output = fs.readFileSync(result.outputPath, "utf-8");
|
|
766
|
+
expect(output).toContain('event_id: t.string().jsonPath("$.payload.id")');
|
|
767
|
+
expect(output).toContain("event_type: t.string()");
|
|
768
|
+
expect(output).not.toContain("jsonPaths: false");
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
it("normalizes backticked schema column names to valid object keys", async () => {
|
|
772
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "tinybird-migrate-"));
|
|
773
|
+
tempDirs.push(tempDir);
|
|
774
|
+
|
|
775
|
+
writeFile(
|
|
776
|
+
tempDir,
|
|
777
|
+
"backticked.datasource",
|
|
778
|
+
`SCHEMA >
|
|
779
|
+
\`_is_deleted\` UInt8 \`json:$._is_deleted\`,
|
|
780
|
+
\`id\` UUID \`json:$.id\`
|
|
781
|
+
|
|
782
|
+
ENGINE "MergeTree"
|
|
783
|
+
ENGINE_SORTING_KEY "id"
|
|
784
|
+
`
|
|
785
|
+
);
|
|
786
|
+
|
|
787
|
+
const result = await runMigrate({
|
|
788
|
+
cwd: tempDir,
|
|
789
|
+
patterns: ["."],
|
|
790
|
+
strict: true,
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
expect(result.success).toBe(true);
|
|
794
|
+
expect(result.errors).toHaveLength(0);
|
|
795
|
+
|
|
796
|
+
const output = fs.readFileSync(result.outputPath, "utf-8");
|
|
797
|
+
expect(output).toContain('_is_deleted: t.uint8().jsonPath("$._is_deleted")');
|
|
798
|
+
expect(output).toContain('id: t.uuid().jsonPath("$.id")');
|
|
799
|
+
expect(output).not.toContain("`_is_deleted`:");
|
|
800
|
+
expect(output).not.toContain("`id`:");
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
it("emits secret helper for tb_secret template values", async () => {
|
|
804
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "tinybird-migrate-"));
|
|
805
|
+
tempDirs.push(tempDir);
|
|
806
|
+
|
|
807
|
+
writeFile(
|
|
808
|
+
tempDir,
|
|
809
|
+
"stream.connection",
|
|
810
|
+
`TYPE kafka
|
|
811
|
+
KAFKA_BOOTSTRAP_SERVERS localhost:9092
|
|
812
|
+
`
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
writeFile(
|
|
816
|
+
tempDir,
|
|
817
|
+
"events.datasource",
|
|
818
|
+
`SCHEMA >
|
|
819
|
+
id UUID
|
|
820
|
+
|
|
821
|
+
ENGINE "MergeTree"
|
|
822
|
+
ENGINE_SORTING_KEY "id"
|
|
823
|
+
KAFKA_CONNECTION_NAME stream
|
|
824
|
+
KAFKA_TOPIC events_topic
|
|
825
|
+
KAFKA_GROUP_ID {{ tb_secret("KAFKA_GROUP_ID_LOCAL_ds_accounts", "accounts_1737295200") }}
|
|
826
|
+
`
|
|
827
|
+
);
|
|
828
|
+
|
|
829
|
+
const result = await runMigrate({
|
|
830
|
+
cwd: tempDir,
|
|
831
|
+
patterns: ["."],
|
|
832
|
+
strict: true,
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
expect(result.success).toBe(true);
|
|
836
|
+
expect(result.errors).toHaveLength(0);
|
|
837
|
+
|
|
838
|
+
const output = fs.readFileSync(result.outputPath, "utf-8");
|
|
839
|
+
expect(output).toContain('import {');
|
|
840
|
+
expect(output).toContain('secret } from "@tinybirdco/sdk";');
|
|
841
|
+
expect(output).not.toContain("const secret = (name: string, defaultValue?: string) =>");
|
|
842
|
+
expect(output).toContain(
|
|
843
|
+
'groupId: secret("KAFKA_GROUP_ID_LOCAL_ds_accounts", "accounts_1737295200"),'
|
|
844
|
+
);
|
|
845
|
+
expect(output).not.toContain(
|
|
846
|
+
'groupId: "{{ tb_secret(\\"KAFKA_GROUP_ID_LOCAL_ds_accounts\\", \\"accounts_1737295200\\") }}",'
|
|
847
|
+
);
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
it("does not emit secret helper when no tb_secret template values are present", async () => {
|
|
851
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "tinybird-migrate-"));
|
|
852
|
+
tempDirs.push(tempDir);
|
|
853
|
+
|
|
854
|
+
writeFile(
|
|
855
|
+
tempDir,
|
|
856
|
+
"stream.connection",
|
|
857
|
+
`TYPE kafka
|
|
858
|
+
KAFKA_BOOTSTRAP_SERVERS localhost:9092
|
|
859
|
+
`
|
|
860
|
+
);
|
|
861
|
+
|
|
862
|
+
writeFile(
|
|
863
|
+
tempDir,
|
|
864
|
+
"events.datasource",
|
|
865
|
+
`SCHEMA >
|
|
866
|
+
id UUID
|
|
867
|
+
|
|
868
|
+
ENGINE "MergeTree"
|
|
869
|
+
ENGINE_SORTING_KEY "id"
|
|
870
|
+
KAFKA_CONNECTION_NAME stream
|
|
871
|
+
KAFKA_TOPIC events_topic
|
|
872
|
+
KAFKA_GROUP_ID events-group
|
|
873
|
+
`
|
|
874
|
+
);
|
|
875
|
+
|
|
876
|
+
const result = await runMigrate({
|
|
877
|
+
cwd: tempDir,
|
|
878
|
+
patterns: ["."],
|
|
879
|
+
strict: true,
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
expect(result.success).toBe(true);
|
|
883
|
+
expect(result.errors).toHaveLength(0);
|
|
884
|
+
|
|
885
|
+
const output = fs.readFileSync(result.outputPath, "utf-8");
|
|
886
|
+
expect(output).not.toContain(", secret,");
|
|
887
|
+
expect(output).not.toContain("const secret = (name: string, defaultValue?: string) =>");
|
|
888
|
+
expect(output).toContain('groupId: "events-group",');
|
|
889
|
+
});
|
|
618
890
|
});
|
|
@@ -51,6 +51,19 @@ describe("Connection Generator", () => {
|
|
|
51
51
|
expect(result.content).toContain('KAFKA_SECRET {{ tb_secret("KAFKA_SECRET") }}');
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
it("includes schema registry URL when provided", () => {
|
|
55
|
+
const conn = defineKafkaConnection("my_kafka", {
|
|
56
|
+
bootstrapServers: "kafka.example.com:9092",
|
|
57
|
+
schemaRegistryUrl: "https://registry-user:registry-pass@registry.example.com",
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const result = generateConnection(conn);
|
|
61
|
+
|
|
62
|
+
expect(result.content).toContain(
|
|
63
|
+
"KAFKA_SCHEMA_REGISTRY_URL https://registry-user:registry-pass@registry.example.com"
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
54
67
|
it("includes SSL CA PEM when provided", () => {
|
|
55
68
|
const conn = defineKafkaConnection("my_kafka", {
|
|
56
69
|
bootstrapServers: "kafka.example.com:9092",
|
|
@@ -42,6 +42,10 @@ function generateKafkaConnection(connection: KafkaConnectionDefinition): string
|
|
|
42
42
|
parts.push(`KAFKA_SECRET ${options.secret}`);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
if (options.schemaRegistryUrl) {
|
|
46
|
+
parts.push(`KAFKA_SCHEMA_REGISTRY_URL ${options.schemaRegistryUrl}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
45
49
|
if (options.sslCaPem) {
|
|
46
50
|
parts.push(`KAFKA_SSL_CA_PEM ${options.sslCaPem}`);
|
|
47
51
|
}
|
|
@@ -263,6 +263,43 @@ describe('Datasource Generator', () => {
|
|
|
263
263
|
expect(schemaLines[1]).toContain(',');
|
|
264
264
|
expect(schemaLines[2]).not.toContain(',');
|
|
265
265
|
});
|
|
266
|
+
|
|
267
|
+
it('autogenerates jsonPath when jsonPaths is enabled and no explicit path is set', () => {
|
|
268
|
+
const ds = defineDatasource('test_ds', {
|
|
269
|
+
schema: {
|
|
270
|
+
event_id: t.string().nullable(),
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const result = generateDatasource(ds);
|
|
275
|
+
expect(result.content).toContain('event_id Nullable(String) `json:$.event_id`');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('uses explicit jsonPath from validator modifier when jsonPaths is enabled', () => {
|
|
279
|
+
const ds = defineDatasource('test_ds', {
|
|
280
|
+
schema: {
|
|
281
|
+
event_id: t.string().nullable().jsonPath('$.explicit_path'),
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
const result = generateDatasource(ds);
|
|
286
|
+
expect(result.content).toContain('event_id Nullable(String) `json:$.explicit_path`');
|
|
287
|
+
expect(result.content).not.toContain('`json:$.event_id`');
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('omits json paths when jsonPaths is false even if column has explicit jsonPath modifier', () => {
|
|
291
|
+
const ds = defineDatasource('test_ds', {
|
|
292
|
+
jsonPaths: false,
|
|
293
|
+
schema: {
|
|
294
|
+
event_id: t.string().nullable().jsonPath('$.explicit_path'),
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
const result = generateDatasource(ds);
|
|
299
|
+
expect(result.content).toContain('event_id Nullable(String)');
|
|
300
|
+
expect(result.content).not.toContain('`json:$.explicit_path`');
|
|
301
|
+
expect(result.content).not.toContain('`json:$.event_id`');
|
|
302
|
+
});
|
|
266
303
|
});
|
|
267
304
|
|
|
268
305
|
describe('generateAllDatasources', () => {
|
|
@@ -380,6 +417,29 @@ describe('Datasource Generator', () => {
|
|
|
380
417
|
expect(result.content).toContain('KAFKA_AUTO_OFFSET_RESET earliest');
|
|
381
418
|
});
|
|
382
419
|
|
|
420
|
+
it('includes store raw value when provided', () => {
|
|
421
|
+
const kafkaConn = defineKafkaConnection('my_kafka', {
|
|
422
|
+
bootstrapServers: 'kafka.example.com:9092',
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
const ds = defineDatasource('kafka_events', {
|
|
426
|
+
schema: {
|
|
427
|
+
timestamp: t.dateTime(),
|
|
428
|
+
event: t.string(),
|
|
429
|
+
},
|
|
430
|
+
engine: engine.mergeTree({ sortingKey: ['timestamp'] }),
|
|
431
|
+
kafka: {
|
|
432
|
+
connection: kafkaConn,
|
|
433
|
+
topic: 'events',
|
|
434
|
+
storeRawValue: true,
|
|
435
|
+
},
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
const result = generateDatasource(ds);
|
|
439
|
+
|
|
440
|
+
expect(result.content).toContain('KAFKA_STORE_RAW_VALUE True');
|
|
441
|
+
});
|
|
442
|
+
|
|
383
443
|
it('generates complete Kafka datasource with all options', () => {
|
|
384
444
|
const kafkaConn = defineKafkaConnection('my_kafka', {
|
|
385
445
|
bootstrapServers: 'kafka.example.com:9092',
|
|
@@ -166,6 +166,9 @@ function generateKafkaConfig(kafka: KafkaConfig): string {
|
|
|
166
166
|
if (kafka.autoOffsetReset) {
|
|
167
167
|
parts.push(`KAFKA_AUTO_OFFSET_RESET ${kafka.autoOffsetReset}`);
|
|
168
168
|
}
|
|
169
|
+
if (kafka.storeRawValue !== undefined) {
|
|
170
|
+
parts.push(`KAFKA_STORE_RAW_VALUE ${kafka.storeRawValue ? "True" : "False"}`);
|
|
171
|
+
}
|
|
169
172
|
|
|
170
173
|
return parts.join("\n");
|
|
171
174
|
}
|
package/src/index.test.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -97,6 +97,9 @@ export type {
|
|
|
97
97
|
VersionedCollapsingMergeTreeConfig,
|
|
98
98
|
} from "./schema/engines.js";
|
|
99
99
|
|
|
100
|
+
// ============ Utilities ============
|
|
101
|
+
export { secret } from "./schema/secret.js";
|
|
102
|
+
|
|
100
103
|
// ============ Datasource ============
|
|
101
104
|
export { defineDatasource, isDatasourceDefinition, column, getColumnType, getColumnJsonPath, getColumnNames } from "./schema/datasource.js";
|
|
102
105
|
export type {
|