@formfeed/devkit 0.2.0 → 0.3.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.
@@ -0,0 +1,6 @@
1
+ import { type TemplateTypes } from './model.js';
2
+ /**
3
+ * `formfeed_templates.py`: a TypedDict per template and `typed(client)`, whose `renders.create`
4
+ * overloads check `data` for the known slugs and fall back to the plain signature otherwise.
5
+ */
6
+ export declare function emitPython(templates: TemplateTypes[]): string;
@@ -0,0 +1,10 @@
1
+ import { type TemplateTypes } from './model.cjs';
2
+ export interface TypeScriptOptions {
3
+ /** The module the generated file augments; `@formfeed/sdk` for customers. */
4
+ sdkModule?: string;
5
+ }
6
+ /**
7
+ * `formfeed.d.ts`: one data type per template plus the augmentation of `FormfeedTemplates`, which
8
+ * makes `renders.create({ template: 'invoice', data })` check `data` against `InvoiceData`.
9
+ */
10
+ export declare function emitTypeScript(templates: TemplateTypes[], options?: TypeScriptOptions): string;
@@ -0,0 +1,10 @@
1
+ import { type TemplateTypes } from './model.js';
2
+ export interface TypeScriptOptions {
3
+ /** The module the generated file augments; `@formfeed/sdk` for customers. */
4
+ sdkModule?: string;
5
+ }
6
+ /**
7
+ * `formfeed.d.ts`: one data type per template plus the augmentation of `FormfeedTemplates`, which
8
+ * makes `renders.create({ template: 'invoice', data })` check `data` against `InvoiceData`.
9
+ */
10
+ export declare function emitTypeScript(templates: TemplateTypes[], options?: TypeScriptOptions): string;
@@ -0,0 +1,15 @@
1
+ import type { LocalTemplate } from '../project.cjs';
2
+ import { type TypeScriptOptions } from './emit-ts.cjs';
3
+ import { type TypeSource } from './model.cjs';
4
+ export type TypesLanguage = 'ts' | 'python';
5
+ export declare const defaultTypesFile: Record<TypesLanguage, string>;
6
+ /**
7
+ * The schema of a template folder: `schema.json` when it has one, else inferred over all its data
8
+ * sets (a field only some sets carry is optional), marked as inferred so every field is optional.
9
+ */
10
+ export declare function localTypeSource(tpl: LocalTemplate): TypeSource;
11
+ /** The generated file for `sources` in `language`; the same input always gives the same bytes. */
12
+ export declare function generateTypes(sources: TypeSource[], language: TypesLanguage, options?: TypeScriptOptions): string;
13
+ export { buildTypes, pascalCase, relaxRequired, singular } from './model.cjs';
14
+ export type { SchemaOrigin, TemplateTypes, TypeNode, TypeSource } from './model.cjs';
15
+ export type { TypeScriptOptions } from './emit-ts.cjs';
@@ -0,0 +1,15 @@
1
+ import type { LocalTemplate } from '../project.js';
2
+ import { type TypeScriptOptions } from './emit-ts.js';
3
+ import { type TypeSource } from './model.js';
4
+ export type TypesLanguage = 'ts' | 'python';
5
+ export declare const defaultTypesFile: Record<TypesLanguage, string>;
6
+ /**
7
+ * The schema of a template folder: `schema.json` when it has one, else inferred over all its data
8
+ * sets (a field only some sets carry is optional), marked as inferred so every field is optional.
9
+ */
10
+ export declare function localTypeSource(tpl: LocalTemplate): TypeSource;
11
+ /** The generated file for `sources` in `language`; the same input always gives the same bytes. */
12
+ export declare function generateTypes(sources: TypeSource[], language: TypesLanguage, options?: TypeScriptOptions): string;
13
+ export { buildTypes, pascalCase, relaxRequired, singular } from './model.js';
14
+ export type { SchemaOrigin, TemplateTypes, TypeNode, TypeSource } from './model.js';
15
+ export type { TypeScriptOptions } from './emit-ts.js';
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The language-neutral model `formfeed types` emits from (spec 19 §2.4): each template's data schema
3
+ * becomes a tree of type nodes plus the named objects it refers to, so the TypeScript and Python
4
+ * emitters share one reading of JSON Schema and differ only in spelling.
5
+ */
6
+ export type TypeNode = {
7
+ kind: 'unknown';
8
+ note?: string;
9
+ } | {
10
+ kind: 'never';
11
+ } | {
12
+ kind: 'primitive';
13
+ name: 'string' | 'number' | 'integer' | 'boolean' | 'null';
14
+ } | {
15
+ kind: 'literal';
16
+ value: string | number | boolean | null;
17
+ } | {
18
+ kind: 'array';
19
+ items: TypeNode;
20
+ } | {
21
+ kind: 'record';
22
+ values: TypeNode;
23
+ } | {
24
+ kind: 'ref';
25
+ name: string;
26
+ } | {
27
+ kind: 'union';
28
+ members: TypeNode[];
29
+ } | {
30
+ kind: 'intersection';
31
+ members: TypeNode[];
32
+ };
33
+ export interface Field {
34
+ key: string;
35
+ type: TypeNode;
36
+ required: boolean;
37
+ doc: string[];
38
+ }
39
+ export interface NamedObject {
40
+ name: string;
41
+ doc: string[];
42
+ fields: Field[];
43
+ /** Type of properties the schema does not list, when `additionalProperties` is a schema. */
44
+ extra: TypeNode | null;
45
+ }
46
+ /** Where a template's schema came from; the header of the generated file says it per template. */
47
+ export type SchemaOrigin = 'local' | 'stored' | 'inferred';
48
+ export interface TypeSource {
49
+ slug: string;
50
+ schema: Record<string, unknown>;
51
+ origin: SchemaOrigin;
52
+ /** The version the schema belongs to, for the header. */
53
+ version?: number | null;
54
+ channel?: string | null;
55
+ }
56
+ export interface TemplateTypes {
57
+ slug: string;
58
+ origin: SchemaOrigin;
59
+ version: number | null;
60
+ channel: string | null;
61
+ /** The name the data type is exported under (`InvoiceData`). */
62
+ rootName: string;
63
+ /** The data type; a `ref` to `rootName` when the schema is an object. */
64
+ root: TypeNode;
65
+ /** Named objects in the order they were first met, the root first. */
66
+ objects: NamedObject[];
67
+ }
68
+ export declare function pascalCase(text: string): string;
69
+ /** `items` → `Item`, `addresses` → `Address`, `entries` → `Entry`; null when the word is not a plural. */
70
+ export declare function singular(word: string): string | null;
71
+ /** Names already handed out in one generated file; a clash gets a number. */
72
+ export declare class NameRegistry {
73
+ private readonly used;
74
+ constructor(reserved?: Iterable<string>);
75
+ claim(wanted: string): string;
76
+ }
77
+ /** An inferred schema knows which fields the sample had, not which the template needs: all optional. */
78
+ export declare function relaxRequired(schema: unknown): unknown;
79
+ /** Builds the model for a set of templates; names are unique across the whole file. */
80
+ export declare function buildTypes(sources: TypeSource[], reserved?: Iterable<string>): TemplateTypes[];
81
+ export declare function originNote(t: Pick<TemplateTypes, 'origin' | 'version' | 'channel'>): string;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The language-neutral model `formfeed types` emits from (spec 19 §2.4): each template's data schema
3
+ * becomes a tree of type nodes plus the named objects it refers to, so the TypeScript and Python
4
+ * emitters share one reading of JSON Schema and differ only in spelling.
5
+ */
6
+ export type TypeNode = {
7
+ kind: 'unknown';
8
+ note?: string;
9
+ } | {
10
+ kind: 'never';
11
+ } | {
12
+ kind: 'primitive';
13
+ name: 'string' | 'number' | 'integer' | 'boolean' | 'null';
14
+ } | {
15
+ kind: 'literal';
16
+ value: string | number | boolean | null;
17
+ } | {
18
+ kind: 'array';
19
+ items: TypeNode;
20
+ } | {
21
+ kind: 'record';
22
+ values: TypeNode;
23
+ } | {
24
+ kind: 'ref';
25
+ name: string;
26
+ } | {
27
+ kind: 'union';
28
+ members: TypeNode[];
29
+ } | {
30
+ kind: 'intersection';
31
+ members: TypeNode[];
32
+ };
33
+ export interface Field {
34
+ key: string;
35
+ type: TypeNode;
36
+ required: boolean;
37
+ doc: string[];
38
+ }
39
+ export interface NamedObject {
40
+ name: string;
41
+ doc: string[];
42
+ fields: Field[];
43
+ /** Type of properties the schema does not list, when `additionalProperties` is a schema. */
44
+ extra: TypeNode | null;
45
+ }
46
+ /** Where a template's schema came from; the header of the generated file says it per template. */
47
+ export type SchemaOrigin = 'local' | 'stored' | 'inferred';
48
+ export interface TypeSource {
49
+ slug: string;
50
+ schema: Record<string, unknown>;
51
+ origin: SchemaOrigin;
52
+ /** The version the schema belongs to, for the header. */
53
+ version?: number | null;
54
+ channel?: string | null;
55
+ }
56
+ export interface TemplateTypes {
57
+ slug: string;
58
+ origin: SchemaOrigin;
59
+ version: number | null;
60
+ channel: string | null;
61
+ /** The name the data type is exported under (`InvoiceData`). */
62
+ rootName: string;
63
+ /** The data type; a `ref` to `rootName` when the schema is an object. */
64
+ root: TypeNode;
65
+ /** Named objects in the order they were first met, the root first. */
66
+ objects: NamedObject[];
67
+ }
68
+ export declare function pascalCase(text: string): string;
69
+ /** `items` → `Item`, `addresses` → `Address`, `entries` → `Entry`; null when the word is not a plural. */
70
+ export declare function singular(word: string): string | null;
71
+ /** Names already handed out in one generated file; a clash gets a number. */
72
+ export declare class NameRegistry {
73
+ private readonly used;
74
+ constructor(reserved?: Iterable<string>);
75
+ claim(wanted: string): string;
76
+ }
77
+ /** An inferred schema knows which fields the sample had, not which the template needs: all optional. */
78
+ export declare function relaxRequired(schema: unknown): unknown;
79
+ /** Builds the model for a set of templates; names are unique across the whole file. */
80
+ export declare function buildTypes(sources: TypeSource[], reserved?: Iterable<string>): TemplateTypes[];
81
+ export declare function originNote(t: Pick<TemplateTypes, 'origin' | 'version' | 'channel'>): string;