ztechno_core 0.0.66 → 0.0.68

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.
@@ -55,7 +55,7 @@ export type MailOptions = MailOptionsBase & {
55
55
  html?: string;
56
56
  };
57
57
  export type ZMailSendOptTemplate = MailOptionsBase & {
58
- template: 'template.html';
58
+ template: 'C:/example/template.html' | string;
59
59
  inject: {
60
60
  title: string;
61
61
  content: string;
@@ -66,7 +66,7 @@ export type ZMailSendOptTemplate = MailOptionsBase & {
66
66
  export type ZMailSendOptAll = MailOptionsBase & {
67
67
  body: string;
68
68
  html: string;
69
- template: 'template.html' | string;
69
+ template: 'C:/example/template.html' | string;
70
70
  inject: {
71
71
  title: string;
72
72
  content: string;
@@ -1,4 +1,4 @@
1
- export type ZUser = {
1
+ export type ZUserCore = {
2
2
  user_id: number;
3
3
  email: string;
4
4
  session: string;
@@ -7,12 +7,24 @@ export type ZUser = {
7
7
  updated_at: any;
8
8
  created_at: any;
9
9
  };
10
+ export type ZUser = ZUserCore;
11
+ export interface ZUserExtended extends ZUserCore {
12
+ username?: string;
13
+ first_name?: string;
14
+ last_name?: string;
15
+ avatar_url?: string;
16
+ bio?: string;
17
+ is_active?: 0 | 1;
18
+ email_verified?: 0 | 1;
19
+ last_login?: any;
20
+ }
10
21
  export type ZRequiredUserColumns = {
11
22
  email: string;
12
23
  role: string | null;
13
24
  pass: string;
14
25
  admin: 0 | 1;
15
26
  };
27
+ export type ZRequiredUserColumnsExtended<T = {}> = ZRequiredUserColumns & Partial<T>;
16
28
  export type ZUserCredentials = {
17
29
  email: string;
18
30
  pass: string;
@@ -20,3 +32,10 @@ export type ZUserCredentials = {
20
32
  export type ZUserSession = {
21
33
  session: string;
22
34
  };
35
+ export type ZUserTableConfig = {
36
+ tableName?: string;
37
+ customColumns?: {
38
+ [columnName: string]: string;
39
+ };
40
+ customIndexes?: string[];
41
+ };
@@ -1,27 +1,65 @@
1
1
  import { ZSQLService } from './sql_service';
2
- import { ZRequiredUserColumns, ZUser, ZUserSession, ZUserCredentials } from './typings';
3
- export declare class ZUserService {
2
+ import { ZRequiredUserColumns, ZUser, ZUserCore, ZUserSession, ZUserCredentials, ZUserTableConfig } from './typings';
3
+ /**
4
+ * Generic User Service that can be extended with custom user fields
5
+ * @template TUser - The user type (defaults to ZUser for backward compatibility)
6
+ * @template TUserCreate - The user creation type (defaults to ZRequiredUserColumns)
7
+ */
8
+ export declare class ZUserService<
9
+ TUser extends ZUserCore = ZUser,
10
+ TUserCreate extends ZRequiredUserColumns = ZRequiredUserColumns,
11
+ > {
4
12
  private tableName;
5
13
  private sqlService;
6
14
  private salt;
7
- constructor({ sqlService, tableName }: { sqlService: ZSQLService; tableName?: string });
8
- private checkTableExists;
15
+ protected tableConfig: ZUserTableConfig;
16
+ /**
17
+ * Creates a new ZUserService instance
18
+ * @param options - Configuration options including SQL service and optional table configuration
19
+ */
20
+ constructor({ sqlService, tableConfig }: { sqlService: ZSQLService; tableConfig?: ZUserTableConfig });
21
+ /**
22
+ * Gets the base table columns definition
23
+ * @returns SQL column definitions for core user fields
24
+ * @protected
25
+ */
26
+ protected getBaseTableColumns(): string;
27
+ /**
28
+ * Gets custom table columns if defined
29
+ * @returns SQL column definitions for custom fields
30
+ * @protected
31
+ */
32
+ protected getCustomTableColumns(): string;
33
+ /**
34
+ * Gets base table indexes
35
+ * @returns SQL index definitions for core fields
36
+ * @protected
37
+ */
38
+ protected getBaseTableIndexes(): string;
39
+ /**
40
+ * Gets custom table indexes if defined
41
+ * @returns SQL index definitions for custom fields
42
+ * @protected
43
+ */
44
+ protected getCustomTableIndexes(): string;
45
+ protected checkTableExists(): Promise<boolean>;
9
46
  checkTableHasAdmin(): Promise<boolean>;
10
- private createTable;
47
+ protected createTable(): Promise<void>;
11
48
  ensureTableExists(): Promise<void>;
12
- register({ email, pass, role, admin }: ZRequiredUserColumns): Promise<{
49
+ /**
50
+ * Registers a new user with extensible data
51
+ * @param userData - User data including core fields and any custom fields
52
+ * @returns Promise resolving to session information
53
+ */
54
+ register(userData: TUserCreate): Promise<{
13
55
  session: string;
14
56
  }>;
15
- fetch(opt?: { limit: number }): Promise<any[][]>;
16
- exists(
17
- opt:
18
- | {
19
- email: string;
20
- }
21
- | {
22
- user_id: number;
23
- },
24
- ): Promise<boolean>;
57
+ /**
58
+ * Gets all available columns for SELECT queries
59
+ * @returns Comma-separated list of column names
60
+ * @protected
61
+ */
62
+ protected getSelectColumns(): string;
25
63
  find(
26
64
  opt:
27
65
  | {
@@ -30,12 +68,13 @@ export declare class ZUserService {
30
68
  | {
31
69
  user_id: number;
32
70
  },
33
- ): Promise<ZUser | undefined>;
71
+ ): Promise<TUser | undefined>;
34
72
  auth(opt: ZUserSession | ZUserCredentials): Promise<{
35
- user?: ZUser;
73
+ user?: TUser;
36
74
  session?: string;
37
75
  authenticated: boolean;
38
76
  }>;
77
+ fetch(opt?: { limit?: number }): Promise<TUser[]>;
39
78
  private genSession;
40
79
  private hashPass;
41
80
  }
@@ -2,12 +2,79 @@
2
2
  Object.defineProperty(exports, '__esModule', { value: true });
3
3
  exports.ZUserService = void 0;
4
4
  const crypto_service_1 = require('./crypto_service');
5
+ /**
6
+ * Generic User Service that can be extended with custom user fields
7
+ * @template TUser - The user type (defaults to ZUser for backward compatibility)
8
+ * @template TUserCreate - The user creation type (defaults to ZRequiredUserColumns)
9
+ */
5
10
  class ZUserService {
6
- constructor({ sqlService, tableName }) {
11
+ /**
12
+ * Creates a new ZUserService instance
13
+ * @param options - Configuration options including SQL service and optional table configuration
14
+ */
15
+ constructor({ sqlService, tableConfig }) {
7
16
  this.sqlService = sqlService;
8
- this.tableName = tableName || 'users';
17
+ this.tableConfig = tableConfig || {};
18
+ this.tableName = this.tableConfig.tableName || 'users';
9
19
  this.salt = sqlService.database;
10
20
  }
21
+ /**
22
+ * Gets the base table columns definition
23
+ * @returns SQL column definitions for core user fields
24
+ * @protected
25
+ */
26
+ getBaseTableColumns() {
27
+ return `
28
+ \`user_id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
29
+ \`email\` varchar(255) NOT NULL,
30
+ \`role\` varchar(64) DEFAULT NULL,
31
+ \`pass\` varchar(512) NOT NULL,
32
+ \`session\` varchar(512) NOT NULL,
33
+ \`admin\` tinyint(1) NOT NULL DEFAULT 0,
34
+ \`updated_at\` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
35
+ \`created_at\` datetime NOT NULL DEFAULT current_timestamp()
36
+ `;
37
+ }
38
+ /**
39
+ * Gets custom table columns if defined
40
+ * @returns SQL column definitions for custom fields
41
+ * @protected
42
+ */
43
+ getCustomTableColumns() {
44
+ if (!this.tableConfig.customColumns) return '';
45
+ return Object.entries(this.tableConfig.customColumns)
46
+ .map(([columnName, definition]) => `\`${columnName}\` ${definition}`)
47
+ .join(',\n ');
48
+ }
49
+ /**
50
+ * Gets base table indexes
51
+ * @returns SQL index definitions for core fields
52
+ * @protected
53
+ */
54
+ getBaseTableIndexes() {
55
+ return `
56
+ PRIMARY KEY (\`user_id\`),
57
+ UNIQUE KEY \`email_UNIQUE\` (\`email\`),
58
+ KEY \`email\` (\`email\`),
59
+ KEY \`role\` (\`role\`),
60
+ KEY \`admin\` (\`admin\`),
61
+ KEY \`created_at\` (\`created_at\`),
62
+ KEY \`updated_at\` (\`updated_at\`),
63
+ KEY \`session\` (\`session\`)
64
+ `;
65
+ }
66
+ /**
67
+ * Gets custom table indexes if defined
68
+ * @returns SQL index definitions for custom fields
69
+ * @protected
70
+ */
71
+ getCustomTableIndexes() {
72
+ if (!this.tableConfig.customIndexes) return '';
73
+ return this.tableConfig.customIndexes
74
+ .map((index) => index.trim())
75
+ .filter((index) => index.length > 0)
76
+ .join(',\n ');
77
+ }
11
78
  async checkTableExists() {
12
79
  const res = await this.sqlService.query(`
13
80
  SELECT ENGINE, VERSION, CREATE_TIME FROM information_schema.tables
@@ -23,23 +90,17 @@ class ZUserService {
23
90
  return res.length > 0;
24
91
  }
25
92
  async createTable() {
93
+ const baseColumns = this.getBaseTableColumns();
94
+ const customColumns = this.getCustomTableColumns();
95
+ const baseIndexes = this.getBaseTableIndexes();
96
+ const customIndexes = this.getCustomTableIndexes();
97
+ const allColumns = customColumns ? `${baseColumns},\n ${customColumns}` : baseColumns;
98
+ const allIndexes = customIndexes ? `${baseIndexes},\n ${customIndexes}` : baseIndexes;
26
99
  await this.sqlService.query(`
27
100
  CREATE TABLE \`${this.tableName}\` (
28
- \`user_id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
29
- \`email\` varchar(64) NOT NULL,
30
- \`role\` varchar(64) DEFAULT NULL,
31
- \`pass\` varchar(512) NOT NULL,
32
- \`session\` varchar(512) NOT NULL,
33
- \`admin\` tinyint(1) NOT NULL,
34
- \`updated_at\` datetime NOT NULL DEFAULT current_timestamp(),
35
- \`created_at\` datetime NOT NULL DEFAULT current_timestamp(),
36
- PRIMARY KEY (\`user_id\`),
37
- UNIQUE KEY \`email_UNIQUE\` (\`email\`),
38
- KEY \`email\` (\`email\`),
39
- KEY \`createdat\` (\`created_at\`),
40
- KEY \`updatedat\` (\`updated_at\`),
41
- KEY \`session\` (\`session\`)
42
- ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
101
+ ${allColumns},
102
+ ${allIndexes}
103
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
43
104
  `);
44
105
  }
45
106
  async ensureTableExists() {
@@ -48,36 +109,49 @@ class ZUserService {
48
109
  await this.createTable();
49
110
  }
50
111
  }
51
- async register({ email, pass, role, admin }) {
52
- const session = this.genSession({ email, pass });
112
+ /**
113
+ * Registers a new user with extensible data
114
+ * @param userData - User data including core fields and any custom fields
115
+ * @returns Promise resolving to session information
116
+ */
117
+ async register(userData) {
118
+ const session = this.genSession({ email: userData.email, pass: userData.pass });
119
+ // Build dynamic SQL for insertion
120
+ const coreFields = ['email', 'pass', 'session', 'role', 'admin'];
121
+ const customFields = Object.keys(userData).filter((key) => !coreFields.includes(key) && key !== 'pass');
122
+ const allFields = [...coreFields, ...customFields];
123
+ const placeholders = allFields.map(() => '?').join(', ');
124
+ const fieldNames = allFields.map((field) => `\`${field}\``).join(', ');
125
+ const values = allFields.map((field) => {
126
+ if (field === 'pass') return this.hashPass({ email: userData.email, pass: userData.pass });
127
+ if (field === 'session') return session;
128
+ return userData[field];
129
+ });
53
130
  await this.sqlService.query(
54
131
  `
55
- INSERT INTO \`${this.tableName}\` (email, pass, session, role, admin)
56
- VALUES (?, ?, ?, ?, ?)
132
+ INSERT INTO \`${this.tableName}\` (${fieldNames})
133
+ VALUES (${placeholders})
57
134
  `,
58
- [email, this.hashPass({ email, pass }), session, role, admin],
135
+ values,
59
136
  );
60
137
  return { session };
61
138
  }
62
- async fetch(opt) {
63
- const rows = await this.sqlService.query(
64
- `
65
- SELECT user_id, email, role, admin, created_at FROM \`${this.tableName}\`
66
- LIMIT ?
67
- `,
68
- [opt.limit],
69
- );
70
- return rows;
71
- }
72
- async exists(opt) {
73
- const user = await this.find(opt);
74
- return user !== undefined;
139
+ /**
140
+ * Gets all available columns for SELECT queries
141
+ * @returns Comma-separated list of column names
142
+ * @protected
143
+ */
144
+ getSelectColumns() {
145
+ const baseColumns = ['user_id', 'email', 'session', 'role', 'admin', 'updated_at', 'created_at'];
146
+ const customColumns = this.tableConfig.customColumns ? Object.keys(this.tableConfig.customColumns) : [];
147
+ return [...baseColumns, ...customColumns].map((col) => `\`${col}\``).join(', ');
75
148
  }
76
149
  async find(opt) {
150
+ const selectColumns = this.getSelectColumns();
77
151
  if (opt.email !== undefined) {
78
152
  const rows = await this.sqlService.query(
79
153
  `
80
- SELECT user_id, email, session, role, admin, updated_at, created_at FROM \`${this.tableName}\`
154
+ SELECT ${selectColumns} FROM \`${this.tableName}\`
81
155
  WHERE email=?`,
82
156
  [opt.email],
83
157
  );
@@ -85,7 +159,7 @@ class ZUserService {
85
159
  } else if (opt.user_id !== undefined) {
86
160
  const rows = await this.sqlService.query(
87
161
  `
88
- SELECT user_id, email, session, role, admin, updated_at, created_at FROM \`${this.tableName}\`
162
+ SELECT ${selectColumns} FROM \`${this.tableName}\`
89
163
  WHERE user_id=?`,
90
164
  [opt.user_id],
91
165
  );
@@ -98,21 +172,35 @@ class ZUserService {
98
172
  if (!opt.session && !opt.email && !opt.pass) {
99
173
  return { authenticated: false };
100
174
  }
175
+ const selectColumns = this.getSelectColumns();
101
176
  const res = await (opt.session
102
177
  ? this.sqlService.query(
103
178
  `
104
- SELECT user_id, email, session, role, admin, updated_at, created_at FROM \`${this.tableName}\`
179
+ SELECT ${selectColumns} FROM \`${this.tableName}\`
105
180
  WHERE session=?`,
106
181
  [opt.session],
107
182
  )
108
183
  : this.sqlService.query(
109
184
  `
110
- SELECT user_id, email, session, role, admin, updated_at, created_at FROM \`${this.tableName}\`
185
+ SELECT ${selectColumns} FROM \`${this.tableName}\`
111
186
  WHERE email=? AND pass=?`,
112
187
  [opt.email, this.hashPass(opt)],
113
188
  ));
114
189
  return res.length === 0 ? { authenticated: false } : { user: res[0], session: res[0].session, authenticated: true };
115
190
  }
191
+ async fetch(opt) {
192
+ const selectColumns = this.getSelectColumns();
193
+ const limit = opt?.limit || 100;
194
+ const rows = await this.sqlService.query(
195
+ `
196
+ SELECT ${selectColumns} FROM \`${this.tableName}\`
197
+ ORDER BY created_at DESC
198
+ LIMIT ?
199
+ `,
200
+ [limit],
201
+ );
202
+ return rows;
203
+ }
116
204
  genSession({ email }) {
117
205
  const salt = this.salt;
118
206
  const data = email + Date.now() * Math.random();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ztechno_core",
3
- "version": "0.0.66",
3
+ "version": "0.0.68",
4
4
  "description": "Core files for ztechno framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",