openxiangda 1.0.162 → 1.0.164

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 (33) hide show
  1. package/README.md +6 -2
  2. package/lib/change-baseline.js +88 -2
  3. package/lib/cli.js +565 -73
  4. package/lib/js-code-build.js +120 -8
  5. package/lib/publish-lease.js +13 -1
  6. package/lib/release-mainline.js +545 -0
  7. package/lib/runtime-lineage.js +19 -12
  8. package/lib/sdd.js +137 -0
  9. package/lib/workspace-bootstrap.js +36 -7
  10. package/lib/workspace-init.js +12 -3
  11. package/lib/worktree-owner.js +13 -0
  12. package/openxiangda-skills/SKILL.md +9 -3
  13. package/openxiangda-skills/references/automation-v3.md +1 -1
  14. package/openxiangda-skills/references/resource-manifest-cheatsheet.md +1 -1
  15. package/openxiangda-skills/references/workflow-v3.md +1 -1
  16. package/openxiangda-skills/skills/openxiangda-core/SKILL.md +8 -2
  17. package/openxiangda-skills/skills/openxiangda-workflow-automation/SKILL.md +2 -2
  18. package/package.json +3 -1
  19. package/templates/openxiangda-react-spa/.cursor/rules/openxiangda-resources.mdc +2 -1
  20. package/templates/openxiangda-react-spa/.cursor/rules/openxiangda.mdc +2 -2
  21. package/templates/openxiangda-react-spa/.qoder/rules/openxiangda-resources.md +2 -1
  22. package/templates/openxiangda-react-spa/.qoder/rules/openxiangda.md +3 -3
  23. package/templates/openxiangda-react-spa/AGENTS.md +8 -6
  24. package/templates/openxiangda-react-spa/scripts/build-js-code.mjs +172 -20
  25. package/templates/openxiangda-react-spa/scripts/deploy.mjs +19 -39
  26. package/templates/openxiangda-react-spa/scripts/guard-publish.mjs +4 -5
  27. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-resources.mdc +3 -1
  28. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda.mdc +1 -1
  29. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-resources.md +3 -1
  30. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda.md +1 -1
  31. package/templates/sy-lowcode-app-workspace/AGENTS.md +4 -4
  32. package/templates/sy-lowcode-app-workspace/scripts/build-js-code.mjs +172 -20
  33. package/templates/sy-lowcode-app-workspace/scripts/guard-publish.mjs +4 -5
@@ -1,6 +1,16 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
1
3
  const { spawnSync } = require('child_process');
2
4
 
3
5
  const JS_CODE_SOURCE_KINDS = new Set(['js-code-nodes', 'automations', 'functions']);
6
+ const CANONICAL_BUILD_SCRIPT = path.join(
7
+ __dirname,
8
+ '..',
9
+ 'templates',
10
+ 'openxiangda-react-spa',
11
+ 'scripts',
12
+ 'build-js-code.mjs'
13
+ );
4
14
 
5
15
  function normalizeJsCodeBuildTargets(targets = []) {
6
16
  const normalized = [];
@@ -42,20 +52,122 @@ function buildJsCodeBatchArgs(targets, options = {}) {
42
52
  ];
43
53
  }
44
54
 
55
+ function readWorkspacePackage(workspaceRoot) {
56
+ try {
57
+ return JSON.parse(
58
+ fs.readFileSync(path.join(workspaceRoot, 'package.json'), 'utf8')
59
+ );
60
+ } catch {
61
+ return null;
62
+ }
63
+ }
64
+
65
+ function isStandardWorkspaceJsCodeBuilder(workspaceRoot) {
66
+ const command = String(
67
+ readWorkspacePackage(workspaceRoot)?.scripts?.['build-js-code'] || ''
68
+ ).trim().replace(/\\/g, '/');
69
+ if (!command) return true;
70
+ // Only bypass the exact template-shaped command. Extra flags, command
71
+ // chaining, or wrappers may be meaningful custom preprocessing and must keep
72
+ // using the workspace builder.
73
+ const matched = command.match(
74
+ /^(?:node\s+)?((?:\.\/)?scripts\/build-js-code\.(?:mjs|cjs|js))$/
75
+ );
76
+ if (!matched) return false;
77
+ try {
78
+ const source = fs.readFileSync(path.resolve(workspaceRoot, matched[1]), 'utf8');
79
+ return [
80
+ 'tsconfig.js-code-nodes.json',
81
+ 'sourceKinds',
82
+ 'buildScript',
83
+ ].every(marker => source.includes(marker)) &&
84
+ (source.includes('resolveBuildTargets') ||
85
+ source.includes('resolveBuildSelection'));
86
+ } catch {
87
+ return false;
88
+ }
89
+ }
90
+
91
+ function findWorkspaceTargetEntry(workspaceRoot, target) {
92
+ const base = path.join(
93
+ workspaceRoot,
94
+ 'src',
95
+ target.sourceKind,
96
+ target.scriptCode,
97
+ 'index'
98
+ );
99
+ return ['.ts', '.tsx']
100
+ .map(extension => `${base}${extension}`)
101
+ .find(filePath => fs.existsSync(filePath));
102
+ }
103
+
104
+ function canUseCanonicalJsCodeBuilder(workspaceRoot, targets, options = {}) {
105
+ if (
106
+ options.preferWorkspaceBuilder ||
107
+ process.env.OPENXIANGDA_USE_WORKSPACE_JS_CODE_BUILDER === '1'
108
+ ) {
109
+ return false;
110
+ }
111
+ if (
112
+ !fs.existsSync(CANONICAL_BUILD_SCRIPT) ||
113
+ !fs.existsSync(path.join(workspaceRoot, 'tsconfig.js-code-nodes.json')) ||
114
+ !isStandardWorkspaceJsCodeBuilder(workspaceRoot)
115
+ ) {
116
+ return false;
117
+ }
118
+ return targets.every(target => findWorkspaceTargetEntry(workspaceRoot, target));
119
+ }
120
+
121
+ function resolveWorkspaceJsCodeBuildCommand(workspaceRoot, targets, options = {}) {
122
+ const normalized = normalizeJsCodeBuildTargets(targets);
123
+ const packageArgs = buildJsCodeBatchArgs(normalized, options);
124
+ if (canUseCanonicalJsCodeBuilder(workspaceRoot, normalized, options)) {
125
+ return {
126
+ mode: 'canonical-scoped',
127
+ command: options.nodeBinary || process.execPath,
128
+ args: [CANONICAL_BUILD_SCRIPT, ...packageArgs.slice(1)],
129
+ env: {
130
+ OPENXIANGDA_WORKSPACE_ROOT: path.resolve(workspaceRoot),
131
+ },
132
+ };
133
+ }
134
+ return {
135
+ mode: 'workspace-script',
136
+ command: options.packageManager || 'pnpm',
137
+ args: packageArgs,
138
+ env: {},
139
+ };
140
+ }
141
+
45
142
  function runWorkspaceJsCodeBuildBatch(workspaceRoot, targets, options = {}) {
46
- return spawnSync(
47
- options.packageManager || 'pnpm',
48
- buildJsCodeBatchArgs(targets, options),
49
- {
50
- cwd: workspaceRoot,
51
- encoding: 'utf8',
52
- ...options.spawnOptions,
53
- }
143
+ const resolved = resolveWorkspaceJsCodeBuildCommand(
144
+ workspaceRoot,
145
+ targets,
146
+ options
54
147
  );
148
+ const spawnOptions = {
149
+ cwd: workspaceRoot,
150
+ encoding: 'utf8',
151
+ ...options.spawnOptions,
152
+ };
153
+ if (resolved.mode === 'canonical-scoped') {
154
+ spawnOptions.env = {
155
+ ...process.env,
156
+ ...(options.spawnOptions?.env || {}),
157
+ ...resolved.env,
158
+ };
159
+ }
160
+ const result = spawnSync(resolved.command, resolved.args, spawnOptions);
161
+ Object.defineProperty(result, 'openxiangdaBuildMode', {
162
+ value: resolved.mode,
163
+ enumerable: false,
164
+ });
165
+ return result;
55
166
  }
56
167
 
57
168
  module.exports = {
58
169
  buildJsCodeBatchArgs,
59
170
  normalizeJsCodeBuildTargets,
171
+ resolveWorkspaceJsCodeBuildCommand,
60
172
  runWorkspaceJsCodeBuildBatch,
61
173
  };
@@ -91,6 +91,11 @@ function normalizePublishLease(input, target) {
91
91
  const leaseId = String(input?.leaseId || '').trim();
92
92
  const expiresAt = normalizeDate(input?.expiresAt, 'expiresAt');
93
93
  if (!leaseId) throw new Error('publish lease response 缺少 leaseId');
94
+ const currentWorkspace = readWorkspaceIdentity(optionsCwd(target));
95
+ const suppliedWorkspace =
96
+ input?.workspace && typeof input.workspace === 'object'
97
+ ? input.workspace
98
+ : {};
94
99
  return {
95
100
  leaseId,
96
101
  appType: String(input?.appType || target?.appType || '').trim(),
@@ -100,7 +105,14 @@ function normalizePublishLease(input, target) {
100
105
  baseRevision: String(input?.baseRevision || '').trim() || null,
101
106
  expiresAt,
102
107
  holder: input?.holder === 'other' ? 'other' : 'self',
103
- workspace: readWorkspaceIdentity(optionsCwd(target)),
108
+ workspace: {
109
+ ...currentWorkspace,
110
+ ...suppliedWorkspace,
111
+ cwd: currentWorkspace.cwd,
112
+ worktreeRoot:
113
+ suppliedWorkspace.worktreeRoot || currentWorkspace.worktreeRoot,
114
+ threadId: currentCodexThreadId() || suppliedWorkspace.threadId || null,
115
+ },
104
116
  updatedAt: new Date().toISOString(),
105
117
  };
106
118
  }