ngx-dynamic-entity 2.5.0 → 3.0.0-rc.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-dynamic-entity",
3
- "version": "2.5.0",
3
+ "version": "3.0.0-rc.2",
4
4
  "description": "Angular standalone UI library for rendering dynamic entity forms.",
5
5
  "//typings": "Local workspace resolution only: ng-packagr 21 writes types/ngx-dynamic-entity.d.ts into dist/package.json. Do NOT add a 'main' field here — ng-packagr does not generate one, so it would be copied verbatim and resolve wrongly in the published package.",
6
6
  "typings": "types/ngx-dynamic-entity.d.ts",
@@ -8,7 +8,7 @@
8
8
  "@angular/common": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0",
9
9
  "@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0",
10
10
  "@angular/forms": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0",
11
- "@dynamic-entity/core": "^2.5.0",
11
+ "@dynamic-entity/core": "^3.0.0-rc.2",
12
12
  "rxjs": "^7.0.0"
13
13
  },
14
14
  "keywords": [
@@ -1,10 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Type, EnvironmentProviders, WritableSignal, OnInit, OnChanges, OnDestroy, EventEmitter, SimpleChanges, Provider } from '@angular/core';
3
- import { ReferenceOption, LocalizedText, EntityFormConfig, FormRule, ImportLookups, DateOrder, MappingPlan, CsvDelimiter, ImportResult, TemplateSpec, SheetGrid, CommonModuleEntry, EntityReferenceLoader, LookupListSource, RecordMigration, FileUploadHandler, FieldValidators, NestedFieldConfig, ReferenceLoaderContext, DropdownOption, LookupListValue, NestedTabConfig, RuleEvaluationResult, FieldScopeEntry, EvaluateFormRulesOptions, ImportColumn, MappingEntry, UnsupportedColumn, ImportRowError, SliderBounds } from '@dynamic-entity/core';
3
+ import { ReferenceOption, LocalizedText, EntityFormConfig, FormRule, ImportLookups, DateOrder, AnyMappingPlan, CsvDelimiter, ImportResult, TemplateSpec, SheetGrid, CommonModuleEntry, EntityReferenceLoader, LookupListSource, RecordMigration, FileUploadHandler, FieldValidators, NestedFieldConfig, ReferenceLoaderContext, DropdownOption, LookupListValue, NestedTabConfig, RuleEvaluationResult, FieldScopeEntry, EvaluateFormRulesOptions, MappingPlan, ImportColumn, MappingEntry, UnsupportedColumn, ImportRowError, SliderBounds } from '@dynamic-entity/core';
4
4
  export { AutoPatchConfig, CommonModuleEntry, ComponentClass, DropdownOption, EntityFormConfig, EntityPermissions, EntityReferenceConfig, EntityReferenceLoader, FieldTableConfig, FieldValidators, FileRef, FormRule, LocalizedText, NestedFieldConfig, NestedTabConfig, PatchOnTrueMapping, RbacContext, ReferenceLoaderContext, ReferenceOption, RichFieldType, RuleAction, RuleCondition, RuleEvaluationResult, VersionedRecord, formatDisplayValue, normalizeConfig, normalizeOption, resolveLabel, resolveOptionLabel, resolveOptionValue, valuesMatch } from '@dynamic-entity/core';
5
5
  import { ValidatorFn, AsyncValidatorFn, AbstractControl, ValidationErrors, FormGroup, FormArray } from '@angular/forms';
6
6
  import * as rxjs from 'rxjs';
7
7
  import * as ngx_dynamic_entity from 'ngx-dynamic-entity';
8
+ import * as sheet_to_schema from 'sheet-to-schema';
8
9
 
9
10
  /**
10
11
  * Backing store for cached reference options.
@@ -239,6 +240,10 @@ declare class UiTextService {
239
240
  * text is whatever a library's formatter printed. A parser returning text (`SheetData`, as 2.2's
240
241
  * did) still fits.
241
242
  *
243
+ * Covered cells of a merged range are `''` (as the server reader emits). The master cell at
244
+ * the top-left of the range holds the value; every covered cell must be `''`, never repeating
245
+ * the master value and never omitted.
246
+ *
242
247
  * The library ships a delimited-text reader and no more. Registering one that understands
243
248
  * `.xlsx` is how a consumer adds it, and which spreadsheet library they use stays their
244
249
  * choice — this package has no runtime dependency and gains none here.
@@ -247,6 +252,7 @@ declare class UiTextService {
247
252
  * // SheetJS 0.20.3+ from https://cdn.sheetjs.com — the npm `xlsx` package stopped at 0.18.5,
248
253
  * // which has known vulnerabilities. `UTC: true` matters: without it a date cell arrives at
249
254
  * // *local* midnight, which is the previous day in UTC for anyone east of Greenwich.
255
+ * // `defval: ''` ensures covered cells of merged ranges are `''`, matching the server reader.
250
256
  * provideNgxDynamicEntity({
251
257
  * sheetParser: async file => {
252
258
  * const workbook = XLSX.read(await file.arrayBuffer(), { cellDates: true });
@@ -290,7 +296,7 @@ interface ImportPreview {
290
296
  /** The first few rows, for the mapping screen to show under each column. */
291
297
  sample: string[][];
292
298
  /** Where the suggester got to. Every inferred match is tagged `guess`. */
293
- suggestion: MappingPlan;
299
+ suggestion: AnyMappingPlan;
294
300
  /** Total data rows in the file, which may be far more than `sample` holds. */
295
301
  rowCount: number;
296
302
  /**
@@ -335,7 +341,7 @@ interface ImportTransport {
335
341
  /** Headers, a sample, and a suggested mapping for a freshly chosen file. */
336
342
  preview(file: File, context: ImportContext): Promise<ImportPreview>;
337
343
  /** Apply a plan to the whole file. */
338
- commit(file: File, plan: MappingPlan, context: ImportContext): Promise<ImportResult>;
344
+ commit(file: File, plan: AnyMappingPlan, context: ImportContext): Promise<ImportResult>;
339
345
  /**
340
346
  * Render a template for download.
341
347
  *
@@ -481,11 +487,11 @@ declare const UPLOAD_HANDLER: InjectionToken<FileUploadHandler>;
481
487
  * @example
482
488
  * provideNgxDynamicEntity({
483
489
  * sheetParser: async file => {
484
- * const wb = XLSX.read(await file.arrayBuffer());
490
+ * const wb = XLSX.read(await file.arrayBuffer(), { cellDates: true });
485
491
  * const rows = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], {
486
- * header: 1, raw: false, defval: '',
487
- * }) as string[][];
488
- * return { headers: rows[0] ?? [], rows: rows.slice(1) };
492
+ * header: 1, raw: true, defval: '', UTC: true,
493
+ * }) as unknown[][];
494
+ * return { headers: (rows[0] ?? []).map(cellText), rows: rows.slice(1) };
489
495
  * },
490
496
  * })
491
497
  */
@@ -2087,8 +2093,14 @@ declare class LocalImportTransport implements ImportTransport {
2087
2093
  private readonly parsed;
2088
2094
  /** The registered parser, or the built-in CSV one. */
2089
2095
  private read;
2090
- preview(file: File, context: ImportContext): Promise<ImportPreview>;
2091
- commit(file: File, plan: MappingPlan, context: ImportContext): Promise<ImportResult>;
2096
+ /**
2097
+ * The suggestion made here is always plan v2, and the return type says so. The contract's is
2098
+ * a plan in either shape, because a 2.x server sends the older one.
2099
+ */
2100
+ preview(file: File, context: ImportContext): Promise<ImportPreview & {
2101
+ suggestion: MappingPlan;
2102
+ }>;
2103
+ commit(file: File, plan: AnyMappingPlan, context: ImportContext): Promise<ImportResult>;
2092
2104
  template(spec: TemplateSpec, format: TemplateFormat): Promise<Blob>;
2093
2105
  static ɵfac: i0.ɵɵFactoryDeclaration<LocalImportTransport, never>;
2094
2106
  static ɵprov: i0.ɵɵInjectableDeclaration<LocalImportTransport>;
@@ -2117,8 +2129,9 @@ interface HttpImportTransportOptions {
2117
2129
  /**
2118
2130
  * Where a warning goes. Defaults to `console.warn`.
2119
2131
  *
2120
- * There is exactly one warning, and it is the engine-version mismatch below — which is a
2121
- * developer's problem, not a user's, so it does not belong in the wizard's error banner.
2132
+ * What is warned about is the two deploys having moved apart: the engine version, the
2133
+ * adapter, the date order the server did not confirm. Those are a developer's problem, not
2134
+ * a user's, so they do not belong in the wizard's error banner.
2122
2135
  */
2123
2136
  warn?: (message: string) => void;
2124
2137
  }
@@ -2129,6 +2142,12 @@ declare class HttpImportTransport implements ImportTransport {
2129
2142
  * Keyed on the `File`, so it lives exactly as long as the file does.
2130
2143
  */
2131
2144
  private readonly reported;
2145
+ /**
2146
+ * The plan versions each previewed file's server said it reads. A file with no entry was
2147
+ * never previewed here, and one whose server said nothing is from before plan v2: either
2148
+ * way `commit` sends nothing that only a v2 reader would understand.
2149
+ */
2150
+ private readonly planVersions;
2132
2151
  constructor(options: HttpImportTransportOptions);
2133
2152
  private warn;
2134
2153
  /**
@@ -2149,8 +2168,15 @@ declare class HttpImportTransport implements ImportTransport {
2149
2168
  * patch release is not a reason to stop somebody importing.
2150
2169
  */
2151
2170
  private checkEngine;
2171
+ /**
2172
+ * Warn when the server runs another adapter, or this one at another major version.
2173
+ *
2174
+ * Since 3.0 a server says which adapter turned its rows into records. A server from before
2175
+ * that says nothing, and `checkEngine` has already compared the one version it does report.
2176
+ */
2177
+ private checkAdapter;
2152
2178
  preview(file: File, context: ImportContext): Promise<ImportPreview>;
2153
- commit(file: File, plan: MappingPlan, context: ImportContext): Promise<ImportResult>;
2179
+ commit(file: File, plan: AnyMappingPlan, context: ImportContext): Promise<ImportResult>;
2154
2180
  template(spec: TemplateSpec, format: TemplateFormat, context: ImportContext, fields?: readonly string[]): Promise<Blob>;
2155
2181
  }
2156
2182
  /**
@@ -2222,11 +2248,11 @@ declare class EntityImportComponent {
2222
2248
  protected readonly sample: i0.WritableSignal<string[][]>;
2223
2249
  protected readonly rowCount: i0.WritableSignal<number>;
2224
2250
  /** The separator a delimited file turned out to use, so the user can see how it was read. */
2225
- protected readonly delimiter: i0.WritableSignal<CsvDelimiter>;
2251
+ protected readonly delimiter: i0.WritableSignal<sheet_to_schema.CsvDelimiter>;
2226
2252
  /** The date order the transport said it will read with at commit, from its preview. */
2227
2253
  protected readonly reportedDateOrder: i0.WritableSignal<DateOrder>;
2228
2254
  protected readonly fileName: i0.WritableSignal<string>;
2229
- protected readonly plan: i0.WritableSignal<MappingPlan>;
2255
+ protected readonly plan: i0.WritableSignal<AnyMappingPlan>;
2230
2256
  protected readonly result: i0.WritableSignal<ImportResult>;
2231
2257
  private readonly registered;
2232
2258
  private readonly local;
@@ -2322,11 +2348,11 @@ interface ArraySlots {
2322
2348
  declare class ImportMapperComponent implements OnChanges {
2323
2349
  config: EntityFormConfig;
2324
2350
  headers: readonly string[];
2325
- /** The starting point, normally `suggestMapping`'s output. */
2326
- plan: MappingPlan | null;
2351
+ /** The starting point, normally `suggestMapping`'s output. A stored 2.x plan is taken too. */
2352
+ plan: AnyMappingPlan | null;
2327
2353
  language: string;
2328
- /** Emitted whenever the user changes a selection. */
2329
- readonly planChange: EventEmitter<MappingPlan>;
2354
+ /** Emitted whenever the user changes a selection. Always plan v2, whichever shape came in. */
2355
+ readonly planChange: EventEmitter<sheet_to_schema.MappingPlan>;
2330
2356
  protected readonly ui: UiTextService;
2331
2357
  protected readonly rows: i0.WritableSignal<MappingRow[]>;
2332
2358
  /**
@@ -2338,7 +2364,7 @@ declare class ImportMapperComponent implements OnChanges {
2338
2364
  */
2339
2365
  protected readonly unsupported: i0.WritableSignal<number>;
2340
2366
  /** A plan entry whose field this config no longer has. Kept, and emitted, until removed. */
2341
- protected readonly stale: i0.WritableSignal<MappingEntry[]>;
2367
+ protected readonly stale: i0.WritableSignal<sheet_to_schema.MappingEntry[]>;
2342
2368
  /** Repeating fields the user can add a row to. */
2343
2369
  protected readonly arrays: i0.WritableSignal<ArraySlots[]>;
2344
2370
  protected readonly constant = -1;
@@ -2369,6 +2395,10 @@ declare class ImportMapperComponent implements OnChanges {
2369
2395
  * Every entry of the incoming plan survives in its own position — a fixed value, a ref the
2370
2396
  * config no longer has — unless the user changed or removed it, and an untouched entry is
2371
2397
  * emitted exactly as it arrived. New selections follow, in field order.
2398
+ *
2399
+ * What is emitted is plan v2, whichever shape came in: `target` and `schemaVersion`, where a
2400
+ * 2.x plan said `entity` and `configVersion`. Anything else the incoming plan carried, such
2401
+ * as its lists and its grouping, is kept.
2372
2402
  */
2373
2403
  private toPlan;
2374
2404
  static ɵfac: i0.ɵɵFactoryDeclaration<ImportMapperComponent, never>;
@@ -2411,7 +2441,7 @@ interface PreviewRow {
2411
2441
  */
2412
2442
  declare class ImportPreviewComponent implements OnChanges {
2413
2443
  config: EntityFormConfig;
2414
- plan: MappingPlan;
2444
+ plan: AnyMappingPlan;
2415
2445
  rows: readonly (readonly string[])[];
2416
2446
  lookups?: ImportLookups;
2417
2447
  /** The same rules the commit will apply; without them a rule-driven rejection is invisible. */