@kollors/deep-json-server 1.0.0-alpha.6 → 1.0.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +344 -230
  2. package/README.ru.md +341 -227
  3. package/dist/bin/deep-json-server.js +1 -1
  4. package/dist/bin/deep-json-server.js.map +1 -1
  5. package/dist/index.d.ts +10 -8
  6. package/dist/index.js +3 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/src/auth/contract.d.ts +3 -2
  9. package/dist/src/auth/contract.js.map +1 -1
  10. package/dist/src/auth/password.d.ts +9 -0
  11. package/dist/src/auth/password.js +12 -0
  12. package/dist/src/auth/password.js.map +1 -1
  13. package/dist/src/auth/routes.d.ts +3 -0
  14. package/dist/src/auth/routes.js +3 -0
  15. package/dist/src/auth/routes.js.map +1 -1
  16. package/dist/src/auth/service.d.ts +21 -0
  17. package/dist/src/auth/service.js +38 -7
  18. package/dist/src/auth/service.js.map +1 -1
  19. package/dist/src/cli/index.d.ts +7 -0
  20. package/dist/src/{cli.js → cli/index.js} +32 -14
  21. package/dist/src/cli/index.js.map +1 -0
  22. package/dist/src/{constants.d.ts → core/constants.d.ts} +1 -1
  23. package/dist/src/{constants.js → core/constants.js} +1 -1
  24. package/dist/src/core/constants.js.map +1 -0
  25. package/dist/src/core/database.d.ts +50 -0
  26. package/dist/src/{database.js → core/database.js} +21 -1
  27. package/dist/src/core/database.js.map +1 -0
  28. package/dist/src/core/engine.d.ts +64 -0
  29. package/dist/src/{engine.js → core/engine.js} +64 -18
  30. package/dist/src/core/engine.js.map +1 -0
  31. package/dist/src/{errors.d.ts → core/errors.d.ts} +4 -1
  32. package/dist/src/core/errors.js +12 -0
  33. package/dist/src/core/errors.js.map +1 -0
  34. package/dist/src/core/http-errors.d.ts +9 -0
  35. package/dist/src/core/http-errors.js +15 -0
  36. package/dist/src/core/http-errors.js.map +1 -0
  37. package/dist/src/core/lifecycle/mutation.d.ts +49 -0
  38. package/dist/src/core/lifecycle/mutation.js +170 -0
  39. package/dist/src/core/lifecycle/mutation.js.map +1 -0
  40. package/dist/src/core/lifecycle/options.d.ts +20 -0
  41. package/dist/src/core/lifecycle/options.js +21 -0
  42. package/dist/src/core/lifecycle/options.js.map +1 -0
  43. package/dist/src/core/model.d.ts +130 -0
  44. package/dist/src/{model.js → core/model.js} +106 -10
  45. package/dist/src/core/model.js.map +1 -0
  46. package/dist/src/{mutations → core/mutations}/write.d.ts +3 -2
  47. package/dist/src/{mutations → core/mutations}/write.js +14 -4
  48. package/dist/src/core/mutations/write.js.map +1 -0
  49. package/dist/src/core/pagination.d.ts +10 -0
  50. package/dist/src/{pagination.js → core/pagination.js} +3 -0
  51. package/dist/src/core/pagination.js.map +1 -0
  52. package/dist/src/core/paths.d.ts +16 -0
  53. package/dist/src/{paths.js → core/paths.js} +12 -0
  54. package/dist/src/core/paths.js.map +1 -0
  55. package/dist/src/core/query/contract.d.ts +6 -0
  56. package/dist/src/{query → core/query}/contract.js +3 -0
  57. package/dist/src/core/query/contract.js.map +1 -0
  58. package/dist/src/core/query/filter.d.ts +6 -0
  59. package/dist/src/{query → core/query}/filter.js +18 -4
  60. package/dist/src/core/query/filter.js.map +1 -0
  61. package/dist/src/core/query/options.d.ts +30 -0
  62. package/dist/src/{query → core/query}/options.js +12 -0
  63. package/dist/src/core/query/options.js.map +1 -0
  64. package/dist/src/core/records.d.ts +46 -0
  65. package/dist/src/{records.js → core/records.js} +24 -3
  66. package/dist/src/core/records.js.map +1 -0
  67. package/dist/src/core/relation-metadata.d.ts +15 -0
  68. package/dist/src/{relation-metadata.js → core/relation-metadata.js} +7 -1
  69. package/dist/src/core/relation-metadata.js.map +1 -0
  70. package/dist/src/core/types.d.ts +10 -0
  71. package/dist/src/{types.js.map → core/types.js.map} +1 -1
  72. package/dist/src/core/utils.d.ts +56 -0
  73. package/dist/src/core/utils.js +102 -0
  74. package/dist/src/core/utils.js.map +1 -0
  75. package/dist/src/files/contract.d.ts +33 -0
  76. package/dist/src/files/contract.js +25 -3
  77. package/dist/src/files/contract.js.map +1 -1
  78. package/dist/src/files/disk-store.d.ts +3 -0
  79. package/dist/src/files/disk-store.js +27 -3
  80. package/dist/src/files/disk-store.js.map +1 -1
  81. package/dist/src/files/http.d.ts +8 -3
  82. package/dist/src/files/http.js +9 -0
  83. package/dist/src/files/http.js.map +1 -1
  84. package/dist/src/files/index.d.ts +4 -3
  85. package/dist/src/files/index.js +3 -1
  86. package/dist/src/files/index.js.map +1 -1
  87. package/dist/src/files/memory-store.d.ts +4 -1
  88. package/dist/src/files/memory-store.js +8 -2
  89. package/dist/src/files/memory-store.js.map +1 -1
  90. package/dist/src/files/routes.d.ts +3 -0
  91. package/dist/src/files/routes.js +25 -1
  92. package/dist/src/files/routes.js.map +1 -1
  93. package/dist/src/graphql/entry.d.ts +2 -2
  94. package/dist/src/graphql/entry.js.map +1 -1
  95. package/dist/src/graphql/lazy.d.ts +10 -0
  96. package/dist/src/graphql/lazy.js +13 -0
  97. package/dist/src/graphql/lazy.js.map +1 -0
  98. package/dist/src/graphql/preflight.d.ts +4 -1
  99. package/dist/src/graphql/preflight.js +3 -0
  100. package/dist/src/graphql/preflight.js.map +1 -1
  101. package/dist/src/graphql/public.d.ts +10 -2
  102. package/dist/src/graphql/public.js +10 -4
  103. package/dist/src/graphql/public.js.map +1 -1
  104. package/dist/src/graphql/resolvers.d.ts +10 -2
  105. package/dist/src/graphql/resolvers.js +8 -2
  106. package/dist/src/graphql/resolvers.js.map +1 -1
  107. package/dist/src/graphql/routes.d.ts +6 -2
  108. package/dist/src/graphql/routes.js +6 -3
  109. package/dist/src/graphql/routes.js.map +1 -1
  110. package/dist/src/graphql/schema.d.ts +6 -0
  111. package/dist/src/{graphql.js → graphql/schema.js} +14 -11
  112. package/dist/src/graphql/schema.js.map +1 -0
  113. package/dist/src/graphql/write.d.ts +3 -0
  114. package/dist/src/graphql/write.js +3 -0
  115. package/dist/src/graphql/write.js.map +1 -1
  116. package/dist/src/openapi/auth.d.ts +13 -0
  117. package/dist/src/{auth/openapi.js → openapi/auth.js} +15 -5
  118. package/dist/src/openapi/auth.js.map +1 -0
  119. package/dist/src/openapi/document.d.ts +5 -2
  120. package/dist/src/openapi/document.js +29 -33
  121. package/dist/src/openapi/document.js.map +1 -1
  122. package/dist/src/openapi/entry.d.ts +2 -2
  123. package/dist/src/openapi/entry.js.map +1 -1
  124. package/dist/src/openapi/files.d.ts +6 -0
  125. package/dist/src/{files/openapi.js → openapi/files.js} +6 -3
  126. package/dist/src/openapi/files.js.map +1 -0
  127. package/dist/src/openapi/helpers.d.ts +10 -1
  128. package/dist/src/openapi/helpers.js +9 -0
  129. package/dist/src/openapi/helpers.js.map +1 -1
  130. package/dist/src/openapi/index.d.ts +7 -1
  131. package/dist/src/openapi/index.js +14 -5
  132. package/dist/src/openapi/index.js.map +1 -1
  133. package/dist/src/openapi/lazy.d.ts +11 -0
  134. package/dist/src/openapi/lazy.js +13 -0
  135. package/dist/src/openapi/lazy.js.map +1 -0
  136. package/dist/src/openapi/public.d.ts +10 -2
  137. package/dist/src/openapi/public.js +9 -3
  138. package/dist/src/openapi/public.js.map +1 -1
  139. package/dist/src/{types.d.ts → openapi/types.d.ts} +1 -10
  140. package/dist/src/openapi/types.js +2 -0
  141. package/dist/src/openapi/types.js.map +1 -0
  142. package/dist/src/rest/options.d.ts +11 -2
  143. package/dist/src/rest/options.js +12 -3
  144. package/dist/src/rest/options.js.map +1 -1
  145. package/dist/src/rest/projection.d.ts +10 -4
  146. package/dist/src/rest/projection.js +10 -4
  147. package/dist/src/rest/projection.js.map +1 -1
  148. package/dist/src/rest/routes.d.ts +6 -2
  149. package/dist/src/rest/routes.js +7 -3
  150. package/dist/src/rest/routes.js.map +1 -1
  151. package/dist/src/server/config.d.ts +79 -0
  152. package/dist/src/{config.js → server/config.js} +57 -19
  153. package/dist/src/server/config.js.map +1 -0
  154. package/dist/src/server/create.d.ts +18 -0
  155. package/dist/src/{server.js → server/create.js} +31 -23
  156. package/dist/src/server/create.js.map +1 -0
  157. package/dist/src/server/features.d.ts +15 -0
  158. package/dist/src/{features.js → server/features.js} +8 -2
  159. package/dist/src/server/features.js.map +1 -0
  160. package/dist/src/server/public.d.ts +3 -3
  161. package/dist/src/server/public.js +1 -1
  162. package/dist/src/server/public.js.map +1 -1
  163. package/package.json +1 -1
  164. package/dist/src/auth/openapi.d.ts +0 -10
  165. package/dist/src/auth/openapi.js.map +0 -1
  166. package/dist/src/cli.d.ts +0 -4
  167. package/dist/src/cli.js.map +0 -1
  168. package/dist/src/config.d.ts +0 -86
  169. package/dist/src/config.js.map +0 -1
  170. package/dist/src/constants.js.map +0 -1
  171. package/dist/src/database.d.ts +0 -20
  172. package/dist/src/database.js.map +0 -1
  173. package/dist/src/engine.d.ts +0 -36
  174. package/dist/src/engine.js.map +0 -1
  175. package/dist/src/errors.js +0 -9
  176. package/dist/src/errors.js.map +0 -1
  177. package/dist/src/features.d.ts +0 -9
  178. package/dist/src/features.js.map +0 -1
  179. package/dist/src/files/openapi.d.ts +0 -3
  180. package/dist/src/files/openapi.js.map +0 -1
  181. package/dist/src/graphql.d.ts +0 -3
  182. package/dist/src/graphql.js.map +0 -1
  183. package/dist/src/http/errors.d.ts +0 -6
  184. package/dist/src/http/errors.js +0 -3
  185. package/dist/src/http/errors.js.map +0 -1
  186. package/dist/src/model.d.ts +0 -72
  187. package/dist/src/model.js.map +0 -1
  188. package/dist/src/mutations/write.js.map +0 -1
  189. package/dist/src/pagination.d.ts +0 -7
  190. package/dist/src/pagination.js.map +0 -1
  191. package/dist/src/paths.d.ts +0 -7
  192. package/dist/src/paths.js.map +0 -1
  193. package/dist/src/query/contract.d.ts +0 -3
  194. package/dist/src/query/contract.js.map +0 -1
  195. package/dist/src/query/filter.d.ts +0 -3
  196. package/dist/src/query/filter.js.map +0 -1
  197. package/dist/src/query/options.d.ts +0 -18
  198. package/dist/src/query/options.js.map +0 -1
  199. package/dist/src/records.d.ts +0 -25
  200. package/dist/src/records.js.map +0 -1
  201. package/dist/src/relation-metadata.d.ts +0 -9
  202. package/dist/src/relation-metadata.js.map +0 -1
  203. package/dist/src/schema.d.ts +0 -8
  204. package/dist/src/schema.js +0 -13
  205. package/dist/src/schema.js.map +0 -1
  206. package/dist/src/server.d.ts +0 -12
  207. package/dist/src/server.js.map +0 -1
  208. package/dist/src/utils.d.ts +0 -12
  209. package/dist/src/utils.js +0 -58
  210. package/dist/src/utils.js.map +0 -1
  211. /package/dist/src/{types.js → core/types.js} +0 -0
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import process from 'node:process';
3
- import { runCli } from '../src/cli.js';
3
+ import { runCli } from '../src/cli/index.js';
4
4
  try {
5
5
  await runCli();
6
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"deep-json-server.js","sourceRoot":"","sources":["../../bin/deep-json-server.ts"],"names":[],"mappings":";AAEA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,IAAI,CAAC;IACH,MAAM,MAAM,EAAE,CAAC;AACjB,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"deep-json-server.js","sourceRoot":"","sources":["../../bin/deep-json-server.ts"],"names":[],"mappings":";AAEA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,IAAI,CAAC;IACH,MAAM,MAAM,EAAE,CAAC;AACjB,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,12 +1,14 @@
1
1
  export type { AuthConfig, AuthSession, AuthUser, AuthUserRecord } from './src/auth/contract.js';
2
2
  export { hashPassword } from './src/auth/public.js';
3
- export type { DatabaseConfig, DeepJsonServerConfig, FilesConfig, GraphqlConfig, MemoryFile, OpenapiConfig, ServerConfig } from './src/config.js';
4
- export type { ServerFeatures } from './src/features.js';
3
+ export type { EntityDefinition, Field, ModelSchema } from './src/core/model.js';
5
4
  export type { FileUpdate } from './src/files/contract.js';
6
5
  export type { FileMetadata } from './src/files/http.js';
7
- export type { EntityDefinition, Field, ModelSchema } from './src/model.js';
8
- export type { OpenapiOptions } from './src/schema.js';
9
- export { generateGraphql, generateOpenapi, writeGraphql, writeOpenapi } from './src/schema.js';
10
- export type { ServerFacade } from './src/server.js';
11
- export { createServer } from './src/server.js';
12
- export type { OpenapiDocument } from './src/types.js';
6
+ export { generateGraphql, writeGraphql } from './src/graphql/lazy.js';
7
+ export type { GraphqlOptions } from './src/graphql/public.js';
8
+ export { generateOpenapi, writeOpenapi } from './src/openapi/lazy.js';
9
+ export type { OpenapiOptions } from './src/openapi/public.js';
10
+ export type { OpenapiDocument } from './src/openapi/types.js';
11
+ export type { DatabaseConfig, DeepJsonServerConfig, FilesConfig, GraphqlConfig, MemoryFile, OpenapiConfig, ServerConfig } from './src/server/config.js';
12
+ export type { ServerFacade } from './src/server/create.js';
13
+ export { createServer } from './src/server/create.js';
14
+ export type { ServerFeatures } from './src/server/features.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { hashPassword } from './src/auth/public.js';
2
- export { generateGraphql, generateOpenapi, writeGraphql, writeOpenapi } from './src/schema.js';
3
- export { createServer } from './src/server.js';
2
+ export { generateGraphql, writeGraphql } from './src/graphql/lazy.js';
3
+ export { generateOpenapi, writeOpenapi } from './src/openapi/lazy.js';
4
+ export { createServer } from './src/server/create.js';
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOpD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/F,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIpD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAKtE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
@@ -1,12 +1,13 @@
1
1
  export interface AuthUser {
2
2
  id: string;
3
3
  username: string;
4
+ isAdmin: boolean;
4
5
  }
5
- export interface AuthUserRecord extends AuthUser {
6
+ export interface AuthUserRecord extends Omit<AuthUser, 'isAdmin'> {
7
+ isAdmin?: boolean;
6
8
  passwordHash: string;
7
9
  }
8
10
  export interface AuthConfig {
9
- enabled?: boolean;
10
11
  users: string | AuthUserRecord[];
11
12
  /** Session lifetime in seconds. Defaults to one hour. */
12
13
  expiresIn?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/auth/contract.ts"],"names":[],"mappings":"AAkBA,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAW,CAAC;AACpG,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAC5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC"}
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/auth/contract.ts"],"names":[],"mappings":"AAmBA,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAW,CAAC;AACpG,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAC5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC"}
@@ -1,4 +1,13 @@
1
+ /** Проверяет формат строки с параметрами scrypt, солью и хешем; пароль не проверяет.
2
+ * @example validPasswordHash('plain text') → false.
3
+ */
1
4
  export declare const validPasswordHash: (value: unknown) => value is string;
5
+ /** Создаёт хеш пароля со случайной солью и сохраняет параметры вычисления в строке.
6
+ * @example hashPassword('secret') → Promise<string> вида 'scrypt$16384$8$5$<соль>$<хеш>'; результат случаен.
7
+ */
2
8
  export declare function hashPassword(password: string): Promise<string>;
9
+ /** Сравнивает пароль с сохранённым хешем за постоянное время после вычисления scrypt.
10
+ * @example verifyPassword('secret', await hashPassword('secret')) → true; другой пароль → false.
11
+ */
3
12
  export declare function verifyPassword(password: string, encoded: string): Promise<boolean>;
4
13
  export declare const DUMMY_HASH: string;
@@ -3,10 +3,19 @@ import { MAX_PASSWORD_LENGTH } from './contract.js';
3
3
  // OWASP scrypt profile: N=2^14, r=8, p=5 (16 MiB memory).
4
4
  const PREFIX = 'scrypt$16384$8$5';
5
5
  const HASH_PATTERN = /^scrypt\$16384\$8\$5\$([0-9a-f]{32})\$([0-9a-f]{64})$/;
6
+ /** Проверяет формат строки с параметрами scrypt, солью и хешем; пароль не проверяет.
7
+ * @example validPasswordHash('plain text') → false.
8
+ */
6
9
  export const validPasswordHash = (value) => typeof value === 'string' && HASH_PATTERN.test(value);
10
+ /** Вычисляет 32 байта scrypt для пароля и заданной соли.
11
+ * @example derive('secret', Buffer.alloc(16)) → Promise<Buffer> длиной 32 байта; одинаковые входы дают одинаковый результат.
12
+ */
7
13
  const derive = (password, salt) => new Promise((resolve, reject) => {
8
14
  scrypt(password, salt, 32, { N: 16384, r: 8, p: 5 }, (error, key) => (error ? reject(error) : resolve(key)));
9
15
  });
16
+ /** Создаёт хеш пароля со случайной солью и сохраняет параметры вычисления в строке.
17
+ * @example hashPassword('secret') → Promise<string> вида 'scrypt$16384$8$5$<соль>$<хеш>'; результат случаен.
18
+ */
10
19
  export async function hashPassword(password) {
11
20
  if (typeof password !== 'string' || !password.length || password.length > MAX_PASSWORD_LENGTH)
12
21
  throw new Error(`Password must contain 1..${MAX_PASSWORD_LENGTH} characters`);
@@ -14,6 +23,9 @@ export async function hashPassword(password) {
14
23
  const hash = await derive(password, salt);
15
24
  return `${PREFIX}$${salt.toString('hex')}$${hash.toString('hex')}`;
16
25
  }
26
+ /** Сравнивает пароль с сохранённым хешем за постоянное время после вычисления scrypt.
27
+ * @example verifyPassword('secret', await hashPassword('secret')) → true; другой пароль → false.
28
+ */
17
29
  export async function verifyPassword(password, encoded) {
18
30
  const parts = HASH_PATTERN.exec(encoded);
19
31
  if (!parts)
@@ -1 +1 @@
1
- {"version":3,"file":"password.js","sourceRoot":"","sources":["../../../src/auth/password.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,0DAA0D;AAC1D,MAAM,MAAM,GAAG,kBAAkB,CAAC;AAClC,MAAM,YAAY,GAAG,uDAAuD,CAAC;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5H,MAAM,MAAM,GAAG,CAAC,QAAgB,EAAE,IAAY,EAAmB,EAAE,CACjE,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC9B,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC/G,CAAC,CAAC,CAAC;AACL,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,mBAAmB;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,mBAAmB,aAAa,CAAC,CAAC;IAC7K,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC1C,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AACrE,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB,EAAE,OAAe;IACpE,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACpE,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAC/D,CAAC;AACD,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC"}
1
+ {"version":3,"file":"password.js","sourceRoot":"","sources":["../../../src/auth/password.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,0DAA0D;AAC1D,MAAM,MAAM,GAAG,kBAAkB,CAAC;AAClC,MAAM,YAAY,GAAG,uDAAuD,CAAC;AAC7E;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5H;;GAEG;AACH,MAAM,MAAM,GAAG,CAAC,QAAgB,EAAE,IAAY,EAAmB,EAAE,CACjE,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC9B,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC/G,CAAC,CAAC,CAAC;AACL;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,mBAAmB;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,mBAAmB,aAAa,CAAC,CAAC;IAC7K,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC1C,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AACrE,CAAC;AACD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB,EAAE,OAAe;IACpE,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACpE,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAC/D,CAAC;AACD,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC"}
@@ -1,3 +1,6 @@
1
1
  import type { FastifyInstance } from 'fastify';
2
2
  import type { AuthService } from './service.js';
3
+ /** Регистрирует вход, выход и получение текущего пользователя, запрещая кеширование ответов.
4
+ * @example После регистрации ответы содержат Cache-Control: no-store; функция возвращает undefined.
5
+ */
3
6
  export declare function registerAuthRoutes(server: FastifyInstance, auth: AuthService): void;
@@ -1,4 +1,7 @@
1
1
  import { AUTH_PATHS } from './contract.js';
2
+ /** Регистрирует вход, выход и получение текущего пользователя, запрещая кеширование ответов.
3
+ * @example После регистрации ответы содержат Cache-Control: no-store; функция возвращает undefined.
4
+ */
2
5
  export function registerAuthRoutes(server, auth) {
3
6
  server.register(async (app) => {
4
7
  app.addHook('onRequest', async (_request, reply) => {
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/auth/routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,UAAU,kBAAkB,CAAC,MAAuB,EAAE,IAAiB;IAC3E,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAC5B,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;YACjD,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACxE,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;QAClF,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/auth/routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAuB,EAAE,IAAiB;IAC3E,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAC5B,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;YACjD,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACxE,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;QAClF,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -6,13 +6,34 @@ export declare class AuthService {
6
6
  private pendingLogins;
7
7
  private closed;
8
8
  constructor(users: Map<string, AuthUserRecord>, expiresIn: number);
9
+ /** Проверяет пароль, создаёт сессию и возвращает токен с публичными данными пользователя.
10
+ * @example Корректные username и password → { accessToken, expiresIn, user }; неверный пароль → исключение.
11
+ */
9
12
  login(body: unknown): Promise<AuthSession>;
13
+ /** Проверяет Bearer-токен и возвращает копию публичных данных пользователя.
14
+ * @example Заголовок 'Bearer <действительный токен>' → { id, username, isAdmin }.
15
+ */
10
16
  me(authorization: unknown): AuthUser;
17
+ /** Проверяет токен и удаляет соответствующую сессию.
18
+ * @example Действительный токен → { success: true }; повторный выход с ним → ошибка.
19
+ */
11
20
  logout(authorization: unknown): {
12
21
  success: boolean;
13
22
  };
23
+ /** Запрещает новые входы и очищает учётные записи и сессии в памяти.
24
+ * @example close() → undefined; последующий login() → отказ.
25
+ */
14
26
  close(): void;
27
+ /** Находит сессию по хешу токена и проверяет срок; просроченную сессию удаляет.
28
+ * @example Действительный Bearer-токен → [ключ, сессия]; отсутствующий или истёкший → ошибка.
29
+ */
15
30
  private session;
31
+ /** Удаляет из памяти сессии, срок которых истёк к текущему моменту.
32
+ * @example Одна истёкшая и одна действующая сессия → остаётся одна действующая; результат undefined.
33
+ */
16
34
  private prune;
17
35
  }
36
+ /** Читает и проверяет учётные записи из массива или файла и создаёт хранилище сессий в памяти.
37
+ * @example createAuthService({ users: [] }) → Promise<AuthService>; повторяющиеся id → ошибка.
38
+ */
18
39
  export declare function createAuthService(config: AuthConfig): Promise<AuthService>;
@@ -1,12 +1,21 @@
1
1
  import { createHash, randomBytes } from 'node:crypto';
2
2
  import { readFile } from 'node:fs/promises';
3
- import { domainError } from '../errors.js';
4
- import { isObject } from '../utils.js';
3
+ import { domainError } from '../core/errors.js';
4
+ import { hasOnlyKeys, isObject } from '../core/utils.js';
5
5
  import { DEFAULT_SESSION_SECONDS, MAX_PASSWORD_LENGTH, MAX_USERNAME_LENGTH } from './contract.js';
6
6
  import { DUMMY_HASH, validPasswordHash, verifyPassword } from './password.js';
7
+ /** Создаёт исключение отсутствия действительной сессии без раскрытия причины отказа.
8
+ * @example unauthorized() → Error с code = 'UNAUTHENTICATED'.
9
+ */
7
10
  const unauthorized = () => domainError('UNAUTHENTICATED', 'Invalid credentials or expired session');
11
+ /** Вычисляет SHA-256 строки в шестнадцатеричном виде для хранения вместо исходного токена.
12
+ * @example tokenKey('abc') → 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'.
13
+ */
8
14
  const tokenKey = (token) => createHash('sha256').update(token).digest('hex');
9
- const publicUser = (user) => ({ id: user.id, username: user.username });
15
+ /** Возвращает публичные поля пользователя в новом объекте; отсутствие isAdmin означает false.
16
+ * @example publicUser({ id: '1', username: 'anna' }) → { id: '1', username: 'anna', isAdmin: false }.
17
+ */
18
+ const publicUser = (user) => ({ id: user.id, username: user.username, isAdmin: user.isAdmin ?? false });
10
19
  export class AuthService {
11
20
  users;
12
21
  expiresIn;
@@ -17,9 +26,12 @@ export class AuthService {
17
26
  this.users = users;
18
27
  this.expiresIn = expiresIn;
19
28
  }
29
+ /** Проверяет пароль, создаёт сессию и возвращает токен с публичными данными пользователя.
30
+ * @example Корректные username и password → { accessToken, expiresIn, user }; неверный пароль → исключение.
31
+ */
20
32
  async login(body) {
21
33
  if (!isObject(body) ||
22
- Object.keys(body).some((key) => !['username', 'password'].includes(key)) ||
34
+ !hasOnlyKeys(body, ['username', 'password']) ||
23
35
  typeof body.username !== 'string' ||
24
36
  !body.username.length ||
25
37
  body.username.length > MAX_USERNAME_LENGTH ||
@@ -51,20 +63,32 @@ export class AuthService {
51
63
  this.sessions.set(tokenKey(accessToken), { user: identity, expiresAt: Date.now() + this.expiresIn * 1000 });
52
64
  return { accessToken, expiresIn: this.expiresIn, user: publicUser(identity) };
53
65
  }
66
+ /** Проверяет Bearer-токен и возвращает копию публичных данных пользователя.
67
+ * @example Заголовок 'Bearer <действительный токен>' → { id, username, isAdmin }.
68
+ */
54
69
  me(authorization) {
55
70
  const [, session] = this.session(authorization);
56
71
  return publicUser(session.user);
57
72
  }
73
+ /** Проверяет токен и удаляет соответствующую сессию.
74
+ * @example Действительный токен → { success: true }; повторный выход с ним → ошибка.
75
+ */
58
76
  logout(authorization) {
59
77
  const [key] = this.session(authorization);
60
78
  this.sessions.delete(key);
61
79
  return { success: true };
62
80
  }
81
+ /** Запрещает новые входы и очищает учётные записи и сессии в памяти.
82
+ * @example close() → undefined; последующий login() → отказ.
83
+ */
63
84
  close() {
64
85
  this.closed = true;
65
86
  this.sessions.clear();
66
87
  this.users.clear();
67
88
  }
89
+ /** Находит сессию по хешу токена и проверяет срок; просроченную сессию удаляет.
90
+ * @example Действительный Bearer-токен → [ключ, сессия]; отсутствующий или истёкший → ошибка.
91
+ */
68
92
  session(authorization) {
69
93
  if (typeof authorization !== 'string')
70
94
  throw unauthorized();
@@ -79,6 +103,9 @@ export class AuthService {
79
103
  }
80
104
  return [key, session];
81
105
  }
106
+ /** Удаляет из памяти сессии, срок которых истёк к текущему моменту.
107
+ * @example Одна истёкшая и одна действующая сессия → остаётся одна действующая; результат undefined.
108
+ */
82
109
  prune() {
83
110
  const now = Date.now();
84
111
  for (const [key, session] of this.sessions)
@@ -86,6 +113,9 @@ export class AuthService {
86
113
  this.sessions.delete(key);
87
114
  }
88
115
  }
116
+ /** Читает и проверяет учётные записи из массива или файла и создаёт хранилище сессий в памяти.
117
+ * @example createAuthService({ users: [] }) → Promise<AuthService>; повторяющиеся id → ошибка.
118
+ */
89
119
  export async function createAuthService(config) {
90
120
  const records = typeof config.users === 'string' ? JSON.parse(await readFile(config.users, 'utf8')) : config.users;
91
121
  if (!Array.isArray(records))
@@ -94,18 +124,19 @@ export async function createAuthService(config) {
94
124
  const ids = new Set();
95
125
  for (const record of records) {
96
126
  if (!isObject(record) ||
97
- Object.keys(record).some((key) => !['id', 'username', 'passwordHash'].includes(key)) ||
127
+ !hasOnlyKeys(record, ['id', 'username', 'passwordHash', 'isAdmin']) ||
98
128
  typeof record.id !== 'string' ||
99
129
  !record.id.trim() ||
100
130
  typeof record.username !== 'string' ||
101
131
  !record.username.trim() ||
102
132
  record.username.length > MAX_USERNAME_LENGTH ||
103
- !validPasswordHash(record.passwordHash))
133
+ !validPasswordHash(record.passwordHash) ||
134
+ (record.isAdmin !== undefined && typeof record.isAdmin !== 'boolean'))
104
135
  throw new Error('Auth users require id, username and a valid passwordHash');
105
136
  if (ids.has(record.id) || users.has(record.username))
106
137
  throw new Error('Auth user ids and usernames must be unique');
107
138
  ids.add(record.id);
108
- users.set(record.username, { id: record.id, username: record.username, passwordHash: record.passwordHash });
139
+ users.set(record.username, { id: record.id, username: record.username, passwordHash: record.passwordHash, isAdmin: record.isAdmin ?? false });
109
140
  }
110
141
  return new AuthService(users, config.expiresIn ?? DEFAULT_SESSION_SECONDS);
111
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/auth/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/auth/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { createConfiguredServer } from '../server/create.js';
2
+ /** Разбирает аргументы командной строки и запускает сервер либо экспорт; справку и версию пишет в stdout.
3
+ * @example runCli(['--help']) → Promise<void> и текст справки без запуска сервера.
4
+ */
5
+ export declare function runCli(args?: string[], services?: {
6
+ createServer: typeof createConfiguredServer;
7
+ }): Promise<void>;
@@ -1,18 +1,20 @@
1
1
  import process from 'node:process';
2
- import { configure, configureGeneration, readConfigModule } from './config.js';
3
- import { DEFAULT_HOST, DEFAULT_PORT, VERSION } from './constants.js';
4
- import { resolveFeatures } from './features.js';
5
- import { inputPaths, validateExportPaths } from './paths.js';
6
- import { generateGraphql, generateOpenapi, writeGraphql, writeOpenapi } from './schema.js';
7
- import { createConfiguredServer } from './server.js';
8
- import { isObject } from './utils.js';
2
+ import { DEFAULT_HOST, DEFAULT_PORT, VERSION } from '../core/constants.js';
3
+ import { inputPaths, validateExportPaths } from '../core/paths.js';
4
+ import { isObject } from '../core/utils.js';
5
+ import { generateGraphql, writeGraphql } from '../graphql/lazy.js';
6
+ import { generateOpenapi, writeOpenapi } from '../openapi/lazy.js';
7
+ import { configure, configureGeneration, readConfigModule } from '../server/config.js';
8
+ import { createConfiguredServer } from '../server/create.js';
9
+ import { resolveFeatures } from '../server/features.js';
9
10
  const HELP_TEXT = `Deep JSON Server
10
11
 
11
12
  Usage:
12
13
  deep-json-server [options] <server.config.js>
13
14
  deep-json-server generate <openapi|graphql|openapi,graphql> <server.config.js>
14
15
 
15
- --auth Enable REST authentication and its OpenAPI description
16
+ --timestamps Track record creation and update times
17
+ --soft-delete Mark deleted records instead of removing them
16
18
  --files Enable file routes
17
19
  --graphql Enable the GraphQL endpoint
18
20
  --openapi Enable the OpenAPI endpoint
@@ -22,6 +24,9 @@ Usage:
22
24
  --version, -v Show version
23
25
 
24
26
  Files are enabled when configured. Generate writes schemas to the configured paths.`;
27
+ /** Разбирает аргументы командной строки и запускает сервер либо экспорт; справку и версию пишет в stdout.
28
+ * @example runCli(['--help']) → Promise<void> и текст справки без запуска сервера.
29
+ */
25
30
  export async function runCli(args = process.argv.slice(2), services = { createServer: createConfiguredServer }) {
26
31
  if (args.includes('--help') || args.includes('-h')) {
27
32
  process.stdout.write(`${HELP_TEXT}\n`);
@@ -34,6 +39,7 @@ export async function runCli(args = process.argv.slice(2), services = { createSe
34
39
  const positional = [];
35
40
  const seen = new Set();
36
41
  const features = {};
42
+ const recordFlags = {};
37
43
  let host;
38
44
  let port;
39
45
  for (let index = 0; index < args.length; index++) {
@@ -42,7 +48,7 @@ export async function runCli(args = process.argv.slice(2), services = { createSe
42
48
  positional.push(arg);
43
49
  continue;
44
50
  }
45
- if (!['--files', '--graphql', '--openapi', '--auth', '--host', '--port'].includes(arg) || seen.has(arg))
51
+ if (!['--files', '--graphql', '--openapi', '--timestamps', '--soft-delete', '--host', '--port'].includes(arg) || seen.has(arg))
46
52
  throw new Error(`Неизвестный параметр или повтор: ${arg}`);
47
53
  seen.add(arg);
48
54
  if (arg === '--host' || arg === '--port') {
@@ -57,6 +63,10 @@ export async function runCli(args = process.argv.slice(2), services = { createSe
57
63
  port = Number(value);
58
64
  }
59
65
  }
66
+ else if (arg === '--timestamps')
67
+ recordFlags.timestamps = true;
68
+ else if (arg === '--soft-delete')
69
+ recordFlags.softDelete = true;
60
70
  else
61
71
  features[arg.slice(2)] = true;
62
72
  }
@@ -77,8 +87,12 @@ export async function runCli(args = process.argv.slice(2), services = { createSe
77
87
  throw new Error('config.server must be an object');
78
88
  const overrides = { host: host ?? serverOptions.host ?? process.env.HOST ?? DEFAULT_HOST, port: port ?? serverOptions.port ?? Number(process.env.PORT ?? DEFAULT_PORT) };
79
89
  const config = generate
80
- ? configureGeneration(source.config, formats, source.directory, source.path, { ...overrides, files: features.files, auth: features.auth })
81
- : configure({ ...source.config, server: { ...serverOptions, ...overrides } }, source.directory, source.path);
90
+ ? configureGeneration(source.config, formats, source.directory, source.path, { ...overrides, files: features.files, ...recordFlags })
91
+ : configure({
92
+ ...source.config,
93
+ ...(Object.keys(recordFlags).length ? { database: { ...(isObject(source.config.database) ? source.config.database : {}), ...recordFlags } } : {}),
94
+ server: { ...serverOptions, ...overrides },
95
+ }, source.directory, source.path);
82
96
  if (generate) {
83
97
  if (!config.database.schema)
84
98
  throw new Error('Generation requires an explicit model schema');
@@ -92,7 +106,9 @@ export async function runCli(args = process.argv.slice(2), services = { createSe
92
106
  const openapi = formats.includes('openapi')
93
107
  ? await generateOpenapi(config.database.schema, {
94
108
  files: config.files != null,
95
- auth: config.auth?.enabled,
109
+ auth: config.auth != null,
110
+ timestamps: config.database.timestamps,
111
+ softDelete: config.database.softDelete,
96
112
  host: config.server.host,
97
113
  port: config.server.port,
98
114
  pageSize: config.server.pageSize,
@@ -100,7 +116,9 @@ export async function runCli(args = process.argv.slice(2), services = { createSe
100
116
  info: config.openapi.info,
101
117
  })
102
118
  : undefined;
103
- const graphql = formats.includes('graphql') ? await generateGraphql(config.database.schema) : undefined;
119
+ const graphql = formats.includes('graphql')
120
+ ? await generateGraphql(config.database.schema, { auth: config.auth != null, timestamps: config.database.timestamps, softDelete: config.database.softDelete })
121
+ : undefined;
104
122
  if (openapi) {
105
123
  await writeOpenapi(openapi, config.openapi.path);
106
124
  process.stdout.write(`OpenAPI: ${config.openapi.path}\n`);
@@ -115,4 +133,4 @@ export async function runCli(args = process.argv.slice(2), services = { createSe
115
133
  await server.listen();
116
134
  server.log.info('Deep JSON Server started');
117
135
  }
118
- //# sourceMappingURL=cli.js.map
136
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -3,4 +3,4 @@ export declare const DEFAULT_MAX_FILE_SIZE: number;
3
3
  export declare const DEFAULT_MAX_PAGE_SIZE = 100;
4
4
  export declare const DEFAULT_PAGE_SIZE = 10;
5
5
  export declare const DEFAULT_PORT = 4001;
6
- export declare const VERSION = "1.0.0-alpha.6";
6
+ export declare const VERSION = "1.0.0-alpha.7";
@@ -3,5 +3,5 @@ export const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024;
3
3
  export const DEFAULT_MAX_PAGE_SIZE = 100;
4
4
  export const DEFAULT_PAGE_SIZE = 10;
5
5
  export const DEFAULT_PORT = 4001;
6
- export const VERSION = '1.0.0-alpha.6';
6
+ export const VERSION = '1.0.0-alpha.7';
7
7
  //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/core/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC;AACxC,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AACvD,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AACzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AACjC,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,CAAC"}
@@ -0,0 +1,50 @@
1
+ import type { RecordOptions } from './lifecycle/options.js';
2
+ import type { ModelSchema } from './model.js';
3
+ import type { DatabaseData, DatabaseRecord } from './types.js';
4
+ export type DatabaseConfig = Pick<RecordOptions, 'timestamps' | 'softDelete'> & ({
5
+ data: DatabaseData;
6
+ path?: never;
7
+ schema?: ModelSchema | string;
8
+ } | {
9
+ data?: never;
10
+ path: string;
11
+ schema?: ModelSchema | string;
12
+ });
13
+ export interface DatabaseContainer {
14
+ data: DatabaseData;
15
+ counters?: Record<string, number>;
16
+ }
17
+ export interface DatabaseStore {
18
+ database: DatabaseContainer;
19
+ path?: string;
20
+ read(): Promise<DatabaseData>;
21
+ update<T>(operation: (database: DatabaseContainer) => T): Promise<T>;
22
+ }
23
+ /** Проверяет сериализуемое JSON-значение; отвергает циклы, разреженные массивы, NaN и бесконечности.
24
+ * @example validateJsonValue({ a: [1, null] }, 'data') → undefined; NaN → ошибка.
25
+ */
26
+ export declare const validateJsonValue: (value: unknown, path: string, ancestors?: WeakSet<object>) => void;
27
+ /** Проверяет объект коллекций, записи и уникальность ключей; возвращает исходный объект.
28
+ * @example validateDatabase({ notes: [{ id: '1' }] }) → тот же объект; повторный id → ошибка.
29
+ */
30
+ export declare const validateDatabase: (data: unknown, primaryKeys?: Map<string, string>) => DatabaseData;
31
+ /** Читает UTF-8 JSON-файл и проверяет, что верхний уровень является объектом.
32
+ * @example Файл с {"a":1} → Promise<{ a: 1 }>; файл с [] → ошибка.
33
+ */
34
+ export declare const readJsonObjectFile: (path: string, label: string) => Promise<Record<string, unknown>>;
35
+ /** Читает файл и проверяет коллекции и первичные ключи.
36
+ * @example Файл с {"notes":[]} → Promise<{ notes: [] }>.
37
+ */
38
+ export declare const readDatabaseFile: (databasePath: string, keys?: Map<string, string>) => Promise<DatabaseData>;
39
+ /** Создаёт дисковое хранилище или хранилище в памяти по настройкам.
40
+ * @example createDatabaseStore({ data: { notes: [] } }) → Promise<DatabaseStore>.
41
+ */
42
+ export declare const createDatabaseStore: (config: DatabaseConfig, keys?: Map<string, string>) => Promise<DatabaseStore>;
43
+ /** Ищет индекс записи, сравнивая строковые представления id.
44
+ * @example findItemIndex([{ id: 1 }], '1') → 0; пустой массив → -1.
45
+ */
46
+ export declare const findItemIndex: (collection: DatabaseRecord[], id: unknown) => number;
47
+ /** Генерирует случайный строковый id, отсутствующий в переданной коллекции.
48
+ * @example createId([]) → строка из 11 символов; конкретное значение зависит от генератора случайных чисел.
49
+ */
50
+ export declare const createId: (collection: DatabaseRecord[]) => string;
@@ -5,6 +5,9 @@ import { JSONFile } from 'lowdb/node';
5
5
  import { domainError } from './errors.js';
6
6
  import { createSerialQueue, createUniqueId, isObject, isSafeKey, isSystemError, resolveDatabasePath } from './utils.js';
7
7
  const RESOURCE_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*$/;
8
+ /** Проверяет сериализуемое JSON-значение; отвергает циклы, разреженные массивы, NaN и бесконечности.
9
+ * @example validateJsonValue({ a: [1, null] }, 'data') → undefined; NaN → ошибка.
10
+ */
8
11
  export const validateJsonValue = (value, path, ancestors = new WeakSet()) => {
9
12
  if (value === null || typeof value === 'string' || typeof value === 'boolean') {
10
13
  return;
@@ -41,6 +44,9 @@ export const validateJsonValue = (value, path, ancestors = new WeakSet()) => {
41
44
  }
42
45
  ancestors.delete(value);
43
46
  };
47
+ /** Проверяет объект коллекций, записи и уникальность ключей; возвращает исходный объект.
48
+ * @example validateDatabase({ notes: [{ id: '1' }] }) → тот же объект; повторный id → ошибка.
49
+ */
44
50
  export const validateDatabase = (data, primaryKeys) => {
45
51
  if (!isObject(data)) {
46
52
  throw new Error('База данных должна содержать JSON-объект');
@@ -74,6 +80,9 @@ export const validateDatabase = (data, primaryKeys) => {
74
80
  });
75
81
  return data;
76
82
  };
83
+ /** Читает UTF-8 JSON-файл и проверяет, что верхний уровень является объектом.
84
+ * @example Файл с {"a":1} → Promise<{ a: 1 }>; файл с [] → ошибка.
85
+ */
77
86
  export const readJsonObjectFile = async (path, label) => {
78
87
  const resolvedPath = resolve(path);
79
88
  let source;
@@ -92,6 +101,9 @@ export const readJsonObjectFile = async (path, label) => {
92
101
  }
93
102
  return value;
94
103
  };
104
+ /** Читает файл и проверяет коллекции и первичные ключи.
105
+ * @example Файл с {"notes":[]} → Promise<{ notes: [] }>.
106
+ */
95
107
  export const readDatabaseFile = async (databasePath, keys) => validateDatabase(await readJsonObjectFile(databasePath, 'Файл базы данных'), keys);
96
108
  const validateDraft = (data, keys) => {
97
109
  try {
@@ -144,8 +156,16 @@ const createMemoryDatabaseStore = (sourceData, keys) => {
144
156
  });
145
157
  return { database, read, update };
146
158
  };
147
- /** Creates a disk- or memory-backed database with serialized updates. */
159
+ /** Создаёт дисковое хранилище или хранилище в памяти по настройкам.
160
+ * @example createDatabaseStore({ data: { notes: [] } }) → Promise<DatabaseStore>.
161
+ */
148
162
  export const createDatabaseStore = async (config, keys) => config.data != null ? createMemoryDatabaseStore(config.data, keys) : createDiskDatabaseStore(config.path, keys);
163
+ /** Ищет индекс записи, сравнивая строковые представления id.
164
+ * @example findItemIndex([{ id: 1 }], '1') → 0; пустой массив → -1.
165
+ */
149
166
  export const findItemIndex = (collection, id) => collection.findIndex((item) => String(item.id) === String(id));
167
+ /** Генерирует случайный строковый id, отсутствующий в переданной коллекции.
168
+ * @example createId([]) → строка из 11 символов; конкретное значение зависит от генератора случайных чисел.
169
+ */
150
170
  export const createId = (collection) => createUniqueId((id) => findItemIndex(collection, id) !== -1);
151
171
  //# sourceMappingURL=database.js.map