├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── backend
└── README.md
├── development-workflow
├── README.md
├── definition-of-done-per-phase.md
├── details
│ └── story.md
├── development-workflow.md
├── local-development-config-with-vault.md
└── local-development-using-telepresence.md
├── frontend
├── README.md
└── docs
│ ├── environment.md
│ ├── react.md
│ ├── starter-kits.md
│ └── tooling.md
├── general
├── README.md
├── anatomy_of_an_application.png
├── code-review-guidelines.md
├── details
│ ├── README.md
│ └── naming-cheatsheet
│ │ ├── LICENSE.md
│ │ └── README.md
├── languages
│ ├── README.md
│ └── typescript.md
└── production-level-code.md
└── templates
├── pull-request.md
├── readme-example.md
└── rfc.md
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | indent_style = space
7 | indent_size = 2
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.py]
13 | indent_style = space
14 | indent_size = 4
15 |
16 | [*.rb]
17 | indent_style = space
18 | indent_size = 4
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # =========================
2 | # Operating System Files
3 | # =========================
4 |
5 | # OSX
6 | # =========================
7 |
8 | .DS_Store
9 | .AppleDouble
10 | .LSOverride
11 |
12 | # Thumbnails
13 | ._*
14 |
15 | # Files that might appear on external disk
16 | .Spotlight-V100
17 | .Trashes
18 |
19 | # Directories potentially created on remote AFP share
20 | .AppleDB
21 | .AppleDesktop
22 | Network Trash Folder
23 | Temporary Items
24 | .apdisk
25 |
26 | # Windows
27 | # =========================
28 |
29 | # Windows image file caches
30 | Thumbs.db
31 | ehthumbs.db
32 |
33 | # Folder config file
34 | Desktop.ini
35 |
36 | # Recycle Bin used on file shares
37 | $RECYCLE.BIN/
38 |
39 | # Windows Installer files
40 | *.cab
41 | *.msi
42 | *.msm
43 | *.msp
44 |
45 | # Windows shortcuts
46 | *.lnk
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Attribution-NonCommercial-ShareAlike 4.0 International
2 |
3 | =======================================================================
4 |
5 | Creative Commons Corporation ("Creative Commons") is not a law firm and
6 | does not provide legal services or legal advice. Distribution of
7 | Creative Commons public licenses does not create a lawyer-client or
8 | other relationship. Creative Commons makes its licenses and related
9 | information available on an "as-is" basis. Creative Commons gives no
10 | warranties regarding its licenses, any material licensed under their
11 | terms and conditions, or any related information. Creative Commons
12 | disclaims all liability for damages resulting from their use to the
13 | fullest extent possible.
14 |
15 | Using Creative Commons Public Licenses
16 |
17 | Creative Commons public licenses provide a standard set of terms and
18 | conditions that creators and other rights holders may use to share
19 | original works of authorship and other material subject to copyright
20 | and certain other rights specified in the public license below. The
21 | following considerations are for informational purposes only, are not
22 | exhaustive, and do not form part of our licenses.
23 |
24 | Considerations for licensors: Our public licenses are
25 | intended for use by those authorized to give the public
26 | permission to use material in ways otherwise restricted by
27 | copyright and certain other rights. Our licenses are
28 | irrevocable. Licensors should read and understand the terms
29 | and conditions of the license they choose before applying it.
30 | Licensors should also secure all rights necessary before
31 | applying our licenses so that the public can reuse the
32 | material as expected. Licensors should clearly mark any
33 | material not subject to the license. This includes other CC-
34 | licensed material, or material used under an exception or
35 | limitation to copyright. More considerations for licensors:
36 | wiki.creativecommons.org/Considerations_for_licensors
37 |
38 | Considerations for the public: By using one of our public
39 | licenses, a licensor grants the public permission to use the
40 | licensed material under specified terms and conditions. If
41 | the licensor's permission is not necessary for any reason--for
42 | example, because of any applicable exception or limitation to
43 | copyright--then that use is not regulated by the license. Our
44 | licenses grant only permissions under copyright and certain
45 | other rights that a licensor has authority to grant. Use of
46 | the licensed material may still be restricted for other
47 | reasons, including because others have copyright or other
48 | rights in the material. A licensor may make special requests,
49 | such as asking that all changes be marked or described.
50 | Although not required by our licenses, you are encouraged to
51 | respect those requests where reasonable. More considerations
52 | for the public:
53 | wiki.creativecommons.org/Considerations_for_licensees
54 |
55 | =======================================================================
56 |
57 | Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
58 | Public License
59 |
60 | By exercising the Licensed Rights (defined below), You accept and agree
61 | to be bound by the terms and conditions of this Creative Commons
62 | Attribution-NonCommercial-ShareAlike 4.0 International Public License
63 | ("Public License"). To the extent this Public License may be
64 | interpreted as a contract, You are granted the Licensed Rights in
65 | consideration of Your acceptance of these terms and conditions, and the
66 | Licensor grants You such rights in consideration of benefits the
67 | Licensor receives from making the Licensed Material available under
68 | these terms and conditions.
69 |
70 |
71 | Section 1 -- Definitions.
72 |
73 | a. Adapted Material means material subject to Copyright and Similar
74 | Rights that is derived from or based upon the Licensed Material
75 | and in which the Licensed Material is translated, altered,
76 | arranged, transformed, or otherwise modified in a manner requiring
77 | permission under the Copyright and Similar Rights held by the
78 | Licensor. For purposes of this Public License, where the Licensed
79 | Material is a musical work, performance, or sound recording,
80 | Adapted Material is always produced where the Licensed Material is
81 | synched in timed relation with a moving image.
82 |
83 | b. Adapter's License means the license You apply to Your Copyright
84 | and Similar Rights in Your contributions to Adapted Material in
85 | accordance with the terms and conditions of this Public License.
86 |
87 | c. BY-NC-SA Compatible License means a license listed at
88 | creativecommons.org/compatiblelicenses, approved by Creative
89 | Commons as essentially the equivalent of this Public License.
90 |
91 | d. Copyright and Similar Rights means copyright and/or similar rights
92 | closely related to copyright including, without limitation,
93 | performance, broadcast, sound recording, and Sui Generis Database
94 | Rights, without regard to how the rights are labeled or
95 | categorized. For purposes of this Public License, the rights
96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar
97 | Rights.
98 |
99 | e. Effective Technological Measures means those measures that, in the
100 | absence of proper authority, may not be circumvented under laws
101 | fulfilling obligations under Article 11 of the WIPO Copyright
102 | Treaty adopted on December 20, 1996, and/or similar international
103 | agreements.
104 |
105 | f. Exceptions and Limitations means fair use, fair dealing, and/or
106 | any other exception or limitation to Copyright and Similar Rights
107 | that applies to Your use of the Licensed Material.
108 |
109 | g. License Elements means the license attributes listed in the name
110 | of a Creative Commons Public License. The License Elements of this
111 | Public License are Attribution, NonCommercial, and ShareAlike.
112 |
113 | h. Licensed Material means the artistic or literary work, database,
114 | or other material to which the Licensor applied this Public
115 | License.
116 |
117 | i. Licensed Rights means the rights granted to You subject to the
118 | terms and conditions of this Public License, which are limited to
119 | all Copyright and Similar Rights that apply to Your use of the
120 | Licensed Material and that the Licensor has authority to license.
121 |
122 | j. Licensor means the individual(s) or entity(ies) granting rights
123 | under this Public License.
124 |
125 | k. NonCommercial means not primarily intended for or directed towards
126 | commercial advantage or monetary compensation. For purposes of
127 | this Public License, the exchange of the Licensed Material for
128 | other material subject to Copyright and Similar Rights by digital
129 | file-sharing or similar means is NonCommercial provided there is
130 | no payment of monetary compensation in connection with the
131 | exchange.
132 |
133 | l. Share means to provide material to the public by any means or
134 | process that requires permission under the Licensed Rights, such
135 | as reproduction, public display, public performance, distribution,
136 | dissemination, communication, or importation, and to make material
137 | available to the public including in ways that members of the
138 | public may access the material from a place and at a time
139 | individually chosen by them.
140 |
141 | m. Sui Generis Database Rights means rights other than copyright
142 | resulting from Directive 96/9/EC of the European Parliament and of
143 | the Council of 11 March 1996 on the legal protection of databases,
144 | as amended and/or succeeded, as well as other essentially
145 | equivalent rights anywhere in the world.
146 |
147 | n. You means the individual or entity exercising the Licensed Rights
148 | under this Public License. Your has a corresponding meaning.
149 |
150 |
151 | Section 2 -- Scope.
152 |
153 | a. License grant.
154 |
155 | 1. Subject to the terms and conditions of this Public License,
156 | the Licensor hereby grants You a worldwide, royalty-free,
157 | non-sublicensable, non-exclusive, irrevocable license to
158 | exercise the Licensed Rights in the Licensed Material to:
159 |
160 | a. reproduce and Share the Licensed Material, in whole or
161 | in part, for NonCommercial purposes only; and
162 |
163 | b. produce, reproduce, and Share Adapted Material for
164 | NonCommercial purposes only.
165 |
166 | 2. Exceptions and Limitations. For the avoidance of doubt, where
167 | Exceptions and Limitations apply to Your use, this Public
168 | License does not apply, and You do not need to comply with
169 | its terms and conditions.
170 |
171 | 3. Term. The term of this Public License is specified in Section
172 | 6(a).
173 |
174 | 4. Media and formats; technical modifications allowed. The
175 | Licensor authorizes You to exercise the Licensed Rights in
176 | all media and formats whether now known or hereafter created,
177 | and to make technical modifications necessary to do so. The
178 | Licensor waives and/or agrees not to assert any right or
179 | authority to forbid You from making technical modifications
180 | necessary to exercise the Licensed Rights, including
181 | technical modifications necessary to circumvent Effective
182 | Technological Measures. For purposes of this Public License,
183 | simply making modifications authorized by this Section 2(a)
184 | (4) never produces Adapted Material.
185 |
186 | 5. Downstream recipients.
187 |
188 | a. Offer from the Licensor -- Licensed Material. Every
189 | recipient of the Licensed Material automatically
190 | receives an offer from the Licensor to exercise the
191 | Licensed Rights under the terms and conditions of this
192 | Public License.
193 |
194 | b. Additional offer from the Licensor -- Adapted Material.
195 | Every recipient of Adapted Material from You
196 | automatically receives an offer from the Licensor to
197 | exercise the Licensed Rights in the Adapted Material
198 | under the conditions of the Adapter's License You apply.
199 |
200 | c. No downstream restrictions. You may not offer or impose
201 | any additional or different terms or conditions on, or
202 | apply any Effective Technological Measures to, the
203 | Licensed Material if doing so restricts exercise of the
204 | Licensed Rights by any recipient of the Licensed
205 | Material.
206 |
207 | 6. No endorsement. Nothing in this Public License constitutes or
208 | may be construed as permission to assert or imply that You
209 | are, or that Your use of the Licensed Material is, connected
210 | with, or sponsored, endorsed, or granted official status by,
211 | the Licensor or others designated to receive attribution as
212 | provided in Section 3(a)(1)(A)(i).
213 |
214 | b. Other rights.
215 |
216 | 1. Moral rights, such as the right of integrity, are not
217 | licensed under this Public License, nor are publicity,
218 | privacy, and/or other similar personality rights; however, to
219 | the extent possible, the Licensor waives and/or agrees not to
220 | assert any such rights held by the Licensor to the limited
221 | extent necessary to allow You to exercise the Licensed
222 | Rights, but not otherwise.
223 |
224 | 2. Patent and trademark rights are not licensed under this
225 | Public License.
226 |
227 | 3. To the extent possible, the Licensor waives any right to
228 | collect royalties from You for the exercise of the Licensed
229 | Rights, whether directly or through a collecting society
230 | under any voluntary or waivable statutory or compulsory
231 | licensing scheme. In all other cases the Licensor expressly
232 | reserves any right to collect such royalties, including when
233 | the Licensed Material is used other than for NonCommercial
234 | purposes.
235 |
236 |
237 | Section 3 -- License Conditions.
238 |
239 | Your exercise of the Licensed Rights is expressly made subject to the
240 | following conditions.
241 |
242 | a. Attribution.
243 |
244 | 1. If You Share the Licensed Material (including in modified
245 | form), You must:
246 |
247 | a. retain the following if it is supplied by the Licensor
248 | with the Licensed Material:
249 |
250 | i. identification of the creator(s) of the Licensed
251 | Material and any others designated to receive
252 | attribution, in any reasonable manner requested by
253 | the Licensor (including by pseudonym if
254 | designated);
255 |
256 | ii. a copyright notice;
257 |
258 | iii. a notice that refers to this Public License;
259 |
260 | iv. a notice that refers to the disclaimer of
261 | warranties;
262 |
263 | v. a URI or hyperlink to the Licensed Material to the
264 | extent reasonably practicable;
265 |
266 | b. indicate if You modified the Licensed Material and
267 | retain an indication of any previous modifications; and
268 |
269 | c. indicate the Licensed Material is licensed under this
270 | Public License, and include the text of, or the URI or
271 | hyperlink to, this Public License.
272 |
273 | 2. You may satisfy the conditions in Section 3(a)(1) in any
274 | reasonable manner based on the medium, means, and context in
275 | which You Share the Licensed Material. For example, it may be
276 | reasonable to satisfy the conditions by providing a URI or
277 | hyperlink to a resource that includes the required
278 | information.
279 | 3. If requested by the Licensor, You must remove any of the
280 | information required by Section 3(a)(1)(A) to the extent
281 | reasonably practicable.
282 |
283 | b. ShareAlike.
284 |
285 | In addition to the conditions in Section 3(a), if You Share
286 | Adapted Material You produce, the following conditions also apply.
287 |
288 | 1. The Adapter's License You apply must be a Creative Commons
289 | license with the same License Elements, this version or
290 | later, or a BY-NC-SA Compatible License.
291 |
292 | 2. You must include the text of, or the URI or hyperlink to, the
293 | Adapter's License You apply. You may satisfy this condition
294 | in any reasonable manner based on the medium, means, and
295 | context in which You Share Adapted Material.
296 |
297 | 3. You may not offer or impose any additional or different terms
298 | or conditions on, or apply any Effective Technological
299 | Measures to, Adapted Material that restrict exercise of the
300 | rights granted under the Adapter's License You apply.
301 |
302 |
303 | Section 4 -- Sui Generis Database Rights.
304 |
305 | Where the Licensed Rights include Sui Generis Database Rights that
306 | apply to Your use of the Licensed Material:
307 |
308 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right
309 | to extract, reuse, reproduce, and Share all or a substantial
310 | portion of the contents of the database for NonCommercial purposes
311 | only;
312 |
313 | b. if You include all or a substantial portion of the database
314 | contents in a database in which You have Sui Generis Database
315 | Rights, then the database in which You have Sui Generis Database
316 | Rights (but not its individual contents) is Adapted Material,
317 | including for purposes of Section 3(b); and
318 |
319 | c. You must comply with the conditions in Section 3(a) if You Share
320 | all or a substantial portion of the contents of the database.
321 |
322 | For the avoidance of doubt, this Section 4 supplements and does not
323 | replace Your obligations under this Public License where the Licensed
324 | Rights include other Copyright and Similar Rights.
325 |
326 |
327 | Section 5 -- Disclaimer of Warranties and Limitation of Liability.
328 |
329 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
330 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
331 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
332 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
333 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
334 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
335 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
336 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
337 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
338 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
339 |
340 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
341 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
342 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
343 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
344 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
345 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
346 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
347 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
348 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
349 |
350 | c. The disclaimer of warranties and limitation of liability provided
351 | above shall be interpreted in a manner that, to the extent
352 | possible, most closely approximates an absolute disclaimer and
353 | waiver of all liability.
354 |
355 |
356 | Section 6 -- Term and Termination.
357 |
358 | a. This Public License applies for the term of the Copyright and
359 | Similar Rights licensed here. However, if You fail to comply with
360 | this Public License, then Your rights under this Public License
361 | terminate automatically.
362 |
363 | b. Where Your right to use the Licensed Material has terminated under
364 | Section 6(a), it reinstates:
365 |
366 | 1. automatically as of the date the violation is cured, provided
367 | it is cured within 30 days of Your discovery of the
368 | violation; or
369 |
370 | 2. upon express reinstatement by the Licensor.
371 |
372 | For the avoidance of doubt, this Section 6(b) does not affect any
373 | right the Licensor may have to seek remedies for Your violations
374 | of this Public License.
375 |
376 | c. For the avoidance of doubt, the Licensor may also offer the
377 | Licensed Material under separate terms or conditions or stop
378 | distributing the Licensed Material at any time; however, doing so
379 | will not terminate this Public License.
380 |
381 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
382 | License.
383 |
384 |
385 | Section 7 -- Other Terms and Conditions.
386 |
387 | a. The Licensor shall not be bound by any additional or different
388 | terms or conditions communicated by You unless expressly agreed.
389 |
390 | b. Any arrangements, understandings, or agreements regarding the
391 | Licensed Material not stated herein are separate from and
392 | independent of the terms and conditions of this Public License.
393 |
394 |
395 | Section 8 -- Interpretation.
396 |
397 | a. For the avoidance of doubt, this Public License does not, and
398 | shall not be interpreted to, reduce, limit, restrict, or impose
399 | conditions on any use of the Licensed Material that could lawfully
400 | be made without permission under this Public License.
401 |
402 | b. To the extent possible, if any provision of this Public License is
403 | deemed unenforceable, it shall be automatically reformed to the
404 | minimum extent necessary to make it enforceable. If the provision
405 | cannot be reformed, it shall be severed from this Public License
406 | without affecting the enforceability of the remaining terms and
407 | conditions.
408 |
409 | c. No term or condition of this Public License will be waived and no
410 | failure to comply consented to unless expressly agreed to by the
411 | Licensor.
412 |
413 | d. Nothing in this Public License constitutes or may be interpreted
414 | as a limitation upon, or waiver of, any privileges and immunities
415 | that apply to the Licensor or You, including from the legal
416 | processes of any jurisdiction or authority.
417 |
418 | =======================================================================
419 |
420 | Creative Commons is not a party to its public
421 | licenses. Notwithstanding, Creative Commons may elect to apply one of
422 | its public licenses to material it publishes and in those instances
423 | will be considered the “Licensor.” The text of the Creative Commons
424 | public licenses is dedicated to the public domain under the CC0 Public
425 | Domain Dedication. Except for the limited purpose of indicating that
426 | material is shared under a Creative Commons public license or as
427 | otherwise permitted by the Creative Commons policies published at
428 | creativecommons.org/policies, Creative Commons does not authorize the
429 | use of the trademark "Creative Commons" or any other trademark or logo
430 | of Creative Commons without its prior written consent including,
431 | without limitation, in connection with any unauthorized modifications
432 | to any of its public licenses or any other arrangements,
433 | understandings, or agreements concerning use of licensed material. For
434 | the avoidance of doubt, this paragraph does not form part of the
435 | public licenses.
436 |
437 | Creative Commons may be contacted at creativecommons.org.
438 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kata Platform Development Standard
2 |
3 | *Work in progress*
4 |
5 | ## Overview
6 |
7 | This is a living document outlining the general development guidelines within the Kata Platform. You can read about the styleguide we follow and the tools we use below.
8 |
9 | This is a public version of our Development Standard, meaning this repository is also automatically mirrored to GitHub:
10 |
11 | https://github.com/kata-ai/development-standard
12 |
13 | ## Contents
14 |
15 | | Section | |
16 | |--|--|
17 | | [General Guidelines](./general#readme) | Guidelines that apply to all frontend projects within Kata.ai. |
18 | | [Frontend Guidelines](./frontend#readme) | Guidelines specific to the Kata.ai frontend team. |
19 | | [Backend Guidelines](./backend#readme) | Guidelines specific to the Kata.ai backend team. |
20 | | [Development Workflow](./development-workflow#readme) | Outlines the development workflow + standard operating procedures (SOP) for the Kata.ai engineering team. |
21 |
--------------------------------------------------------------------------------
/backend/README.md:
--------------------------------------------------------------------------------
1 | # Kata Platform Development Standard - Backend Guidelines
2 |
3 | > **Note:** This page is a stub. Please help expand it.
4 |
--------------------------------------------------------------------------------
/development-workflow/README.md:
--------------------------------------------------------------------------------
1 | # Development Workflow
2 |
3 | ## Overview
4 |
5 | This document outlines the development workflow within Kata.ai.
6 |
7 | ## Contents
8 |
9 | - [Definition of Done](./definition-of-done-per-phase.md)
10 |
--------------------------------------------------------------------------------
/development-workflow/definition-of-done-per-phase.md:
--------------------------------------------------------------------------------
1 | # Definition of Done of Development Phase
2 |
3 | This document defines definition of what should be achieved per phase to enter the next phase.
4 |
5 | For example, to be able to go to Ready phase, each items in Backlog should have clear business requirements.
6 |
7 | Another example, for each items to be deployed to Production, it should have technical release notes, passed QA, have technical notes, and code documentation.
8 |
9 | The goal of these guidelines is to make sure we **identify things early so that we don't develop premature product which causes hidden cost or unused products**.
10 |
11 | ## Backlog
12 |
13 | In this phase, stories is gathered as business requirements. Every stories should hava a clear description and standard scrum stories definition.
14 |
15 | ```
16 | As a ..., I should be able to ...
17 | So that, ...
18 | ```
19 |
20 | Prerequisite to go to Ready phase:
21 |
22 | * Business requirements is clear according to System Design guidelines
23 | * Stories should also comes from GIST process
24 |
25 | Actors: Tech Lead, Principals, PM
26 |
27 | ## Ready
28 |
29 | In this phase, there'll be technical discussions, and it is expected to be long to produced Ready to pick stories.
30 |
31 | Prerequisite to go to In Progress phase:
32 |
33 | * Architecture is defined and written in Architectures Decision Record (ADR).
34 | * Has been through UI or UX process.
35 | * Translated into specific technical requiements, from business requirements.
36 | * Requirement is clear, comes from System Design guidelines.
37 | * Acceptance criteria is complete, small, and testable.
38 | * Use case is defined.
39 | * Estimation is given.
40 | * Success metrics is defined.
41 | * Analytics requirements are clear.
42 |
43 | Actors: Principals, Tech Lead, Software Engineers, QAs, PM, Infra
44 |
45 | Details on how story is better written, can be seen [here](./details/story.md).
46 |
47 | ## In Progress
48 |
49 | In this phase, engineers will pick the stories and start developing features.
50 |
51 | Prerequisite to go to QA phase:
52 |
53 | * Contract is defined in the form of Swagger.
54 | * Development time should be tracked in Gitlab. Development time is not including QA time.
55 | * The feature is complete according to specification defined in Ready phase.
56 |
57 | Actors: Tech Lead, Software Engineers, QAs
58 |
59 | ## QA
60 |
61 | QA can test features when an Epic is done. For example say there're 3 stories per epic those 3 stories should be feature complete first before QA can test.
62 |
63 | Prerequisite to go to Done phase:
64 |
65 | * Tagged with Version and commit hash. Example v1.0.0-wquyrei.
66 | * The features are feature-complete and runnable.
67 | * Pass code review.
68 | * Pass linter.
69 | * Unit test is 100 percent passed.
70 | * Code documentation is written. Eg. Class has description, public method has description.
71 |
72 | Actors: QAs, PM at some case to consult about bug / improvement.
73 |
74 | ## Done
75 |
76 | Prerequisite to go to Deployments:
77 |
78 | * Stories passed the QA process.
79 | * Codes finished within the sprint, should be tagged with version according to semantic versioning.
80 | * Should have Technical Release notes.
81 | * [Javascript | Go] doc generated from code documentation.
82 |
83 | Actors: PM, Infra, Software Engineers, and SRE
84 |
85 | ## Notes
86 |
87 | - These phases are carried out using Scrum or Kanban.
88 |
89 | - Before make it to In-Progress phase, each stories should be thought carefully to identify dependencies with existing systems, pitfalls, etc, so that development phase is smooth. If after it goes to In-Progress, development team find an incompleteness, the story should be brought back to Ready phase for discussions.
90 |
91 | - Each items in could be returned to specific phase, for example in QA phase, items could be brought back to In-Progress, if during QA process a bug is found. In progress could be brought back to Ready, if it's later it has some difficulties that needs to be discussed by principals and tech leads.
92 |
93 | - If stories has been given estimation time, if it's stuck for more than one day, the team should regroup to decide whether the story is postponed or adjusting the scope of the story.
94 |
95 | - Testing can be done right away if several stories or one story has done, and its independent from other stories in another epics.
96 |
97 | - If a story in the end doesn't meet success metrics or the story's goal is not achieved as seen in analytics, product team with the help of principals and tech leads should discuss further to evaluate the results.
98 |
--------------------------------------------------------------------------------
/development-workflow/details/story.md:
--------------------------------------------------------------------------------
1 | # Story Description
2 |
3 | ** As a Product Ownser, I should be able to ..., so that ... **
4 |
5 | ## Overview
6 |
7 | Filled with background about stories and the reason behind the stories.
8 |
9 | ## Requirements
10 |
11 | Filled with detailed requirements based on the scope of the story.
12 |
13 | It should limiting the story to the scope to avoid scope-creep.
14 |
15 | ## Tasks
16 |
17 | From the requirements separate the story to several tasks in the todo list manner.
18 |
19 | This will help to make a better estimate the story.
20 |
21 | Breaking into several tasks should be done by engineers with tech lead's guidance.
22 |
23 | ## Acceptance Criteria
24 |
25 | Acceptance criteria is the only reason the story is complete.
26 |
27 | This will be used as a test cases for your application.
28 |
29 | This should be written in a todo list manner.
30 |
31 | QA uses this as their guides to accepting / rejecting a story.
32 |
33 | ---
34 | ## Example
35 |
36 | **As a Tech Lead, I want to know current Sendbird functionalities on doing Handover.**
37 |
38 | ## Overview
39 |
40 | We want to implement functionalties on handover using Sendbird. But currently, there's difference on implementations on Sendbird on handover and our scheme on handover.
41 |
42 | ## Requirements
43 |
44 | Take some time to research on Send Desk API, find out what their capablities are.
45 |
46 | Can we actually integrate with theirs with our current Kanal - Handover-System scheme?
47 |
48 | ## Tasks
49 |
50 | Please check Sendbird's API functionalities [here](https://sendbird.com/docs/desk/v1/platform-api/guides/bot)
51 |
52 | Register and play around their functionalities.
53 |
54 | Checks whether their API offering can be integrated with ours.
55 |
56 | Related doc can be seen [here](https://docs.google.com/document/d/1-p7VWgwZis-zJQAZRl4cGFdRrkz2yU4w50-0Tq-0wjg/edit).
57 |
58 | ## Acceptance Criteria
59 |
60 | - [ ] We know how currently their Desk API work
61 |
62 | - [ ] Can we actually integrate with theirs with our current Kanal - Handover-System scheme?
63 |
64 | - [ ] The results of the finding should be writen in google docs on Kanal folder.
--------------------------------------------------------------------------------
/development-workflow/development-workflow.md:
--------------------------------------------------------------------------------
1 | # TBD
2 |
--------------------------------------------------------------------------------
/development-workflow/local-development-config-with-vault.md:
--------------------------------------------------------------------------------
1 | # Prerequisite
2 | 1. [Install Vault](https://learn.hashicorp.com/tutorials/vault/getting-started-install?in=vault/getting-started#install-vault)
3 | 2. [Install jq](https://stedolan.github.io/jq/). This is optional for converting json key value to environment variables.
4 | 3. Connect to VPN Staging.
5 |
6 | # Configuration
7 |
8 | Launch a new terminal session.
9 |
10 | Copy this following snippet to your `~/.bashrc` or `~/.zshrc` if you are running zshell. This will configure the Vault client to talk to the dev server.
11 |
12 |
13 | ```shell-session
14 | export VAULT_ADDR='http://127.0.0.1:8200'
15 | export VAULT_TOKEN="vault-token-value-here"
16 | ```
17 |
18 | You can consult to your leads regarding these values.
19 |
20 | And then source the file to apply changes.
21 |
22 | ```shell-session
23 | source ~/.zshrc
24 | ```
25 |
26 | ## Verify vault connection
27 |
28 | Verify the server is running by running the `vault status` command. If it ran successfully, the output should look like the following:
29 |
30 | ```shell-session
31 | $ vault status
32 |
33 | Key Value
34 | --- -----
35 | Seal Type shamir
36 | Initialized true
37 | Sealed false
38 | Total Shares 1
39 | Threshold 1
40 | Version 1.5.0
41 | Cluster Name vault-cluster-4d862b44
42 | Cluster ID 92143a5a-0566-be89-f229-5a9f9c47fb1a
43 | HA Enabled false
44 | ```
45 |
46 | # Getting environment variables
47 | With the client connection to vault server estabilished you can get the service config. Let's try getting module secrets with this following command
48 |
49 | ```shell-session
50 | vault kv get -format=json platform/module
51 | ```
52 |
53 | Output:
54 | ```
55 | {
56 | "request_id": "516b95c8-b6c4-5e9a-313c-69a69d126a58",
57 | "lease_id": "",
58 | "lease_duration": 0,
59 | "renewable": false,
60 | "data": {
61 | "data": {
62 | "APP_PORT": "8006",
63 | "DEFAULT_SENDER": "noreply@kata.ai",
64 | "EMAIL_FOOTER": "templates/footer.html",
65 | ......
66 | }
67 | }
68 | }
69 | ```
70 |
71 | To make life easier, we created simple bash script to generate json format result from above command to enviroment variables format. You will need [jq](https://stedolan.github.io/jq) for this to work.
72 |
73 | Simply copy this following function to `~/.bashrc` or `~/.zshrc` file.
74 |
75 | ```shell-session
76 | kataenv() {
77 | vault kv get -format=json $1 | jq '.data.data' | sed -E '1d; $d;s/[[:space:]]+//g;s/,$//;s/^"/export /;s/":/=/'
78 | }
79 | ```
80 |
81 | And then source the file to apply the changes.
82 | ```shell-session
83 | source ~/.zshrc
84 | # source ~/.bashrc
85 | ```
86 |
87 | Run this command to get environment variables format.
88 | ```shell-session
89 | kataenv platform/module
90 |
91 | # Write output to the file and source the file before starting the application
92 | # $ kataenv platform/module > .env && source .env
93 | ```
94 |
95 | Output:
96 | ```shell-session
97 | export APP_PORT="8006"
98 | export DEFAULT_SENDER="noreply@kata.ai"
99 | export EMAIL_FOOTER="templates/footer.html"
100 | ...
101 | ```
102 |
103 | # Supported Services
104 | This is the growing lists of supported kata services in vault as of now. The lists might be changed over time.
105 |
106 | 1. [Zaun](https://gitlab.com/kata-ai/quelle/-/tree/master/zaun)
107 | 2. [Projekt](https://gitlab.com/kata-ai/quelle/-/tree/master/projekt)
108 | 3. [Inhalt](https://gitlab.com/kata-ai/quelle/-/tree/master/inhalt)
109 | 4. [Diaenne](https://gitlab.com/kata-ai/quelle/-/tree/master/diaenne)
110 | 5. [Wache](https://gitlab.com/kata-ai/quelle/-/tree/master/wache)
111 | 6. [Postbote](https://gitlab.com/kata-ai/quelle/-/tree/master/postbote)
112 | 7. [Einsatz](https://gitlab.com/kata-ai/quelle/-/tree/master/einsatz)
113 | 8. [Kanal](https://gitlab.com/kata-ai/quelle/-/tree/master/kanal)
114 | 9. [Scheduler2](https://gitlab.com/kata-ai/quelle/-/tree/master/scheduler2)
115 | 10. [Module](https://gitlab.com/kata-ai/quelle/-/tree/master/module)
116 | 11. [Empfang-Backend](https://gitlab.com/kata-ai/quelle/-/tree/master/empfang-backend)
117 |
118 | # References
119 | - [Vault - Getting Started](https://learn.hashicorp.com/collections/vault/getting-started)
120 |
--------------------------------------------------------------------------------
/development-workflow/local-development-using-telepresence.md:
--------------------------------------------------------------------------------
1 | ## Introduction
2 |
3 | Telepresence is an open source tool that lets you run a single service locally, while connecting that service to a remote Kubernetes cluster, so we can treat our local development machine as if it's part of Kubernetes cluster.
4 |
5 | ## Context and Goals
6 |
7 | Currently to develop services we can run the entire platform locally via Docker Compose. This gives us a fast dev/debug cycle. However, it's less realistic since we are not running our services actually inside Kubernetes, and there are cloud services we might use (e.g., a database) that might not be easy to use locally. With Telepresence we can run everything in a remote Kubernetes cluster and do live coding/debugging.
8 |
9 |
10 | ## Debugging
11 |
12 | ### Prerequisite
13 | 1. [Install Google Cloud SDK](https://cloud.google.com/sdk/docs/install)
14 | 2. [Install kubectl CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
15 | 3. [Install Telepresence](https://www.telepresence.io/reference/install)
16 |
17 | ### Configuration
18 | Access Kata.ai staging Kubernetes cluster with `gcloud` command.
19 | Ask Infra team to get Kata.ai staging gke-engineer.json service account to get access to `kubernetes` resource.
20 |
21 | Then run this following commands to setup connection to `kubernetes` staging.
22 |
23 | ```shell-session
24 | gcloud auth activate-service-account --key-file=gke-engineer.json
25 | gcloud config set project kata-staging-238005
26 | gcloud config set container/cluster kata-staging-kubernetes-cluster
27 | gcloud config set compute/zone asia-southeast1-a
28 | ```
29 |
30 |
31 | Next we need to setup kubectl command to access kata-ai-staging cluster.
32 |
33 | ```shell-session
34 | gcloud container clusters get-credentials kata-staging-kubernetes-cluster --zone asia-southeast1-a
35 | kubectl config use-context gke_kata-staging-238005_asia-southeast1-a_kata-staging-kubernetes-cluster
36 | ```
37 |
38 | Verify the configuration above, by running.
39 |
40 | ```bash
41 | kubectl get pod -n platform-2018
42 | ```
43 |
44 |
45 | ### Exposing local service with Telepresence
46 |
47 | If you want to swap the `postbote` service in kubernetes with local application running in port 5000. Run this following command.
48 |
49 | ```
50 | telepresence --swap-deployment postbote --namespace platform-2018 --expose 5000
51 | ```
52 |
53 | Now test `postbote` service that served from local port.
54 | ```bash
55 | curl https://posbote.katalabs.io/info
56 | ```
57 |
58 | Let's try kill the telepresence process by hitting `Ctrl+C` and wait for few second to swap back to old code.
59 |
60 | ## Bugs and Limitations
61 | Here's a list of bugs and limitations we found during our exploration and trying out telepresence workflow. The lists might be changed overtime with the update of the telepresence version.
62 |
63 | 1. Error in command line after telepresence launched.
64 | ```
65 | Looks like there's a bug in our code. Sorry about that!
66 |
67 | Traceback (most recent call last):
68 | File "/usr/local/bin/telepresence/telepresence/cli.py", line 135, in crash\_reporting
69 | yield
70 | File "/usr/local/bin/telepresence/telepresence/main.py", line 71, in main
71 | env, pod\_info = get\_remote\_env(runner, ssh, remote\_info)
72 | File "/usr/local/bin/telepresence/telepresence/remote\_env.py", line 32, in get\_remote\_env
73 | json\_data = runner.get\_output(
74 | File "/usr/local/bin/telepresence/telepresence/runner/runner.py", line 479, in get\_output
75 | output = self.\_run\_command\_sync(
76 | File "/usr/local/bin/telepresence/telepresence/runner/runner.py", line 437, in \_run\_command\_sync
77 | raise CalledProcessError(
78 | subprocess.CalledProcessError: Command '\['kubectl', '--context', 'default', '--namespace', 'platform-2018', 'exec', 'wache-256aecfb76984b2486619760dbd5e9b9', '--container', 'wache', '--'
79 | , 'python3', 'podinfo.py'\]' returned non-zero exit status 1.
80 | Would you like to file an issue in our issue tracker? You'll be able to review and edit before anything is posted to the public. We'd really appreciate the help improving our product. \[Y
81 | /n\]:
82 | ```
83 | **Workaround**: If you encounter this issue don't issue any key (Y/n) because it will exit the process.
84 |
85 | 2. Old pod doesn't spawn back when telepresence exited.
86 | **Workaround**: Rerun the pipelines in gitlab CI.
87 |
88 | ## References
89 | - [Telepresence - Introduction](https://www.telepresence.io/discussion/overview)
90 |
--------------------------------------------------------------------------------
/frontend/README.md:
--------------------------------------------------------------------------------
1 | # Kata Platform Development Standard - Frontend
2 |
3 | ## Overview
4 |
5 | This is a living document outlining guidelines for developing frontend projects within Kata.ai, as well as the tools we use. You can read about the styleguide we follow and the tools we use below.
6 |
7 | ## Contents
8 |
9 | | Section | |
10 | |--|--|
11 | | [Starter kits](./docs/starter-kits.md#readme) | |
12 | | [Environment](./docs/environment.md#readme) | |
13 | | [Tooling](./docs/tooling.md#readme) | |
14 | | [React Styleguide](./docs/react.md#readme) | Guidelines specific to Kata.ai's React codebase. |
15 |
16 |
--------------------------------------------------------------------------------
/frontend/docs/environment.md:
--------------------------------------------------------------------------------
1 | # Environment
2 |
3 | ## Node.js
4 |
5 | Always keep your Node.js environment up to date. Strive for keeping your Node.js version in the latest LTS version. **Don't** use versions outside of the LTS release cycle.
6 |
7 | > To check the current release cycle of Node.js, check out [nodejs/Release](https://github.com/nodejs/Release).
8 |
9 | ## Yarn
10 |
11 | - Use yarn. If you encounter projects still using npm, convert them to yarn ASAP.
12 | - Installing yarn will generate a `yarn.lock` file. **Always** commit the `yarn.lock` file into your repository.
13 | - Always periodically check your packages for vulnerabilities with the `yarn audit` command.
14 |
--------------------------------------------------------------------------------
/frontend/docs/react.md:
--------------------------------------------------------------------------------
1 | # React Styleguide
2 |
3 | *Work in progress*
4 |
5 | ## Overview
6 |
7 | [React](https://reactjs.org/) is the framework we choose for building frontend projects at Kata.ai. We chose this framework due to its ease of use, as well as extensive community support and library ecosystem. This document outlines React-specific extensions for our TypeScript Styleguide.
8 |
9 | You can use our unified ESLint + Prettier config to enforce these styleguides on your project. See [Tooling](./tooling.md) for more information.
10 |
11 | ## Table of Contents
12 |
13 | - [Naming](#naming)
14 | - [Class components](#class-components)
15 | - [Function components](#function-components)
16 | - [Types](#types)
17 |
18 | ---
19 |
20 | ## Naming
21 |
22 | ### Use `.jsx` and/or `.tsx` extensions for React components
23 |
24 | Any JS/TS files with a JSX syntax should always be marked as such.
25 |
26 | > Note that using `.js` for JSX files will also give problems for Emmet autocompletion on VS Code, see [Microsoft/vscode#4962](https://github.com/Microsoft/vscode/issues/4962).
27 |
28 | ### File names should match the component name
29 |
30 | When writing React components, file names should match the name of the component being exported.
31 |
32 | ```tsx
33 | // CheckoutButton.tsx
34 | export const CheckoutButton = () => ;
35 | ```
36 |
37 | ### Use PascalCase when naming React components.
38 |
39 | This is according to the JSX specification. Use the PascalCase convention for filenames, too.
40 |
41 | ### Keep component/prop names clear and concise.
42 |
43 | Use component names that are as clear and standard as possible. Strive for component names no longer than 2-3 words.
44 |
45 | ### Use the `onVerb` prop naming structure for event handlers
46 |
47 | For internal event handlers, use the `handleVerb` naming structure.
48 |
49 | ```tsx
50 |
51 | ...
52 |
53 | ```
54 |
55 | ### Use the `isVerb` prop naming structure for represeting state
56 |
57 | ```tsx
58 |
59 | ...
60 |
61 | ```
62 |
63 | ### Use the `Props` and `State` naming structure for component props/state
64 |
65 | ```tsx
66 | // Bad example
67 | interface Props {}
68 |
69 | // Good example
70 | interface CheckoutButtonProps {}
71 | ```
72 |
73 | ## Class components
74 |
75 | ### Use `public` for all default React lifecycles
76 |
77 | All React component lifecycles (including `static` lifecycles like `getDerivedStateFromProps`) **should** be set to `public`.
78 |
79 | ### Use `private` when defining internal class properties
80 |
81 | Class properties that are only used privately should be marked as such.
82 |
83 | ## Function components
84 |
85 | ### Use `React.FC` type over `React.SFC` type for function components
86 |
87 | The `React.SFC` type is deprecated as of `@types/react@16.7.0`, since with the upcoming [Hooks](https://reactjs.org/docs/hooks-intro.html), function components can also have state, so calling them "stateless" is a misnomer.
88 |
89 | ```tsx
90 | // Bad example
91 | const App: React.SFC = ({ children }) =>
{children}
;
92 | ```
93 |
94 | ```tsx
95 | // Good example
96 | const App: React.FC = ({ children }) =>
{children}
;
97 | ```
98 |
99 | ## Types
100 |
101 | ### Don't inline prop types
102 |
103 | You should always declare the props of a component separately.
104 |
105 | ```tsx
106 | // Bad example
107 | const App: React.FC<{ message: string }> = ({ message }) =>
;
117 | ```
118 |
--------------------------------------------------------------------------------
/frontend/docs/starter-kits.md:
--------------------------------------------------------------------------------
1 | # Starter kits
2 |
3 | Generally, for our single-page apps we use [React](https://reactjs.org) with tooling provided by [create-react-app](https://create-react-app.dev/). For React apps with server-side rendering, we use [Next.js](https://nextjs.org/).
4 |
5 | - A frontend starter kit with SSR support powered by Next.js is available (**crucible**)
6 |
--------------------------------------------------------------------------------
/frontend/docs/tooling.md:
--------------------------------------------------------------------------------
1 | # Tooling
2 |
3 | ## Overview
4 |
5 | We're committed to the quality of our development stack and tooling. This document contains guides on the tools we use for daily development as a frontend engineer in Kata.ai. This also contains our unified ESLint config that you can use and extend from.
6 |
7 | ## Table of Contents
8 |
9 | - [IDE](#ide)
10 | - [TypeScript](#typescript)
11 | - [Linting and Formatting](#linting-and-formatting)
12 | - [Tests](#tests)
13 |
14 | ---
15 |
16 | ## IDE
17 |
18 | Use [Visual Studio Code](https://code.visualstudio.com). It has first-class support for JavaScript and TypeScript, complete with code-aware statement completion, Emmet integration for JSX elements, as well top-notch debugging environment.
19 |
20 | ## TypeScript
21 |
22 | Below are guides on how we use TypeScript projects.
23 |
24 | ### Prefer using Babel TS preset on frontend projects
25 |
26 | The TypeScript compiler supports most modern ES2015+ JavaScript features up to stage-3 proposals. However, in some cases, chaining TypeScript with Babel, or using the Babel transpiler altogether allows us to use features like hot reloading, additional Babel plugins for e.g. `styled-components`, and a faster compile time.
27 |
28 | CRA 2.1 already uses Babel as the default TypeScript transpilation pipeline, so everything's already handled for you.
29 |
30 | Note that the Babel compiler **only** removes the types from your code. **It does not do any additional type-checking!** If compiling TS using Babel, make sure to run type-checking separately with `tsc --noEmit`. It's also better to include in your CI process!
31 |
32 | ### Use `--strict` mode
33 |
34 | Make sure to enable strict mode in your tsconfig! Anything less will cause a huge mess in our codebase further down the road.
35 |
36 | ```json
37 | {
38 | "compilerOptions": {
39 | "strict": true
40 | }
41 | }
42 | ```
43 |
44 | If you do need to disable some rules that the `--strict` flag emits, override it after the `strict` rule in your tsconfig:
45 |
46 | ```json
47 | {
48 | "compilerOptions": {
49 | "strict": true,
50 | "strictBindCallApply": false
51 | }
52 | }
53 | ```
54 |
55 | ## Linting and Formatting
56 |
57 | ### ESLint
58 |
59 | Kata.ai provides a [custom ESLint config](https://github.com/kata-ai/eslint-config-kata) to enforce the styleguides outlined in this document. To use it, install `eslint-config-kata`.
60 |
61 | ```sh
62 | $ yarn add --dev eslint-config-kata
63 | ```
64 |
65 | Then, extend `eslint-config-kata/react` in your `.eslintrc` file.
66 |
67 | ```json
68 | {
69 | "extends": ["eslint-config-kata/react"]
70 | }
71 | ```
72 |
73 | ### Prettier
74 |
75 | [Prettier](https://prettier.io/) is a tool to automatically format your code during save. It supports various editors, from VSCode, Atom, Sublime, and even Emacs.
76 |
77 | To use this ESLint config in conjunction with Prettier, copy the following `.prettierrc` template:
78 |
79 | ```json
80 | {
81 | "printWidth": 120,
82 | "tabWidth": 2,
83 | "useTabs": false,
84 | "semi": true,
85 | "singleQuote": true,
86 | "trailingComma": "es5",
87 | "bracketSpacing": true,
88 | "jsxBracketSameLine": false,
89 | "arrowParens": "avoid",
90 | "endOfLine": "auto"
91 | }
92 | ```
93 |
94 | Then install the Prettier eslint config and plugin:
95 |
96 | ```sh
97 | $ yarn add --dev eslint-plugin-prettier eslint-config-prettier prettier
98 | ```
99 |
100 | And finally, include them as follows. (**IMPORTANT:** `eslint-config-prettier` MUST be extended after `eslint-config-kata`!)
101 |
102 | ```json
103 | {
104 | "extends": ["eslint-config-kata/react", "prettier", "prettier/@typescript-eslint", "plugin:prettier/recommended"],
105 | "plugins": ["prettier"],
106 | "rules": {
107 | "prettier/prettier": "error"
108 | }
109 | }
110 | ```
111 |
112 | ## Tests
113 |
114 | Write tests. Please.
115 |
116 | Writing tests ensures that:
117 |
118 | - We could add new functionality without breaking old ones
119 | - We could refactor parts of the codebase without fearing that stuff would break.
120 |
121 | We use [Jest](https://jestjs.io/) as our test runner. To run test coverage within Jest, run `jest --coverage`. New projects must aim for at least 70% test coverage. Don't forget to use code coverage/code quality tracking tools like [codecov](https://codecov.io/) or [CodeClimate](https://codeclimate.com/).
122 |
123 | We use [react-testing-library](https://testing-library.com/docs/react-testing-library/intro) as our React testing framework. This library helps us write better tests for our React components by encouraging good test practices.
124 |
--------------------------------------------------------------------------------
/general/README.md:
--------------------------------------------------------------------------------
1 | # Kata Platform Development Standard - General
2 |
3 | ## Overview
4 |
5 | This is a living document outlining guidelines that apply for all projects within Kata.ai. This includes frontend and backend projects. You can read about the styleguide we follow and the tools/processes we use below.
6 |
7 | ## Contents
8 |
9 | | Section | |
10 | |--|--|
11 | | [Languages](./languages#readme) | A list of languages we use as well as the styleguide for them. |
12 | | [Details](./details#readme) | Other small details provided as extensions to language styleguides. |
13 | | [Code Review Guidelines](./code-review-guidelines.md#readme) | |
14 | | [Production Level Code Guidelines](./production-level-code.md#readme) | |
15 |
--------------------------------------------------------------------------------
/general/anatomy_of_an_application.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kata-ai/development-standard/7c1892a1d52ece865e8c0eec047ffea4c4f79ae8/general/anatomy_of_an_application.png
--------------------------------------------------------------------------------
/general/code-review-guidelines.md:
--------------------------------------------------------------------------------
1 | # Code Review Guidelines
2 |
3 | ## General
4 |
5 | ### The application or service should be runnable
6 | Make sure reviewer clone, and run the service / application. If it’s not running, never merge it to master.
7 |
8 | Or, it’s better if we have Integration Test.
9 |
10 | ### Linter is passed
11 | You need to define linter for your application / service, and use it as a standard part of your CI/CD.
12 | Never merge code that hasn’t passed the linter.
13 |
14 | ### The code should be correct
15 | The logic should be correct according to specs or TODO list.
16 |
17 | ### The code should be defensive
18 |
19 | The code should be checked against NULL and invalid values.
20 | You can use assertions or just plain if clause
21 |
22 | ```python
23 | def add_number(first: int, second: int):
24 | assert first is not None, “first number should not be None”
25 | assert second is not None, “second number should not be None”
26 |
27 | return first + second
28 | ```
29 |
30 | ### Unit test is green
31 | Make sure all unit test is green, code coverage is between 60-75 percent is categorised as [sufficient](https://testing.googleblog.com/2014/07/measuring-coverage-at-google.html) .
32 |
33 | ### The code should be easy to understand
34 | Can you understand the code *without asking the committer*?
35 |
36 | Is the structure clearly defined?
37 |
38 | Is the naming on methods and variables readable enough?
39 |
40 | ### The code should follow clean code principles
41 | You can read the book [Clean Code: A Handbook of Agile Software Craftsmanship Book](https://learning.oreilly.com/library/view/clean-code-a/9780136083238/) and [this](https://benscabbia.co.uk/programming/clean-code-cheatsheet) as a summary.
42 |
43 | Also, here’s [some examples](https://github.com/ryanmcdermott/clean-code-javascript) written in JS.
44 |
45 | Mostly should follow DRY, KISS, YAGNI.
46 |
47 | ### The code should be efficient
48 | Is the code use efficient data structures?
49 |
50 | Is the code use efficient algorithm?
51 |
52 | Is the code have potential Time Bomb issues:
53 |
54 | Looks Good To Me (LGTM), but when the time comes, will produce errors or exception.
55 |
56 | * [Shlemiel The Painter Algorithm](https://wiki.c2.com/?ShlemielThePainter) , basically O(n) algorithm, with n large enough and it iterates often, it will become slower.
57 |
58 | * Silent error: open a file, but not closing it.
59 |
60 | * Running a query against unindexed column.
61 |
62 | * StackOverflow error
63 |
64 | * And many more…
65 |
66 |
67 | ### The merge request should use template
68 | You should use [template](https://gitlab.com/kata-ai/core/development-standard/-/blob/master/templates/pull-request.md) for your merge request, it makes the reviewer easier to review the code.
69 |
70 | ### The code should use “good enough” 3rd Party Library
71 |
72 | It should be:
73 | * popular, shown by github stars
74 | * actively maintained
75 | * have unit tests with coverage
76 | * easy to use
77 |
78 | ## Error Handling
79 |
80 | ### Error / Exception should be caught, then logged to stdout
81 | Follow guidelines of your programming language and your favourite framework.
82 |
83 | If your framework have minimal support on error handling, ditch it.
84 |
85 | ### API should have proper error code
86 | Common API error code, use error code according to its usage, never use the same error code for a lot of different errors.
87 |
88 | Several common error code, message, and reasons:
89 |
90 | 400
91 | Bad Request
92 | Payload from user is invalid
93 |
94 | 401
95 | Unauthorized
96 | Invalid auth token, no token, or expired token
97 |
98 | 403
99 | Forbidden
100 | User is authenticated, but does not have access to resource
101 |
102 | 404
103 | Not Found
104 | No resource is available at the endpoint
105 |
106 | 500
107 | Internal server error
108 | App encounters unhandled exceptions, or uncaught errors
109 |
110 | ### Error message should be meaningful
111 | You need to provide context to each error message you logs.
112 | Mostly write *what your error is*and *provide reasoning*why it’s happening.
113 |
114 | *Bad*
115 | “Error on converse”
116 |
117 | *Good*
118 | “Error on converse, you need to provide channelID and botID”
119 |
120 | *Bad*
121 | “Error on transaction, code: 112”
122 | *Good*
123 | “Error on transaction, code: 112, reason: insufficient fund”
124 |
125 | *Bad JSON Response*
126 | 500 Internal server error — Written as text
127 |
128 | *Good JSON Response — Written as JSON*
129 | {
130 | “status”: “error”,
131 | “message”: “Internal server error”
132 | }
133 |
134 | # Comments
135 | ### Never comment each line of code, only use if necessary
136 |
137 | Example
138 |
139 | ```javascript
140 | // DON’T DO THIS
141 | function username(fullname) {
142 | if (!fullname) {
143 | // throw error
144 | throw new Error(“no fullname”)
145 | }
146 | // check if name is valid
147 | const isValid = validateName(fullname)
148 |
149 | // return firstname
150 | return isValid ? username.split(“”)[0] : null
151 | }
152 | ```
153 |
154 | ```javascript
155 | // THIS IS BETTER
156 | function username(fullname) {
157 | if (!fullname) {
158 | throw new Error(“no fullname”);
159 | }
160 |
161 | // check if name is valid
162 | const isValid = validateName(fullname);
163 |
164 | return isValid ? username.split(“”)[0] : null
165 | }
166 | ```
167 |
168 | ### Never use comment for disabling line(s) of code
169 | ```javascript
170 | function validName(name) {
171 | // console.log(name) DON’T DO THIS!
172 | return name.length > 3;
173 | }
174 | ```
175 |
176 | ### Remove any print-like code, use logger instead.
177 |
178 | # Documentations
179 | ### Always document public methods
180 | Public methods should have documentation.
181 |
182 | It should explain the intent of the methods, arguments, and return values.
183 |
184 | ```
185 | // EXAMPLE in Javascript
186 | /**
187 | * Is configured checks config has been configured or not
188 | *
189 | * @param config in Json
190 | * @returns true if it’s configured, false otherwise
191 | */
192 | function isConfigured(config: Json): bool {
193 | return false;
194 | }
195 | ```
196 |
197 | ### Always have README for each service or applications
198 | You can use this [README](https://kata.quip.com/HfKJAbbcRSa5/Kataai-Repo-Documentation-Template) template.
199 |
200 | ## Package
201 |
202 | Make sure all dependencies needed for running an app / servce is written inside a repository / project and committed.
203 |
204 | Otherwise the build won't run or we're late to know if the language is an interpeter one.
205 |
206 |
207 | ## Security
208 | Checks for top [10 OWASP](https://owasp.org/www-project-top-ten/)
209 |
210 | ### All data inputs from frontend should be validated
211 | Use trusted ORM and database driver to prevent SQL injection.
212 |
213 | Checks for data type conversion from JSON fields to Object fields.
214 | Example:
215 | string to number, etc
216 |
--------------------------------------------------------------------------------
/general/details/README.md:
--------------------------------------------------------------------------------
1 | # Details
2 |
3 | ## Overview
4 |
5 | Other small details provided as extensions to language styleguides.
6 |
7 | ## Contents
8 |
9 | | Section | |
10 | |--|--|
11 | | [Naming Cheatsheet](./naming-cheatsheet#readme) | Naming things is hard. This cheatsheet attempts to make it easier. (By Artem Zakharchenko [(@kettanaito)](https://github.com/kettanaito)) |
12 |
--------------------------------------------------------------------------------
/general/details/naming-cheatsheet/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018—preset Artem Zakharchenko
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/general/details/naming-cheatsheet/README.md:
--------------------------------------------------------------------------------
1 | # Naming cheatsheet
2 |
3 | > This naming cheatsheet is originated from "Naming cheatsheet" repository by [Artem Zakharchenko](https://github.com/kettanaito).
4 | >
5 | > Original link: https://github.com/kettanaito/naming-cheatsheet
6 |
7 | - [English language](#english-language)
8 | - [Naming convention](#naming-convention)
9 | - [S-I-D](#s-i-d)
10 | - [Avoid contractions](#avoid-contractions)
11 | - [Avoid context duplication](#avoid-context-duplication)
12 | - [Reflect the expected result](#reflect-the-expected-result)
13 | - [Naming functions](#naming-functions)
14 | - [A/HC/LC pattern](#ahclc-pattern)
15 | - [Actions](#actions)
16 | - [Context](#context)
17 | - [Prefixes](#prefixes)
18 | - [Singular and Plurals](#singular-and-plurals)
19 |
20 | ---
21 |
22 | Naming things is hard. This sheet attempts to make it easier.
23 |
24 | Although these suggestions can be applied to any programming language, I will use JavaScript to illustrate them in practice.
25 |
26 | ## English language
27 |
28 | Use English language when naming your variables and functions.
29 |
30 | ```js
31 | /* Bad */
32 | const primerNombre = 'Gustavo'
33 | const amigos = ['Kate', 'John']
34 |
35 | /* Good */
36 | const firstName = 'Gustavo'
37 | const friends = ['Kate', 'John']
38 | ```
39 |
40 | > Like it or not, English is the dominant language in programming: the syntax of all programming languages is written in English, as well as countless documentations and educational materials. By writing your code in English you dramatically increase its cohesiveness.
41 |
42 | ## Naming convention
43 |
44 | Pick **one** naming convention and follow it. It may be `camelCase`, `PascalCase`, `snake_case`, or anything else, as long as it remains consistent. Many programming languages have their own traditions regarding naming conventions; check the documentation for your language or study some popular repositories on Github!
45 |
46 | ```js
47 | /* Bad */
48 | const page_count = 5
49 | const shouldUpdate = true
50 |
51 | /* Good */
52 | const pageCount = 5
53 | const shouldUpdate = true
54 |
55 | /* Good as well */
56 | const page_count = 5
57 | const should_update = true
58 | ```
59 |
60 | ## S-I-D
61 |
62 | A name must be _short_, _intuitive_ and _descriptive_:
63 |
64 | - **Short**. A name must not take long to type and, therefore, remember;
65 | - **Intuitive**. A name must read naturally, as close to the common speech as possible;
66 | - **Descriptive**. A name must reflect what it does/possesses in the most efficient way.
67 |
68 | ```js
69 | /* Bad */
70 | const a = 5 // "a" could mean anything
71 | const isPaginatable = a > 10 // "Paginatable" sounds extremely unnatural
72 | const shouldPaginatize = a > 10 // Made up verbs are so much fun!
73 |
74 | /* Good */
75 | const postCount = 5
76 | const hasPagination = postCount > 10
77 | const shouldPaginate = postCount > 10 // alternatively
78 | ```
79 |
80 | ## Avoid contractions
81 |
82 | Do **not** use contractions. They contribute to nothing but decreased readability of the code. Finding a short, descriptive name may be hard, but contraction is not an excuse for not doing so.
83 |
84 | ```js
85 | /* Bad */
86 | const onItmClk = () => {}
87 |
88 | /* Good */
89 | const onItemClick = () => {}
90 | ```
91 |
92 | ## Avoid context duplication
93 |
94 | A name should not duplicate the context in which it is defined. Always remove the context from a name if that doesn't decrease its readability.
95 |
96 | ```js
97 | class MenuItem {
98 | /* Method name duplicates the context (which is "MenuItem") */
99 | handleMenuItemClick = (event) => { ... }
100 |
101 | /* Reads nicely as `MenuItem.handleClick()` */
102 | handleClick = (event) => { ... }
103 | }
104 | ```
105 |
106 | ## Reflect the expected result
107 |
108 | A name should reflect the expected result.
109 |
110 | ```jsx
111 | /* Bad */
112 | const isEnabled = itemCount > 3
113 | return
114 |
115 | /* Good */
116 | const isDisabled = itemCount <= 3
117 | return
118 | ```
119 |
120 | ---
121 |
122 | # Naming functions
123 |
124 | ## A/HC/LC Pattern
125 |
126 | There is a useful pattern to follow when naming functions:
127 |
128 | ```
129 | prefix? + action (A) + high context (HC) + low context? (LC)
130 | ```
131 |
132 | Take a look at how this pattern may be applied in the table below.
133 |
134 | | Name | Prefix | Action (A) | High context (HC) | Low context (LC) |
135 | | ---------------------- | -------- | ---------- | ----------------- | ---------------- |
136 | | `getUser` | | `get` | `User` | |
137 | | `getUserMessages` | | `get` | `User` | `Messages` |
138 | | `handleClickOutside` | | `handle` | `Click` | `Outside` |
139 | | `shouldDisplayMessage` | `should` | `Display` | `Message` | |
140 |
141 | > **Note:** The order of context affects the meaning of a variable. For example, `shouldUpdateComponent` means _you_ are about to update a component, while `shouldComponentUpdate` tells you that _component_ will update on itself, and you are but controlling when it should be updated.
142 | > In other words, **high context emphasizes the meaning of a variable**.
143 |
144 | ---
145 |
146 | ## Actions
147 |
148 | The verb part of your function name. The most important part responsible for describing what the function _does_.
149 |
150 | ### `get`
151 |
152 | Accesses data immediately (i.e. shorthand getter of internal data).
153 |
154 | ```js
155 | function getFruitCount() {
156 | return this.fruits.length
157 | }
158 | ```
159 |
160 | > See also [compose](#compose).
161 |
162 | ### `set`
163 |
164 | Sets a variable in a declarative way, with value `A` to value `B`.
165 |
166 | ```js
167 | let fruits = 0
168 |
169 | function setFruits(nextFruits) {
170 | fruits = nextFruits
171 | }
172 |
173 | setFruits(5)
174 | console.log(fruits) // 5
175 | ```
176 |
177 | ### `reset`
178 |
179 | Sets a variable back to its initial value or state.
180 |
181 | ```js
182 | const initialFruits = 5
183 | let fruits = initialFruits
184 | setFruits(10)
185 | console.log(fruits) // 10
186 |
187 | function resetFruits() {
188 | fruits = initialFruits
189 | }
190 |
191 | resetFruits()
192 | console.log(fruits) // 5
193 | ```
194 |
195 | ### `fetch`
196 |
197 | Request for some data, which takes some indeterminate time (i.e. async request).
198 |
199 | ```js
200 | function fetchPosts(postCount) {
201 | return fetch('https://api.dev/posts', {...})
202 | }
203 | ```
204 |
205 | ### `remove`
206 |
207 | Removes something _from_ somewhere.
208 |
209 | For example, if you have a collection of selected filters on a search page, removing one of them from the collection is `removeFilter`, **not** `deleteFilter` (and this is how you would naturally say it in English as well):
210 |
211 | ```js
212 | function removeFilter(filterName, filters) {
213 | return filters.filter((name) => name !== filterName)
214 | }
215 |
216 | const selectedFilters = ['price', 'availability', 'size']
217 | removeFilter('price', selectedFilters)
218 | ```
219 |
220 | > See also [delete](#delete).
221 |
222 | ### `delete`
223 |
224 | Completely erases something from the realms of existence.
225 |
226 | Imagine you are a content editor, and there is that notorious post you wish to get rid of. Once you clicked a shiny "Delete post" button, the CMS performed a `deletePost` action, **not** `removePost`.
227 |
228 | ```js
229 | function deletePost(id) {
230 | return database.find({ id }).delete()
231 | }
232 | ```
233 |
234 | > See also [remove](#remove).
235 |
236 | ### `compose`
237 |
238 | Creates new data from the existing one. Mostly applicable to strings, objects, or functions.
239 |
240 | ```js
241 | function composePageUrl(pageName, pageId) {
242 | return (pageName.toLowerCase() + '-' + pageId)
243 | }
244 | ```
245 |
246 | > See also [get](#get).
247 |
248 | ### `handle`
249 |
250 | Handles an action. Often used when naming a callback method.
251 |
252 | ```js
253 | function handleLinkClick() {
254 | console.log('Clicked a link!')
255 | }
256 |
257 | link.addEventListener('click', handleLinkClick)
258 | ```
259 |
260 | ---
261 |
262 | ## Context
263 |
264 | A domain that a function operates on.
265 |
266 | A function is often an action on _something_. It is important to state what its operable domain is, or at least an expected data type.
267 |
268 | ```js
269 | /* A pure function operating with primitives */
270 | function filter(list, predicate) {
271 | return list.filter(predicate)
272 | }
273 |
274 | /* Function operating exactly on posts */
275 | function getRecentPosts(posts) {
276 | return filter(posts, (post) => post.date === Date.now())
277 | }
278 | ```
279 |
280 | > Some language-specific assumptions may allow omitting the context. For example, in JavaScript, it's common that `filter` operates on Array. Adding explicit `filterArray` would be unnecessary.
281 |
282 | --
283 |
284 | ## Prefixes
285 |
286 | Prefix enhances the meaning of a variable. It is rarely used in function names.
287 |
288 | ### `is`
289 |
290 | Describes a characteristic or state of the current context (usually `boolean`).
291 |
292 | ```js
293 | const color = 'blue'
294 | const isBlue = color === 'blue' // characteristic
295 | const isPresent = true // state
296 |
297 | if (isBlue && isPresent) {
298 | console.log('Blue is present!')
299 | }
300 | ```
301 |
302 | ### `has`
303 |
304 | Describes whether the current context possesses a certain value or state (usually `boolean`).
305 |
306 | ```js
307 | /* Bad */
308 | const isProductsExist = productsCount > 0
309 | const areProductsPresent = productsCount > 0
310 |
311 | /* Good */
312 | const hasProducts = productsCount > 0
313 | ```
314 |
315 | ### `should`
316 |
317 | Reflects a positive conditional statement (usually `boolean`) coupled with a certain action.
318 |
319 | ```js
320 | function shouldUpdateUrl(url, expectedUrl) {
321 | return url !== expectedUrl
322 | }
323 | ```
324 |
325 | ### `min`/`max`
326 |
327 | Represents a minimum or maximum value. Used when describing boundaries or limits.
328 |
329 | ```js
330 | /**
331 | * Renders a random amount of posts within
332 | * the given min/max boundaries.
333 | */
334 | function renderPosts(posts, minPosts, maxPosts) {
335 | return posts.slice(0, randomBetween(minPosts, maxPosts))
336 | }
337 | ```
338 |
339 | ### `prev`/`next`
340 |
341 | Indicate the previous or the next state of a variable in the current context. Used when describing state transitions.
342 |
343 | ```jsx
344 | function fetchPosts() {
345 | const prevPosts = this.state.posts
346 |
347 | const fetchedPosts = fetch('...')
348 | const nextPosts = concat(prevPosts, fetchedPosts)
349 |
350 | this.setState({ posts: nextPosts })
351 | }
352 | ```
353 |
354 | ## Singular and Plurals
355 |
356 | Like a prefix, variable names can be made singular or plural depending on whether they hold a single value or multiple values.
357 |
358 | ```js
359 | /* Bad */
360 | const friends = 'Bob'
361 | const friend = ['Bob', 'Tony', 'Tanya']
362 |
363 | /* Good */
364 | const friend = 'Bob'
365 | const friends = ['Bob', 'Tony', 'Tanya']
366 | ```
367 |
--------------------------------------------------------------------------------
/general/languages/README.md:
--------------------------------------------------------------------------------
1 | # Languages
2 |
3 | ## Overview
4 |
5 | This section contains styleguides for programming languages used within Kata.ai. Other times, it also outlines our considerations as to why we're using them. If you would like to add more languages into the styleguide, please read the [Adding New Languages](#adding-new-languages) section.
6 |
7 | ## Contents
8 |
9 | | Section | |
10 | |--|--|
11 | | [TypeScript Styleguide](./typescript.md#readme) | Styleguide for writing TypeScript code within Kata.ai. |
12 |
13 | ## Adding New Languages
14 |
15 | [TODO]
16 |
--------------------------------------------------------------------------------
/general/languages/typescript.md:
--------------------------------------------------------------------------------
1 | # TypeScript Styleguide
2 |
3 | ## Overview
4 |
5 | At Kata.ai, we use [TypeScript](https://www.typescriptlang.org/) across our entire JavaScript stack. TypeScript combines the familiarity of JavaScript with the power of static typing.
6 |
7 | In general, using static typing in your JavaScript code [can help prevent about 15%](https://blog.acolyer.org/2017/09/19/to-type-or-not-to-type-quantifying-detectable-bugs-in-javascript/) of the bugs that end up in committed code. Not only static typing, TypeScript also provides various productivity enhancements like advanced statement completion, as well as smart code refactoring.
8 |
9 | This document outlines the general styleguide for TypeScript projects within Kata.ai. Our styleguide is mostly derived from the [Airbnb JavaScript styleguide](https://github.com/airbnb/javascript), with changes made to accomodate TypeScript projects.
10 |
11 | You can use our unified ESLint + Prettier config to enforce these styleguides on your project. See [Tooling](../../frontend/docs/tooling.md#readme) for more information.
12 |
13 | ## Table of Contents
14 |
15 | - [Naming](#naming)
16 | - [Indentation & Line length](#indentation--line-length)
17 | - [Style](#style)
18 | - [Types](#types)
19 | - [Functions](#functions)
20 | - [Classes](#classes)
21 | - [Interfaces](#interfaces)
22 | - [Enums](#enums)
23 | - [Modules](#modules)
24 |
25 | ---
26 |
27 | ## Naming
28 |
29 | ### Pick one naming convention and stick to it
30 |
31 | Any form of naming conventions (`camelCase`, `PascalCase`, or `snake_case`) are allowed, as long as you pick one and stick with it throughout the project.
32 |
33 | > An exception to this rule would be when there are instances where it is **required** to use a certain naming convention, e.g. `PascalCase` for React components.
34 |
35 | ### Keep all names clear and concise
36 |
37 | Use filenames that are as clear and standard as possible. Strive for names no longer than 2-3 words, with unabbreviated phrases.
38 |
39 | - **Good example:** `findPathOptions.ts`
40 | - **Bad example:** `fpOpts.ts`
41 |
42 | For naming functions, or methods inside classes, refer to the [A/HC/LC pattern](../details/naming-cheatsheet#ahclc-pattern).
43 |
44 | ### Test files
45 |
46 | All test files must be written either separately inside a `__tests__/` folder, or within the same folder with a `.test.{js,ts,tsx}` suffix.
47 |
48 | ### Autogenerated files
49 |
50 | All auto-generated files must be written either separately inside a `__generated__/` folder, or within the same folder with a `.generated.{js,ts,tsx}` suffix.
51 |
52 | > Make sure to ignore these files in your TSLint/Prettier config.
53 |
54 | ## Indentation & Line length
55 |
56 | ### Use a 2-space indentation
57 |
58 | Using space indentation ensures that indentation will look the same on all IDEs.
59 |
60 | ### Lines shouldn't exceed 120 characters
61 |
62 | This is how long most modern screens could display monospace text inside any window without wrapping.
63 |
64 | ## Style
65 |
66 | ### Semicolons
67 |
68 | Yes.
69 |
70 | ```ts
71 | // Bad example
72 | const maxThreshold = 25
73 |
74 | // Good example
75 | const maxThreshold = 25;
76 | ```
77 |
78 | ### Trailing comma
79 |
80 | It is recommended to include a trailing comma in multiline array/object statements. This will lead to cleaner git diffs.
81 |
82 | ```js
83 | // Bad example
84 | const hero = {
85 | firstName: 'Ada',
86 | lastName: 'Lovelace',
87 | birthYear: 1815,
88 | superPower: 'computers'
89 | };
90 |
91 | // Good example
92 | const hero = {
93 | firstName: 'Ada',
94 | lastName: 'Lovelace',
95 | birthYear: 1815,
96 | superPower: 'computers',
97 | };
98 | ```
99 |
100 | > Leaving the trailing comma on used to be a problem with legacy JavaScript, but ES6 no longer has that issue. Also, tools like Babel automatically removes the additional comma when compiling to older JavaScript.
101 |
102 | ## Types
103 |
104 | ### Avoid `any`
105 |
106 | The whole point of TypeScript is to be more specific than this. So when you can, try to replace `any` with a more specific type declaration, or use `unknown` to force explicit type-checking of external types.
107 |
108 | ### Prefer `undefined` over `null`.
109 |
110 | When dealing with code that uses `null` (e.g. in HTML selectors or Redux), these should be kept isolated using selectors.
111 |
112 | ### Use `// @ts-ignore` comment to ignore type errors
113 |
114 | If a type error cannot be fixed for some reason, put a `// @ts-ignore` comment above the line with an explanation.
115 |
116 | ```ts
117 | // @ts-ignore: doThing() api is changed on version 3.0 but the typings haven't been updated yet
118 | const thing = doThing(one, two);
119 | ```
120 |
121 | > Note that these should be treated as TODO items, since they're type errors that should be fixed next time there's a chance.
122 |
123 | ### Use PascalCase when declaring types.
124 |
125 | ```ts
126 | // Bad example
127 | type responseObject = {}
128 |
129 | // Good example
130 | type ResponseObject = {}
131 | ```
132 |
133 | ## Functions
134 |
135 | ### Declare function return type
136 |
137 | If declaring a function, you should always specify the return type, even if it is nothing (i.e. `void`.)
138 |
139 | ```typescript
140 | // Bad example
141 | function healthCheck() {
142 | return fetch(apiUrl + '/healthCheck');
143 | }
144 |
145 | // Good example
146 | function healthCheck(): Promise {
147 | return fetch(apiUrl + '/healthCheck');
148 | }
149 | ```
150 |
151 | ### Declare function argument type
152 |
153 | The type of a function's arguments must be declared, even if it's `any`.
154 |
155 | ```ts
156 | // Bad example
157 | function add(a, b): number {
158 | return a + b;
159 | }
160 |
161 | // Good example
162 | function add(a: number, b: number): number {
163 | return a + b
164 | }
165 | ```
166 |
167 | ## Classes
168 |
169 | ### Declare access modifiers for each class property
170 |
171 | You should always specify whether a class property is `public`, `private`, or `protected`.
172 |
173 | ```ts
174 | class Button extends React.Component {
175 | constructor() {}
176 |
177 | // Bad example
178 | render(): JSX.Element {}
179 |
180 | // Good example
181 | public componentDidMount(): void {}
182 | }
183 | ```
184 |
185 | > React component lifecycles are generally classified as `public`, so use that whenever you come across one.
186 |
187 | ## Interfaces
188 |
189 | ### Use PascalCase when declaring interfaces.
190 |
191 | ```ts
192 | // Bad example
193 | interface checkoutButtonProps {}
194 |
195 | // Good example
196 | interface CheckoutButtonProps {}
197 | ```
198 |
199 | ### Don't use `I` as a prefix when declaring interfaces.
200 |
201 | This convention is a leftover from early-day TS when people who mainly do C# started trying out TS, and is generally frowned upon nowadays, especially in frontend TS code.
202 |
203 | We avoid prefixing interfaces with `I` specifically in the frontend.
204 |
205 | ```ts
206 | // Bad example
207 | interface ICheckoutButtonProps {}
208 |
209 | // Good example
210 | interface CheckoutButtonProps {}
211 | ```
212 |
213 | ## Enums
214 |
215 | ### Use PascalCase when declaring enums.
216 |
217 | ```ts
218 | // Bad example
219 | enum botStates {}
220 |
221 | // Good example
222 | enum BotStates {}
223 | ```
224 |
225 | ### Avoid `const` enums
226 |
227 | Tools like Babel [don't support this syntax](https://babeljs.io/docs/en/babel-plugin-transform-typescript.html#caveats). Use regular enums instead, or just use a plain old JS object.
228 |
229 | ## Modules
230 |
231 | ### Prefer using a single entry point
232 |
233 | When exporting modules from multiple files within the same folder, collect those exports inside an `index.js` file in the root level of that folder.
234 |
235 | ```
236 | components/
237 | └── Button/
238 | ├── index.ts
239 | ├── Button.tsx
240 | ├── LinkButton.tsx
241 | ├── HollowButton.tsx
242 | └── IconicButton.tsx
243 | ```
244 |
--------------------------------------------------------------------------------
/general/production-level-code.md:
--------------------------------------------------------------------------------
1 | # Production Level Code Guidelines
2 | ## Production Level Code
3 | Program we write should be correct, clear, efficient, and secure.
4 |
5 | **Correct** means that our program is done according to acceptance criteria, and have test to make sure it is indeed pass that acceptance criteria.
6 |
7 | **Clear**
8 |
9 | > Any fool can write code that a computer can understand. Good programmers write code that humans can understand. - Martin Fowler
10 |
11 | **The key to clear code is you need to write it for the sake for your friend to read, not just for computers to run.**
12 |
13 | Your code should be written as if it is written in English. Simple, straightforward, no hidden meaning.
14 |
15 | ```python
16 | is_valid_name = validate_name(fullname)
17 |
18 | return "ok" if is_valid_name else "not ok"
19 | ```
20 |
21 | It should be readable, so that we can actually skim it, read fast, and can understand the meaning just by reading it at first time without having to look in detail. Other engineers who look at the code,should understand a glimpse of what we’ve done by skimming the code. More of this later.
22 |
23 | **Efficient**
24 |
25 | After our code is correct and clear, it should be efficient in terms of time and space complexity. We should use proper data structures and efficient algorithm for a problem we try to solve. Understand trade-offs between time and space usage, then adopt the most efficient way given problem we have at hands.
26 |
27 | For example in Python, for checking for a value in an iterable (tuple, list, set, dictionary), use dictionary or set, it will give constant O(1) time retrieval instead of O(n).
28 |
29 | ```python
30 | # don't do this
31 | data = [2,3,1,2,4,5]
32 | found = 2 in data
33 |
34 | # do this
35 | data = {2,3,1,2,4,5}
36 | found = 2 in data
37 |
38 | ```
39 |
40 | **Secure**
41 |
42 | Follow [OWASP Top 10](https://owasp.org/www-project-top-ten/) for web application security risk.
43 |
44 | Implements and assess them regularly.
45 |
46 | Tell your tech leads if you encounter issue about this.
47 |
48 | ### Writing Correct Code and Being Defensive
49 | Oftenly, we solve a given problem by writing program just to make sure that it is finished. It is compiled, test against a simple value, test against wrong value, seems correct, think it’s done, and ship it. But, things that looks correct for one case, could be incorrect for others. A function that needs an unsigned integer, but inputted a signed one can cause incorrect results, and at some case devastating.
50 |
51 | So, how can we make sure our code is correct?
52 |
53 | #### Write Proper Test Cases
54 | Write proper test cases ensuring that our code is correct for every possible values.
55 |
56 | *Healthy programs have code coverage about 70-75 percent*.
57 |
58 | You can try some problems at LeetCode, and see how many test cases written to make sure that the program is correct.
59 |
60 | #### Defensive Programming
61 | Make sure function and methods are defensive against invalid values, such as nulls.
62 |
63 | Throw exception or assertion early helps too. Fail fast early will help you go a long way.
64 |
65 | For example
66 |
67 | ```python
68 | def add_number(first: int, second: int):
69 | assert first is not None, “first number should not be None”
70 | assert second is not None, “second number should not be None”
71 |
72 | return first + second
73 |
74 | ```
75 |
76 | Also, never ever ever ever silence an exception catch. This will produce hard-to-debug-nasty bug.
77 |
78 | ```python
79 | try:
80 | do_things_exception_throwing()
81 | except Exception e:
82 | pass // NEVER DO THIS! THIS IS EVIL!
83 | ```
84 |
85 | Some modern programming language like Scala has an Optional type to helps nullability check. Use it, it will prevent your program from crashes, because of the infamous null pointer exception.
86 |
87 | ### Learn More About Computer Science
88 |
89 | #### Algorithm Complexity
90 |
91 | Learn Big O Notation and what’s the meaning of it.
92 |
93 | You should learn this to understand the cost of algorithm you create to solve a problem, given number of N.
94 |
95 | Source: [Big O Notation | Interview Cake](https://www.interviewcake.com/article/python3/big-o-notation-time-and-space-complexity?)
96 |
97 | #### Learn Common Data Structures
98 |
99 | Understand commonly used data sructures:
100 |
101 | - Linked List
102 | - Array
103 | - Set
104 | - Map / Dictionary / HashMap
105 | - Tree
106 | - Queue
107 | - Stack
108 |
109 | You can learn it interactively on LeetCode [learn page](https://leetcode.com/explore/learn/).
110 |
111 | #### Less is more
112 | By minimizing what we need to do to achieve something, we can do more.
113 |
114 | Strive to write less code, simplify everything.
115 |
116 | You can start by writing a lot of code, then you need to refactor it to produce leaner code.
117 |
118 | #### There are tradeoffs for everything
119 | In computer science, there is no silver bullet, no single solution for every problem out there, there is only an optimal solution and non-optimal solution.
120 |
121 | **Our goal is to use optimal solution given the case**
122 |
123 | For example, on recursion vs iterative approach.
124 |
125 | Unoptimise recursion is simple and fairly easy to read, but it will produce N stack that causes famous Stack Overflow error. While iterative approach is ease on memory usage but not simple to grasp.
126 |
127 | Another example, doing linear search on a list is easy to do, but with large number of elements, in worst case scenario (target element is in the last element), it will be slow. Use binary search instead.
128 |
129 | So make sure you *understand what common algorithms*, like brute force, greedy, dynamic programming, sorting, etc *and common data structures*, like array, linked-list, set, map, tree, stack, and queue *and its tradeoffs*.
130 |
131 | ### Writing Clear Code
132 |
133 | #### Use clear names for every variables, functions, and methods
134 | Don’t make readers need to guess what it is by looking at implementations details.
135 | Unless it has type inference, add types to clarify its data types
136 |
137 | ```python
138 | # don't do this
139 | value = 12
140 | usr = {"id": "qwewq12421", "name":"mamazo", "age": 17}
141 |
142 | def get_usr():
143 | return {"id": "qwewq12421", "name":"mamazo", "age": 17}
144 |
145 | # do this
146 | REQUEST_TIMEOUT_S = 12
147 | active_user = {"id": "qwewq12421", "name":"mamazo", "age": 17}
148 |
149 | def get_active_user():
150 | return {"id": "qwewq12421", "name":"mamazo", "age": 17}
151 | ```
152 |
153 | More on this in [Naming Cheatsheet](../details/naming-cheatsheet#readme)
154 |
155 | #### Use comment to explain vague part of the code. Don’t explain each lines
156 |
157 | ```javascript
158 | // don't do this
159 | function getUsername(fullname) {
160 | // split names into array
161 | const names = fullname.split(" ");
162 |
163 | // get names length
164 | const nameLength = text.split(" ").length;
165 |
166 | // create username
167 | const username = names[0] + "." + names[nameLength-1];
168 | return nameLength === 1 ? fullname : username;
169 | }
170 |
171 | // do this
172 | function getUsername(fullname) {
173 | const names = fullname.split(" ");
174 | const nameLength = text.split(" ").length;
175 | const username = names[0] + "." + names[nameLength-1]; // . format
176 | return nameLength === 1 ? fullname : username;
177 | }
178 | ```
179 |
180 | #### Do One Thing
181 | Most of bugs and complexities in codes happens by writing one thing to be 2 or more things.
182 |
183 | Let’s take a look at this code:
184 |
185 | ```typescript
186 | public async closeTicket(partnerId: string, channelId: string): Promise {
187 | const id = partnerId + "~" + channelId;
188 | const deleteHandover = await this.redisRepo.srem(this.HANDOVER_KEY, id);
189 | const deleteRequest = await this.redisRepo.srem(this.REQUEST_KEY, id);
190 | return Boolean(deleteHandover) || Boolean(deleteRequest);
191 | }
192 |
193 | public async closeTicketFromUser(partnerId: string, channelId: string): Promise {
194 | const id = partnerId + "~" + channelId;
195 | const channel = await this.channelManager.getChannel(channelId);
196 | const agent = await this.agentManager.getAgent(channel.agentId);
197 | const options = {
198 | body: {
199 | id,
200 | },
201 | json: true,
202 | method: "POST",
203 | url: agent.closeUrl,
204 | };
205 | await request(options);
206 |
207 | return await this.closeTicket(partnerId, channelId); // this makes tightly coupled wih closeTicket
208 | }
209 | ```
210 |
211 | `closeTicketFromUser` has dependencies with `closeTicket` and `closeTicket` called redis to remove a ticket id from a set in redis.
212 |
213 | `closeTicketFromUser` tightly coupled with `closeTicket`, when we want to just call the API without having to remove the state we can’t do that without separating them.
214 |
215 | We can refactor the code into:
216 |
217 | ```typescript
218 | public async closeTicket(partnerId: string, channelId: string): Promise {
219 | const id = partnerId + "~" + channelId;
220 | const deleteHandover = await this.redisRepo.srem(this.HANDOVER_KEY, id);
221 | const deleteRequest = await this.redisRepo.srem(this.REQUEST_KEY, id);
222 | return Boolean(deleteHandover) || Boolean(deleteRequest);
223 | }
224 |
225 | public async closeTicketFromUser(partnerId: string, channelId: string): Promise