@sha3/code-standards 0.1.1 → 0.1.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.
Files changed (34) hide show
  1. package/README.md +47 -9
  2. package/bin/code-standards.mjs +30 -36
  3. package/package.json +1 -1
  4. package/resources/ai/templates/examples/demo/src/billing/billing-service.ts +102 -0
  5. package/resources/ai/templates/examples/demo/src/invoices/invoice-errors.ts +89 -0
  6. package/resources/ai/templates/examples/demo/src/invoices/invoice-service.ts +123 -0
  7. package/resources/ai/templates/examples/demo/src/invoices/invoice-types.ts +20 -0
  8. package/resources/ai/templates/examples/rules/async-bad.ts +94 -0
  9. package/resources/ai/templates/examples/rules/async-good.ts +94 -0
  10. package/resources/ai/templates/examples/rules/class-first-bad.ts +90 -0
  11. package/resources/ai/templates/examples/rules/class-first-good.ts +99 -0
  12. package/resources/ai/templates/examples/rules/constructor-bad.ts +98 -0
  13. package/resources/ai/templates/examples/rules/constructor-good.ts +97 -0
  14. package/resources/ai/templates/examples/rules/control-flow-bad.ts +85 -0
  15. package/resources/ai/templates/examples/rules/control-flow-good.ts +92 -0
  16. package/resources/ai/templates/examples/rules/errors-bad.ts +86 -0
  17. package/resources/ai/templates/examples/rules/errors-good.ts +89 -0
  18. package/resources/ai/templates/examples/rules/functions-bad.ts +106 -0
  19. package/resources/ai/templates/examples/rules/functions-good.ts +102 -0
  20. package/resources/ai/templates/examples/rules/returns-bad.ts +92 -0
  21. package/resources/ai/templates/examples/rules/returns-good.ts +94 -0
  22. package/resources/ai/templates/examples/rules/testing-bad.ts +88 -0
  23. package/resources/ai/templates/examples/rules/testing-good.ts +92 -0
  24. package/resources/ai/templates/rules/architecture.md +5 -15
  25. package/resources/ai/templates/rules/async.md +2 -12
  26. package/resources/ai/templates/rules/class-first.md +23 -82
  27. package/resources/ai/templates/rules/control-flow.md +2 -8
  28. package/resources/ai/templates/rules/errors.md +2 -11
  29. package/resources/ai/templates/rules/functions.md +2 -15
  30. package/resources/ai/templates/rules/returns.md +2 -22
  31. package/resources/ai/templates/rules/testing.md +2 -14
  32. package/standards/style.md +9 -1
  33. package/templates/node-lib/gitignore +5 -0
  34. package/templates/node-service/gitignore +5 -0
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @section imports:externals
3
+ */
4
+
5
+ // empty
6
+
7
+ /**
8
+ * @section imports:internals
9
+ */
10
+
11
+ // empty
12
+
13
+ /**
14
+ * @section consts
15
+ */
16
+
17
+ // empty
18
+
19
+ /**
20
+ * @section types
21
+ */
22
+
23
+ type SyncInvoicesCommand = { accountId: string };
24
+ type Invoice = { id: string; accountId: string };
25
+ type SyncResult = { saved: number };
26
+ type InvoiceSource = { fetch(accountId: string): Promise<Invoice[]> };
27
+ type InvoiceWriter = { persist(invoices: Invoice[]): Promise<SyncResult> };
28
+
29
+ export class InvoiceSyncService {
30
+ /**
31
+ * @section private:attributes
32
+ */
33
+
34
+ // empty
35
+
36
+ /**
37
+ * @section private:properties
38
+ */
39
+
40
+ private readonly source: InvoiceSource;
41
+ private readonly writer: InvoiceWriter;
42
+
43
+ /**
44
+ * @section public:properties
45
+ */
46
+
47
+ // empty
48
+
49
+ /**
50
+ * @section constructor
51
+ */
52
+
53
+ public constructor(source: InvoiceSource, writer: InvoiceWriter) {
54
+ this.source = source;
55
+ this.writer = writer;
56
+ }
57
+
58
+ /**
59
+ * @section static:properties
60
+ */
61
+
62
+ // empty
63
+
64
+ /**
65
+ * @section factory
66
+ */
67
+
68
+ public static create(source: InvoiceSource, writer: InvoiceWriter): InvoiceSyncService {
69
+ const service = new InvoiceSyncService(source, writer);
70
+ return service;
71
+ }
72
+
73
+ /**
74
+ * @section private:methods
75
+ */
76
+
77
+ // empty
78
+
79
+ /**
80
+ * @section public:methods
81
+ */
82
+
83
+ public execute(command: SyncInvoicesCommand): Promise<SyncResult> {
84
+ return this.source.fetch(command.accountId).then((invoices: Invoice[]) => {
85
+ return this.writer.persist(invoices);
86
+ });
87
+ }
88
+
89
+ /**
90
+ * @section static:methods
91
+ */
92
+
93
+ // empty
94
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @section imports:externals
3
+ */
4
+
5
+ // empty
6
+
7
+ /**
8
+ * @section imports:internals
9
+ */
10
+
11
+ // empty
12
+
13
+ /**
14
+ * @section consts
15
+ */
16
+
17
+ // empty
18
+
19
+ /**
20
+ * @section types
21
+ */
22
+
23
+ type SyncInvoicesCommand = { accountId: string };
24
+ type Invoice = { id: string; accountId: string };
25
+ type SyncResult = { saved: number };
26
+ type InvoiceSource = { fetch(accountId: string): Promise<Invoice[]> };
27
+ type InvoiceWriter = { persist(invoices: Invoice[]): Promise<SyncResult> };
28
+
29
+ export class InvoiceSyncService {
30
+ /**
31
+ * @section private:attributes
32
+ */
33
+
34
+ // empty
35
+
36
+ /**
37
+ * @section private:properties
38
+ */
39
+
40
+ private readonly source: InvoiceSource;
41
+ private readonly writer: InvoiceWriter;
42
+
43
+ /**
44
+ * @section public:properties
45
+ */
46
+
47
+ // empty
48
+
49
+ /**
50
+ * @section constructor
51
+ */
52
+
53
+ public constructor(source: InvoiceSource, writer: InvoiceWriter) {
54
+ this.source = source;
55
+ this.writer = writer;
56
+ }
57
+
58
+ /**
59
+ * @section static:properties
60
+ */
61
+
62
+ // empty
63
+
64
+ /**
65
+ * @section factory
66
+ */
67
+
68
+ public static create(source: InvoiceSource, writer: InvoiceWriter): InvoiceSyncService {
69
+ const service = new InvoiceSyncService(source, writer);
70
+ return service;
71
+ }
72
+
73
+ /**
74
+ * @section private:methods
75
+ */
76
+
77
+ // empty
78
+
79
+ /**
80
+ * @section public:methods
81
+ */
82
+
83
+ public async execute(command: SyncInvoicesCommand): Promise<SyncResult> {
84
+ const invoices: Invoice[] = await this.source.fetch(command.accountId);
85
+ const result: SyncResult = await this.writer.persist(invoices);
86
+ return result;
87
+ }
88
+
89
+ /**
90
+ * @section static:methods
91
+ */
92
+
93
+ // empty
94
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * @section imports:externals
3
+ */
4
+
5
+ // empty
6
+
7
+ /**
8
+ * @section imports:internals
9
+ */
10
+
11
+ // empty
12
+
13
+ /**
14
+ * @section consts
15
+ */
16
+
17
+ // empty
18
+
19
+ /**
20
+ * @section types
21
+ */
22
+
23
+ type CreateInvoiceCommand = { customerId: string; amount: number };
24
+ type Invoice = { id: string; customerId: string; amount: number };
25
+
26
+ export class InvoiceService {
27
+ /**
28
+ * @section private:attributes
29
+ */
30
+
31
+ // empty
32
+
33
+ /**
34
+ * @section private:properties
35
+ */
36
+
37
+ // empty
38
+
39
+ /**
40
+ * @section public:properties
41
+ */
42
+
43
+ // empty
44
+
45
+ /**
46
+ * @section constructor
47
+ */
48
+
49
+ // empty
50
+
51
+ /**
52
+ * @section static:properties
53
+ */
54
+
55
+ // empty
56
+
57
+ /**
58
+ * @section factory
59
+ */
60
+
61
+ public static create(): InvoiceService {
62
+ const service = new InvoiceService();
63
+ return service;
64
+ }
65
+
66
+ /**
67
+ * @section private:methods
68
+ */
69
+
70
+ // empty
71
+
72
+ /**
73
+ * @section public:methods
74
+ */
75
+
76
+ public async create(command: CreateInvoiceCommand): Promise<Invoice> {
77
+ if (!command.customerId) {
78
+ return Promise.reject(new Error("invalid command"));
79
+ }
80
+
81
+ const invoice: Invoice = { id: "1", customerId: command.customerId, amount: command.amount };
82
+ return invoice;
83
+ }
84
+
85
+ /**
86
+ * @section static:methods
87
+ */
88
+
89
+ // empty
90
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * @section imports:externals
3
+ */
4
+
5
+ import { randomUUID } from "node:crypto";
6
+
7
+ /**
8
+ * @section imports:internals
9
+ */
10
+
11
+ // empty
12
+
13
+ /**
14
+ * @section consts
15
+ */
16
+
17
+ const SERVICE_NAME = "invoice-service";
18
+
19
+ /**
20
+ * @section types
21
+ */
22
+
23
+ type CreateInvoiceCommand = { customerId: string; amount: number };
24
+ type Invoice = { id: string; customerId: string; amount: number; createdAt: Date };
25
+
26
+ export class InvoiceService {
27
+ /**
28
+ * @section private:attributes
29
+ */
30
+
31
+ private readonly requestId: string;
32
+
33
+ /**
34
+ * @section private:properties
35
+ */
36
+
37
+ private readonly invoicesById: Map<string, Invoice>;
38
+
39
+ /**
40
+ * @section public:properties
41
+ */
42
+
43
+ public readonly serviceName: string;
44
+
45
+ /**
46
+ * @section constructor
47
+ */
48
+
49
+ public constructor() {
50
+ this.invoicesById = new Map<string, Invoice>();
51
+ this.requestId = randomUUID();
52
+ this.serviceName = SERVICE_NAME;
53
+ }
54
+
55
+ /**
56
+ * @section static:properties
57
+ */
58
+
59
+ // empty
60
+
61
+ /**
62
+ * @section factory
63
+ */
64
+
65
+ public static create(): InvoiceService {
66
+ const service = new InvoiceService();
67
+ return service;
68
+ }
69
+
70
+ /**
71
+ * @section private:methods
72
+ */
73
+
74
+ private toInvoice(command: CreateInvoiceCommand): Invoice {
75
+ const invoice: Invoice = {
76
+ id: randomUUID(),
77
+ customerId: command.customerId,
78
+ amount: command.amount,
79
+ createdAt: new Date()
80
+ };
81
+ return invoice;
82
+ }
83
+
84
+ /**
85
+ * @section public:methods
86
+ */
87
+
88
+ public async create(command: CreateInvoiceCommand): Promise<Invoice> {
89
+ const invoice: Invoice = this.toInvoice(command);
90
+ this.invoicesById.set(invoice.id, invoice);
91
+ return invoice;
92
+ }
93
+
94
+ /**
95
+ * @section static:methods
96
+ */
97
+
98
+ // empty
99
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * @section imports:externals
3
+ */
4
+
5
+ // empty
6
+
7
+ /**
8
+ * @section imports:internals
9
+ */
10
+
11
+ // empty
12
+
13
+ /**
14
+ * @section consts
15
+ */
16
+
17
+ const FALLBACK_PREFIX = "INV";
18
+
19
+ /**
20
+ * @section types
21
+ */
22
+
23
+ type Clock = () => Date;
24
+ type IdFactory = () => string;
25
+
26
+ export class InvoiceIdBuilder {
27
+ /**
28
+ * @section private:attributes
29
+ */
30
+
31
+ // empty
32
+
33
+ /**
34
+ * @section private:properties
35
+ */
36
+
37
+ private readonly clock: Clock;
38
+ private readonly idFactory: IdFactory;
39
+ private readonly prefix: string;
40
+
41
+ /**
42
+ * @section public:properties
43
+ */
44
+
45
+ // empty
46
+
47
+ /**
48
+ * @section constructor
49
+ */
50
+
51
+ public constructor() {
52
+ // Bad: constructor wires concrete dependencies and environment details directly.
53
+ this.clock = () => new Date();
54
+ this.idFactory = () => Math.random().toString(36).slice(2, 8);
55
+ this.prefix = process.env.INVOICE_PREFIX || FALLBACK_PREFIX;
56
+ }
57
+
58
+ /**
59
+ * @section static:properties
60
+ */
61
+
62
+ // empty
63
+
64
+ /**
65
+ * @section factory
66
+ */
67
+
68
+ public static create(): InvoiceIdBuilder {
69
+ const builder = new InvoiceIdBuilder();
70
+ return builder;
71
+ }
72
+
73
+ /**
74
+ * @section private:methods
75
+ */
76
+
77
+ private currentYear(): number {
78
+ const year = this.clock().getUTCFullYear();
79
+ return year;
80
+ }
81
+
82
+ /**
83
+ * @section public:methods
84
+ */
85
+
86
+ public build(): string {
87
+ const rawId = this.idFactory();
88
+ const year = this.currentYear();
89
+ const invoiceId = `${this.prefix}-${year}-${rawId}`;
90
+ return invoiceId;
91
+ }
92
+
93
+ /**
94
+ * @section static:methods
95
+ */
96
+
97
+ // empty
98
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @section imports:externals
3
+ */
4
+
5
+ // empty
6
+
7
+ /**
8
+ * @section imports:internals
9
+ */
10
+
11
+ // empty
12
+
13
+ /**
14
+ * @section consts
15
+ */
16
+
17
+ const DEFAULT_INVOICE_PREFIX = "INV";
18
+
19
+ /**
20
+ * @section types
21
+ */
22
+
23
+ type Clock = () => Date;
24
+ type IdFactory = () => string;
25
+
26
+ export class InvoiceIdBuilder {
27
+ /**
28
+ * @section private:attributes
29
+ */
30
+
31
+ // empty
32
+
33
+ /**
34
+ * @section private:properties
35
+ */
36
+
37
+ private readonly clock: Clock;
38
+ private readonly idFactory: IdFactory;
39
+ private readonly prefix: string;
40
+
41
+ /**
42
+ * @section public:properties
43
+ */
44
+
45
+ // empty
46
+
47
+ /**
48
+ * @section constructor
49
+ */
50
+
51
+ public constructor(clock: Clock, idFactory: IdFactory, prefix = DEFAULT_INVOICE_PREFIX) {
52
+ this.clock = clock;
53
+ this.idFactory = idFactory;
54
+ this.prefix = prefix;
55
+ }
56
+
57
+ /**
58
+ * @section static:properties
59
+ */
60
+
61
+ // empty
62
+
63
+ /**
64
+ * @section factory
65
+ */
66
+
67
+ public static create(clock: Clock, idFactory: IdFactory): InvoiceIdBuilder {
68
+ const builder = new InvoiceIdBuilder(clock, idFactory);
69
+ return builder;
70
+ }
71
+
72
+ /**
73
+ * @section private:methods
74
+ */
75
+
76
+ private currentYear(): number {
77
+ const year = this.clock().getUTCFullYear();
78
+ return year;
79
+ }
80
+
81
+ /**
82
+ * @section public:methods
83
+ */
84
+
85
+ public build(): string {
86
+ const rawId = this.idFactory();
87
+ const year = this.currentYear();
88
+ const invoiceId = `${this.prefix}-${year}-${rawId}`;
89
+ return invoiceId;
90
+ }
91
+
92
+ /**
93
+ * @section static:methods
94
+ */
95
+
96
+ // empty
97
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @section imports:externals
3
+ */
4
+
5
+ // empty
6
+
7
+ /**
8
+ * @section imports:internals
9
+ */
10
+
11
+ // empty
12
+
13
+ /**
14
+ * @section consts
15
+ */
16
+
17
+ // empty
18
+
19
+ /**
20
+ * @section types
21
+ */
22
+
23
+ // empty
24
+
25
+ export class ControlFlowPolicy {
26
+ /**
27
+ * @section private:attributes
28
+ */
29
+
30
+ // empty
31
+
32
+ /**
33
+ * @section private:properties
34
+ */
35
+
36
+ // empty
37
+
38
+ /**
39
+ * @section public:properties
40
+ */
41
+
42
+ // empty
43
+
44
+ /**
45
+ * @section constructor
46
+ */
47
+
48
+ // empty
49
+
50
+ /**
51
+ * @section static:properties
52
+ */
53
+
54
+ // empty
55
+
56
+ /**
57
+ * @section factory
58
+ */
59
+
60
+ public static create(): ControlFlowPolicy {
61
+ const policy = new ControlFlowPolicy();
62
+ return policy;
63
+ }
64
+
65
+ /**
66
+ * @section private:methods
67
+ */
68
+
69
+ // empty
70
+
71
+ /**
72
+ * @section public:methods
73
+ */
74
+
75
+ public badSnippet(): string {
76
+ const snippet = "if (isEnabled) executeTask();";
77
+ return snippet;
78
+ }
79
+
80
+ /**
81
+ * @section static:methods
82
+ */
83
+
84
+ // empty
85
+ }