@ojiepermana/angular 21.1.16 → 21.1.18

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.
@@ -1,15 +1,7 @@
1
1
  /**
2
- * @ojiepermana/angular/etos complete Etos brand stylesheet.
2
+ * Compatibility entry for consumers that resolve the explicit index file.
3
3
  *
4
- * Import before Tailwind, then import the shared Tailwind token bridge.
4
+ * Keep this publish-safe because ng-packagr copies it verbatim to
5
+ * `@ojiepermana/angular/etos/styles/index.css`.
5
6
  */
6
- @import '../../../theme/src/lib/styles/themes/library/_layers.css';
7
- @import '../../../theme/src/lib/styles/themes/mode/index.css';
8
- @import '../../../theme/src/lib/styles/themes/library/color/index.css';
9
- @import '../../../theme/src/lib/styles/themes/library/style/index.css';
10
- @import './color.css';
11
- @import './style.css';
12
- @import './layout.css';
13
- @import '../../../theme/src/lib/styles/themes/library/_tokens.css';
14
- @import '../../../theme/src/lib/styles/themes/library/_material-overrides.css';
15
- @import '../../../theme/src/lib/styles/themes/library/_components.css';
7
+ @import './package.css';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @ojiepermana/angular/etos — published Etos brand stylesheet.
3
+ *
4
+ * Import before Tailwind, then import the shared Tailwind token bridge.
5
+ */
6
+ @import '@ojiepermana/angular/theme/styles/themes/library/_layers.css';
7
+ @import '@ojiepermana/angular/theme/styles/themes/mode/index.css';
8
+ @import '@ojiepermana/angular/theme/styles/themes/library/color/index.css';
9
+ @import '@ojiepermana/angular/theme/styles/themes/library/style/index.css';
10
+ @import './color.css';
11
+ @import './style.css';
12
+ @import './layout.css';
13
+ @import '@ojiepermana/angular/theme/styles/themes/library/_tokens.css';
14
+ @import '@ojiepermana/angular/theme/styles/themes/library/_material-overrides.css';
15
+ @import '@ojiepermana/angular/theme/styles/themes/library/_components.css';
@@ -38,8 +38,8 @@ async function generate(target, workspaceRoot) {
38
38
  // public-api barrel is emitted last so it sees the final feature set.
39
39
  files.push(...(0, public_api_1.emitPublicApi)(ir, target));
40
40
  const laidOut = target.splitByDomain ? (0, per_domain_1.relayoutPerDomain)(files, ir, target) : files;
41
- const wrapped = applyMode(laidOut, ir, target);
42
41
  const outputDir = (0, node_path_1.isAbsolute)(target.output) ? target.output : (0, node_path_1.resolve)(workspaceRoot, target.output);
42
+ const wrapped = applyMode(laidOut, ir, target, workspaceRoot, outputDir);
43
43
  return {
44
44
  target,
45
45
  outputDir,
@@ -52,12 +52,12 @@ async function generate(target, workspaceRoot) {
52
52
  },
53
53
  };
54
54
  }
55
- function applyMode(files, ir, target) {
55
+ function applyMode(files, ir, target, workspaceRoot, outputDir) {
56
56
  switch (target.mode) {
57
57
  case 'library':
58
- return (0, index_1.writeLibrary)(files, ir, target);
58
+ return (0, index_1.writeLibrary)(files, ir, target, workspaceRoot, outputDir);
59
59
  case 'secondary-entrypoint':
60
- return (0, index_1.writeSecondaryEntrypoint)(files, ir, target);
60
+ return (0, index_1.writeSecondaryEntrypoint)(files, ir, target, workspaceRoot, outputDir);
61
61
  case 'standalone':
62
62
  default:
63
63
  return (0, index_1.writeStandalone)(files);
@@ -293,7 +293,7 @@ function emitPublicApis(ir, target, mapping) {
293
293
  }
294
294
  if (target.features.metadata) {
295
295
  sharedLines.push(`export * from './metadata-types';`);
296
- sharedLines.push(`export * from './validators';`);
296
+ sharedLines.push(`export * from './validators/index';`);
297
297
  sharedLines.push('');
298
298
  }
299
299
  if (target.features.navigation) {
@@ -303,16 +303,9 @@ function emitPublicApis(ir, target, mapping) {
303
303
  // Per-domain public-api.ts.
304
304
  for (const domain of mapping.domains) {
305
305
  const lines = [target.banner, ''];
306
- // Re-export shared namespace for convenience. `domain` may be nested
307
- // (e.g. `storage/gcs`), so compute the relative path instead of
308
- // hard-coding `../shared/public-api`.
309
- const domainDir = node_path_1.posix.join(VIRTUAL_ROOT, domain);
310
- const sharedTarget = node_path_1.posix.join(VIRTUAL_ROOT, SHARED, 'public-api');
311
- let sharedSpec = node_path_1.posix.relative(domainDir, sharedTarget);
312
- if (!sharedSpec.startsWith('.'))
313
- sharedSpec = `./${sharedSpec}`;
314
- lines.push(`export * from '${sharedSpec}';`);
315
- lines.push('');
306
+ // Keep each domain entrypoint scoped to its own surface. Re-exporting the
307
+ // shared barrel here makes the root barrel publish the same names twice
308
+ // once it also exports `./shared/public-api`.
316
309
  if (target.features.models) {
317
310
  const ownedModels = schemaNames.filter((n) => mapping.modelOwner.get(n) === domain);
318
311
  for (const name of ownedModels) {
@@ -321,6 +314,14 @@ function emitPublicApis(ir, target, mapping) {
321
314
  if (ownedModels.length)
322
315
  lines.push('');
323
316
  }
317
+ if (target.features.metadata) {
318
+ const tags = (mapping.domainServices.get(domain) ?? []).slice().sort();
319
+ for (const tag of tags) {
320
+ lines.push(`export { ${(0, template_1.camelCase)(tag)}OperationRules } from './permissions/${(0, template_1.kebabCase)(tag)}';`);
321
+ }
322
+ if (tags.length)
323
+ lines.push('');
324
+ }
324
325
  if (target.features.services) {
325
326
  const tags = mapping.domainServices.get(domain) ?? [];
326
327
  for (const tag of tags.sort()) {
@@ -3,7 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.writeStandalone = writeStandalone;
4
4
  exports.writeLibrary = writeLibrary;
5
5
  exports.writeSecondaryEntrypoint = writeSecondaryEntrypoint;
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
6
8
  const template_1 = require("../render/template");
9
+ const ROOT_ENTRYPOINT = '';
10
+ const VIRTUAL_ROOT = '/__sdk__';
7
11
  /**
8
12
  * No-op writer for the standalone mode — returns emitted files unchanged. Kept
9
13
  * as a named function so modes are composable from a single switch at the
@@ -16,10 +20,11 @@ function writeStandalone(files) {
16
20
  * Library mode: add `ng-package.json`, `package.json`, and a top-level README
17
21
  * so the `output` folder can be built with ng-packagr directly.
18
22
  */
19
- function writeLibrary(files, ir, target) {
23
+ function writeLibrary(files, ir, target, workspaceRoot, outputDir) {
24
+ const normalizedFiles = rewriteCrossEntrypointImports(files, target, workspaceRoot, outputDir);
20
25
  const ngPackage = {
21
- $schema: '../../node_modules/ng-packagr/ng-package.schema.json',
22
- dest: `../dist/${target.packageName.replace(/^@/, '').replace(/\//g, '-')}`,
26
+ $schema: toPosixPath((0, node_path_1.relative)(outputDir, (0, node_path_1.resolve)(workspaceRoot, 'node_modules/ng-packagr/ng-package.schema.json'))),
27
+ dest: toPosixPath((0, node_path_1.relative)(outputDir, (0, node_path_1.resolve)(workspaceRoot, 'dist', packageSlug(target.packageName)))),
23
28
  lib: { entryFile: 'public-api.ts' },
24
29
  };
25
30
  const pkg = {
@@ -34,9 +39,9 @@ function writeLibrary(files, ir, target) {
34
39
  sideEffects: false,
35
40
  };
36
41
  return [
37
- ...files,
42
+ ...normalizedFiles,
38
43
  createNgPackageFile('ng-package.json', ngPackage),
39
- ...createNestedEntrypointNgPackages(files),
44
+ ...createNestedEntrypointNgPackages(normalizedFiles),
40
45
  {
41
46
  path: 'package.json',
42
47
  content: (0, template_1.finalize)(JSON.stringify(pkg, null, 2)),
@@ -53,11 +58,154 @@ function writeLibrary(files, ir, target) {
53
58
  * existing library (e.g. `projects/angular/sdk-api/`) so ng-packagr picks it
54
59
  * up automatically as a secondary entrypoint of the parent library.
55
60
  */
56
- function writeSecondaryEntrypoint(files, _ir, _target) {
61
+ function writeSecondaryEntrypoint(files, _ir, target, workspaceRoot, outputDir) {
62
+ const normalizedFiles = rewriteCrossEntrypointImports(files, target, workspaceRoot, outputDir);
57
63
  const ngPackage = {
58
64
  lib: { entryFile: 'public-api.ts' },
59
65
  };
60
- return [...files, createNgPackageFile('ng-package.json', ngPackage), ...createNestedEntrypointNgPackages(files)];
66
+ return [
67
+ ...normalizedFiles,
68
+ createNgPackageFile('ng-package.json', ngPackage),
69
+ ...createNestedEntrypointNgPackages(normalizedFiles),
70
+ ];
71
+ }
72
+ function rewriteCrossEntrypointImports(files, target, workspaceRoot, outputDir) {
73
+ const entrypointDirs = collectEntrypointDirs(files);
74
+ if (entrypointDirs.length <= 1) {
75
+ return [...files];
76
+ }
77
+ const packageImportBase = resolvePackageImportBase(target, workspaceRoot, outputDir);
78
+ if (!packageImportBase) {
79
+ return [...files];
80
+ }
81
+ const knownFiles = new Set(files.map((file) => file.path));
82
+ return files.map((file) => {
83
+ const owner = findEntrypointOwner(file.path, entrypointDirs);
84
+ if (owner === ROOT_ENTRYPOINT) {
85
+ return file;
86
+ }
87
+ return {
88
+ ...file,
89
+ content: file.content.replace(/(from\s+['"])([^'"]+)(['"])/g, (_match, prefix, spec, suffix) => {
90
+ const nextSpec = rewriteModuleSpecifier(spec, file.path, owner, entrypointDirs, knownFiles, packageImportBase);
91
+ return `${prefix}${nextSpec}${suffix}`;
92
+ }),
93
+ };
94
+ });
95
+ }
96
+ function rewriteModuleSpecifier(specifier, currentPath, currentOwner, entrypointDirs, knownFiles, packageImportBase) {
97
+ if (!specifier.startsWith('./') && !specifier.startsWith('../')) {
98
+ return specifier;
99
+ }
100
+ const targetPath = resolveVirtualFilePath(currentPath, specifier, knownFiles);
101
+ if (!targetPath) {
102
+ return specifier;
103
+ }
104
+ const targetOwner = findEntrypointOwner(targetPath, entrypointDirs);
105
+ if (targetOwner === currentOwner) {
106
+ return specifier;
107
+ }
108
+ return buildEntrypointImport(packageImportBase, targetOwner);
109
+ }
110
+ function resolveVirtualFilePath(currentPath, specifier, knownFiles) {
111
+ const currentAbs = node_path_1.posix.join(VIRTUAL_ROOT, currentPath);
112
+ const resolved = node_path_1.posix.normalize(node_path_1.posix.join((0, node_path_1.dirname)(currentAbs), specifier));
113
+ const candidates = [`${resolved}.ts`, `${resolved}/index.ts`, `${resolved}/public-api.ts`, resolved];
114
+ for (const candidate of candidates) {
115
+ if (!candidate.startsWith(`${VIRTUAL_ROOT}/`)) {
116
+ continue;
117
+ }
118
+ const relativePath = candidate.slice(VIRTUAL_ROOT.length + 1);
119
+ if (knownFiles.has(relativePath)) {
120
+ return relativePath;
121
+ }
122
+ }
123
+ return undefined;
124
+ }
125
+ function resolvePackageImportBase(target, workspaceRoot, outputDir) {
126
+ if (target.mode === 'library') {
127
+ return target.packageName;
128
+ }
129
+ if (target.mode !== 'secondary-entrypoint') {
130
+ return '';
131
+ }
132
+ return inferSecondaryEntrypointPackageName(workspaceRoot, outputDir, target.packageName);
133
+ }
134
+ function inferSecondaryEntrypointPackageName(workspaceRoot, outputDir, fallback) {
135
+ let currentDir = outputDir;
136
+ let nearestPackageDir;
137
+ let nearestPackagrDir;
138
+ while (isWithinWorkspace(currentDir, workspaceRoot)) {
139
+ const packageJsonPath = (0, node_path_1.resolve)(currentDir, 'package.json');
140
+ if ((0, node_fs_1.existsSync)(packageJsonPath)) {
141
+ nearestPackageDir ??= currentDir;
142
+ if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(currentDir, 'ng-package.json'))) {
143
+ nearestPackagrDir = currentDir;
144
+ break;
145
+ }
146
+ }
147
+ if (currentDir === workspaceRoot) {
148
+ break;
149
+ }
150
+ const parentDir = (0, node_path_1.dirname)(currentDir);
151
+ if (parentDir === currentDir) {
152
+ break;
153
+ }
154
+ currentDir = parentDir;
155
+ }
156
+ const packageDir = nearestPackagrDir ?? nearestPackageDir;
157
+ if (!packageDir) {
158
+ return fallback;
159
+ }
160
+ const packageName = readPackageName(packageDir);
161
+ if (!packageName) {
162
+ return fallback;
163
+ }
164
+ const relativeOutput = toPosixPath((0, node_path_1.relative)(packageDir, outputDir)).replace(/^\.\//, '');
165
+ if (!relativeOutput || relativeOutput === '.') {
166
+ return packageName;
167
+ }
168
+ return `${packageName}/${relativeOutput}`;
169
+ }
170
+ function readPackageName(packageDir) {
171
+ const packageJsonPath = (0, node_path_1.resolve)(packageDir, 'package.json');
172
+ if (!(0, node_fs_1.existsSync)(packageJsonPath)) {
173
+ return undefined;
174
+ }
175
+ const raw = JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, 'utf8'));
176
+ return typeof raw.name === 'string' && raw.name.length > 0 ? raw.name : undefined;
177
+ }
178
+ function isWithinWorkspace(candidate, workspaceRoot) {
179
+ const rel = (0, node_path_1.relative)(workspaceRoot, candidate);
180
+ return rel === '' || (!rel.startsWith('..') && !(0, node_path_1.isAbsolute)(rel));
181
+ }
182
+ function collectEntrypointDirs(files) {
183
+ const dirs = new Set();
184
+ for (const file of files) {
185
+ if (file.path === 'public-api.ts') {
186
+ dirs.add(ROOT_ENTRYPOINT);
187
+ continue;
188
+ }
189
+ if (!file.path.endsWith('/public-api.ts')) {
190
+ continue;
191
+ }
192
+ dirs.add(file.path.slice(0, -'/public-api.ts'.length));
193
+ }
194
+ return [...dirs].sort((left, right) => right.length - left.length || left.localeCompare(right));
195
+ }
196
+ function findEntrypointOwner(filePath, entrypointDirs) {
197
+ for (const entrypointDir of entrypointDirs) {
198
+ if (entrypointDir === ROOT_ENTRYPOINT) {
199
+ continue;
200
+ }
201
+ if (filePath === `${entrypointDir}/public-api.ts` || filePath.startsWith(`${entrypointDir}/`)) {
202
+ return entrypointDir;
203
+ }
204
+ }
205
+ return ROOT_ENTRYPOINT;
206
+ }
207
+ function buildEntrypointImport(packageImportBase, entrypointDir) {
208
+ return entrypointDir ? `${packageImportBase}/${entrypointDir}` : packageImportBase;
61
209
  }
62
210
  function createNestedEntrypointNgPackages(files) {
63
211
  return collectSecondaryEntrypointDirs(files).map((dir) => createNgPackageFile(`${dir}/ng-package.json`, {
@@ -74,6 +222,12 @@ function collectSecondaryEntrypointDirs(files) {
74
222
  }
75
223
  return [...dirs].sort();
76
224
  }
225
+ function packageSlug(packageName) {
226
+ return packageName.replace(/^@/, '').replace(/\//g, '-');
227
+ }
228
+ function toPosixPath(value) {
229
+ return value.split('\\').join('/');
230
+ }
77
231
  function createNgPackageFile(path, content) {
78
232
  return {
79
233
  path,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ojiepermana/angular",
3
- "version": "21.1.16",
3
+ "version": "21.1.18",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/ojiepermana/angular.git"
@@ -65,11 +65,11 @@
65
65
  "sideEffects": false,
66
66
  "schematics": "./collection.json",
67
67
  "exports": {
68
- "./etos/styles": "./etos/styles/index.css",
68
+ "./etos/styles": "./etos/styles/package.css",
69
69
  "./etos/styles/*": "./etos/styles/*",
70
70
  "./theme/styles": "./theme/styles/index.css",
71
71
  "./theme/styles/*": "./theme/styles/*",
72
- "./theme/tailwind/theme.css": "./theme/styles/themes/taildwind.css",
72
+ "./theme/tailwind/theme.css": "./theme/styles/themes/tailwind.css",
73
73
  "./package.json": {
74
74
  "default": "./package.json"
75
75
  },
@@ -3,4 +3,4 @@
3
3
  *
4
4
  * The Etos implementation now lives under the dedicated `./etos` entrypoint.
5
5
  */
6
- @import '../../../../brand/etos/themes/index.css';
6
+ @import '@ojiepermana/angular/etos/styles';
@@ -109,4 +109,4 @@
109
109
 
110
110
  --font-sans: var(--theme-font-sans);
111
111
  --font-mono: var(--theme-font-mono);
112
- }
112
+ }