Skip to main content

Project Module

The source we are porting​

The data product we create is a direct port of the customer-data-product.odps.yaml from the ODPS project. It is helpful to read that file first: it describes a Customer Data Product owned by a Data Team at RetailCorp, with input ports for payments and online transactions, output ports for raw and consolidated transactions, a management port for dictionary updates, two support channels, and a two-person team. It is short enough to read in one sitting, yet it already exercises every top-level section of the standard. Our goal is to represent the same document as typed KCL, but in a shorter, simpler way at every level.

Two deliberate differences are worth calling out before we start:

  • Default values are omitted. The main schema defines apiVersion = "v1.0.0" and kind = "DataProduct" as default values, so we never write them manually. KCL adds them when exporting. Note that the upstream document pins apiVersion: v0.9.0; Enkinex ODPS v1.0.0 models the ODPS v1.0.0 shape and does not aim to provide earlier versions, so the default applies instead.
  • Custom property names are normalized to camelCase. The upstream example writes transactions_version, kafka_topic, and data_team; CustomProperty.property calls for camelCase names, "the same as if they were permanent properties in the contract", so this port writes transactionsVersion, kafkaTopic, and dataTeam.

Everything else — every ID, URL, port, value, and team member — is ported as-is.

Creating the data product project module​

A data product project is a KCL module: a directory with a kcl.mod manifest that declares the module's identity and its dependencies.

Initialize the module​

Use kcl mod init to scaffold it. This creates the kcl.mod manifest, a kcl.mod.lock lockfile, and an initial main.k:

kcl mod init enkinex-odps-tutorial --version 1.0.0

Running it without a name initializes the current directory as a module; passing a name creates a subdirectory for it.

Add the enkinex-odps dependency​

Use kcl mod add to pull the library straight from its GitHub repository. Pin it to a branch, tag, or commit so builds stay reproducible:

kcl mod add --git https://github.com/enkinex/enkinex-odps --tag 'v1.0.0'

That records the dependency under [dependencies] in your kcl.mod. Whenever you later change kcl.mod resync the lockfile with kcl mod update:

kcl mod update

The finished manifest — the one in enkinex-odps-tutorial/kcl.mod — is exactly what those commands produce:

[package]
name = "enkinex-odps-tutorial"
edition = "0.12.7"
version = "1.0.0"
description = "Enkinex ODPS Tutorial"

[dependencies]
enkinex_odps = { git = "https://github.com/enkinex/enkinex-odps", tag = "v1.0.0" }

Note the underscore in enkinex_odps: KCL module names replace hyphens with underscores, and that is the name you import from in your .k files.

The project structure we are building​

The point of authoring in KCL is modularity, so we do not pack everything into one file. The project follows the same layout as the enkinex-odps library — one directory per logical group of the standard — and a root file composes the pieces into the final DataProduct:

enkinex-odps-tutorial/
├── kcl.mod # module manifest + enkinex-odps dependency
├── kcl.mod.lock # resolved dependency lockfile
├── product.k # root: composes every part into a DataProduct
├── product.yaml # exported ODPS YAML (generated)
├── metadata/ # product-level description
│ └── description.k
├── input/ # what the product consumes
│ └── port.k
├── output/ # what the product produces
│ └── port.k
├── management/ # access points for operating the product
│ └── port.k
├── support/ # where consumers get help
│ └── channels.k
└── team/ # ownership
├── member.k
└── team.k

We build it bottom-up: the leaf files in metadata/, team/, management/, support/, input/, and output/ each declare a named, typed value, and the root product.k references those values by name. The sections that follow cover one group at a time, starting with the product metadata and the first version of product.k.

note

The finished project lives under enkinex-odps-tutorial repository.