Kandra.DataImport.AdminCaller
Runs a non-interactive flow (startup, setup) as the admin user when nobody is signed in.
Kandra.DataImport.CanonicalJson
Canonical form of a package item, used to detect "the package changed" without caring about formatting: properties sorted by ordinal name at every level, no insignificant whitespace, numbers exactly as written, strings re-encoded the same way whichever escapes the source used. $ref/$code objects and date tokens are left unresolved on purpose - resolved values change every day ($today-23d) and would make every document look edited.
Methods
| Method | Description |
|---|
Hash(JsonNode) | SHA-256 of the canonical JSON, lowercase hex (64 chars). |
Kandra.DataImport.DataImportService
The import engine. See IDataImportService and docs/kandra-data-import-design.md. Every write goes through IEntityOperationExecutor (the real CRUD services: behaviors, validators, posting and authorization run exactly as for a user), inside IImportStampScope so the row is stamped. Each item runs in its own DI scope (fresh DbContext - the same lifetime as one HTTP request) with the caller's identity copied across; there is no global transaction, the work is idempotent instead.
Constructors
| Constructor | Description |
|---|
DataImportService(IServiceScopeFactory, DbContext, IEntityOperationExecutor, ImportPackageValidator, ICallerContext, ILicenseService) | The import engine. See IDataImportService and docs/kandra-data-import-design.md. Every write goes through IEntityOperationExecutor (the real CRUD services: behaviors, validators, posting and authorization run exactly as for a user), inside IImportStampScope so the row is stamped. Each item runs in its own DI scope (fresh DbContext - the same lifetime as one HTTP request) with the caller's identity copied across; there is no global transaction, the work is idempotent instead. |
Methods
| Method | Description |
|---|
CheckLicenseAsync(ImportPackage, Pass, List<ImportDiagnostic>, CancellationToken) | Fails before anything is written when the package would exceed the licence: documents count against the calendar month they are created in (all of them land in the current month), so the check is "documents this month + documents the package would create" against the monthly limit, plus the per-document line limit. |
NormalizeForWire(JsonObject, EntityCatalogEntry) | A hierarchical dictionary DTO is polymorphic on the wire: the folder/leaf discriminator is the string "1"/"0" and must be the first property. A package writes it as "isFolder": true. |
Overlay(JsonObject, JsonObject, IReadOnlyList<EntityFieldInfo>, JsonObject, String) | Lays the resolved package item over a base DTO (a New draft for inserts, the current DTO for updates). |
SaveStateAsync(ImportPackage, Pass, CancellationToken) | Written straight to the constants table (not through IConstantsManageService): it is bookkeeping, not a user-facing setting - no constants permission is needed, no change event is produced, and the row is not import-stamped. |
Wire(String) | undocumented |
WithLineIds(JsonArray, JsonArray) | Document lines need an id; keep the existing row's id at the same position on update so the line is rewritten, not replaced. |
WithScopeAsync(Pass, Func<IServiceScope, Task>) | Runs action in a fresh DI scope carrying this caller's identity and the import change origin. |
Fields
| Field | Description |
|---|
PackageStateConstantPrefix | Reserved prefix of the constants rows that hold each package's state; deliberately not a registered [KandraConstant], so the Constants admin page never lists them. |
Kandra.DataImport.DataImportService.Pass
Properties
| Property | Description |
|---|
Ids | $id -> row id for everything processed so far (in a dry pass, planned inserts get a placeholder id). |
PlannedCodes | (entity, code) -> id, for dry passes where an earlier planned insert is referenced by $code. |
Kandra.DataImport.DataImportServiceCollectionExtensions
Methods
| Method | Description |
|---|
AddKandraDataImport(IServiceCollection, String) | Registers the import package validator and schema provider. Requires AddKandraEntityOperations<TCatalog>() (the entity catalog and field metadata the validator and schema are built from). |
Kandra.DataImport.DemoContentUpdater
After an update that ships a newer demo package, applies it once at startup (see ApplyPendingUpdateAsync). Never blocks or fails the host.
Constructors
| Constructor | Description |
|---|
DemoContentUpdater(IServiceScopeFactory, ILogger<DemoContentUpdater>) | After an update that ships a newer demo package, applies it once at startup (see ApplyPendingUpdateAsync). Never blocks or fails the host. |
Kandra.DataImport.DemoInstallation
What a demo installation was seeded from; read by the demo banner and by factory reset.
Constructors
| Constructor | Description |
|---|
DemoInstallation(String, DateTime) | What a demo installation was seeded from; read by the demo banner and by factory reset. |
Kandra.DataImport.DemoSeedResult
Constructors
| Constructor | Description |
|---|
DemoSeedResult(Boolean, ImportReport, IReadOnlyList<String>) | undocumented |
Properties
| Property | Description |
|---|
AlreadySeeded | The installation already carries the demo marker: nothing was created (a newer package version, if any, is applied by ApplyPendingUpdateAsync). |
Kandra.DataImport.DemoSeedingConstants
Fields
| Field | Description |
|---|
MarkerConstantName | Reserved name, deliberately not a registered [KandraConstant], so the Constants admin page never lists it. |
Kandra.DataImport.DemoSeedingServiceCollectionExtensions
Methods
| Method | Description |
|---|
AddKandraDemoSeeding<T0, T1>(IServiceCollection) | Registers IDemoSeeding and the startup update of demo content. Needs AddKandraDataImport and an IDemoUserProvider if the configuration wants demo users. |
Kandra.DataImport.DemoSeeding<T0, T1>
Methods
| Method | Description |
|---|
CheckUserLimitAsync(IReadOnlyList<DemoUser>, CancellationToken) | Free-tier fit: the demo users plus the existing real users must stay within the licensed user count. |
EnsureCallerAsync | The import runs as the calling user; at startup or from a setup flow nobody is signed in, so it runs as admin. |
WriteMarkerAsync(DemoInstallation, CancellationToken) | Written straight to the constants table, like the package state: bookkeeping, not a user-facing setting. |
Kandra.DataImport.IDataImportService
Applies an import package (docs/kandra-data-import-design.md) through the entity-operations layer. Idempotent: every row it writes carries an ImportStamp, so a re-run inserts what is missing, updates what the package changed, and leaves everything else (including rows users edited or deleted) alone unless the step's policies say otherwise. Demo seeding and real import use the same code; only the package's origin differs. Runs as the calling user (ICallerContext).
Kandra.DataImport.IDemoSeeding
Turns an installation into a demo one: applies the configuration's demo import package through the import engine, creates the demo users and writes the installation marker (MarkerConstantName). Re-running is a no-op. A regular installation never calls it and so never has sample users.
Methods
| Method | Description |
|---|
ApplyPendingUpdateAsync(CancellationToken) | When the installation is a demo one and its embedded package is newer than the applied one, runs the import so new demo objects appear (the default policies keep the user's own edits). Returns the report, or null when nothing was due. |
DryRunAsync(String, CancellationToken) | Runs everything SeedAsync would check or import, writing nothing: the licensed user limit and a dry run of the package. Lets a setup flow show errors instead of half-seeding. Throws like SeedAsync when there is no demo package or the demo users do not fit the licence. |
GetInstallationAsync(CancellationToken) | The marker, or null when this is not a demo installation. |
SeedAsync(String, CancellationToken) | undocumented |
Kandra.DataImport.IImportPackageRegistry
The packages a configuration ships as embedded resources (ImportPackages/*.json in its Application project, registered with AddImportPackages).
Methods
| Method | Description |
|---|
Open(String) | Opens a fresh read stream over the package JSON; null when no such package. |
Kandra.DataImport.IImportRowAccessor
Per-entity-type EF access for the importer, behind a non-generic seam so the service needs no per-type code.
Methods
| Method | Description |
|---|
AdoptAsync(DbContext, Guid, ImportStamp, CancellationToken) | Stamps an existing row without otherwise changing it (Adopted). |
FindUnstampedByMatchAsync(DbContext, IReadOnlyList<ValueTuple<String, Object>>, CancellationToken) | Not-deleted rows without a stamp whose properties equal the given values (EF-translatable, string/Guid/int/bool/decimal properties). |
RestoreAsync(DbContext, Guid, Guid, CancellationToken) | Clears the soft-delete flag (Restored); the importer then updates the row through the normal service. |
Kandra.DataImport.IImportRunService
Runs imports in the background and answers "what happened" afterwards. A large import takes longer than an HTTP request should, so Start returns a run id immediately; the run executes as the user who started it (identity and time zone are copied into the run's own DI scope). Live status and the report of recent runs (dry runs included) are held in memory; completed real runs also appear in the package state and keep their report as a blob.
Methods
| Method | Description |
|---|
ListRunsAsync(String, CancellationToken) | Recent runs, newest first; of one package, or of every package when null. |
Start(Byte[], String, ImportOptions) | Starts a run over the package JSON and returns its id. Throws InvalidStateException when another import is running. |
Kandra.DataImport.IImportSchemaProvider
Builds the JSON Schema (draft 2020-12) of the import package format for this configuration, so editors (VS Code) can validate and autocomplete packages through $schema.
Kandra.DataImport.ImportDiagnostic
One finding from reading/validating/applying a package. Path is a JSON-path-like locator, e.g. steps[2].items[0].lines[1].itemId.
Constructors
| Constructor | Description |
|---|
ImportDiagnostic(String, ImportDiagnosticSeverity, String) | One finding from reading/validating/applying a package. Path is a JSON-path-like locator, e.g. steps[2].items[0].lines[1].itemId. |
Kandra.DataImport.ImportEntityTypes
Maps a catalog entry to the EF entity type behind it, and hands out the matching accessor.
Methods
| Method | Description |
|---|
EntityTypeOf(EntityCatalogEntry) | The EF entity of a Dictionary/Document catalog entry: the type argument of the behavior's IDictionaryBehavior<TEntity> / IDocumentBehavior<TEntity> (for a hierarchical dictionary that is the root node type, which is the one EF maps and the repository is registered for). |
Kandra.DataImport.ImportHostInfo
The configuration an import host belongs to; a package declares the one it targets.
Constructors
| Constructor | Description |
|---|
ImportHostInfo(String) | The configuration an import host belongs to; a package declares the one it targets. |
Kandra.DataImport.ImportItem
One object of a step: its $id (becomes ImportStamp.Key) and the item JSON as written (including $id).
Constructors
| Constructor | Description |
|---|
ImportItem(String, JsonObject, String) | One object of a step: its $id (becomes ImportStamp.Key) and the item JSON as written (including $id). |
Kandra.DataImport.ImportItemResult
What happened to one package object. EntityId is null for a data processor or a failure before an id was known.
Constructors
| Constructor | Description |
|---|
ImportItemResult(Int32, String, String, Nullable<Guid>, ImportItemOutcome, String) | What happened to one package object. EntityId is null for a data processor or a failure before an id was known. |
Kandra.DataImport.ImportOptions
Constructors
| Constructor | Description |
|---|
ImportOptions(Boolean, Boolean, Nullable<Guid>) | undocumented |
Properties
| Property | Description |
|---|
ContinueOnError | When false the run stops at the first failed item; re-running continues where it stopped. |
DryRun | Parse, validate, resolve, look up and plan outcomes - including the licence pre-check - but write nothing. |
RunId | Pre-allocated run id (a background runner hands it to its caller before the run starts); generated when null. |
Kandra.DataImport.ImportPackageInfo
Header of an embedded package: what the admin page and GET Import/packages list.
Constructors
| Constructor | Description |
|---|
ImportPackageInfo(String, Int32, ImportOrigin, String, String) | Header of an embedded package: what the admin page and GET Import/packages list. |
Kandra.DataImport.ImportPackageReader
Parses a kandra-import/1 package into the ImportPackage model (header + steps, items kept as JsonNode) and reports structural problems as ImportDiagnostics. Knows nothing about the configuration entities - see ImportPackageValidator for that.
Methods
| Method | Description |
|---|
PackageIdRegex | undocumented |
Kandra.DataImport.ImportPackageServiceCollectionExtensions
Methods
| Method | Description |
|---|
AddImportPackages(IServiceCollection, Assembly) | Registers the packages embedded in assembly (resources under an ImportPackages folder). Call once per assembly that ships packages; typically typeof(SomeTypeInYourApplicationProject).Assembly. |
Kandra.DataImport.ImportPackageState
The applied version of a package (null = never applied) and its most recent runs.
Constructors
| Constructor | Description |
|---|
ImportPackageState(String, Nullable<Int32>, IReadOnlyList<ImportRunSummary>) | The applied version of a package (null = never applied) and its most recent runs. |
Kandra.DataImport.ImportPackageValidator
Checks a parsed package against this configuration: entity/constant/processor names, item properties (against the field metadata of the Dto, i.e. the real wire shape), required fields, $id uniqueness, $ref (must point at an earlier object) / $code (field must reference an entity), date tokens and match properties. Findings come back as ImportDiagnostics; nothing is thrown or written.
Constructors
| Constructor | Description |
|---|
ImportPackageValidator(IEntityCatalog, EntityFieldMetadataBuilder, ImportHostInfo) | Checks a parsed package against this configuration: entity/constant/processor names, item properties (against the field metadata of the Dto, i.e. the real wire shape), required fields, $id uniqueness, $ref (must point at an earlier object) / $code (field must reference an entity), date tokens and match properties. Findings come back as ImportDiagnostics; nothing is thrown or written. |
Methods
| Method | Description |
|---|
FieldsFor(EntityCatalogEntry) | The properties an item of this entity may carry. A hierarchical dictionary's catalog Dto is the abstract root, so folder and leaf properties are unioned; the polymorphic discriminator (isFolder) is added explicitly. |
RequiredFieldsFor(EntityCatalogEntry, JsonObject, IReadOnlyList<EntityFieldInfo>) | undocumented |
Kandra.DataImport.ImportRowInfo
What the importer needs to know about an existing row to decide an outcome. Soft-deleted rows are included.
Constructors
| Constructor | Description |
|---|
ImportRowInfo(Guid, Boolean, DateTime, Nullable<DateTime>, String, Nullable<DateTime>) | What the importer needs to know about an existing row to decide an outcome. Soft-deleted rows are included. |
Properties
| Property | Description |
|---|
ModifiedAfterImport | A user (or anything else) changed the row after the import wrote it. |
Kandra.DataImport.ImportRunInfo
One run as seen by GetRunAsync: live status plus, once finished, the report.
Constructors
| Constructor | Description |
|---|
ImportRunInfo(Guid, String, ImportRunStatus, Boolean, DateTime, Nullable<DateTime>, String, ImportReport, String) | One run as seen by GetRunAsync: live status plus, once finished, the report. |
Kandra.DataImport.ImportRunSummary
A line of the run history. HasReport is true when the full report can still be fetched.
Constructors
| Constructor | Description |
|---|
ImportRunSummary(Guid, String, DateTime, String, Boolean, IReadOnlyDictionary<String, Int32>, ImportRunStatus, Boolean) | A line of the run history. HasReport is true when the full report can still be fetched. |
Kandra.DataImport.ImportRunTracker
In-memory view of runs started by this process. Singleton.
Kandra.DataImport.ImportSchemaProvider
Source generators can only emit C#, so the schema is built at runtime from the entity catalog and field metadata (the same sources the validator uses). The result is deterministic: entries are ordered by kind then name.
Constructors
| Constructor | Description |
|---|
ImportSchemaProvider(IEntityCatalog, ImportPackageValidator, ImportHostInfo) | Source generators can only emit C#, so the schema is built at runtime from the entity catalog and field metadata (the same sources the validator uses). The result is deterministic: entries are ordered by kind then name. |
Kandra.DataImport.ImportStep
One step of a package. Which members are meaningful depends on Kind: Dictionary/Document use Items; Constant uses Id + Value; CreateFrom uses Id + Source + Set; DataProcessor uses Id + Input. EntityName is the catalog name (dictionary/document/constant/processor name, or the createFrom target).
Properties
| Property | Description |
|---|
Raw | The step's own JSON as written - hashed for Constant/CreateFrom/DataProcessor steps, which have no items. |
Kandra.DataImport.ImportTokens
Date tokens usable as string values in a package: $now, $today, $today-23d, $today+14d.
Methods
| Method | Description |
|---|
TokenRegex | undocumented |
TryParse(String, Boolean, Int32) | Parses a token. $now takes no offset; days is the signed day offset of $today. |
Kandra.DataImport.OnChangePolicy
What to do when the package item changed since the last apply.
Kandra.DataImport.OnDeletedPolicy
What to do when a user soft-deleted the imported row.
Kandra.DataImport.OnUserModifiedPolicy
What to do when a user modified the row after it was imported.
System.Text.RegularExpressions.Generated.PackageIdRegex_0
Custom Regex-derived type for the PackageIdRegex method.
Constructors
| Constructor | Description |
|---|
PackageIdRegex_0 | Initializes the instance. |
Fields
| Field | Description |
|---|
Instance | Cached, thread-safe singleton instance. |
System.Text.RegularExpressions.Generated.PackageIdRegex_0.RunnerFactory
Provides a factory for creating RegexRunner instances to be used by methods on Regex.
Methods
| Method | Description |
|---|
CreateInstance | Creates an instance of a RegexRunner used by methods on Regex. |
System.Text.RegularExpressions.Generated.PackageIdRegex_0.RunnerFactory.Runner
Provides the runner that contains the custom logic implementing the specified regular expression.
Methods
| Method | Description |
|---|
Scan(ReadOnlySpan<Char>) | Scan the inputSpan starting from base.runtextstart for the next match. |
TryFindNextPossibleStartingPosition(ReadOnlySpan<Char>) | Search inputSpan starting from base.runtextpos for the next location a match could possibly start. Returns: true if a possible match was found; false if no more matches are possible. |
TryMatchAtCurrentPosition(ReadOnlySpan<Char>) | Determine whether inputSpan at base.runtextpos is a match for the regular expression. Returns: true if the regular expression matches at the current position; otherwise, false. |
System.Text.RegularExpressions.Generated.TokenRegex_1
Custom Regex-derived type for the TokenRegex method.
Constructors
| Constructor | Description |
|---|
TokenRegex_1 | Initializes the instance. |
Fields
| Field | Description |
|---|
Instance | Cached, thread-safe singleton instance. |
System.Text.RegularExpressions.Generated.TokenRegex_1.RunnerFactory
Provides a factory for creating RegexRunner instances to be used by methods on Regex.
Methods
| Method | Description |
|---|
CreateInstance | Creates an instance of a RegexRunner used by methods on Regex. |
System.Text.RegularExpressions.Generated.TokenRegex_1.RunnerFactory.Runner
Provides the runner that contains the custom logic implementing the specified regular expression.
Methods
| Method | Description |
|---|
Scan(ReadOnlySpan<Char>) | Scan the inputSpan starting from base.runtextstart for the next match. |
TryFindNextPossibleStartingPosition(ReadOnlySpan<Char>) | Search inputSpan starting from base.runtextpos for the next location a match could possibly start. Returns: true if a possible match was found; false if no more matches are possible. |
TryMatchAtCurrentPosition(ReadOnlySpan<Char>) | Determine whether inputSpan at base.runtextpos is a match for the regular expression. Returns: true if the regular expression matches at the current position; otherwise, false. |
System.Text.RegularExpressions.Generated.Utilities
Helper methods used by generated Regex-derived implementations.
Methods
| Method | Description |
|---|
StackPush(Int32[], Int32, Int32, Int32) | Pushes 2 values onto the backtracking stack. |
Fields
| Field | Description |
|---|
s_defaultTimeout | Default timeout value set in AppContext, or InfiniteMatchTimeout if none was set. |
s_hasTimeout | Whether s_defaultTimeout is non-infinite. |