@powerhousedao/codegen 0.0.3 → 0.0.5

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 (35) hide show
  1. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/actions.esm.t +16 -0
  2. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/creators.esm.t +8 -0
  3. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/customUtils.esm.t +5 -0
  4. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/documentModel.esm.t +7 -0
  5. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/documentModelTest.esm.t +25 -0
  6. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/index.d.ts +3 -2
  7. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/index.esm.t +9 -0
  8. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/index.js +18 -2
  9. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/lib.esm.t +9 -0
  10. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/lib.inject_export.esm.t +7 -0
  11. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/object.esm.t +49 -0
  12. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/reducer.esm.t +35 -0
  13. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/rootIndex.esm.t +44 -0
  14. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/schema.esm.t +6 -0
  15. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/types.esm.t +19 -0
  16. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model/utils.esm.t +43 -0
  17. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model-module/actions.esm.t +22 -0
  18. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model-module/creators.esm.t +34 -0
  19. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model-module/customReducers.esm.t +20 -0
  20. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model-module/customTest.esm.t +38 -0
  21. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model-module/object.esm.t +37 -0
  22. package/dist/codegen/.hygen/templates/powerhouse/generate-document-model-module/operations.esm.t +17 -0
  23. package/dist/codegen/.hygen/templates/powerhouse/generate-editor/editor.esm.t +15 -0
  24. package/dist/codegen/.hygen/templates/powerhouse/generate-editor/index.d.ts +1 -1
  25. package/dist/codegen/.hygen/templates/powerhouse/generate-editor/index.esm.t +16 -0
  26. package/dist/codegen/.hygen/templates/powerhouse/generate-editor/lib.esm.t +9 -0
  27. package/dist/codegen/.hygen/templates/powerhouse/generate-editor/lib.inject_export.esm.t +7 -0
  28. package/dist/codegen/.hygen/templates/powerhouse/generate-editor/story.esm.t +31 -0
  29. package/dist/codegen/hygen.js +7 -4
  30. package/dist/codegen/index.js +4 -2
  31. package/dist/codegen/utils.js +1 -1
  32. package/dist/create-lib/index.js +4 -4
  33. package/dist/utils.d.ts +1 -1
  34. package/dist/utils.js +6 -4
  35. package/package.json +16 -3
@@ -0,0 +1,16 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/actions.ts"
3
+ force: true
4
+ ---
5
+ <% modules.forEach(module => { _%>
6
+ import { <%= h.changeCase.pascal(documentType) %><%= h.changeCase.pascal(module.name) %>Action } from './<%= module.name %>/actions';
7
+ <% }); _%>
8
+
9
+ <% modules.forEach(module => { _%>
10
+ export * from './<%= module.name %>/actions';
11
+ <% }); _%>
12
+
13
+ export type <%= h.changeCase.pascal(documentType) %>Action =
14
+ <% modules.forEach(module => { _%>
15
+ | <%= h.changeCase.pascal(documentType) %><%= h.changeCase.pascal(module.name) %>Action
16
+ <% }); _%>;
@@ -0,0 +1,8 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/creators.ts"
3
+ force: true
4
+ ---
5
+
6
+ <% modules.forEach(module => { _%>
7
+ export * from './<%= module.name %>/creators';
8
+ <% }); _%>
@@ -0,0 +1,5 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/src/utils.ts"
3
+ unless_exists: true
4
+ ---
5
+ export {};
@@ -0,0 +1,7 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/document-model.ts"
3
+ force: true
4
+ ---
5
+ import type { DocumentModelState } from "document-model/document-model";
6
+
7
+ export const documentModel: DocumentModelState = <%- documentModel %>;
@@ -0,0 +1,25 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/src/tests/document-model.test.ts"
3
+ unless_exists: true
4
+ ---
5
+ /**
6
+ * This is a scaffold file meant for customization:
7
+ * - change it by adding new tests or modifying the existing ones
8
+ */
9
+
10
+ import utils, { initialGlobalState, initialLocalState } from '../../gen/utils';
11
+
12
+ describe('<%= h.changeCase.title(documentType) %> Document Model', () => {
13
+ it('should create a new <%= h.changeCase.title(documentType) %> document', () => {
14
+ const document = utils.createDocument();
15
+
16
+ expect(document).toBeDefined();
17
+ expect(document.documentType).toBe('<%- documentTypeId %>');
18
+ });
19
+
20
+ it('should create a new <%= h.changeCase.title(documentType) %> document with a valid initial state', () => {
21
+ const document = utils.createDocument();
22
+ expect(document.state.global).toStrictEqual(initialGlobalState);
23
+ expect(document.state.local).toStrictEqual(initialLocalState);
24
+ });
25
+ });
@@ -6,6 +6,8 @@ declare const _default: {
6
6
  params: ({ args }: {
7
7
  args: Args;
8
8
  }) => {
9
+ initialGlobalState: string;
10
+ initialLocalState: string;
9
11
  rootDir: string;
10
12
  documentModel: string;
11
13
  documentTypeId: string;
@@ -18,9 +20,8 @@ declare const _default: {
18
20
  id: string;
19
21
  operations: import("document-model/document-model").Operation[];
20
22
  }[];
21
- initialGlobalState: string;
22
- initialLocalState: string;
23
23
  fileExtension: string;
24
+ hasLocalSchema: boolean;
24
25
  };
25
26
  };
26
27
  export default _default;
@@ -0,0 +1,9 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/index.ts"
3
+ force: true
4
+ ---
5
+ export * from './actions';
6
+ export * from './document-model';
7
+ export * from './object';
8
+ export * from './types';
9
+ export * as actions from './creators';
@@ -35,9 +35,25 @@ exports.default = {
35
35
  ...m,
36
36
  name: (0, change_case_1.paramCase)(m.name),
37
37
  })),
38
- initialGlobalState: latestSpec.state.global.initialValue,
39
- initialLocalState: latestSpec.state.local.initialValue ?? "{}",
40
38
  fileExtension: documentModel.extension,
39
+ hasLocalSchema: latestSpec.state.local.schema !== '',
40
+ ...getInitialStates(latestSpec.state),
41
41
  };
42
42
  },
43
43
  };
44
+ function getInitialStates(scopeState) {
45
+ const { global, local } = scopeState;
46
+ const scopes = { global, local };
47
+ Object.entries(scopes).forEach(([scope, state]) => {
48
+ if (state.schema !== '' && state.initialValue === '') {
49
+ throw new Error(`${scope.charAt(0).toLocaleUpperCase() + scope.slice(1)} scope has a defined schema but is missing an initial value.`);
50
+ }
51
+ });
52
+ return {
53
+ initialGlobalState: handleEmptyState(global.initialValue),
54
+ initialLocalState: handleEmptyState(local.initialValue),
55
+ };
56
+ }
57
+ function handleEmptyState(state) {
58
+ return state === '' ? '{}' : state;
59
+ }
@@ -0,0 +1,9 @@
1
+ ---
2
+ to: "<%= rootDir %>/index.ts"
3
+ unless_exists: true
4
+ ---
5
+ /**
6
+ * This is a scaffold file meant for customization.
7
+ * Delete the file and run the code generator again to have it reset
8
+ */
9
+
@@ -0,0 +1,7 @@
1
+ ---
2
+ inject: true
3
+ append: true
4
+ to: "<%= rootDir %>/index.ts"
5
+ skip_if: "<%= h.changeCase.pascal(documentType) %>"
6
+ ---
7
+ export { module as <%= h.changeCase.pascal(documentType) %> } from './<%= h.changeCase.param(documentType) %>';
@@ -0,0 +1,49 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/object.ts"
3
+ force: true
4
+ ---
5
+ import { BaseDocument, ExtendedState, PartialState, applyMixins, SignalDispatch } from 'document-model/document';
6
+ import { <%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>LocalState } from './types';
7
+ import { <%= h.changeCase.pascal(documentType) %>Action } from './actions';
8
+ import { reducer } from './reducer';
9
+ import utils from './utils';
10
+ <% modules.forEach(module => { _%>
11
+ import <%= h.changeCase.pascal(documentType) %>_<%= h.changeCase.pascal(module.name) %> from './<%= module.name %>/object';
12
+ <% }); _%>
13
+
14
+ <% modules.forEach(module => { _%>
15
+ export * from './<%= module.name %>/object';
16
+ <% }); _%>
17
+
18
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
19
+ interface <%= h.changeCase.pascal(documentType) %> extends
20
+ <%= modules.map(m => ' ' + h.changeCase.pascal(documentType) + '_' + h.changeCase.pascal(m.name)).join(',\n') %> {}
21
+
22
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
23
+ class <%= h.changeCase.pascal(documentType) %> extends BaseDocument<<%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>Action, <%= h.changeCase.pascal(documentType) %>LocalState> {
24
+ static fileExtension = '<%= extension %>';
25
+
26
+ constructor(initialState?: Partial<ExtendedState<PartialState<<%= h.changeCase.pascal(documentType) %>State>, PartialState<<%= h.changeCase.pascal(documentType) %>LocalState>>>, dispatch?: SignalDispatch) {
27
+ super(reducer, utils.createDocument(initialState), dispatch);
28
+ }
29
+
30
+ public saveToFile(path: string, name?: string) {
31
+ return super.saveToFile(path, <%= h.changeCase.pascal(documentType) %>.fileExtension, name);
32
+ }
33
+
34
+ public loadFromFile(path: string) {
35
+ return super.loadFromFile(path);
36
+ }
37
+
38
+ static async fromFile(path: string) {
39
+ const document = new this();
40
+ await document.loadFromFile(path);
41
+ return document;
42
+ }
43
+ }
44
+
45
+ applyMixins(<%= h.changeCase.pascal(documentType) %>, [
46
+ <%= modules.map(m => ' ' + h.changeCase.pascal(documentType) + '_' + h.changeCase.pascal(m.name)).join(',\n') %>
47
+ ]);
48
+
49
+ export { <%= h.changeCase.pascal(documentType) %> };
@@ -0,0 +1,35 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/reducer.ts"
3
+ force: true
4
+ ---
5
+ import { ImmutableStateReducer, utils } from "document-model/document";
6
+ import { <%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>LocalState, z } from './schema';
7
+ import { <%= h.changeCase.pascal(documentType) %>Action } from './actions';
8
+
9
+ <% modules.forEach(m => { _%>
10
+ import { reducer as <%= h.changeCase.pascal(m.name) %>Reducer } from '../src/reducers/<%= h.changeCase.param(m.name) %>';
11
+ <%_ }); %>
12
+
13
+ const stateReducer: ImmutableStateReducer<<%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>Action, <%= h.changeCase.pascal(documentType) %>LocalState> =
14
+ (state, action, dispatch) => {
15
+ if (utils.isBaseAction(action)) {
16
+ return state;
17
+ }
18
+
19
+ switch (action.type) {
20
+ <%-
21
+ modules.map(m => m.operations.map(o =>
22
+ ' case "' + h.changeCase.constant(o.name) + '":\n' +
23
+ ' ' + (o.schema !== null ?
24
+ 'z.' + h.changeCase.pascalCase(o.name) + 'InputSchema().parse(action.input);\n' :
25
+ 'if (Object.keys(action.input).length > 0) throw new Error("Expected empty input for action ' + h.changeCase.constant(o.name) + '");\n') +
26
+ ' ' + h.changeCase.pascal(m.name) + 'Reducer.' + h.changeCase.camel(o.name) + 'Operation(state[action.scope], action, dispatch);\n' +
27
+ ' break;\n'
28
+ ).join('\n')).join('\n')
29
+ %>
30
+ default:
31
+ return state;
32
+ }
33
+ }
34
+
35
+ export const reducer = utils.createReducer<<%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>Action, <%= h.changeCase.pascal(documentType) %>LocalState>(stateReducer);
@@ -0,0 +1,44 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/index.ts"
3
+ force: true
4
+ ---
5
+ /**
6
+ * This is a scaffold file meant for customization.
7
+ * Delete the file and run the code generator again to have it reset
8
+ */
9
+
10
+ import { actions as BaseActions, DocumentModel } from 'document-model/document';
11
+ import { actions as <%= h.changeCase.pascal(documentType) %>Actions, <%= h.changeCase.pascal(documentType) %> } from './gen';
12
+ import { reducer } from './gen/reducer';
13
+ import { documentModel } from './gen/document-model';
14
+ import genUtils from './gen/utils';
15
+ import * as customUtils from './src/utils';
16
+ import { <%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>Action } from './gen/types';
17
+
18
+ const Document = <%= h.changeCase.pascal(documentType) %>;
19
+ const utils = { ...genUtils, ...customUtils };
20
+ const actions = { ...BaseActions, ...<%= h.changeCase.pascal(documentType) %>Actions };
21
+
22
+ export const module: DocumentModel<
23
+ <%= h.changeCase.pascal(documentType) %>State,
24
+ <%= h.changeCase.pascal(documentType) %>Action,
25
+ <%= h.changeCase.pascal(documentType) %>
26
+ > = {
27
+ Document,
28
+ reducer,
29
+ actions,
30
+ utils,
31
+ documentModel
32
+ };
33
+
34
+ export {
35
+ <%= h.changeCase.pascal(documentType) %>,
36
+ Document,
37
+ reducer,
38
+ actions,
39
+ utils,
40
+ documentModel
41
+ }
42
+
43
+ export * from './gen/types';
44
+ export * from './src/utils';
@@ -0,0 +1,6 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/schema/index.ts"
3
+ force: true
4
+ ---
5
+ export * from "./types";
6
+ export * as z from "./zod";
@@ -0,0 +1,19 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/types.ts"
3
+ force: true
4
+ ---
5
+ import type { Document, ExtendedState } from 'document-model/document';
6
+ import type { <%= h.changeCase.pascal(documentType) %>State } from './schema/types';
7
+ <% if(hasLocalSchema) { -%>
8
+ import type { <%= h.changeCase.pascal(documentType) %>LocalState } from './schema/types';
9
+ <%} -%>
10
+ import type { <%= h.changeCase.pascal(documentType) %>Action } from './actions';
11
+
12
+ export { z } from './schema';
13
+ export type * from './schema/types';
14
+ <% if(!hasLocalSchema) { -%>
15
+ type <%= h.changeCase.pascal(documentType) %>LocalState = Record<PropertyKey, never>;
16
+ <%} -%>
17
+ export type Extended<%= h.changeCase.pascal(documentType) %>State = ExtendedState<<%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>LocalState>;
18
+ export type <%= h.changeCase.pascal(documentType) %>Document = Document<<%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>Action, <%= h.changeCase.pascal(documentType) %>LocalState>;
19
+ export { <%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>LocalState, <%= h.changeCase.pascal(documentType) %>Action };
@@ -0,0 +1,43 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/utils.ts"
3
+ force: true
4
+ ---
5
+ import { DocumentModelUtils, utils as base } from 'document-model/document';
6
+ import { <%= h.changeCase.pascal(documentType) %>Action, <%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>LocalState } from './types';
7
+ import { reducer } from './reducer';
8
+
9
+ export const initialGlobalState: <%= h.changeCase.pascal(documentType) %>State = <%- initialGlobalState %>;
10
+ export const initialLocalState: <%= h.changeCase.pascal(documentType) %>LocalState = <%- initialLocalState %>;
11
+
12
+ const utils: DocumentModelUtils<<%= h.changeCase.pascal(documentType) %>State, <%= h.changeCase.pascal(documentType) %>Action, <%= h.changeCase.pascal(documentType) %>LocalState> = {
13
+ fileExtension: '<%- fileExtension %>',
14
+ createState(state) {
15
+ return { global: { ...initialGlobalState, ...state?.global }, local: { ...initialLocalState, ...state?.local } };
16
+ },
17
+ createExtendedState(extendedState) {
18
+ return base.createExtendedState(
19
+ { ...extendedState, documentType: '<%- documentTypeId %>' },
20
+ utils.createState
21
+ );
22
+ },
23
+ createDocument(state) {
24
+ return base.createDocument(
25
+ utils.createExtendedState(state),
26
+ utils.createState
27
+ );
28
+ },
29
+ saveToFile(document, path, name) {
30
+ return base.saveToFile(document, path, '<%- fileExtension %>', name);
31
+ },
32
+ saveToFileHandle(document, input) {
33
+ return base.saveToFileHandle(document, input);
34
+ },
35
+ loadFromFile(path) {
36
+ return base.loadFromFile(path, reducer);
37
+ },
38
+ loadFromInput(input) {
39
+ return base.loadFromInput(input, reducer);
40
+ },
41
+ };
42
+
43
+ export default utils;
@@ -0,0 +1,22 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/<%= module %>/actions.ts"
3
+ force: true
4
+ ---
5
+ import { Action<% if (actions.find(a => a.hasAttachment)) {%>, ActionWithAttachment<%}%> } from 'document-model/document';
6
+ import {
7
+ <% actions.filter(a => a.hasInput).forEach(action => { _%>
8
+ <%= h.changeCase.pascal(action.name) %>Input,
9
+ <% }); _%>
10
+ } from '../types';
11
+
12
+ <% actions.filter(a => a.hasInput).forEach(actionType => { _%>
13
+ export type <%= h.changeCase.pascal(actionType.name) %>Action = Action<%if(actionType.hasAttachment){ %>WithAttachment<% } %><'<%= h.changeCase.constantCase(actionType.name) %>', <%= h.changeCase.pascal(actionType.name) %>Input, '<%= actionType.scope %>'>;
14
+ <% }); _%>
15
+ <% actions.filter(a => !a.hasInput).forEach(actionType => { _%>
16
+ export type <%= h.changeCase.pascal(actionType.name) %>Action = Action<'<%= h.changeCase.constantCase(actionType.name) %>', never, '<%= actionType.scope %>'>;
17
+ <% }); _%>
18
+
19
+ export type <%= h.changeCase.pascal(documentType) %><%= h.changeCase.pascal(module) %>Action =
20
+ <% actions.forEach(actionType => { _%>
21
+ | <%= h.changeCase.pascal(actionType.name) %>Action
22
+ <% }); _%>;
@@ -0,0 +1,34 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/<%= module %>/creators.ts"
3
+ force: true
4
+ ---
5
+ import { utils<% if (actions.find(a => a.hasAttachment)) {%>, AttachmentInput<%}%> } from 'document-model/document';
6
+ import { z,
7
+ <% actions.filter(a => a.hasInput).forEach(action => { _%>
8
+ <%= h.changeCase.pascal(action.name) %>Input,
9
+ <% }); _%>
10
+ } from '../types';
11
+ import {
12
+ <% actions.forEach(action => { _%>
13
+ <%= h.changeCase.pascal(action.name) %>Action,
14
+ <% }); _%>
15
+ } from './actions';
16
+
17
+ const { createAction } = utils;
18
+
19
+ <% actions.filter(a => a.hasInput).forEach(action => { _%>
20
+ export const <%= h.changeCase.camel(action.name) %> = (input: <%= h.changeCase.pascal(action.name) %>Input<%if(action.hasAttachment){ %>, attachments: AttachmentInput[] <% } %>) =>
21
+ createAction<<%= h.changeCase.pascal(action.name) %>Action>(
22
+ '<%= h.changeCase.constantCase(action.name) %>',
23
+ {...input},
24
+ <%if(action.hasAttachment){ %>attachments<% } else { %>undefined<% } %>,
25
+ z.<%= h.changeCase.pascalCase(action.name) %>InputSchema,
26
+ '<%= action.scope %>'
27
+ );
28
+
29
+ <% }); _%>
30
+
31
+ <% actions.filter(a => !a.hasInput).forEach(action => { _%>
32
+ export const <%= h.changeCase.camel(action.name) %> = () =>
33
+ createAction<<%= h.changeCase.pascal(action.name) %>Action>('<%= h.changeCase.constantCase(action.name) %>');
34
+ <% }); _%>
@@ -0,0 +1,20 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/src/reducers/<%= module %>.ts"
3
+ unless_exists: true
4
+ ---
5
+ /**
6
+ * This is a scaffold file meant for customization:
7
+ * - modify it by implementing the reducer functions
8
+ * - delete the file and run the code generator again to have it reset
9
+ */
10
+
11
+ import { <%= h.changeCase.pascal(documentType) %><%= h.changeCase.pascal(module) %>Operations } from '../../gen/<%= module %>/operations';
12
+
13
+ export const reducer: <%= h.changeCase.pascal(documentType) %><%= h.changeCase.pascal(module) %>Operations = {
14
+ <% actions.forEach(action => { _%>
15
+ <%= h.changeCase.camel(action.name) %>Operation(state, action, dispatch) {
16
+ // TODO: Implement "<%= h.changeCase.camel(action.name) %>Operation" reducer
17
+ throw new Error('Reducer "<%= h.changeCase.camel(action.name) %>Operation" not yet implemented');
18
+ },
19
+ <% }); _%>
20
+ }
@@ -0,0 +1,38 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/src/tests/<%= module %>.test.ts"
3
+ unless_exists: true
4
+ ---
5
+ /**
6
+ * This is a scaffold file meant for customization:
7
+ * - change it by adding new tests or modifying the existing ones
8
+ */
9
+
10
+ import { generateMock } from '@acaldas/powerhouse';
11
+
12
+ import utils from '../../gen/utils';
13
+ import { z } from '../../gen/schema';
14
+ import { reducer } from '../../gen/reducer';
15
+ import * as creators from '../../gen/<%= module %>/creators';
16
+ import { <%= h.changeCase.pascal(documentType) %>Document } from '../../gen/types';
17
+
18
+
19
+ describe('<%= h.changeCase.pascal(module) %> Operations', () => {
20
+ let document: <%= h.changeCase.pascal(documentType) %>Document;
21
+
22
+ beforeEach(() => {
23
+ document = utils.createDocument();
24
+ });
25
+
26
+ <% actions.forEach(action => { _%>
27
+ it('should handle <%= h.changeCase.camel(action.name) %> operation', () => {
28
+ const input = generateMock(z.<%= h.changeCase.pascal(action.name) %>InputSchema());
29
+ const updatedDocument = reducer(document, creators.<%= h.changeCase.camel(action.name) %>(input));
30
+
31
+ expect(updatedDocument.operations.<%= action.scope %>).toHaveLength(1);
32
+ expect(updatedDocument.operations.<%= action.scope %>[0].type).toBe('<%= h.changeCase.constant(action.name) %>');
33
+ expect(updatedDocument.operations.<%= action.scope %>[0].input).toStrictEqual(input);
34
+ expect(updatedDocument.operations.<%= action.scope %>[0].index).toEqual(0);
35
+ });
36
+
37
+ <% }); _%>
38
+ });
@@ -0,0 +1,37 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/<%= module %>/object.ts"
3
+ force: true
4
+ ---
5
+ import { BaseDocument<% if (actions.find(a => a.hasAttachment)) {%>, AttachmentInput<%}%> } from 'document-model/document';
6
+ import {
7
+ <% actions.filter(action => action.hasInput).forEach(action => { _%>
8
+ <%= h.changeCase.pascal(action.name) %>Input,
9
+ <% }); _%>
10
+ <%= h.changeCase.pascal(documentType) %>State,
11
+ <%= h.changeCase.pascal(documentType) %>LocalState
12
+ } from '../types';
13
+ import {
14
+ <% actions.forEach(action => { _%>
15
+ <%= h.changeCase.camel(action.name) %>,
16
+ <% }); _%>
17
+ } from './creators';
18
+ import { <%= h.changeCase.pascal(documentType) %>Action } from '../actions';
19
+
20
+ export default class <%= h.changeCase.pascal(documentType) %>_<%= h.changeCase.pascal(module) %> extends BaseDocument<
21
+ <%= h.changeCase.pascal(documentType) %>State,
22
+ <%= h.changeCase.pascal(documentType) %>Action,
23
+ <%= h.changeCase.pascal(documentType) %>LocalState
24
+ > {
25
+ <% actions.filter(action => action.hasInput).forEach(action => { _%>
26
+ public <%= h.changeCase.camel(action.name) %>(input: <%= h.changeCase.pascal(action.name) %>Input<%if(action.hasAttachment){ %>, attachments: AttachmentInput[] <% } %>) {
27
+ return this.dispatch(<%= h.changeCase.camel(action.name) %>(input<%if(action.hasAttachment){ %>, attachments<% } %>));
28
+ }
29
+
30
+ <% }); _%>
31
+ <% actions.filter(action => !action.hasInput).forEach(action => { _%>
32
+ public <%= h.changeCase.camel(action.name) %>() {
33
+ return this.dispatch(<%= h.changeCase.camel(action.name) %>());
34
+ }
35
+
36
+ <% }); _%>
37
+ }
@@ -0,0 +1,17 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= h.changeCase.param(documentType) %>/gen/<%= module %>/operations.ts"
3
+ force: true
4
+ ---
5
+ import { SignalDispatch } from 'document-model/document';
6
+ import {
7
+ <% actions.forEach(action => { _%>
8
+ <%= h.changeCase.pascal(action.name) %>Action,
9
+ <% }); _%>
10
+ } from './actions';
11
+ import { <%= actions.map(action => h.changeCase.pascal(h.changeCase.pascal(documentType + '_' + action.state + '_State'))).filter((value, index, self) => self.indexOf(value) === index).join(', ') %> } from '../types';
12
+
13
+ export interface <%= h.changeCase.pascal(documentType) %><%= h.changeCase.pascal(module) %>Operations {
14
+ <% actions.forEach(action => { _%>
15
+ <%= h.changeCase.camel(action.name) %>Operation: (state: <%= h.changeCase.pascal(documentType + '_' + action.state + '_State') %>, action: <%= h.changeCase.pascal(action.name) %>Action, dispatch?: SignalDispatch) => void,
16
+ <% }); _%>
17
+ }
@@ -0,0 +1,15 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= name %>/editor.tsx"
3
+ unless_exists: true
4
+ ---
5
+ <% if(!documentTypes.length){ %>import { Action } from 'document-model/document';<% } %>
6
+ import { EditorProps } from 'document-model-editors';
7
+ <% documentTypes.forEach(type => { _%>
8
+ import { <%= documentTypesMap[type] %>State, <%= documentTypesMap[type] %>Action } from "../.<%= documentModelsDir %>/<%= h.changeCase.param(documentTypesMap[type]) %>";
9
+ %><% }); _%>
10
+
11
+ export type IProps = <% if(!documentTypes.length){ %>EditorProps<unknown, Action><% } else { %><% documentTypes.forEach((type, index) => { _%>EditorProps<<%= documentTypesMap[type] %>State, <%= documentTypesMap[type] %>Action%>%>><% if(index < documentTypes.length - 1){ %> | <% }%><% }); _%> <% } %>;
12
+
13
+ export default function Editor(props: IProps) {
14
+ return <></>;
15
+ };
@@ -13,7 +13,7 @@ declare const _default: {
13
13
  documentModelsDir: string;
14
14
  name: string;
15
15
  documentTypes: string[];
16
- documentTypesMap: any;
16
+ documentTypesMap: unknown;
17
17
  };
18
18
  };
19
19
  export default _default;
@@ -0,0 +1,16 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= name %>/index.ts"
3
+ force: true
4
+ ---
5
+ import { type Editor as EditorModule<% if(!documentTypes.length){ %>, Action<% } %> } from 'document-model/document';
6
+ import Editor from './editor';
7
+ <% documentTypes.forEach(type => { _%>
8
+ import { <%= documentTypesMap[type] %>State, <%= documentTypesMap[type] %>Action } from "../.<%= documentModelsDir %>/<%= h.changeCase.param(documentTypesMap[type]) %>";
9
+ %><% }); _%>
10
+
11
+ export const module: <% if(!documentTypes.length){ %>EditorModule<unknown, Action><% } else { %><% documentTypes.forEach((type, index) => { _%>EditorModule<<%= documentTypesMap[type] %>State, <%= documentTypesMap[type] %>Action%>%>> <% if(index < documentTypes.length - 1){ %>| <% }%><% }); _%> <% } %>= {
12
+ Component: Editor,
13
+ documentTypes: [<% if(!documentTypes.length){ %>'*'<% } else { %><% documentTypes.forEach(type => { _%>"<%= type %>", %><% }); _%> <% } %>],
14
+ };
15
+
16
+ export default module;
@@ -0,0 +1,9 @@
1
+ ---
2
+ to: "<%= rootDir %>/index.ts"
3
+ unless_exists: true
4
+ ---
5
+ /**
6
+ * This is a scaffold file meant for customization.
7
+ * Delete the file and run the code generator again to have it reset
8
+ */
9
+
@@ -0,0 +1,7 @@
1
+ ---
2
+ inject: true
3
+ append: true
4
+ to: "<%= rootDir %>/index.ts"
5
+ skip_if: "<%= h.changeCase.pascal(name) %>"
6
+ ---
7
+ export { module as <%= h.changeCase.pascal(name) %> } from './<%= h.changeCase.param(name) %>';
@@ -0,0 +1,31 @@
1
+ ---
2
+ to: "<%= rootDir %>/<%= name %>/<%= name %>.stories.tsx"
3
+ unless_exists: true
4
+ ---
5
+ import Editor from './editor';
6
+ import { createDocumentStory } from 'document-model-editors';
7
+ <% if(!documentTypes.length){ %>import { baseReducer, utils } from 'document-model/document';<% } %>
8
+ <% documentTypes.forEach(type => { _%>
9
+ import * as <%= documentTypesMap[type] %>Module from "../.<%= documentModelsDir %>/<%= h.changeCase.param(documentTypesMap[type]) %>";
10
+ %><% }); _%>
11
+
12
+ <% if(!documentTypes.length){ %>
13
+ const { meta, CreateDocumentStory: <%= h.changeCase.pascal(name) %> } = createDocumentStory(
14
+ Editor,
15
+ (...args) => baseReducer(...args, document => document),
16
+ utils.createExtendedState(),
17
+ );
18
+ export { <%= h.changeCase.pascal(name) %> };
19
+ <% } %>
20
+
21
+ <% documentTypes.forEach((type, index) => { _%>
22
+ const { <% if(index === 0){ %>meta, <% } %>CreateDocumentStory: <%= documentTypesMap[type] %> } = createDocumentStory(
23
+ Editor,
24
+ <%= documentTypesMap[type] %>Module.reducer,
25
+ <%= documentTypesMap[type] %>Module.utils.createDocument(),
26
+ );
27
+ export { <%= documentTypesMap[type] %> }
28
+
29
+ %><% }); _%>
30
+
31
+ export default { ...meta, title: '<%= h.changeCase.title(name) %>' };
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generateEditor = exports.generateDocumentModel = exports.generateAll = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
7
8
  const hygen_1 = require("hygen");
8
9
  const path_1 = __importDefault(require("path"));
9
- const fs_1 = __importDefault(require("fs"));
10
10
  const utils_1 = require("./utils");
11
11
  const logger = new hygen_1.Logger(console.log.bind(console));
12
12
  const defaultTemplates = path_1.default.join(__dirname, '.hygen', 'templates');
@@ -16,10 +16,12 @@ async function run(args, { watch = false, format = false } = {}) {
16
16
  cwd: process.cwd(),
17
17
  logger,
18
18
  createPrompter: () => {
19
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
19
20
  return require('enquirer');
20
21
  },
21
22
  exec: (action, body) => {
22
23
  const opts = body && body.length > 0 ? { input: body } : {};
24
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access
23
25
  return require('execa').shell(action, opts);
24
26
  },
25
27
  debug: !!process.env.DEBUG,
@@ -27,8 +29,10 @@ async function run(args, { watch = false, format = false } = {}) {
27
29
  if (format) {
28
30
  const execa = await import('execa');
29
31
  result.actions
32
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
30
33
  .filter(action => ['added', 'inject'].includes(action.status))
31
34
  .forEach(action => {
35
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
32
36
  execa.$ `prettier --ignore-path --write ${action.subject.replace('.', process.cwd())}`;
33
37
  });
34
38
  }
@@ -63,8 +67,7 @@ async function generateDocumentModel(documentModel, dir, { watch = false, format
63
67
  ], { watch, format });
64
68
  // Generate the module-specific files for the document model logic
65
69
  const latestSpec = documentModel.specifications[documentModel.specifications.length - 1];
66
- const modules = latestSpec.modules.map(m => m.name);
67
- for (let i = 0; i < modules.length; i++) {
70
+ for (const module of latestSpec.modules) {
68
71
  await run([
69
72
  'powerhouse',
70
73
  'generate-document-model-module',
@@ -73,7 +76,7 @@ async function generateDocumentModel(documentModel, dir, { watch = false, format
73
76
  '--root-dir',
74
77
  dir,
75
78
  '--module',
76
- modules[i],
79
+ module.name,
77
80
  ], { watch, format });
78
81
  }
79
82
  }
@@ -48,7 +48,9 @@ function getDocumentTypesMap(dir) {
48
48
  documentTypesMap[spec.id] = (0, change_case_1.pascalCase)(name);
49
49
  }
50
50
  }
51
- catch { }
51
+ catch {
52
+ console.error(`Failed to parse ${specPath}`);
53
+ }
52
54
  });
53
55
  return documentTypesMap;
54
56
  }
@@ -77,7 +79,7 @@ exports.generateFromFile = generateFromFile;
77
79
  async function generateEditor(name, documentTypes, config) {
78
80
  const { documentModelsDir, format } = config;
79
81
  const docummentTypesMap = getDocumentTypesMap(documentModelsDir);
80
- let invalidType = documentTypes.find(type => !Object.keys(docummentTypesMap).includes(type));
82
+ const invalidType = documentTypes.find(type => !Object.keys(docummentTypesMap).includes(type));
81
83
  if (invalidType) {
82
84
  throw new Error(`Document model for ${invalidType} not found`);
83
85
  }
@@ -28,7 +28,7 @@ async function loadDocumentModel(path) {
28
28
  return documentModel;
29
29
  }
30
30
  catch (error) {
31
- // @ts-ignore
31
+ // @ts-expect-error
32
32
  throw error.code === 'MODULE_NOT_FOUND'
33
33
  ? new Error(`Document model not found.`)
34
34
  : error;
@@ -4,16 +4,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ const child_process_1 = require("child_process");
8
+ const enquirer_1 = require("enquirer");
9
+ const fs_1 = __importDefault(require("fs"));
7
10
  const path_1 = __importDefault(require("path"));
8
11
  const util_1 = __importDefault(require("util"));
9
- const fs_1 = __importDefault(require("fs"));
10
- const child_process_1 = require("child_process");
11
12
  const utils_1 = require("../utils");
12
- const enquirer_1 = require("enquirer");
13
13
  const exec = util_1.default.promisify(child_process_1.exec);
14
14
  const BOILERPLATE_REPO = 'https://github.com/powerhouse-inc/document-model-boilerplate.git';
15
15
  function isUsingYarn() {
16
- return (process.env.npm_config_user_agent || '').indexOf('yarn') === 0;
16
+ return (process.env.npm_config_user_agent || '').startsWith('yarn');
17
17
  }
18
18
  function buildPackageJson(appPath, projectName) {
19
19
  const packageJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(appPath, 'package.json'), 'utf-8'));
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import arg from 'arg';
2
1
  import { generateMock as zodGenerateMock } from '@anatine/zod-mock';
2
+ import arg from 'arg';
3
3
  export type PowerhouseConfig = {
4
4
  documentModelsDir: string;
5
5
  editorsDir: string;
package/dist/utils.js CHANGED
@@ -4,10 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generateMock = exports.promptDirectories = exports.parseConfig = exports.parseArgs = exports.writeConfig = exports.getConfig = exports.configSpec = exports.DEFAULT_CONFIG = void 0;
7
- const enquirer_1 = require("enquirer");
7
+ const zod_mock_1 = require("@anatine/zod-mock");
8
8
  const arg_1 = __importDefault(require("arg"));
9
+ const enquirer_1 = require("enquirer");
9
10
  const node_fs_1 = require("node:fs");
10
- const zod_mock_1 = require("@anatine/zod-mock");
11
11
  const DEFAULT_DOCUMENT_MODELS_DIR = './document-models';
12
12
  const DEFAULT_EDITORS_DIR = './editors';
13
13
  exports.DEFAULT_CONFIG = {
@@ -28,10 +28,12 @@ function getConfig() {
28
28
  let config = { ...exports.DEFAULT_CONFIG };
29
29
  try {
30
30
  const configStr = (0, node_fs_1.readFileSync)('./powerhouse.config.json', 'utf-8');
31
- let userConfig = JSON.parse(configStr);
31
+ const userConfig = JSON.parse(configStr);
32
32
  config = { ...config, ...userConfig };
33
33
  }
34
- catch { }
34
+ catch {
35
+ console.warn('No powerhouse.config.json found, using defaults');
36
+ }
35
37
  return config;
36
38
  }
37
39
  exports.getConfig = getConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/codegen",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "license": "AGPL-3.0-only",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
@@ -18,7 +18,10 @@
18
18
  "build": "yarn clean && tsc && yarn copy-files",
19
19
  "build:create-lib": "tsc --project src/create-lib/tsconfig.json",
20
20
  "publish:create-lib": "yarn publish --cwd ./src/create-lib/",
21
- "start": "ts-node src/cli.ts"
21
+ "start": "ts-node src/cli.ts",
22
+ "check-types": "tsc --noEmit",
23
+ "lint": "eslint . && yarn check-types",
24
+ "lint:fix": "eslint . --fix"
22
25
  },
23
26
  "dependencies": {
24
27
  "@acaldas/graphql-codegen-typescript-validation-schema": "^0.12.3",
@@ -36,9 +39,19 @@
36
39
  "typescript": "^5.3.3"
37
40
  },
38
41
  "devDependencies": {
42
+ "@commitlint/cli": "^18.4.4",
43
+ "@commitlint/config-conventional": "^18.4.4",
44
+ "@total-typescript/ts-reset": "^0.5.1",
45
+ "@typescript-eslint/eslint-plugin": "^6.19.0",
46
+ "@typescript-eslint/parser": "^6.19.0",
39
47
  "copyfiles": "^2.4.1",
48
+ "eslint": "^8.56.0",
49
+ "eslint-config-prettier": "^9.1.0",
50
+ "eslint-plugin-prettier": "^5.1.3",
40
51
  "graphql": "^16.8.1",
41
- "prettier": "^3.2.2",
52
+ "husky": "^8.0.3",
53
+ "lint-staged": "^15.2.0",
54
+ "prettier": "^3.2.4",
42
55
  "prettier-plugin-organize-imports": "^3.2.4",
43
56
  "rimraf": "^5.0.5",
44
57
  "ts-node": "^10.9.2"