@texuli/spec 0.0.0-stage → 0.1.0-next.1

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.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -2
  3. package/dist/build.d.ts +47 -0
  4. package/dist/build.js +65 -0
  5. package/dist/canonical.d.ts +17 -0
  6. package/dist/canonical.js +131 -0
  7. package/dist/catalog.d.ts +41 -0
  8. package/dist/catalog.js +45 -0
  9. package/dist/codegen/index.d.ts +14 -0
  10. package/dist/codegen/index.js +13 -0
  11. package/dist/codegen/kotlin.d.ts +18 -0
  12. package/dist/codegen/kotlin.js +328 -0
  13. package/dist/codegen/shared.d.ts +35 -0
  14. package/dist/codegen/shared.js +69 -0
  15. package/dist/codegen/typescript.d.ts +10 -0
  16. package/dist/codegen/typescript.js +167 -0
  17. package/dist/conformance.d.ts +20 -0
  18. package/dist/conformance.js +124 -0
  19. package/dist/dialect.d.ts +56 -0
  20. package/dist/dialect.js +264 -0
  21. package/dist/format.d.ts +9 -0
  22. package/dist/format.js +48 -0
  23. package/dist/generated/typescript/blueprint.d.ts +125 -0
  24. package/dist/generated/typescript/blueprint.js +3 -0
  25. package/dist/generated/typescript/catalog-schema.d.ts +33 -0
  26. package/dist/generated/typescript/catalog-schema.js +3 -0
  27. package/dist/generated/typescript/diagnostics.d.ts +12 -0
  28. package/dist/generated/typescript/diagnostics.js +3 -0
  29. package/dist/generated/typescript/manifest.d.ts +9 -0
  30. package/dist/generated/typescript/manifest.js +3 -0
  31. package/dist/generated/typescript/vocabulary.d.ts +972 -0
  32. package/dist/generated/typescript/vocabulary.js +140 -0
  33. package/dist/index.d.ts +17 -0
  34. package/dist/index.js +13 -0
  35. package/dist/validate.d.ts +27 -0
  36. package/dist/validate.js +143 -0
  37. package/dist/version.d.ts +2 -0
  38. package/dist/version.js +2 -0
  39. package/dist/versioning.d.ts +39 -0
  40. package/dist/versioning.js +87 -0
  41. package/package.json +36 -4
@@ -0,0 +1,140 @@
1
+ // Generated by @texuli/spec from catalog/components.json. Do not edit: run the spec generator.
2
+ // Spec 0.2.0, digest d9eccaba1826e7d87648a4a33787d873245592dda843607a10b2c68a77f1806f
3
+ /** The built catalog this vocabulary was projected from. */
4
+ export const SPEC_CATALOG_HASH = 'b073e30b4c8b1a30b3ef3ccb372e552d2d88e584616b74591c6c32923b471376';
5
+ /** Every closed component id, sorted. */
6
+ export const SPEC_COMPONENT_IDS = [
7
+ 'alert',
8
+ 'alert-dialog',
9
+ 'analytics-grid',
10
+ 'app-nav',
11
+ 'badge',
12
+ 'banner',
13
+ 'blocks-code',
14
+ 'blocks-data',
15
+ 'blocks-diagram',
16
+ 'blocks-embed',
17
+ 'blocks-interactive',
18
+ 'blocks-map',
19
+ 'blocks-media',
20
+ 'blocks-structure',
21
+ 'blocks-text',
22
+ 'breadcrumb',
23
+ 'button',
24
+ 'button-group',
25
+ 'callout',
26
+ 'card',
27
+ 'charts-area',
28
+ 'charts-bar',
29
+ 'charts-bubble',
30
+ 'charts-bullet',
31
+ 'charts-canvas-renderer',
32
+ 'charts-cartesian',
33
+ 'charts-combo',
34
+ 'charts-donut',
35
+ 'charts-funnel',
36
+ 'charts-gauge',
37
+ 'charts-geo-map',
38
+ 'charts-geo-point-map',
39
+ 'charts-heatmap',
40
+ 'charts-line',
41
+ 'charts-network',
42
+ 'charts-pie',
43
+ 'charts-progress-ring',
44
+ 'charts-sankey',
45
+ 'charts-scatter',
46
+ 'charts-sparkline',
47
+ 'charts-stacked-bar',
48
+ 'charts-sunburst',
49
+ 'charts-treemap',
50
+ 'checkbox',
51
+ 'chip',
52
+ 'code',
53
+ 'combobox',
54
+ 'command-palette',
55
+ 'content-layout',
56
+ 'context-menu',
57
+ 'context-menu-trigger',
58
+ 'deck-slide',
59
+ 'description',
60
+ 'detail-panel',
61
+ 'dialog',
62
+ 'drawer',
63
+ 'dropdown-menu',
64
+ 'dropdown-menu-content',
65
+ 'dropdown-menu-item',
66
+ 'dropdown-menu-trigger',
67
+ 'empty-state',
68
+ 'error-state',
69
+ 'field',
70
+ 'field-error',
71
+ 'form',
72
+ 'hover-card',
73
+ 'hover-card-content',
74
+ 'icon-button',
75
+ 'inline-text',
76
+ 'input',
77
+ 'input-group',
78
+ 'kbd',
79
+ 'kpi',
80
+ 'label',
81
+ 'layout-auth-split',
82
+ 'layout-blog',
83
+ 'layout-card',
84
+ 'layout-chrome',
85
+ 'layout-dashboard-grid',
86
+ 'layout-deck',
87
+ 'layout-doc',
88
+ 'layout-docs',
89
+ 'layout-drawer',
90
+ 'layout-dual-sidebar',
91
+ 'layout-editorial',
92
+ 'layout-grid',
93
+ 'layout-host',
94
+ 'layout-landing',
95
+ 'layout-marketing',
96
+ 'layout-page',
97
+ 'layout-pricing',
98
+ 'layout-settings',
99
+ 'layout-sidebar',
100
+ 'layout-top-nav',
101
+ 'layout-wizard',
102
+ 'media-composition-canvas',
103
+ 'media-composition-svg',
104
+ 'media-image',
105
+ 'menubar',
106
+ 'menubar-trigger',
107
+ 'multi-select',
108
+ 'nav-icon',
109
+ 'navigation-menu',
110
+ 'pagination',
111
+ 'popover',
112
+ 'popover-content',
113
+ 'radio',
114
+ 'radio-group',
115
+ 'responsive-modal',
116
+ 'screen-outlet',
117
+ 'select',
118
+ 'select-content',
119
+ 'select-group',
120
+ 'select-item',
121
+ 'select-label',
122
+ 'select-portal',
123
+ 'select-separator',
124
+ 'select-trigger',
125
+ 'select-value',
126
+ 'select-viewport',
127
+ 'sheet',
128
+ 'sidebar',
129
+ 'split-view',
130
+ 'stat',
131
+ 'stepper',
132
+ 'switch',
133
+ 'table',
134
+ 'tag',
135
+ 'text-counter',
136
+ 'textarea',
137
+ 'timeline',
138
+ 'toaster',
139
+ 'tooltip',
140
+ ];
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `@texuli/spec` — the schema-first blueprint contract (spec/Compose design
3
+ * B1), runtime half: the generated types and vocabulary, the dialect
4
+ * validator, the target-neutral blueprint validator and deterministic
5
+ * hashing. Build-time generation and the conformance harness live in
6
+ * `@texuli/spec/codegen`. Framework-free: no DOM, no Svelte and no Node APIs.
7
+ */
8
+ export type * from './generated/typescript/blueprint.js';
9
+ export type * from './generated/typescript/catalog-schema.js';
10
+ export type * from './generated/typescript/diagnostics.js';
11
+ export type * from './generated/typescript/manifest.js';
12
+ export { SPEC_CATALOG_HASH, SPEC_COMPONENT_IDS, type SpecComponentId, type SpecComponentProps, } from './generated/typescript/vocabulary.js';
13
+ export { canonicalJson, sha256 } from './canonical.js';
14
+ export { CAPABILITIES, type Capability, type SpecPropKind, WEB_ONLY_KINDS, WEB_ONLY_PROP_NAMES, } from './catalog.js';
15
+ export { checkSchemaDocument, DIALECT_KEYWORDS, DIALECT_TYPES, DIALECT_URI, type DialectType, type Schema, type SchemaIssue, validateInstance, } from './dialect.js';
16
+ export { type SpecDocuments, validateBlueprint, validateTree, } from './validate.js';
17
+ export { SPEC_VERSION } from './version.js';
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `@texuli/spec` — the schema-first blueprint contract (spec/Compose design
3
+ * B1), runtime half: the generated types and vocabulary, the dialect
4
+ * validator, the target-neutral blueprint validator and deterministic
5
+ * hashing. Build-time generation and the conformance harness live in
6
+ * `@texuli/spec/codegen`. Framework-free: no DOM, no Svelte and no Node APIs.
7
+ */
8
+ export { SPEC_CATALOG_HASH, SPEC_COMPONENT_IDS, } from "./generated/typescript/vocabulary.js";
9
+ export { canonicalJson, sha256 } from "./canonical.js";
10
+ export { CAPABILITIES, WEB_ONLY_KINDS, WEB_ONLY_PROP_NAMES, } from "./catalog.js";
11
+ export { checkSchemaDocument, DIALECT_KEYWORDS, DIALECT_TYPES, DIALECT_URI, validateInstance, } from "./dialect.js";
12
+ export { validateBlueprint, validateTree, } from "./validate.js";
13
+ export { SPEC_VERSION } from "./version.js";
@@ -0,0 +1,27 @@
1
+ import type { SpecDiagnostic, SpecDiagnosticCode, SpecValidation } from './generated/typescript/diagnostics.js';
2
+ import type { SpecCatalog } from './catalog.js';
3
+ import { type Schema } from './dialect.js';
4
+ export type { SpecDiagnostic, SpecDiagnosticCode, SpecValidation };
5
+ export interface SpecDocuments {
6
+ blueprintSchema: Schema;
7
+ catalog: SpecCatalog;
8
+ }
9
+ /**
10
+ * Validate a blueprint envelope against the spec alone: the envelope schema,
11
+ * then every node against the catalog vocabulary (closed ids, closed prop
12
+ * names, prop kinds and enum values, required props, no platform-extension
13
+ * props from data, a `slot` that names a slot prop of the parent) and the
14
+ * declared profile. A `when` condition is checked for shape only; the
15
+ * runtime formula parser checks its operands. With `catalogHash`, an envelope
16
+ * bound to another catalog is refused. This is the shared, target-neutral
17
+ * contract; URL policy, limits, grammar and rendering stay in the runtime
18
+ * validators (`@texuli/catalog/validate`).
19
+ */
20
+ export declare function validateBlueprint(input: unknown, documents: SpecDocuments, options?: {
21
+ catalogHash?: string;
22
+ }): SpecValidation;
23
+ /** Check one catalog tree against the vocabulary. See {@link validateBlueprint}. */
24
+ export declare function validateTree(tree: unknown, catalog: SpecCatalog, options?: {
25
+ portable?: boolean;
26
+ path?: string;
27
+ }): SpecDiagnostic[];
@@ -0,0 +1,143 @@
1
+ import { isRecord, validateInstance } from "./dialect.js";
2
+ const MAX_TREE_DEPTH = 64;
3
+ /**
4
+ * Validate a blueprint envelope against the spec alone: the envelope schema,
5
+ * then every node against the catalog vocabulary (closed ids, closed prop
6
+ * names, prop kinds and enum values, required props, no platform-extension
7
+ * props from data, a `slot` that names a slot prop of the parent) and the
8
+ * declared profile. A `when` condition is checked for shape only; the
9
+ * runtime formula parser checks its operands. With `catalogHash`, an envelope
10
+ * bound to another catalog is refused. This is the shared, target-neutral
11
+ * contract; URL policy, limits, grammar and rendering stay in the runtime
12
+ * validators (`@texuli/catalog/validate`).
13
+ */
14
+ export function validateBlueprint(input, documents, options = {}) {
15
+ const diagnostics = validateInstance(documents.blueprintSchema, input).map((issue) => ({ code: 'schema', path: issue.path, message: `${issue.code}: ${issue.message}` }));
16
+ if (!isRecord(input))
17
+ return { ok: false, diagnostics };
18
+ if (options.catalogHash !== undefined && input.catalog !== options.catalogHash) {
19
+ diagnostics.push({
20
+ code: 'catalog-mismatch',
21
+ path: '$.catalog',
22
+ message: 'The blueprint is bound to another catalog.',
23
+ });
24
+ }
25
+ const portable = input.profile === 'portable';
26
+ if (isRecord(input.tree)) {
27
+ diagnostics.push(...validateTree(input.tree, documents.catalog, { portable, path: '$.tree' }));
28
+ }
29
+ return { ok: diagnostics.length === 0, diagnostics };
30
+ }
31
+ /** Check one catalog tree against the vocabulary. See {@link validateBlueprint}. */
32
+ export function validateTree(tree, catalog, options = {}) {
33
+ const byId = new Map(catalog.components.map((c) => [c.id, c]));
34
+ const out = [];
35
+ const visit = (node, path, depth, parent) => {
36
+ if (!isRecord(node) || typeof node.id !== 'string' || depth > MAX_TREE_DEPTH)
37
+ return;
38
+ checkSlot(node.slot, parent, node.id, path, out);
39
+ const component = byId.get(node.id);
40
+ if (!component) {
41
+ out.push({
42
+ code: 'unknown-id',
43
+ path: `${path}.id`,
44
+ id: node.id,
45
+ message: `"${node.id}" is not in the catalog.`,
46
+ });
47
+ }
48
+ else {
49
+ if (options.portable && component.capability !== 'portable-core') {
50
+ out.push({
51
+ code: 'unsupported-profile',
52
+ path,
53
+ id: node.id,
54
+ message: `"${node.id}" is ${component.capability}, not portable core.`,
55
+ });
56
+ }
57
+ checkProps(node.props, component, `${path}.props`, out);
58
+ }
59
+ if (Array.isArray(node.children)) {
60
+ node.children.forEach((child, index) => {
61
+ visit(child, `${path}.children[${index}]`, depth + 1, component);
62
+ });
63
+ }
64
+ };
65
+ visit(tree, options.path ?? '$', 0, null);
66
+ return out;
67
+ }
68
+ /**
69
+ * A node's `slot` (audit G04) must name a slot prop of its parent; omitted
70
+ * or `children` is the default slot. A root fills no slot. An unknown
71
+ * parent was already reported, so its children's slots are not judged.
72
+ */
73
+ function checkSlot(slot, parent, id, path, out) {
74
+ if (slot === undefined || slot === 'children' || parent === undefined)
75
+ return;
76
+ const named = parent !== null &&
77
+ typeof slot === 'string' &&
78
+ parent.props.some((prop) => prop.kind === 'slot' && prop.name === slot);
79
+ if (named)
80
+ return;
81
+ out.push({
82
+ code: 'unknown-slot',
83
+ path: `${path}.slot`,
84
+ id,
85
+ message: parent === null
86
+ ? 'A root node fills no slot.'
87
+ : `"${String(slot)}" is not a slot of "${parent.id}".`,
88
+ });
89
+ }
90
+ function checkProps(props, component, path, out) {
91
+ const given = isRecord(props) ? props : {};
92
+ const id = component.id;
93
+ const declared = new Map(component.props.map((p) => [p.name, p]));
94
+ for (const [name, value] of Object.entries(given)) {
95
+ const here = `${path}.${name}`;
96
+ const prop = declared.get(name);
97
+ if (!prop) {
98
+ out.push({ code: 'unknown-prop', path: here, id, message: `"${id}" has no "${name}" prop.` });
99
+ continue;
100
+ }
101
+ if (prop.extension) {
102
+ out.push({
103
+ code: 'extension-prop',
104
+ path: here,
105
+ id,
106
+ message: `"${name}" is a ${prop.extension} extension (${prop.kind}) and cannot come from data.`,
107
+ });
108
+ continue;
109
+ }
110
+ const kindOk = prop.kind === 'string' || prop.kind === 'enum'
111
+ ? typeof value === 'string'
112
+ : prop.kind === 'number'
113
+ ? typeof value === 'number' && Number.isFinite(value)
114
+ : prop.kind === 'boolean'
115
+ ? typeof value === 'boolean'
116
+ : prop.kind === 'array'
117
+ ? Array.isArray(value)
118
+ : prop.kind === 'object'
119
+ ? isRecord(value)
120
+ : false;
121
+ if (!kindOk) {
122
+ out.push({ code: 'prop-type', path: here, id, message: `"${name}" must be ${prop.kind}.` });
123
+ }
124
+ else if (prop.kind === 'enum' && !(prop.enumValues ?? []).includes(value)) {
125
+ out.push({
126
+ code: 'enum-value',
127
+ path: here,
128
+ id,
129
+ message: `"${name}" must be one of ${(prop.enumValues ?? []).join(', ')}.`,
130
+ });
131
+ }
132
+ }
133
+ for (const prop of component.props) {
134
+ if (prop.required && !prop.extension && !Object.hasOwn(given, prop.name)) {
135
+ out.push({
136
+ code: 'missing-required',
137
+ path: `${path}.${prop.name}`,
138
+ id,
139
+ message: `"${id}" needs "${prop.name}".`,
140
+ });
141
+ }
142
+ }
143
+ }
@@ -0,0 +1,2 @@
1
+ /** The semantic version of the spec documents in this package. */
2
+ export declare const SPEC_VERSION = "0.2.0";
@@ -0,0 +1,2 @@
1
+ /** The semantic version of the spec documents in this package. */
2
+ export const SPEC_VERSION = '0.2.0';
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The spec's version history (`versions.json`): every released spec version
3
+ * pinned to the digest of its normative files, so the digest and the semantic
4
+ * version cannot drift apart. A normative change (schema, catalog projection,
5
+ * capability claim or fixture) changes the digest; it needs a new version
6
+ * and a new pin, with the change class the policy assigns to it.
7
+ */
8
+ /** What a release changes, by the policy in the package README. */
9
+ export type SpecChangeClass = 'patch' | 'minor' | 'major';
10
+ export interface SpecVersionPin {
11
+ specVersion: string;
12
+ /** The spec digest of that release, or `null` for a release pinned retroactively without one. */
13
+ specDigest: string | null;
14
+ change: SpecChangeClass | 'initial';
15
+ summary: string;
16
+ }
17
+ export interface SpecVersionHistory {
18
+ releases: readonly SpecVersionPin[];
19
+ }
20
+ export interface VersionIssue {
21
+ version: string;
22
+ message: string;
23
+ }
24
+ /**
25
+ * The version that must follow `previous` for a change of `change` class.
26
+ * Before 1.0.0 any change to accepted data (minor or major class) bumps the
27
+ * minor number and a patch-class change bumps the patch; from 1.0.0 each
28
+ * class bumps its own number.
29
+ */
30
+ export declare function nextSpecVersion(previous: string, change: SpecChangeClass): string;
31
+ /**
32
+ * Check the history and that the newest release is the spec as built now:
33
+ * the same version and the same digest. Returns every problem; empty means
34
+ * the version and the digest agree.
35
+ */
36
+ export declare function checkVersionHistory(history: SpecVersionHistory, current: {
37
+ specVersion: string;
38
+ specDigest: string;
39
+ }): VersionIssue[];
@@ -0,0 +1,87 @@
1
+ /**
2
+ * The spec's version history (`versions.json`): every released spec version
3
+ * pinned to the digest of its normative files, so the digest and the semantic
4
+ * version cannot drift apart. A normative change (schema, catalog projection,
5
+ * capability claim or fixture) changes the digest; it needs a new version
6
+ * and a new pin, with the change class the policy assigns to it.
7
+ */
8
+ const SEMVER = /^(\d+)\.(\d+)\.(\d+)$/;
9
+ const DIGEST = /^[0-9a-f]{64}$/;
10
+ function parts(version) {
11
+ const match = SEMVER.exec(version);
12
+ return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
13
+ }
14
+ /**
15
+ * The version that must follow `previous` for a change of `change` class.
16
+ * Before 1.0.0 any change to accepted data (minor or major class) bumps the
17
+ * minor number and a patch-class change bumps the patch; from 1.0.0 each
18
+ * class bumps its own number.
19
+ */
20
+ export function nextSpecVersion(previous, change) {
21
+ const p = parts(previous);
22
+ if (!p)
23
+ throw new Error(`${previous}: not a semantic version`);
24
+ const [major, minor, patch] = p;
25
+ if (change === 'patch')
26
+ return `${major}.${minor}.${patch + 1}`;
27
+ if (major === 0 || change === 'minor')
28
+ return `${major}.${minor + 1}.0`;
29
+ return `${major + 1}.0.0`;
30
+ }
31
+ /**
32
+ * Check the history and that the newest release is the spec as built now:
33
+ * the same version and the same digest. Returns every problem; empty means
34
+ * the version and the digest agree.
35
+ */
36
+ export function checkVersionHistory(history, current) {
37
+ const issues = [];
38
+ const releases = history.releases;
39
+ if (releases.length === 0) {
40
+ return [{ version: current.specVersion, message: 'versions.json lists no release.' }];
41
+ }
42
+ releases.forEach((release, index) => {
43
+ const { specVersion: version } = release;
44
+ if (!parts(version))
45
+ issues.push({ version, message: 'not a semantic version' });
46
+ if (release.specDigest !== null && !DIGEST.test(release.specDigest)) {
47
+ issues.push({ version, message: 'the digest is not a SHA-256 hex string' });
48
+ }
49
+ if (index === 0) {
50
+ if (release.change !== 'initial') {
51
+ issues.push({ version, message: 'the first release must have change "initial"' });
52
+ }
53
+ return;
54
+ }
55
+ const previous = releases[index - 1];
56
+ if (release.change === 'initial') {
57
+ issues.push({ version, message: 'only the first release is "initial"' });
58
+ return;
59
+ }
60
+ if (release.specDigest === null) {
61
+ issues.push({ version, message: 'only the first release may lack a digest' });
62
+ }
63
+ if (parts(previous.specVersion)) {
64
+ const expected = nextSpecVersion(previous.specVersion, release.change);
65
+ if (version !== expected) {
66
+ issues.push({
67
+ version,
68
+ message: `a ${release.change} change after ${previous.specVersion} is ${expected}`,
69
+ });
70
+ }
71
+ }
72
+ });
73
+ const newest = releases[releases.length - 1];
74
+ if (newest.specVersion !== current.specVersion) {
75
+ issues.push({
76
+ version: current.specVersion,
77
+ message: `the newest release in versions.json is ${newest.specVersion}, the spec is ${current.specVersion}`,
78
+ });
79
+ }
80
+ else if (newest.specDigest !== current.specDigest) {
81
+ issues.push({
82
+ version: current.specVersion,
83
+ message: 'the normative files changed without a new version: classify the change, bump SPEC_VERSION, regenerate, and append a release pinning the new digest',
84
+ });
85
+ }
86
+ return issues;
87
+ }
package/package.json CHANGED
@@ -1,6 +1,38 @@
1
1
  {
2
2
  "name": "@texuli/spec",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0-next.1",
4
+ "description": "The schema-first blueprint contract: JSON schemas, the catalog vocabulary, deterministic TypeScript and Kotlin projections, and the conformance harness.",
5
+ "keywords": [
6
+ "svelte",
7
+ "svelte-5",
8
+ "components",
9
+ "design-system",
10
+ "texuli"
11
+ ],
12
+ "homepage": "https://github.com/DailybotHQ/texuli#readme",
13
+ "bugs": "https://github.com/DailybotHQ/texuli/issues",
14
+ "license": "MIT",
15
+ "author": "Dailybot, Inc.",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/DailybotHQ/texuli.git",
19
+ "directory": "packages/spec"
20
+ },
21
+ "type": "module",
22
+ "sideEffects": [
23
+ "**/*.css"
24
+ ],
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ },
30
+ "./codegen": {
31
+ "types": "./dist/codegen/index.d.ts",
32
+ "default": "./dist/codegen/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ]
38
+ }